diff --git a/src/lib.rs b/src/lib.rs index 5538b23..d2b7812 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,13 +19,13 @@ pub mod typed_header; #[cfg(feature = "yaml")] pub mod yaml; -use std::error::Error; -use std::fmt::{Debug, Display, Formatter}; use axum::async_trait; use axum::extract::{FromRequest, FromRequestParts}; use axum::http::request::Parts; use axum::http::{Request, StatusCode}; use axum::response::{IntoResponse, Response}; +use std::error::Error; +use std::fmt::{Debug, Display, Formatter}; use std::ops::{Deref, DerefMut}; use validator::{Validate, ValidationErrors}; @@ -54,6 +54,13 @@ impl DerefMut for Valid { } } +impl Valid { + /// Consume the `Valid` extractor and returns the inner type. + pub fn into_inner(self) -> E { + self.0 + } +} + /// If the valid extractor fails it'll use this "rejection" type. /// This rejection type can be converted into a response. #[derive(Debug)] @@ -73,7 +80,14 @@ impl Display for ValidRejection { } } -impl Error for ValidRejection {} +impl Error for ValidRejection { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + ValidRejection::Valid(ve) => Some(ve), + ValidRejection::Inner(e) => Some(e), + } + } +} impl From for ValidRejection { fn from(value: ValidationErrors) -> Self { @@ -146,8 +160,13 @@ where #[cfg(test)] pub mod tests { + use crate::{Valid, ValidRejection}; use reqwest::{RequestBuilder, StatusCode}; use serde::Serialize; + use std::error::Error; + use std::io; + use std::ops::{Deref, DerefMut}; + use validator::{ValidationError, ValidationErrors}; /// # Valid test parameter pub trait ValidTestParameter: Serialize + 'static { @@ -188,4 +207,45 @@ pub mod tests { pub trait Rejection { const STATUS_CODE: StatusCode; } + + const TEST: &str = "test"; + + #[test] + fn deref_deref_mut_into_inner() { + let mut inner = String::from(TEST); + let mut v = Valid(inner.clone()); + assert_eq!(&inner, v.deref()); + inner.push_str(TEST); + v.deref_mut().push_str(TEST); + assert_eq!(&inner, v.deref()); + assert_eq!(inner, v.into_inner()); + } + + #[test] + fn display_error() { + // ValidRejection::Valid Display + let mut ve = ValidationErrors::new(); + ve.add(TEST, ValidationError::new(TEST)); + let vr = ValidRejection::::Valid(ve.clone()); + assert_eq!(vr.to_string(), ve.to_string()); + + // ValidRejection::Inner Display + let inner = String::from(TEST); + let vr = ValidRejection::::Inner(inner.clone()); + assert_eq!(inner.to_string(), vr.to_string()); + + // ValidRejection::Valid Error + let mut ve = ValidationErrors::new(); + ve.add(TEST, ValidationError::new(TEST)); + let vr = ValidRejection::::Valid(ve.clone()); + assert!( + matches!(vr.source(), Some(source) if source.downcast_ref::().is_some()) + ); + + // ValidRejection::Valid Error + let vr = ValidRejection::::Inner(io::Error::new(io::ErrorKind::Other, TEST)); + assert!( + matches!(vr.source(), Some(source) if source.downcast_ref::().is_some()) + ); + } } diff --git a/src/test.rs b/src/test.rs index 48c6594..441c409 100644 --- a/src/test.rs +++ b/src/test.rs @@ -1,4 +1,3 @@ -use crate::test::extra::{ParametersRejection, WithRejectionValidRejection}; use crate::tests::{ValidTest, ValidTestParameter}; use crate::{HasValidate, Valid, VALIDATION_ERROR_STATUS}; use axum::extract::{Path, Query}; @@ -195,7 +194,9 @@ async fn test_main() -> anyhow::Result<()> { #[cfg(feature = "extra")] { use axum_extra::extract::{Cached, WithRejection}; - use extra::ValidWithRejectionRejection; + use extra::{ + ParametersRejection, ValidWithRejectionRejection, WithRejectionValidRejection, + }; test_executor .execute::>(Method::POST, extra::route::CACHED) .await?;