{"id":13648668,"url":"https://github.com/witnet/protobuf-convert","last_synced_at":"2025-04-23T05:15:05.752Z","repository":{"id":62443027,"uuid":"170518369","full_name":"witnet/protobuf-convert","owner":"witnet","description":"Macros for convenient serialization of Rust data structures into/from Protocol Buffers 3","archived":false,"fork":false,"pushed_at":"2022-09-15T10:08:13.000Z","size":48,"stargazers_count":36,"open_issues_count":1,"forks_count":6,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-23T05:14:58.639Z","etag":null,"topics":["buffers","macro","protobuf","protocol","rust","schema","serialization"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/witnet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-13T14:08:10.000Z","updated_at":"2025-03-03T21:46:51.000Z","dependencies_parsed_at":"2022-11-01T22:16:32.375Z","dependency_job_id":null,"html_url":"https://github.com/witnet/protobuf-convert","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/witnet%2Fprotobuf-convert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/witnet%2Fprotobuf-convert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/witnet%2Fprotobuf-convert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/witnet%2Fprotobuf-convert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/witnet","download_url":"https://codeload.github.com/witnet/protobuf-convert/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250372942,"owners_count":21419724,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["buffers","macro","protobuf","protocol","rust","schema","serialization"],"created_at":"2024-08-02T01:04:26.453Z","updated_at":"2025-04-23T05:15:05.734Z","avatar_url":"https://github.com/witnet.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# protobuf-convert\n\nMacros for convenient serialization of Rust data structures into/from Protocol Buffers.\n\n## Introduction\n\nThis is a fork of [exonum-derive](https://crates.io/crates/exonum-derive) with\nsome changes to allow easier integration with other projects, and some new\nfeatures.\n\n## Usage\n\nFirst, add the dependency in `Cargo.toml`:\n\n```toml\nprotobuf-convert = \"0.4.0\"\n```\n\nThen, define a `ProtobufConvert` trait:\n\n```rust\ntrait ProtobufConvert {\n    /// Type of the protobuf clone of Self\n    type ProtoStruct;\n\n    /// Struct -\u003e ProtoStruct\n    fn to_pb(\u0026self) -\u003e Self::ProtoStruct;\n\n    /// ProtoStruct -\u003e Struct\n    fn from_pb(pb: Self::ProtoStruct) -\u003e Result\u003cSelf, Error\u003e;\n}\n```\n\nAnd to use it, import the trait and the macro:\n\nFor example, given the following protobuf:\n\n```protobuf\nmessage Ping {\n    fixed64 nonce = 1;\n}\n```\n\nrust-protobuf will generate the following struct:\n\n```rust\n#[derive(PartialEq,Clone,Default)]\n#[cfg_attr(feature = \"with-serde\", derive(Serialize, Deserialize))]\npub struct Ping {\n    // message fields\n    pub nonce: u64,\n    // special fields\n    #[cfg_attr(feature = \"with-serde\", serde(skip))]\n    pub unknown_fields: ::protobuf::UnknownFields,\n    #[cfg_attr(feature = \"with-serde\", serde(skip))]\n    pub cached_size: ::protobuf::CachedSize,\n}\n```\n\nWe may want to convert that struct into a more idiomatic one, and derive more traits.\nThis is the necessary code:\n\n```rust\n// Import trait\nuse crate::proto::ProtobufConvert;\n// Import macro\nuse protobuf_convert::ProtobufConvert;\n// Import module autogenerated by protocol buffers\nuse crate::proto::schema;\n\n#[derive(ProtobufConvert)]\n#[protobuf_convert(source = \"schema::Ping\")]\nstruct Ping {\n    nonce: u64,\n}\n```\n\nNote that the `ProtobufConvert` trait must be implemented for all the fields,\nsee an example implementation for `u64`:\n\n```rust\nimpl ProtobufConvert for u64 {\n    type ProtoStruct = u64;\n\n    fn to_pb(\u0026self) -\u003e Self::ProtoStruct {\n        *self\n    }\n\n    fn from_pb(pb: Self::ProtoStruct) -\u003e Result\u003cSelf, Error\u003e {\n        Ok(pb)\n    }\n}\n```\n\nNow, converting between `Ping` and `schema::Ping` can be done effortlessly.\n\n### `Enum` support\n\nA more complex example, featuring enums:\n\n```protobuf\nmessage Ping {\n    fixed64 nonce = 1;\n}\nmessage Pong {\n    fixed64 nonce = 1;\n}\nmessage Message {\n    oneof kind {\n        Ping Ping = 1;\n        Pong Pong = 2;\n    }\n}\n```\n\n```rust\n#[derive(ProtobufConvert)]\n#[protobuf_convert(source = \"schema::Ping\")]\nstruct Ping {\n    nonce: u64,\n}\n#[derive(ProtobufConvert)]\n#[protobuf_convert(source = \"schema::Pong\")]\nstruct Pong {\n    nonce: u64,\n}\n#[derive(ProtobufConvert)]\n#[protobuf_convert(source = \"schema::Message\")]\nenum Message {\n    Ping(Ping),\n    Pong(Pong),\n}\n```\n\nAnd it just works!\n\nYou can also generate `From` and `TryFrom` traits for enum variants. Note that this will not work if enum has variants\nwith the same field types. To use this feature add `impl_from_trait` attribute.\n\n```rust\n#[derive(ProtobufConvert)]\n#[protobuf_convert(source = \"schema::Message\"), impl_from_trait]\nenum Message {\n    Ping(Ping),\n    Pong(Pong),\n}\n```\n\n`From\u003cPing\u003e`, `From\u003cPong\u003e` and also `TryFrom\u003c..\u003e` traits will be generated.\n\nAnother attribute that can be used with enum is `rename`. It instructs macro to generate methods with case\nspecified in attribute param.\n\n```rust\n#[derive(ProtobufConvert)]\n#[protobuf_convert(source = \"schema::Message\"), rename(case = \"snake_case\")]\nenum Message {\n    Ping(Ping),\n    Pong(Pong),\n}\n```\n\nCurrently, only snake case is supported.\n\n### Skipping fields\n\nThis macro also supports skipping fields in `struct`s so they are ignored when serializing, i.e they will not be mapped to any field in the schema:\n\n```rust\n#[derive(ProtobufConvert)]\n#[protobuf_convert(source = \"schema::Ping\")]\nstruct Ping {\n    pub nonce: u64,\n    #[protobuf_convert(skip)]\n    my_private_field: u64\n}\n```\n\nNote that you can only skip fields whose type implements the `Default` trait.\n\n### Overriding conversion rules\n\nThis macro also supports serde-like attribute `with` for modules with the custom implementation of `from_pb` and `to_pb` conversions.\n\n`protobuf-convert` will use functions `$module::from_pb` and `$module::to_pb` instead of `ProtobufConvert` trait for the specified field.\n\n```rust\n#[derive(Debug, Clone, Copy, Eq, PartialEq)]\nenum CustomId {\n    First = 5,\n    Second = 15,\n    Third = 35,\n}\n\n#[derive(Debug, Clone, ProtobufConvert, Eq, PartialEq)]\n#[protobuf_convert(source = \"proto::SimpleMessage\")]\nstruct CustomMessage {\n    #[protobuf_convert(with = \"custom_id_pb_convert\")]\n    id: Option\u003cCustomId\u003e,\n    name: String,\n}\n\nmod custom_id_pb_convert {\n    use super::*;\n\n    pub(super) fn from_pb(pb: u32) -\u003e Result\u003cOption\u003cCustomId\u003e, anyhow::Error\u003e {\n        match pb {\n            0 =\u003e Ok(None),\n            5 =\u003e Ok(Some(CustomId::First)),\n            15 =\u003e Ok(Some(CustomId::Second)),\n            35 =\u003e Ok(Some(CustomId::Third)),\n            other =\u003e Err(anyhow::anyhow!(\"Unknown enum discriminant: {}\", other)),\n        }\n    }\n\n    pub(super) fn to_pb(v: \u0026Option\u003cCustomId\u003e) -\u003e u32 {\n        match v {\n            Some(id) =\u003e *id as u32,\n            None =\u003e 0,\n        }\n    }\n}\n```\n\n## See also\n\n* [rust-protobuf](https://github.com/stepancheg/rust-protobuf)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwitnet%2Fprotobuf-convert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwitnet%2Fprotobuf-convert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwitnet%2Fprotobuf-convert/lists"}