protovalidate-buffa v0.5.1
#[connect_impl] now speaks fluent Connect 0.7 — and still hits 2872 / 2872 (100%) on the upstream conformance suite.
This patch release rounds out the Connect integration story. The #[connect_impl] macro previously understood only buffa's OwnedView<T> handler signatures; it now recognises connectrpc::ServiceRequest<'_, T> as well, so teams that have adopted the Connect 0.7 owned-message wrapper get automatic validation out of the box — no per-handler boilerplate, no forgetting a req.validate()?.
🐛 Bug Fixes
#[connect_impl] validates Connect ServiceRequest handlers
Prior to this release, applying #[connect_impl] to a service impl that used Connect 0.7's ServiceRequest<'_, T> parameter type silently skipped those handlers — the macro only injected validation when it spotted an OwnedView<T>. Any handler written in the newer style received no automatic validation at all.
The macro now detects both shapes:
| Handler signature | Validated? |
|---|---|
request: OwnedView<pb::FooView<'static>> |
✅ (was already working) |
request: connectrpc::ServiceRequest<'_, pb::Foo> |
✅ (fixed in v0.5.1) |
Both types expose to_owned_message(), so the injected code is uniform and zero-surprise:
// Apply once at the impl level — every handler is covered, now and in future.
#[protovalidate_buffa::connect_impl]
impl UserService for UserServiceImpl {
async fn create_user(
&self,
ctx: Context,
// Connect 0.7 ServiceRequest — now fully validated automatically.
request: connectrpc::ServiceRequest<'_, pb::CreateUserRequest>,
) -> Result<(pb::CreateUserResponse, Context), ConnectError> {
// Validation runs before this line.
// Invalid requests are rejected as InvalidArgument before reaching here.
let req = request.into_message();
// ...
}
}Validation failures surface as a structured ConnectError::invalid_argument carrying the full set of rule violations, powered by ValidationError::into_connect_error. The typed error fields let you distinguish failure modes cleanly:
match msg.validate() {
Ok(()) => { /* proceed */ }
Err(e) if e.compile_error.is_some() => {
// Schema mismatch caught at codegen time; this is a bug in the .proto or plugin config.
tracing::error!(compile_error = %e.compile_error.as_deref().unwrap_or(""));
}
Err(e) if e.runtime_error.is_some() => {
// Rule precondition couldn't be evaluated (e.g. non-UTF-8 bytes under `pattern`).
tracing::warn!(runtime_error = %e.runtime_error.as_deref().unwrap_or(""));
}
Err(e) => {
// The common case: one or more field-level rule violations.
for v in &e.violations {
tracing::debug!(field = %v.field_path, message = %v.message);
}
}
}Conformance
2872 / 2872 (100%) — all cases in the upstream protovalidate-conformance harness pass, covering proto2, proto3, and editions 2023. Nothing regressed.
Installation
Library consumers
[dependencies]
protovalidate-buffa = "0.5.1"Enable the connect feature (on by default) to get ValidationError::into_connect_error and the #[connect_impl] macro.
Codegen plugin
cargo install \
--git https://github.com/mathematic-inc/protovalidate-buffa \
--tag v0.5.1 \
protoc-gen-protovalidate-buffaThen wire it into your buf.gen.yaml:
plugins:
- local: protoc-gen-protovalidate-buffa
out: gen/protovalidate
strategy: allDual-licensed Apache-2.0 / MIT.