feat: implement aide::OperationInput/OperationOutput for extractors

This commit is contained in:
gengteng
2024-01-06 15:36:00 +08:00
parent 16283fd562
commit c96c146fd5
4 changed files with 101 additions and 16 deletions

View File

@@ -25,8 +25,8 @@ edition = "2021"
features = ["full", "aide"] features = ["full", "aide"]
[dependencies] [dependencies]
axum = { version = "0.7.1", default-features = false } axum = { version = "0.7.3", default-features = false }
garde = { version = "0.16.3", optional = true } garde = { version = "0.17.0", optional = true }
validator = { version = "0.16.1", optional = true} validator = { version = "0.16.1", optional = true}
validify = { version = "1.3.0", optional = true} validify = { version = "1.3.0", optional = true}
@@ -44,20 +44,20 @@ version = "0.11.0"
optional = true optional = true
[dependencies.serde] [dependencies.serde]
version = "1.0.193" version = "1.0.195"
optional = true optional = true
[dependencies.aide] [dependencies.aide]
version = "0.13.0" version = "0.13.1"
optional = true optional = true
[dev-dependencies] [dev-dependencies]
anyhow = "1.0.72" anyhow = "1.0.75"
axum = { version = "0.7.1", features = ["macros"] } axum = { version = "0.7.1", features = ["macros"] }
tokio = { version = "1.34.0", features = ["full"] } tokio = { version = "1.34.0", features = ["full"] }
hyper = { version = "0.14.27", features = ["full"] } hyper = { version = "0.14.27", features = ["full"] }
reqwest = { version = "0.11.22", features = ["json", "multipart"] } reqwest = { version = "0.11.23", features = ["json", "multipart"] }
serde = { version = "1.0.193", features = ["derive"] } serde = { version = "1.0.195", features = ["derive"] }
validator = { version = "0.16.1", features = ["derive"] } validator = { version = "0.16.1", features = ["derive"] }
serde_json = "1.0.108" serde_json = "1.0.108"
serde_yaml = "0.9.27" serde_yaml = "0.9.27"

View File

@@ -25,7 +25,6 @@ use std::ops::{Deref, DerefMut};
/// If using arguments, you must pass the arguments to Garde extractor via state, meaning implementing `FromRef<StateType>` for your validation arguments type. /// If using arguments, you must pass the arguments to Garde extractor via state, meaning implementing `FromRef<StateType>` for your validation arguments type.
/// ///
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Garde<E>(pub E); pub struct Garde<E>(pub E);
impl<E> Deref for Garde<E> { impl<E> Deref for Garde<E> {
@@ -58,6 +57,16 @@ impl<E> Garde<E> {
} }
} }
#[cfg(feature = "aide")]
impl<T> aide::OperationInput for Garde<T>
where
T: aide::OperationInput,
{
fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) {
T::operation_input(ctx, operation);
}
}
/// `GardeRejection` is returned when the `Garde` extractor fails. /// `GardeRejection` is returned when the `Garde` extractor fails.
/// ///
pub type GardeRejection<E> = ValidationRejection<Report, E>; pub type GardeRejection<E> = ValidationRejection<Report, E>;

View File

@@ -28,7 +28,6 @@ use validator::{Validate, ValidateArgs, ValidationErrors};
/// For examples with custom extractors, check out the `tests/custom.rs` file. /// For examples with custom extractors, check out the `tests/custom.rs` file.
/// ///
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Valid<E>(pub E); pub struct Valid<E>(pub E);
impl<E> Deref for Valid<E> { impl<E> Deref for Valid<E> {
@@ -45,7 +44,7 @@ impl<E> DerefMut for Valid<E> {
} }
} }
impl<T: Display, A> Display for ValidEx<T, A> { impl<T: Display> Display for Valid<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f) self.0.fmt(f)
} }
@@ -58,6 +57,16 @@ impl<E> Valid<E> {
} }
} }
#[cfg(feature = "aide")]
impl<T> aide::OperationInput for Valid<T>
where
T: aide::OperationInput,
{
fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) {
T::operation_input(ctx, operation);
}
}
/// # `ValidEx` data extractor /// # `ValidEx` data extractor
/// ///
/// `ValidEx` can be incorporated with extractors from various modules, similar to `Valid`. /// `ValidEx` can be incorporated with extractors from various modules, similar to `Valid`.
@@ -72,7 +81,6 @@ impl<E> Valid<E> {
/// Although current module documentation predominantly showcases `Valid` examples, the usage of `ValidEx` is analogous. /// Although current module documentation predominantly showcases `Valid` examples, the usage of `ValidEx` is analogous.
/// ///
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct ValidEx<E, A>(pub E, pub A); pub struct ValidEx<E, A>(pub E, pub A);
impl<E, A> Deref for ValidEx<E, A> { impl<E, A> Deref for ValidEx<E, A> {
@@ -89,7 +97,7 @@ impl<E, A> DerefMut for ValidEx<E, A> {
} }
} }
impl<T: Display> Display for Valid<T> { impl<T: Display, A> Display for ValidEx<T, A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f) self.0.fmt(f)
} }
@@ -117,6 +125,16 @@ impl<E, A> ValidEx<E, A> {
} }
} }
#[cfg(feature = "aide")]
impl<T, A> aide::OperationInput for ValidEx<T, A>
where
T: aide::OperationInput,
{
fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) {
T::operation_input(ctx, operation);
}
}
/// `Arguments` provides the validation arguments for the data type `T`. /// `Arguments` provides the validation arguments for the data type `T`.
/// ///
/// This trait has an associated type `T` which represents the data type to /// This trait has an associated type `T` which represents the data type to

View File

@@ -24,7 +24,6 @@ use validify::{Modify, Validate, ValidationErrors, ValidifyPayload};
/// It only does validation, usage is similar to `Valid`. /// It only does validation, usage is similar to `Valid`.
/// ///
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Validated<E>(pub E); pub struct Validated<E>(pub E);
impl<E> Deref for Validated<E> { impl<E> Deref for Validated<E> {
@@ -57,6 +56,16 @@ impl<E> Validated<E> {
} }
} }
#[cfg(feature = "aide")]
impl<T> aide::OperationInput for Validated<T>
where
T: aide::OperationInput,
{
fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) {
T::operation_input(ctx, operation);
}
}
/// # `Modified` data extractor / response /// # `Modified` data extractor / response
/// ///
/// ## Extractor /// ## Extractor
@@ -74,7 +83,6 @@ impl<E> Validated<E> {
/// ///
/// This allows applying modifications during response conversion by leveraging validify. /// This allows applying modifications during response conversion by leveraging validify.
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Modified<E>(pub E); pub struct Modified<E>(pub E);
impl<E> Deref for Modified<E> { impl<E> Deref for Modified<E> {
@@ -114,6 +122,38 @@ impl<E: IntoResponse + HasModify> IntoResponse for Modified<E> {
} }
} }
#[cfg(feature = "aide")]
impl<T> aide::OperationInput for Modified<T>
where
T: aide::OperationInput,
{
fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) {
T::operation_input(ctx, operation);
}
}
#[cfg(feature = "aide")]
impl<T> aide::OperationOutput for Modified<T>
where
T: aide::OperationOutput,
{
type Inner = T::Inner;
fn operation_response(
ctx: &mut aide::gen::GenContext,
operation: &mut aide::openapi::Operation,
) -> Option<aide::openapi::Response> {
T::operation_response(ctx, operation)
}
fn inferred_responses(
ctx: &mut aide::gen::GenContext,
operation: &mut aide::openapi::Operation,
) -> Vec<(Option<u16>, aide::openapi::Response)> {
T::inferred_responses(ctx, operation)
}
}
/// # `Validified` data extractor /// # `Validified` data extractor
/// ///
/// `Validified` provides construction, modification and validation abilities based on `validify`. /// `Validified` provides construction, modification and validation abilities based on `validify`.
@@ -123,7 +163,6 @@ impl<E: IntoResponse + HasModify> IntoResponse for Modified<E> {
/// And can treat missing fields as validation errors. /// And can treat missing fields as validation errors.
/// ///
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Validified<E>(pub E); pub struct Validified<E>(pub E);
impl<E> Deref for Validified<E> { impl<E> Deref for Validified<E> {
@@ -156,6 +195,16 @@ impl<E> Validified<E> {
} }
} }
#[cfg(feature = "aide")]
impl<T> aide::OperationInput for Validified<T>
where
T: aide::OperationInput,
{
fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) {
T::operation_input(ctx, operation);
}
}
/// # `ValidifiedByRef` data extractor /// # `ValidifiedByRef` data extractor
/// ///
/// `ValidifiedByRef` is similar to `Validified`, but operates via reference. /// `ValidifiedByRef` is similar to `Validified`, but operates via reference.
@@ -163,7 +212,6 @@ impl<E> Validified<E> {
/// Suitable for inner extractors not based on `serde`. /// Suitable for inner extractors not based on `serde`.
/// ///
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct ValidifiedByRef<E>(pub E); pub struct ValidifiedByRef<E>(pub E);
impl<E> Deref for ValidifiedByRef<E> { impl<E> Deref for ValidifiedByRef<E> {
@@ -196,6 +244,16 @@ impl<E> ValidifiedByRef<E> {
} }
} }
#[cfg(feature = "aide")]
impl<T> aide::OperationInput for ValidifiedByRef<T>
where
T: aide::OperationInput,
{
fn operation_input(ctx: &mut aide::gen::GenContext, operation: &mut aide::openapi::Operation) {
T::operation_input(ctx, operation);
}
}
/// `ValidifyRejection` is returned when the `Validated` / `Modified` / `Validified` / `ValidifiedByRef` extractor fails. /// `ValidifyRejection` is returned when the `Validated` / `Modified` / `Validified` / `ValidifiedByRef` extractor fails.
/// ///
pub type ValidifyRejection<E> = ValidationRejection<ValidationErrors, E>; pub type ValidifyRejection<E> = ValidationRejection<ValidationErrors, E>;