Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add serde support for tl_types. #277

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/grammers-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ markdown = ["pulldown-cmark"]
html = ["html5ever"]
proxy = ["grammers-mtsender/proxy"]
parse_invite_link = ["url"]
serde = ["grammers-tl-types/impl-serde"]

[dependencies]
chrono = "0.4.38"
Expand Down
4 changes: 4 additions & 0 deletions lib/grammers-tl-gen/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ fn write_enum<W: Write>(
writeln!(file, "{indent}#[derive(Debug)]")?;
}

if config.impl_serde{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting is going to complain here.

writeln!(file, "{indent}#[derive(serde_derive::Serialize, serde_derive::Deserialize)]")?;
}

writeln!(file, "{indent}#[derive(Clone, PartialEq)]")?;
writeln!(
file,
Expand Down
2 changes: 2 additions & 0 deletions lib/grammers-tl-gen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct Config {
pub impl_debug: bool,
pub impl_from_type: bool,
pub impl_from_enum: bool,
pub impl_serde: bool,
}

impl Default for Config {
Expand All @@ -36,6 +37,7 @@ impl Default for Config {
impl_debug: true,
impl_from_type: true,
impl_from_enum: true,
impl_serde: false,
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions lib/grammers-tl-gen/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ fn write_struct<W: Write>(
writeln!(file, "{indent}#[derive(Debug)]")?;
}

if config.impl_serde{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here.

writeln!(file, "{indent}#[derive(serde_derive::Serialize, serde_derive::Deserialize)]")?;
}

writeln!(file, "{indent}#[derive(Clone, PartialEq)]")?;
write!(
file,
Expand Down
1 change: 1 addition & 0 deletions lib/grammers-tl-gen/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ fn gen_rust_code(definitions: &[Definition]) -> io::Result<String> {
impl_debug: true,
impl_from_enum: true,
impl_from_type: true,
impl_serde: true,
},
)?;
Ok(String::from_utf8(file).unwrap())
Expand Down
6 changes: 6 additions & 0 deletions lib/grammers-tl-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,11 @@ deserializable-functions = []
impl-debug = []
impl-from-enum = []
impl-from-type = []
impl-serde = ["dep:serde", "dep:serde_derive", "dep:serde_bytes"]
tl-api = []
tl-mtproto = []

[dependencies]
serde = { version = "1.0.210", optional = true }
serde_bytes = { version = "0.11.15", optional = true }
serde_derive = { version = "1.0.210", optional = true }
12 changes: 12 additions & 0 deletions lib/grammers-tl-types/DEPS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,15 @@ Used to parse the `.tl` files provided by Telegram's open source projects.
## toml

Used to test that this file lists all dependencies from `Cargo.toml`.

## serde

Support serde ecosystem.

## serde_derive

Macros that auto generate serde code.

## serde_bytes

Use better bytes encode/decode pattern in serde.
1 change: 1 addition & 0 deletions lib/grammers-tl-types/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ fn main() -> std::io::Result<()> {
impl_debug: cfg!(feature = "impl-debug"),
impl_from_enum: cfg!(feature = "impl-from-enum"),
impl_from_type: cfg!(feature = "impl-from-type"),
impl_serde: cfg!(feature = "impl-serde"),
};

generate_rust_code(&mut file, &definitions, layer, &config)?;
Expand Down
9 changes: 8 additions & 1 deletion lib/grammers-tl-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
//! * `tl-mtproto`: generates code for the `mtproto.tl`.
//! Only useful for low-level libraries.
//!
//! * `impl-serde`: generates code for serde support
//!
//! [`types`]: types/index.html
//! [`functions`]: functions/index.html
//! [`RemoteCall`]: trait.RemoteCall.html
Expand All @@ -84,19 +86,24 @@ pub use deserialize::{Cursor, Deserializable};
pub use generated::{enums, functions, name_for_id, types, LAYER};
pub use serialize::Serializable;

#[cfg(feature = "impl-serde")]
use serde_derive::{Deserialize, Serialize};

/// This struct represents the concrete type of a vector, that is,
/// `vector` as opposed to the type `Vector`. This bare type is less
/// common, so instead of creating a enum for `Vector` wrapping `vector`
/// as Rust's `Vec` (as we would do with auto-generated code),
/// a new-type for `vector` is used instead.
#[cfg_attr(feature = "impl-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct RawVec<T>(pub Vec<T>);

/// This struct represents an unparsed blob, which should not be deserialized
/// as a bytes string. Used by functions returning generic objects which pass
/// the underlying result without any modification or interpretation.
#[cfg_attr(feature = "impl-serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct Blob(pub Vec<u8>);
pub struct Blob(#[cfg_attr(feature = "impl-serde", serde(with = "serde_bytes"))] pub Vec<u8>);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Help needed.

I am not formiliar with tl proto. Is there any other structure that store bytes in .tl definition files? All bytes-like properties need marked by serde_bytes for better performence.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, Vec<u8> are also generated for the TL bytes type. If that's the case, we may need to check the field types when generating code.

Might be good to write a test that makes sure this works as expected.


impl From<Vec<u8>> for Blob {
fn from(value: Vec<u8>) -> Self {
Expand Down
Loading