1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! Optional integration with [`tonic`] (gRPC).
//!
//! Enabled by the `tonic` cargo feature. Provides a typed bridge between
//! [`ValidationError`] / [`Error`] and [`tonic::Status`], plus a
//! [`ValidateRequest`] extension trait for one-line per-handler validation:
//!
//! ```ignore
//! use prost_protovalidate::{Validate, tonic::ValidateRequest};
//!
//! #[tonic::async_trait]
//! impl my_proto::greeter_server::Greeter for GreeterImpl {
//! async fn say_hello(
//! &self,
//! req: tonic::Request<my_proto::HelloRequest>,
//! ) -> Result<tonic::Response<my_proto::HelloReply>, tonic::Status> {
//! req.validate_inner()?;
//! // ... handler body ...
//! # unimplemented!()
//! }
//! }
//! ```
//!
//! With the additional `tonic-types` feature on, the resulting
//! [`tonic::Status`] carries a `google.rpc.BadRequest` detail with one
//! `FieldViolation` per [`Violation`](crate::Violation), so clients can
//! parse field-level errors without scraping the message string.
//!
//! # Mapping to gRPC codes
//!
//! - [`ValidationError`] → [`tonic::Code::InvalidArgument`]. The status
//! message is the [`Display`](std::fmt::Display) form of the error
//! (a list of `{field}: {message}` lines), which is safe to expose to
//! clients since it derives from rules the client violated.
//! - [`CompilationError`] / [`RuntimeError`] → [`tonic::Code::Internal`]
//! with a **fixed, generic message**. The underlying `cause` strings can
//! contain proto field names, CEL parse output, or type-mismatch details
//! that should not be exposed to untrusted clients. Callers who need the
//! full cause for server-side logging must inspect/log the error
//! **before** invoking the `Into` conversion.
//!
//! # Streaming requests
//!
//! [`ValidateRequest`] applies to handlers whose request shape is
//! `tonic::Request<T>` (unary and server-streaming). For client-streaming
//! and bidirectional handlers, where the request is
//! `tonic::Request<tonic::Streaming<T>>`, validate each message inside the
//! per-message loop:
//!
//! ```ignore
//! use prost_protovalidate::Validate;
//! while let Some(msg) = stream.message().await? {
//! msg.validate().map_err(tonic::Status::from)?;
//! // ... process msg ...
//! }
//! ```
use crateValidate;
use crate;
/// Extension trait that calls [`Validate::validate`] on the inner message of
/// a [`tonic::Request`] and maps any [`ValidationError`] to a
/// [`tonic::Status`] with `Code::InvalidArgument`.
///
/// Applies to handlers whose request shape is `tonic::Request<T>` — unary
/// and server-streaming RPCs. For client-streaming and bidirectional RPCs
/// where the request is `tonic::Request<tonic::Streaming<T>>`, see the
/// per-message pattern in the module-level docs.