All Projects → witnet → Protobuf Convert

witnet / Protobuf Convert

Licence: apache-2.0
Macros for convenient serialization of Rust data structures into/from Protocol Buffers 3

Programming Languages

rust
10112 projects
macro
33 projects

Projects that are alternatives of or similar to Protobuf Convert

Flatcc
FlatBuffers Compiler and Library in C for C
Stars: ✭ 434 (+1872.73%)
Mutual labels:  schema, serialization, protocol
Ocaml Protoc
A Protobuf Compiler for OCaml
Stars: ✭ 129 (+486.36%)
Mutual labels:  protobuf, serialization, protocol
nimpb
Protocol Buffers for Nim
Stars: ✭ 29 (+31.82%)
Mutual labels:  serialization, protobuf
ocaml-pb-plugin
A protoc plugin for generating OCaml code from protobuf (.proto) files.
Stars: ✭ 18 (-18.18%)
Mutual labels:  serialization, protobuf
Strictyaml
Type-safe YAML parser and validator.
Stars: ✭ 836 (+3700%)
Mutual labels:  schema, serialization
javascript-serialization-benchmark
Comparison and benchmark of JavaScript serialization libraries (Protocol Buffer, Avro, BSON, etc.)
Stars: ✭ 54 (+145.45%)
Mutual labels:  serialization, protobuf
tinypacks
A data serialization format for constrained environments like 8-bit and 16-bit microcontrollers.
Stars: ✭ 30 (+36.36%)
Mutual labels:  serialization, protocol
Kotlinx.serialization
Kotlin multiplatform / multi-format serialization
Stars: ✭ 3,550 (+16036.36%)
Mutual labels:  protobuf, serialization
kafka-protobuf-serde
Serializer/Deserializer for Kafka to serialize/deserialize Protocol Buffers messages
Stars: ✭ 52 (+136.36%)
Mutual labels:  serialization, protobuf
Ceras
Universal binary serializer for a wide variety of scenarios https://discord.gg/FGaCX4c
Stars: ✭ 374 (+1600%)
Mutual labels:  serialization, protocol
Fastbinaryencoding
Fast Binary Encoding is ultra fast and universal serialization solution for C++, C#, Go, Java, JavaScript, Kotlin, Python, Ruby, Swift
Stars: ✭ 421 (+1813.64%)
Mutual labels:  serialization, protocol
protobuf-d
Protocol Buffers Compiler Plugin and Support Library for D
Stars: ✭ 32 (+45.45%)
Mutual labels:  serialization, protobuf
protoc-plugin
A protoc compiler plugin for Clojure applications
Stars: ✭ 28 (+27.27%)
Mutual labels:  serialization, protobuf
CppSerialization
Performance comparison of the most popular C++ serialization protocols such as Cap'n'Proto, FastBinaryEncoding, Flatbuffers, Protobuf, JSON
Stars: ✭ 89 (+304.55%)
Mutual labels:  serialization, protobuf
sirdez
Glorious Binary Serialization and Deserialization for TypeScript.
Stars: ✭ 20 (-9.09%)
Mutual labels:  serialization, protocol
Shineframe
高性能超轻量级C++开发库及服务器编程框架
Stars: ✭ 274 (+1145.45%)
Mutual labels:  protobuf, serialization
Cpp Serializers
Benchmark comparing various data serialization libraries (thrift, protobuf etc.) for C++
Stars: ✭ 533 (+2322.73%)
Mutual labels:  protobuf, serialization
elm-protobuf
protobuf plugin for elm
Stars: ✭ 93 (+322.73%)
Mutual labels:  serialization, protobuf
proto2gql
The project has been migrated to https://github.com/EGT-Ukraine/go2gql.
Stars: ✭ 21 (-4.55%)
Mutual labels:  schema, protobuf
Flatbuffers
FlatBuffers: Memory Efficient Serialization Library
Stars: ✭ 17,180 (+77990.91%)
Mutual labels:  protobuf, serialization

protobuf-convert

Macros for convenient serialization of Rust data structures into/from Protocol Buffers.

Introduction

This is a fork of exonum-derive with some changes to allow easier integration with other projects, and some new features.

Usage

First, add the dependency in Cargo.toml:

protobuf-convert = "0.4.0"

Then, define a ProtobufConvert trait:

trait ProtobufConvert {
    /// Type of the protobuf clone of Self
    type ProtoStruct;

    /// Struct -> ProtoStruct
    fn to_pb(&self) -> Self::ProtoStruct;

    /// ProtoStruct -> Struct
    fn from_pb(pb: Self::ProtoStruct) -> Result<Self, Error>;
}

And to use it, import the trait and the macro:

For example, given the following protobuf:

message Ping {
    fixed64 nonce = 1;
}

rust-protobuf will generate the following struct:

#[derive(PartialEq,Clone,Default)]
#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
pub struct Ping {
    // message fields
    pub nonce: u64,
    // special fields
    #[cfg_attr(feature = "with-serde", serde(skip))]
    pub unknown_fields: ::protobuf::UnknownFields,
    #[cfg_attr(feature = "with-serde", serde(skip))]
    pub cached_size: ::protobuf::CachedSize,
}

We may want to convert that struct into a more idiomatic one, and derive more traits. This is the necessary code:

// Import trait
use crate::proto::ProtobufConvert;
// Import macro
use protobuf_convert::ProtobufConvert;
// Import module autogenerated by protocol buffers
use crate::proto::schema;

#[derive(ProtobufConvert)]
#[protobuf_convert(source = "schema::Ping")]
struct Ping {
    nonce: u64,
}

Note that the ProtobufConvert trait must be implemented for all the fields, see an example implementation for u64:

impl ProtobufConvert for u64 {
    type ProtoStruct = u64;

    fn to_pb(&self) -> Self::ProtoStruct {
        *self
    }

    fn from_pb(pb: Self::ProtoStruct) -> Result<Self, Error> {
        Ok(pb)
    }
}

Now, converting between Ping and schema::Ping can be done effortlessly.

Enum support

A more complex example, featuring enums:

message Ping {
    fixed64 nonce = 1;
}
message Pong {
    fixed64 nonce = 1;
}
message Message {
    oneof kind {
        Ping Ping = 1;
        Pong Pong = 2;
    }
}
#[derive(ProtobufConvert)]
#[protobuf_convert(source = "schema::Ping")]
struct Ping {
    nonce: u64,
}
#[derive(ProtobufConvert)]
#[protobuf_convert(source = "schema::Pong")]
struct Pong {
    nonce: u64,
}
#[derive(ProtobufConvert)]
#[protobuf_convert(source = "schema::Message")]
enum Message {
    Ping(Ping),
    Pong(Pong),
}

And it just works!

You can also generate From and TryFrom traits for enum variants. Note that this will not work if enum has variants with the same field types. To use this feature add impl_from_trait attribute.

#[derive(ProtobufConvert)]
#[protobuf_convert(source = "schema::Message"), impl_from_trait]
enum Message {
    Ping(Ping),
    Pong(Pong),
}

From<Ping>, From<Pong> and also TryFrom<..> traits will be generated.

Another attribute that can be used with enum is rename. It instructs macro to generate methods with case specified in attribute param.

#[derive(ProtobufConvert)]
#[protobuf_convert(source = "schema::Message"), rename(case = "snake_case")]
enum Message {
    Ping(Ping),
    Pong(Pong),
}

Currently, only snake case is supported.

Skipping fields

This macro also supports skipping fields in structs so they are ignored when serializing, i.e they will not be mapped to any field in the schema:

#[derive(ProtobufConvert)]
#[protobuf_convert(source = "schema::Ping")]
struct Ping {
    pub nonce: u64,
    #[protobuf_convert(skip)]
    my_private_field: u64
}

Note that you can only skip fields whose type implements the Default trait.

Overriding conversion rules

This macro also supports serde-like attribute with for modules with the custom implementation of from_pb and to_pb conversions.

protobuf-convert will use functions $module::from_pb and $module::to_pb instead of ProtobufConvert trait for the specified field.

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
enum CustomId {
    First = 5,
    Second = 15,
    Third = 35,
}

#[derive(Debug, Clone, ProtobufConvert, Eq, PartialEq)]
#[protobuf_convert(source = "proto::SimpleMessage")]
struct CustomMessage {
    #[protobuf_convert(with = "custom_id_pb_convert")]
    id: Option<CustomId>,
    name: String,
}

mod custom_id_pb_convert {
    use super::*;

    pub(super) fn from_pb(pb: u32) -> Result<Option<CustomId>, anyhow::Error> {
        match pb {
            0 => Ok(None),
            5 => Ok(Some(CustomId::First)),
            15 => Ok(Some(CustomId::Second)),
            35 => Ok(Some(CustomId::Third)),
            other => Err(anyhow::anyhow!("Unknown enum discriminant: {}", other)),
        }
    }

    pub(super) fn to_pb(v: &Option<CustomId>) -> u32 {
        match v {
            Some(id) => *id as u32,
            None => 0,
        }
    }
}

See also

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected]