prost_protovalidate/lib.rs
1//! Runtime validation for Protocol Buffer messages using
2//! [`buf.validate`](https://github.com/bufbuild/protovalidate) rules.
3//!
4//! This crate dynamically inspects `prost-reflect` message descriptors at runtime,
5//! compiles `buf.validate` constraint annotations (including CEL expressions),
6//! and evaluates them against concrete message instances.
7//!
8//! # Quick start
9//!
10//! For one-off validation, use the [`validate`] convenience function:
11//!
12//! ```rust,no_run
13//! use prost_protovalidate::validate;
14//! # fn example(msg: impl prost_reflect::ReflectMessage) {
15//! match validate(&msg) {
16//! Ok(()) => { /* message is valid */ }
17//! Err(e) => eprintln!("validation failed: {e}"),
18//! }
19//! # }
20//! ```
21//!
22//! For repeated validations, construct a [`Validator`] once to cache compiled
23//! rules across calls:
24//!
25//! ```rust,no_run
26//! use prost_protovalidate::Validator;
27//! # fn example(msg: impl prost_reflect::ReflectMessage) {
28//! let validator = Validator::new();
29//! validator.validate(&msg).expect("message should be valid");
30//! # }
31//! ```
32//!
33//! # Feature flags
34//!
35//! | Feature | Default | Description |
36//! |---------------|---------|-------------|
37//! | `cel` | Yes | CEL expression evaluation and `chrono` time support. Disable for a lighter dependency footprint when only standard rules are used. |
38//! | `tonic` | No | Adds [`tonic`](https://docs.rs/tonic) integration: a `From<ValidationError> for tonic::Status` impl and a `ValidateRequest` extension trait so gRPC handlers can call `req.validate_inner()?`. |
39//! | `tonic-types` | No | Implies `tonic`. Attaches a `google.rpc.BadRequest` detail with one `FieldViolation` per [`Violation`] to validation-failure statuses. |
40//!
41//! Without the `cel` feature, any message or field annotated with CEL
42//! expressions (via both `cel` and legacy `cel_expression`, including
43//! `buf.validate.predefined` rules) will produce a [`CompilationError`] at
44//! validation time. Standard rules (range checks, string constraints, format
45//! validators, etc.) work without `cel`.
46//!
47//! # Error types
48//!
49//! | Type | When |
50//! |------|------|
51//! | [`ValidationError`] | One or more constraint violations detected |
52//! | [`CompilationError`] | A CEL expression or constraint definition failed to parse |
53//! | [`RuntimeError`] | An unexpected failure during evaluation |
54//!
55//! All three are unified under [`Error`].
56//!
57//! # Re-exported types
58//!
59//! The [`types`] module re-exports [`prost-protovalidate-types`](https://crates.io/crates/prost-protovalidate-types)
60//! so consumers do not need to depend on it directly.
61
62#![warn(missing_docs)]
63
64mod config;
65mod error;
66pub mod time;
67#[cfg(feature = "tonic")]
68pub mod tonic;
69mod validator;
70pub mod validators;
71mod violation;
72
73/// Re-export of [`prost-protovalidate-types`](https://crates.io/crates/prost-protovalidate-types)
74/// for accessing generated `buf.validate` proto types and descriptor pool.
75pub use prost_protovalidate_types as types;
76
77/// Re-export of [`regex`](https://crates.io/crates/regex) so generated validators
78/// from `prost-protovalidate-build` can construct compiled patterns without the
79/// consumer's `Cargo.toml` needing a direct `regex` dependency.
80pub use regex;
81
82pub use config::{Filter, ValidationOption, ValidatorOption};
83pub use error::{CompilationError, Error, RuntimeError, ValidationError};
84pub use validator::{Validator, validate};
85pub use violation::Violation;
86
87/// Compile-time validation for Protocol Buffer messages with generated validators.
88///
89/// This trait is implemented by `prost-protovalidate-build` for messages that
90/// have **only** standard `buf.validate` rules (no CEL expressions). Validators
91/// run through monomorphized direct field access at runtime — no
92/// `prost-reflect` transcoding, no CEL interpreter on the hot path. For
93/// messages using CEL expressions or a mix of standard + CEL rules, use the
94/// runtime [`Validator`] instead.
95///
96/// # Generated violations
97///
98/// Violations produced by generated validators have identical [`Violation::field_path()`],
99/// [`Violation::rule_id()`], [`Violation::rule_path()`], and [`Violation::message()`]
100/// as the runtime validator. The enrichment accessors
101/// ([`Violation::field_descriptor()`], [`Violation::field_value()`],
102/// [`Violation::rule_descriptor()`], [`Violation::rule_value()`]) return `None` —
103/// these require runtime reflection data not available in generated code.
104///
105/// # Errors
106///
107/// Returns [`ValidationError`] containing all constraint violations found.
108pub trait Validate {
109 /// Validate this message against its `buf.validate` rules.
110 ///
111 /// # Errors
112 /// Returns [`ValidationError`] containing all constraint violations found.
113 fn validate(&self) -> Result<(), ValidationError>;
114}
115
116/// Normalize protobuf Edition 2023 descriptors to proto3 format for
117/// compatibility with `prost-reflect` 0.16 which does not support editions.
118pub use validator::editions::normalize_edition_descriptor_set;