quick-protobuf
A pure Rust library to serialize/deserialize protobuf files.
Description
This library intends to provide a simple yet fast (minimal allocations) protobuf parser implementation.
It provides both:
- pb-rs, a code generation tool:
-
each
.proto
file will generate a minimal rust module (one function to read, one to write, and one to compute the size of the messages) -
each message will generate a rust struct where:
Proto Rust bytes Cow<'a, [u8]>
string Cow<'a, str>
other scalars rust primitive repeated Vec
repeated, packed, fixed size Cow<'a, [M]>
optional Option
message struct
enum enum
map HashMap
oneof Name OneOfName
enumnested m1
mod_m1
modulepackage a.b
mod_a::mod_b
modulesimport file_a.proto use super::file_a::*
-
no need to use google
protoc
tool to generate the modules
-
- quick-protobuf, a protobuf file parser:
- this is the crate that you will typically refer to in your library. The generated modules will assume it has been imported.
- it acts like an event parser, the logic to convert it into struct is handle by
pb-rs
Example: protobuf_example project
-
- Use
pb-rs
binary, located intocodegen
directory to automatically generate a foo_bar.rs module from a foo_bar.proto proto file
- Use
-
- Add a dependency to quick-protobuf
# Cargo.toml
[]
= "0.4.0"
-
- Have fun
// main.rs or lib.rs
extern crate quick_protobuf;
// (see 1.)
use Reader;
// We will suppose here that Foo and Bar are two messages defined in the .proto file
// and converted into rust structs
//
// FooBar is the root message defined like this:
// message FooBar {
// repeated Foo foos = 1;
// repeated Bar bars = 2;
// }
use ;
Examples directory
You can find basic examples in the examples directory.
- codegen_example: A basic write/read loop on all datatypes
Message <-> struct
The best way to check for all kind of generated code is to look for the codegen_example data:
- definition: data_types.proto
- generated code: data_types.rs
Proto definition
enum FooEnum {
FIRST_VALUE = 1;
SECOND_VALUE = 2;
}
message BarMessage {
required int32 b_required_int32 = 1;
}
message FooMessage {
optional int32 f_int32 = 1;
optional int64 f_int64 = 2;
optional uint32 f_uint32 = 3;
optional uint64 f_uint64 = 4;
optional sint32 f_sint32 = 5;
optional sint64 f_sint64 = 6;
optional bool f_bool = 7;
optional FooEnum f_FooEnum = 8;
optional fixed64 f_fixed64 = 9;
optional sfixed64 f_sfixed64 = 10;
optional fixed32 f_fixed32 = 11;
optional sfixed32 f_sfixed32 = 12;
optional double f_double = 13;
optional float f_float = 14;
optional bytes f_bytes = 15;
optional string f_string = 16;
optional FooMessage f_self_message = 17;
optional BarMessage f_bar_message = 18;
repeated int32 f_repeated_int32 = 19;
repeated int32 f_repeated_packed_int32 = 20 [ packed = true ];
}
Generated structs
Leverage rust module system
Nested Messages
message A {
message B {
// ...
}
}
As rust does not allow a struct and a module to share the same name, we use mod_Name
for the nested messages.
Package
package a.b;
Here we could have used the same name, but for consistency with nested messages, modules are prefixed with mod_
as well.
Why not rust-protobuf
This library is an alternative to the widely used rust-protobuf.
Pros / Cons
-
Pros
- Much faster, in particular when working with string, bytes and repeated packed fixed size fields (no extra allocation)
- No need to install
protoc
on your machine - No trait objects: faster/simpler parser
- Very simple generated modules (~10x smaller) so you can easily understand what is happening
-
Cons
- Younger library
- not battle tested, even if most rust-protobuf tests have been migrated here (see v2 and v3)
- some missing functionalities
- Not a drop-in replacement of rust-protobuf
- everything being explicit you have to handle more things yourself (e.g.
Option
unwrapping,Cow
management)
- everything being explicit you have to handle more things yourself (e.g.
- Younger library
Codegen
Have a look at the different generated modules for the same .proto file:
- rust-protobuf: 2371 loc
- quick-protobuf: 302 loc
Benchmarks
An adaptation of rust-protobuf perftest is available and show, on these particular examples, that quick-protobuf is much faster than rust-protobuf.
Contribution
Any help is welcomed! (Pull requests of course, bug report, missing functionality etc...)
Licence
MIT