axum_valid/path.rs
1//! # Support for `Path<T>`
2//!
3//! ## Usage
4//!
5//! 1. Implement `Deserialize` and `Validate` for your data type `T`.
6//! 2. In your handler function, use `Valid<Path<T>>` as some parameter's type.
7//!
8//! ## Example
9//!
10//! ```no_run
11//! #[cfg(feature = "validator")]
12//! mod validator_example {
13//! use axum::extract::Path;
14//! use axum::routing::post;
15//! use axum::Router;
16//! use axum_valid::Valid;
17//! use serde::Deserialize;
18//! use validator::Validate;
19//!
20//! pub fn router() -> Router {
21//! Router::new().route("/path", post(handler))
22//! }
23//!
24//! async fn handler(Valid(Path(parameter)): Valid<Path<Parameter>>) {
25//! assert!(parameter.validate().is_ok());
26//! // Support automatic dereferencing
27//! println!("v0 = {}, v1 = {}", parameter.v0, parameter.v1);
28//! }
29//!
30//! #[derive(Validate, Deserialize)]
31//! pub struct Parameter {
32//! #[validate(range(min = 5, max = 10))]
33//! pub v0: i32,
34//! #[validate(length(min = 1, max = 10))]
35//! pub v1: String,
36//! }
37//! }
38//!
39//! #[cfg(feature = "garde")]
40//! mod garde_example {
41//! use axum::routing::post;
42//! use axum::extract::Path;
43//! use axum::Router;
44//! use axum_valid::Garde;
45//! use serde::Deserialize;
46//! use garde::Validate;
47//!
48//! pub fn router() -> Router {
49//! Router::new().route("/path", post(handler))
50//! }
51//!
52//! async fn handler(Garde(Path(parameter)): Garde<Path<Parameter>>) {
53//! assert!(parameter.validate_with(&()).is_ok());
54//! // Support automatic dereferencing
55//! println!("v0 = {}, v1 = {}", parameter.v0, parameter.v1);
56//! }
57//!
58//! #[derive(Validate, Deserialize)]
59//! pub struct Parameter {
60//! #[garde(range(min = 5, max = 10))]
61//! pub v0: i32,
62//! #[garde(length(min = 1, max = 10))]
63//! pub v1: String,
64//! }
65//! }
66//!
67//! # #[tokio::main]
68//! # async fn main() -> anyhow::Result<()> {
69//! # use std::net::SocketAddr;
70//! # use axum::Router;
71//! # use tokio::net::TcpListener;
72//! # let router = Router::new();
73//! # #[cfg(feature = "validator")]
74//! # let router = router.nest("/validator", validator_example::router());
75//! # #[cfg(feature = "garde")]
76//! # let router = router.nest("/garde", garde_example::router());
77//! # let listener = TcpListener::bind(&SocketAddr::from(([0u8, 0, 0, 0], 0u16))).await?;
78//! # axum::serve(listener, router.into_make_service())
79//! # .await?;
80//! # Ok(())
81//! # }
82//! ```
83
84use crate::HasValidate;
85#[cfg(feature = "validator")]
86use crate::HasValidateArgs;
87use axum::extract::Path;
88#[cfg(feature = "validator")]
89use validator::ValidateArgs;
90
91impl<T> HasValidate for Path<T> {
92 type Validate = T;
93 fn get_validate(&self) -> &T {
94 &self.0
95 }
96}
97
98#[cfg(feature = "validator")]
99impl<'v, T: ValidateArgs<'v>> HasValidateArgs<'v> for Path<T> {
100 type ValidateArgs = T;
101 fn get_validate_args(&self) -> &Self::ValidateArgs {
102 &self.0
103 }
104}
105
106#[cfg(feature = "validify")]
107impl<T: validify::Modify> crate::HasModify for Path<T> {
108 type Modify = T;
109
110 fn get_modify(&mut self) -> &mut Self::Modify {
111 &mut self.0
112 }
113}
114
115#[cfg(feature = "validify")]
116impl<T> crate::PayloadExtractor for Path<T> {
117 type Payload = T;
118
119 fn get_payload(self) -> Self::Payload {
120 self.0
121 }
122}
123
124#[cfg(feature = "validify")]
125impl<T: validify::Validify + validify::ValidifyPayload> crate::HasValidify for Path<T> {
126 type Validify = T;
127 type PayloadExtractor = Path<T::Payload>;
128
129 fn from_validify(v: Self::Validify) -> Self {
130 Path(v)
131 }
132}