A pure Rust library to serialize/deserialize protobuf files.
This crate intends to provide a simple yet fast (minimal allocations) protobuf parser implementation. In general, you should probably NOT need to use this crate directly, else, you should use the modules automatically generated by pb-rs tool.
```sh cargo install pb-rs pb-rs /path/to/your/protobuf/file.proto
```
```toml
[dependencies] quick-protobuf = "0.6.2" ```
```rust extern crate quick_protobuf;
mod foo_bar; // (see 1.)
use quick_protobuf::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;
// }
// FooBar is a message generated from a proto file
// in parcicular it contains a from_reader
function
use foobar::FooBar;
use quickprotobuf::{MessageRead, BytesReader};
fn main() {
// bytes is a buffer on the data we want to deserialize
// typically bytes is read from a `Read`:
// r.read_to_end(&mut bytes).expect("cannot read bytes");
let bytes: Vec<u8> = ...;
// In the most simple form, we want to deserialize from a `&[u8]`
let foobar = deserialize_from_slice(&bytes).expect("Cannot convert into a `FooBar`");
// ...
// ...
// Alternatively, we can go lower level and work with a `BytesReader`
// It gives more control of the bytes we are reading
let mut reader = BytesReader::from_bytes(&bytes);
// now using the generated module decoding is as easy as:
let foobar = FooBar::from_reader(&mut reader, &bytes).expect("Cannot read FooBar");
// if instead the buffer contains a length delimited stream of message we could use:
// while !r.is_eof() {
// let foobar: FooBar = r.read_message(&bytes).expect(...);
// ...
// }
println!("Found {} foos and {} bars", foobar.foos.len(), foobar.bars.len());
// Similarly, if we want to serialize the message you can use a `Writer` or use
// `serialize_into_vec`
let vec = serialize_into_vec(&foobar).expect("Cannot serialize `foobar`");
// ... or for more control (more than one message)
let mut buf = Vec::new();
let mut writer = Writer::new(&mut buf);
writer.write_message(&foobar).expect("Cannot write `foobar`);
} ```
The best way to check for all kind of generated code is to look for the codegenexample data: - definition: datatypes.proto - generated code: data_types.rs
``` enum FooEnum { FIRSTVALUE = 1; SECONDVALUE = 2; }
message BarMessage { required int32 brequiredint32 = 1; }
message FooMessage { optional int32 fint32 = 1; optional int64 fint64 = 2; optional uint32 fuint32 = 3; optional uint64 fuint64 = 4; optional sint32 fsint32 = 5; optional sint64 fsint64 = 6; optional bool fbool = 7; optional FooEnum fFooEnum = 8; optional fixed64 ffixed64 = 9; optional sfixed64 fsfixed64 = 10; optional fixed32 ffixed32 = 11; optional sfixed32 fsfixed32 = 12; optional double fdouble = 13; optional float ffloat = 14; optional bytes fbytes = 15; optional string fstring = 16; optional FooMessage fselfmessage = 17; optional BarMessage fbarmessage = 18; repeated int32 frepeatedint32 = 19; repeated int32 frepeatedpacked_int32 = 20 [ packed = true ]; } ```
```rust
pub enum FooEnum { FIRSTVALUE = 1, SECONDVALUE = 2, }
pub struct BarMessage { // all fields are owned: no lifetime parameter pub brequiredint32: i32, }
pub struct FooMessage<'a> { // has borrowed fields: lifetime parameter
pub fint32: Option
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.
```rust
pub struct A {
//...
}
pub mod mod_A { pub struct B { // ... } } ```
package a.b;
Here we could have used the same name, but for consistency with nested messages, modules are prefixed with mod_
as well.
rust
pub mod mod_a {
pub mod mod_b {
// ...
}
}
This library is an alternative to the widely used rust-protobuf.
Pros
protoc
on your machineCons
Option
unwrapping, Cow
management)Any help is welcomed! (Pull requests of course, bug report, missing functionality etc...)
MIT