Skip to content

protoc-gen-protovalidate-buffa-v0.5.0

Choose a tag to compare

@jrandolf jrandolf released this 28 Jun 01:22
d8d61e6

protoc-gen-protovalidate-buffa v0.5.0

This release hardens the codegen plugin against real-world proto schemas, cleans up
the optional Connect dependency, and upgrades the entire workspace to buffa 0.7 — all
while keeping the 2872 / 2872 (100%) upstream conformance score untouched across
proto2, proto3, and editions 2023. If you have proto fields or oneofs named after Rust
keywords (type, self, super, Self, crate, …), this release fixes a class of
panics and invalid-code-generation bugs that would have silently broken your validator
output. Upgrade is strongly recommended.


🐛 Bug Fixes

Rust keyword field and oneof names no longer break codegen

The plugin previously constructed field accessors by passing raw proto field names
directly to format_ident! / Ident::new / parse_str::<Ident>. Any field or
oneof whose proto name happened to be a Rust keyword crashed or produced unparseable
output:

  • format_ident!("type") — emitted self.type which syn rejects.
  • parse_str::<Ident>("self") — returned Err, halting generation.
  • Ident::new_raw("self")panicked because self cannot be a raw identifier.

All accessor construction is now routed through a shared field_ident helper that
delegates to buffa_codegen::idents::make_field_ident — the same function buffa uses
when generating the message structs. This guarantees that emitted accessors always match
the generated types by construction:

Proto field name Generated accessor
type self.r#type
self self.self_
crate self.crate_
// Previously crashed the plugin. Now works.
message Request {
  string type = 1 [(buf.validate.field).string.min_len = 1];
}

Regression tests covering required fields, CEL rules, and required oneofs with
keyword names are included to pin this behaviour permanently.

Connect feature no longer pulls in streaming/compression transitive deps

Enabling the connect feature only requires ConnectError and ErrorCode from the
connectrpc crate. Default features (which include streaming and compression support)
were previously activated unconditionally, bloating the dependency graph for users who
only needed the InvalidArgument mapping. default-features = false is now set on
the connectrpc dependency, so you get exactly the error types and nothing more.


⚡ Improvements

buffa 0.7

The workspace now tracks the buffa 0.7 line across all crates (buffa, buffa-build,
buffa-codegen, connectrpc). If you are already on buffa 0.7 in your own project,
all transitive dependencies now resolve cleanly to a single version with no duplication.


Error handling reference

Match on the typed ValidationError fields — never on rule_id string prefixes:

use protovalidate_buffa::{Validate, ValidationError};

match req.validate() {
    Ok(()) => { /* all rules passed */ }
    Err(ValidationError { compile_error: Some(msg), .. }) => {
        // Schema mismatch caught at codegen time (rule/field type mismatch,
        // unknown CEL field reference, etc.).
        eprintln!("schema error: {msg}");
    }
    Err(ValidationError { runtime_error: Some(msg), .. }) => {
        // Rule precondition failed at runtime (e.g. bytes.pattern on non-UTF-8 input).
        eprintln!("runtime error: {msg}");
    }
    Err(ValidationError { violations, .. }) => {
        // One or more field rules failed — the common case.
        for v in violations {
            eprintln!("[{}] {}", v.rule_id, v.message);
        }
    }
}

Installation

Library — 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 protoc-gen-protovalidate-buffa-v0.5.0 \
  protoc-gen-protovalidate-buffa

Then wire it into buf.gen.yaml as before:

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