protowire 0.75.0

Protowire umbrella crate — re-exports envelope, pb, pxf, sbe.
Documentation

protowire-rust

License: MIT Crates.io docs.rs CI

Rust port of protowire — a protobuf-backed wire-format toolkit. Standalone (no FFI), descriptor-driven via prost-reflect. Verified for byte-equivalence against the canonical Go reference and seven other sibling ports.

CI exercises stable × {Linux, macOS, Windows} plus beta on Linux and an MSRV (1.74) pin, with cargo fmt --check, cargo clippy -- -D warnings, and cargo miri test on the codec crates as separate gating jobs.

Crates

This is a Cargo workspace. The crates published to crates.io are:

Crate Purpose
protowire Umbrella — re-exports the four sub-crates.
protowire-pb Schema-free protobuf wire codec.
protowire-envelope API response envelope (status, data, error).
protowire-pxf PXF (Proto eXpressive Format) text codec.
protowire-sbe FIX SBE binary codec + XML schema conversion.

The bench-pxf, bench-sbe, dump-envelope, and check-decode workspace members are internal cross-port harnesses and stay unpublished.

Vendored proto annotation sources live in proto/ — they're the cross-port wire contract (extension field numbers in the 50000s).

Use it

[dependencies]
protowire = "0.70"
use protowire::{pxf, sbe, envelope, pb};

Or pull in just the sub-crate you need:

[dependencies]
protowire-pxf = "0.70"
protowire-pb  = "0.70"

Build from source

cargo build --workspace
cargo test --workspace

Required: Rust 1.74+ (the workspace's rust-version pin). No external protoc dependency at build time — prost-build ships a vendored protoc binary.

Command-line tool

The protowire CLI is shared across every port and lives in the spec repo at github.com/trendvidia/protowire/cmd/protowire. Install:

go install github.com/trendvidia/protowire/cmd/protowire@latest

Rust users use this library for in-process encode/decode and the shared CLI for command-line operations. There is no separate Rust CLI binary.

Wire compatibility

Verified for byte-equivalence against the canonical Go reference and the other ports through:

bash ../protowire/scripts/cross_envelope_check.sh

The Rust dumper is on by default; pass WITH_RUST=0 to skip it.

Limitations & open gaps

The Rust port is descriptor-driven via prost-reflectDynamicMessage everywhere, no codegen-bound types. A few items fall out of that or are explicit deferred work:

  • No native BigInt / Decimal / BigFloat implementations (planned for 0.73.0). The codec faithfully encodes/decodes the bytes for the pxf.* arbitrary-precision schemas, but the user-facing type is Vec<u8> — callers convert to num-bigint::BigInt / rust_decimal::Decimal themselves. The Go reference's bignum_test.go is not yet ported (none of the sibling ports have it either).
  • No runtime .proto compilation. The Go port uses protocompile to turn a .proto schema into a FileDescriptorSet in-process; the prost ecosystem has no comparable embeddable compiler. You must pre-build a .binpb FileDescriptorSet (with buf build or protoc --include_imports --descriptor_set_out=…) and load it via DescriptorPool::decode. This is also the reason SBE XML round-trip is not implemented here.
  • prost-reflect upstream-API drift. The FieldOptions extension API has shifted shape across recent releases, so the workspace pins prost-reflect = "0.14" (and prost = "0.13"). Bumping either may require small migrations in protowire-pxf's annotation reader; tracked but not breaking today.
  • The shared CLI lives in trendvidia/protowire/cmd/protowire, not here. This repo ships only library crates plus the four cross-port harnesses.

Implemented (mentioned because external reviews keep flagging them)

  • PXF decoder is the fused single-pass path — mirrors Go's decode_fast.go::unmarshalDirect. The lexer drives a descriptor walk in lockstep and writes straight into DynamicMessage; there is no separate AST-walking slow path to swap in. See crates/protowire-pxf/src/decode.rs.
  • HARDENING.md decoder safety (M8): bounded recursion depth and PB length-prefix overflow rejection. The check-decode harness under crates/check-decode/ runs the upstream adversarial corpus on every PR.

Repository layout

protowire-rust/
├── LICENSE                                   # MIT
├── README.md
├── CHANGELOG.md
├── CONTRIBUTING.md, SECURITY.md,
│   GOVERNANCE.md, CODE_OF_CONDUCT.md
├── Cargo.toml                                # workspace + shared deps
├── Cargo.lock
├── crates/
│   ├── protowire/                            # umbrella
│   ├── protowire-pb/
│   ├── protowire-pxf/
│   ├── protowire-sbe/
│   ├── protowire-envelope/
│   ├── check-decode/                         # HARDENING corpus runner
│   ├── dump-envelope/, bench-pxf/, bench-sbe/  # cross-port harnesses
├── proto/                                    # vendored .proto annotations
└── .github/                                  # CI: build matrix + miri + CodeQL + publish