Skip to content

v0.5.0

Choose a tag to compare

@jrandolf jrandolf released this 28 Jun 01:22
d8d61e6

protovalidate-buffa v0.5.0

protovalidate-buffa v0.5.0 lands three important correctness fixes that make the codegen plugin robust across real-world proto schemas: keyword-named fields now produce valid Rust instead of panicking at generation time, the optional Connect integration no longer drags in streaming and compression crates you never asked for, and the whole workspace has been updated to the buffa 0.7 line. The 100% conformance score — 2872 / 2872 cases across proto2, proto3, and editions 2023 — remains intact throughout.


🐛 Bug Fixes

Keyword-named fields and oneofs no longer break codegen

The plugin was building field accessors (self.<field>) directly from raw proto names. Any field or oneof whose name is a Rust keyword caused one of three failure modes:

  • format_ident!("type") emits the raw invalid token self.typesyn / prettyplease refuse to parse it.
  • parse_str::<Ident>("type") returns Err and fails the render pipeline.
  • Keywords that can't be raw identifiers (self, super, crate, Self) caused an outright Ident::new panic at codegen time.

The fix routes every proto-name-to-ident conversion through a shared field_ident helper that delegates to buffa_codegen::idents::make_field_ident — the same function buffa itself uses when naming struct fields. Emitted accessors now match the generated message types by construction:

// proto
message Request {
  string type = 1 [(buf.validate.field).string.min_len = 1];
  string self = 2 [(buf.validate.field).string.min_len = 1];
}
// generated (before this fix: compile error / panic)
impl Validate for Request {
    fn validate(&self) -> Result<(), ValidationError> {
        // raw-able keyword → r#type
        if self.r#type.len() < 1 { /* ... */ }
        // non-raw-able keyword → suffixed
        if self.self_.len() < 1 { /* ... */ }
        Ok(())
    }
}

Regression tests covering keyword fields, keyword-named oneofs, and CEL rules on keyword-named fields are now part of the plugin's integration test suite.

This is a breaking change if you were working around the bug by renaming proto fields — you can remove those workarounds now.

Connect feature no longer pulls in streaming and compression crates

The optional connect feature only ever needed ConnectError and ErrorCode from connectrpc. By default, connectrpc previously enabled its streaming and compression feature flags, which added async-compression and related transitive dependencies to your build even when you just wanted req.validate()?InvalidArgument. Those are now gone. Enabling the connect feature is leaner than it used to be.


⚡ Improvements

buffa 0.7

The workspace — runtime, macros, protos, plugin, and conformance harness — is now on the buffa 0.7 line. connectrpc has been moved to its matching 0.7 release to keep the transitive dependency graph consistent.


Conformance

2872 / 2872 (100%) against the upstream protovalidate-conformance suite, covering proto2, proto3, and editions 2023. Every rule family in the standard-rules catalogue and predefined-rules support is covered.


Error handling reminder

Match on the typed ValidationError fields, not on rule_id prefixes:

match req.validate() {
    Ok(()) => { /* proceed */ }
    Err(e) if e.compile_error.is_some() => {
        // Schema-level mismatch caught at codegen time — this is a bug
        // in your proto annotations or plugin version. Log and panic in dev.
        panic!("protovalidate compile error: {}", e.compile_error.unwrap());
    }
    Err(e) if e.runtime_error.is_some() => {
        // Rule precondition failed at runtime (e.g. bytes.pattern on non-UTF-8).
        return Err(e.into_connect_error());
    }
    Err(e) => {
        // The common case: one or more field violations.
        return Err(e.into_connect_error()); // → InvalidArgument
    }
}

Installation

Library consumers — add to Cargo.toml:

protovalidate-buffa = "0.5.0"

Codegen plugin — install from source:

cargo install \
  --git https://github.com/mathematic-inc/protovalidate-buffa \
  --tag v0.5.0 \
  protoc-gen-protovalidate-buffa

Then wire it into your buf.gen.yaml:

plugins:
  - local: protoc-gen-protovalidate-buffa
    out: gen/protovalidate
    strategy: all