diff --git a/src/lib.rs b/src/lib.rs index 05cf6c8..f7d19c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,16 +122,6 @@ impl ValidEx { } } -/// `ValidationArguments` configures the response returned when validation fails. -/// -/// By providing a ValidationArguments to the Valid extractor, you can customize -/// the HTTP status code and response body returned on validation failure. -/// -#[derive(Debug, Copy, Clone, Default)] -pub struct ValidationContext { - arguments: Arguments, -} - fn response_builder(ve: ValidationErrors) -> Response { #[cfg(feature = "into_json")] { @@ -143,30 +133,17 @@ fn response_builder(ve: ValidationErrors) -> Response { } } -impl ValidationContext<()> { - /// Creates a new `ValidationArguments`. - pub fn with_arguments(self, arguments: Arguments) -> ValidationContext { - ValidationContext { arguments } - } -} - -impl ValidationContext { - /// Creates a `ValidationArguments` with arguments - pub fn new(arguments: Arguments) -> Self { - Self { arguments } - } -} - -/// # Arguments +/// `Arguments` provides the validation arguments for the data type `T`. /// -/// * `T`: The data type to validate using arguments +/// This trait has an associated type `T` which represents the data type to +/// validate. `T` must implement the `ValidateArgs` trait which defines the +/// validation logic. /// -pub trait Arguments<'a, T> -where - T: ValidateArgs<'a>, -{ - /// Get arguments from `self` - fn get(&'a self) -> T::Args; +pub trait Arguments<'a> { + /// The data type to validate using this arguments + type T: ValidateArgs<'a>; + /// This method gets the arguments required by `ValidateArgs::validate_args` + fn get(&'a self) -> <>::T as ValidateArgs<'a>>::Args; } /// `ValidRejection` is returned when the `Valid` extractor fails. @@ -276,15 +253,17 @@ impl FromRequest for ValidEx Arguments<'a, >::ValidateArgs>, + Args: Send + + Sync + + FromRef + + for<'a> Arguments<'a, T = >::ValidateArgs>, Extractor: for<'v> HasValidateArgs<'v> + FromRequest, for<'v> >::ValidateArgs: ValidateArgs<'v>, - ValidationContext: FromRef, { type Rejection = ValidRejection<>::Rejection>; async fn from_request(req: Request, state: &State) -> Result { - let ValidationContext { arguments }: ValidationContext = FromRef::from_ref(state); + let arguments: Args = FromRef::from_ref(state); let inner = Extractor::from_request(req, state) .await .map_err(ValidRejection::Inner)?; @@ -298,15 +277,17 @@ where impl FromRequestParts for ValidEx where State: Send + Sync, - Args: Send + Sync + for<'a> Arguments<'a, >::ValidateArgs>, + Args: Send + + Sync + + FromRef + + for<'a> Arguments<'a, T = >::ValidateArgs>, Extractor: for<'v> HasValidateArgs<'v> + FromRequestParts, for<'v> >::ValidateArgs: ValidateArgs<'v>, - ValidationContext: FromRef, { type Rejection = ValidRejection<>::Rejection>; async fn from_request_parts(parts: &mut Parts, state: &State) -> Result { - let ValidationContext { arguments }: ValidationContext = FromRef::from_ref(state); + let arguments: Args = FromRef::from_ref(state); let inner = Extractor::from_request_parts(parts, state) .await .map_err(ValidRejection::Inner)?; diff --git a/src/test.rs b/src/test.rs index effc373..79cf96a 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,6 +1,6 @@ use crate::test::extra_typed_path::TypedPathParamExValidationArguments; use crate::tests::{ValidTest, ValidTestParameter}; -use crate::{Arguments, HasValidate, Valid, ValidEx, ValidationContext, VALIDATION_ERROR_STATUS}; +use crate::{Arguments, HasValidate, Valid, ValidEx, VALIDATION_ERROR_STATUS}; use axum::extract::{FromRef, Path, Query}; use axum::routing::{get, post}; use axum::{Form, Json, Router}; @@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize}; use std::any::type_name; use std::net::SocketAddr; use std::ops::{Deref, RangeInclusive}; +use std::sync::Arc; use validator::{Validate, ValidateArgs, ValidationError}; #[derive(Clone, Deserialize, Serialize, Validate, Eq, PartialEq)] @@ -56,18 +57,24 @@ fn validate_v1(v: &str, args: &RangeInclusive) -> Result<(), ValidationEr } #[derive(Debug, Clone)] -pub struct ParametersExValidationArguments { +struct ParametersExValidationArgumentsInner { v0_range: RangeInclusive, v1_length_range: RangeInclusive, } -impl<'a> Arguments<'a, ParametersEx> for ParametersExValidationArguments { +#[derive(Debug, Clone, Default)] +pub struct ParametersExValidationArguments { + inner: Arc, +} + +impl<'a> Arguments<'a> for ParametersExValidationArguments { + type T = ParametersEx; fn get(&'a self) -> >::Args { - (&self.v0_range, &self.v1_length_range) + (&self.inner.v0_range, &self.inner.v1_length_range) } } -impl Default for ParametersExValidationArguments { +impl Default for ParametersExValidationArgumentsInner { fn default() -> Self { Self { v0_range: 5..=10, @@ -110,16 +117,15 @@ impl HasValidate for Parameters { #[derive(Debug, Clone, FromRef)] struct MyState { - param_validation_ctx: ValidationContext, - typed_path_validation_ctx: ValidationContext, + param_validation_ctx: ParametersExValidationArguments, + typed_path_validation_ctx: TypedPathParamExValidationArguments, } #[tokio::test] async fn test_main() -> anyhow::Result<()> { let state = MyState { - param_validation_ctx: ValidationContext::::default(), - typed_path_validation_ctx: - ValidationContext::::default(), + param_validation_ctx: ParametersExValidationArguments::default(), + typed_path_validation_ctx: TypedPathParamExValidationArguments::default(), }; let router = Router::new() @@ -1068,7 +1074,8 @@ mod extra_typed_path { } } - impl<'a> Arguments<'a, TypedPathParamEx> for TypedPathParamExValidationArguments { + impl<'a> Arguments<'a> for TypedPathParamExValidationArguments { + type T = TypedPathParamEx; fn get(&'a self) -> >::Args { (&self.v0_range, &self.v1_length_range) }