Skip to main content

axum_valid/extra/
typed_path.rs

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