pbrs 0.2.0

Pure-Rust Protocol Buffers kernel with the Google protobuf v4 application API
Documentation

pbrs

Crates.io Documentation License

pbrs is a pure-Rust Protocol Buffers runtime and code generator for Rust developers who want the Google protobuf v4 application API without a C or C++ runtime. This workspace also contains pbrs-grpc for native gRPC over HTTP/2 and protobuf-tonic for tonic 0.14+ users.

Current status: published versions are available for evaluation, with recorded conformance through Protocol Buffers Edition 2023; production qualification and stronger performance claims still require the evidence in the roadmap.

Why use pbrs?

  • Pure Rust build: pbrs compiles with rustc. It does not wrap Google's upb C library through foreign function interface (FFI).
  • Google protobuf v4-shaped API: generated types use the application-level traits and shapes such as Parse, Serialize, Clear, proto!, ProtoStr, RepeatedView, and DynamicMessage.
  • Recorded conformance: Google's conformance_test_runner v35.1 passes 5,631 binary + JSON cases and 909 text cases with no unexpected results.
  • Broad protobuf surface: proto2, proto3, Edition 2023 behavior, well-known types (WKT), dynamic reflection, JSON formatting, and text formatting are in scope.
  • Performance-oriented storage: small-string optimization, zero-allocation empty collections, lazy materialization after wire validation, and specialized packed-scalar handling are built into the runtime.

pbrs is an application API alternative, not a drop-in replacement for official generated internals or prost::Message. See the upb comparison and implementation status for the tested boundaries.

Quick start: install, generate, use

This quick start generates Rust from proto/person.proto during your Cargo build. Direct .proto generation requires protoc on your PATH; see code generation options if you want checked-in descriptors instead.

  1. Add pbrs as both a runtime and build dependency:

    [dependencies]
    pbrs = "0.2"
    
    [build-dependencies]
    pbrs = "0.2"
    
  2. Add a proto file at proto/person.proto:

    syntax = "proto3";
    package tutorial;
    
    message Person {
      string name = 1;
      int32 id = 2;
      string email = 3;
      repeated string phones = 4;
    }
    
  3. Generate Rust in build.rs:

    fn main() -> Result<(), Box<dyn std::error::Error>> {
        pbrs::codegen::compile_protos(&["proto/person.proto"], &["proto"])?;
        Ok(())
    }
    
  4. Include and use the generated type:

    use pbrs::prelude::*;
    
    include!(concat!(env!("OUT_DIR"), "/person.rs"));
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        let mut person = Person::new();
        person.set_name("Ada Lovelace");
        person.set_id(42);
        person.set_email("ada@example.com");
        person.phones_mut().push("555-0100");
    
        let bytes: Vec<u8> = person.serialize()?;
        let decoded = Person::parse(&bytes)?;
    
        assert_eq!(decoded.name(), "Ada Lovelace");
        assert_eq!(decoded.id(), 42);
    
        println!("Parsed: {} (ID: {})", decoded.name(), decoded.id());
        Ok(())
    }
    

For protos that define services, compile_protos emits native pbrs-grpc stubs by default. tonic users must opt in with Config::emit_tonic_stubs(true).

Which crate do I need?

Need Use Notes
Protocol Buffers messages, parsing, serialization, reflection, JSON/text, or code generation pbrs Core crate and protoc-gen-pbrs plugin
Native Rust gRPC without tonic pbrs-grpc HTTP/2 gRPC client/server kernel built on h2, rustls, and Graviola
tonic 0.14+ services that use pbrs messages protobuf-tonic Codec adapter; not a prost::Message drop-in
End-to-end reference service examples/greeter Generated stubs, health checks, and server reflection

Workspace Crates

Crate What it contains crates.io Status
pbrs Core Protocol Buffers runtime: parser, serializer, code generator (protoc-gen-pbrs), dynamic messages, well-known types, JSON format, and text format. 0.2.0 (Published; qualification in progress)
pbrs-grpc Standalone pure-Rust HTTP/2 gRPC client and server kernel. It does not depend on C or tonic. 0.1.0-alpha.2 (Pre-release / Preview)
protobuf-tonic tonic 0.14+ Codec adapter for clients and servers that use regenerated pbrs message types. 0.1.0-alpha.2 (Pre-release / Preview)
examples/greeter Complete example with generated stubs, gRPC health checking (grpc.health.v1), and server reflection (grpc.reflection.v1). Example only (publish = false)

Code generation options

Generating directly from .proto files needs protoc. Generating from a previously compiled descriptor set does not run protoc during the application build.

Task Needs protoc? Notes
Build the core pbrs crate No The crate uses a bundled FileDescriptorSet.
Build pbrs-grpc and protobuf-tonic (0.1.0-alpha.2 and later, or this checkout) No They build from checked descriptor sets.
Build the older pbrs-grpc / protobuf-tonic 0.1.0-alpha.1 crates Yes Those alphas predate the checked-descriptor change.
Run compile_protos or protoc-gen-pbrs on application .proto files Yes protoc must be on PATH.
Run Config::compile_descriptor_set from a checked descriptor set No during the app build Creating or updating the descriptor set still needs protoc.

There is no enforced universal protoc version; see the support matrix.

Direct .proto generation with build.rs

Use this when your build environment has protoc available:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    pbrs::codegen::compile_protos(&["proto/person.proto"], &["proto"])?;
    Ok(())
}

Then include the generated file in src/lib.rs or src/main.rs:

include!(concat!(env!("OUT_DIR"), "/person.rs"));

Checked descriptor set generation

Use this when you want application builds to avoid running protoc. First create and check in a descriptor set with imports included:

protoc -I proto --include_imports --descriptor_set_out=proto/person.fds proto/person.proto

Then compile from that descriptor set:

fn main() -> Result<(), Box<dyn std::error::Error>> {
    pbrs::codegen::Config::new()
        .out_dir(std::env::var("OUT_DIR")?)
        .compile_descriptor_set("proto/person.fds", &["person.proto"], &["proto"])?;
    Ok(())
}

Descriptor targets use include-relative names such as person.proto. The descriptor and available source imports are tracked for rebuilds. See the codegen guide for native stubs, tonic stubs, and messages-only generation.

Against this checkout, a consumer using a checked descriptor set can cold-build messages, native stubs, and tonic stubs without protoc on its build PATH. The older 0.1.0-alpha.1 adapter archives still require it.

protoc-gen-pbrs plugin

Install or build the plugin binary:

cargo install --path . --bin protoc-gen-pbrs

Run protoc with the --pbrs_out flag:

protoc --pbrs_out=./gen --proto_path=./proto ./proto/hello.proto

Or use the helper script:

./scripts/gen.sh -I proto -o gen proto/your.proto

gRPC choices

Stack Choose it when Read more
pbrs-grpc native kernel You want a pure-Rust gRPC client/server stack independent of tonic. gRPC guide, pbrs-grpc/README.md
protobuf-tonic adapter You already use tonic 0.14+ and can use regenerated pbrs stubs instead of prost messages. Middleware must accept those message traits. protobuf-tonic/README.md

For a complete service with generated stubs, health checking, and server reflection, see examples/greeter.

Support matrix

Recorded against this repository on stable rustc 1.98. Declared rust-version is the continuous integration (CI) minimum supported Rust version (MSRV) job, not this host's toolchain. Releases follow the release guide: tag/dispatch only; main pushes do not publish.

The maintained crates and tools use Rust language Edition 2024, available from rustc 1.85. Frozen reference/comparator and discarded-experiment manifests keep their original edition for reproducibility. This is independent of Protocol Buffers Edition 2024.

Crate Declared MSRV Tested protoc Stub default
pbrs 1.85 rustc 1.98 (this host); CI msrv-core 1.85 --lib, stable Linux + macOS Not required to build the crate (bundled FileDescriptorSet). Required for compile_protos / protoc-gen-pbrs. Messages; .proto service blocks emit native pbrs-grpc stubs
pbrs-grpc 1.85 rustc 1.98 (this host); CI msrv-core 1.85 --lib (incl. tcp::tests), stable Linux + macOS Current source: no compiler needed to build from checked FileDescriptorSets; required to regenerate descriptors or compile application .proto. Older 0.1.0-alpha.1: still requires protoc. Native kernel (compile_protos default)
protobuf-tonic 1.88 rustc 1.98 (this host); CI msrv-tonic 1.88 Current source: no compiler needed to build from the checked FileDescriptorSet. Older 0.1.0-alpha.1: still requires protoc. Direct .proto compilation needs it in either version. Must call Config::emit_tonic_stubs(true); not a prost::Message drop-in
examples/greeter 1.85 rustc 1.98 (this host); CI stable Linux (--workspace) + macOS onboarding Required Native kernel default

Untested / unsupported (not a support commitment):

  • tonic 0.12 and 0.13 are unsupported.
  • Protocol Buffers Edition 2024 descriptor fixtures are tested, but generated consumers and conformance beyond Edition 2023 are not qualified.
  • Windows CI is untested.

Performance and stack selection

Use the benchmark report for versioned, workload-specific comparisons with prost, the Google Rust/upb wrapper, buffa, tonic, and grpc-go. Those results include wins, losses, and caveats; they do not establish universal feature parity or superiority. The roadmap scorecard defines the evidence needed for stronger claims.

For large payloads and copy behavior, also see Large payloads / zero-copy.

Conformance and testing

pbrs is tested against Google's official protobuf test suite:

Suite Recorded result Scope
Official conformance_test_runner v35.1 required tests (×2) 5,631 binary + JSON, 0 unexpected failures Pinned runner through Edition 2023
Text format tests 909 text tests, 0 unexpected failures Pinned runner through Edition 2023
Recommended tests (--enforce_recommended) Passed with 0 unexpected failures Does not imply every upstream suite

The separate rust/test/shared coverage has documented exclusions.

Run the conformance suite locally:

./scripts/fetch-protobuf.sh
./scripts/conformance.sh

Documentation

Topic Start here
Architecture and crate boundaries Architecture overview
Runtime design and storage choices Design and internals
API and representation differences from Google's C-based upb kernel Relative to upb
Performance numbers, caveats, and losses Benchmarks and performance
Large payloads and copy behavior Large payloads / zero-copy
Supported features and conformance breakdown Implementation status
Native pbrs-grpc services Native gRPC kernel guide
Code generation, RPC shapes, interceptors, and operations recipes Task guides and recipes
tonic 0.14+ integration Tonic adapter guide
Toolchain and protoc requirements Support matrix
Publishing policy Release policy
Roadmap and stronger-claim evidence Implementation plan and scorecard
Current execution planning Granular execution plan, task cards, execution queue
gRPC performance program World-class gRPC program and worker cards

License

Licensed under either of:

at your option.