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"]
[dependencies]
axum = { version = "0.7.1", default-features = false }
garde = { version = "0.16.3", optional = true }
axum = { version = "0.7.3", default-features = false }
garde = { version = "0.17.0", optional = true }
validator = { version = "0.16.1", optional = true}
validify = { version = "1.3.0", optional = true}
@@ -44,20 +44,20 @@ version = "0.11.0"
optional = true
[dependencies.serde]
version = "1.0.193"
version = "1.0.195"
optional = true
[dependencies.aide]
version = "0.13.0"
version = "0.13.1"
optional = true
[dev-dependencies]
anyhow = "1.0.72"
anyhow = "1.0.75"
axum = { version = "0.7.1", features = ["macros"] }
tokio = { version = "1.34.0", features = ["full"] }
hyper = { version = "0.14.27", features = ["full"] }
reqwest = { version = "0.11.22", features = ["json", "multipart"] }
serde = { version = "1.0.193", features = ["derive"] }
reqwest = { version = "0.11.23", features = ["json", "multipart"] }
serde = { version = "1.0.195", features = ["derive"] }
validator = { version = "0.16.1", features = ["derive"] }
serde_json = "1.0.108"
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.
///
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Garde<E>(pub 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.
///
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.
///
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Valid<E>(pub 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 {
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` 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.
///
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct ValidEx<E, A>(pub E, pub 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 {
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`.
///
/// 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`.
///
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Validated<E>(pub 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
///
/// ## Extractor
@@ -74,7 +83,6 @@ impl<E> Validated<E> {
///
/// This allows applying modifications during response conversion by leveraging validify.
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Modified<E>(pub 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` 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.
///
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct Validified<E>(pub 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` is similar to `Validified`, but operates via reference.
@@ -163,7 +212,6 @@ impl<E> Validified<E> {
/// Suitable for inner extractors not based on `serde`.
///
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "aide", derive(aide::OperationIo))]
pub struct ValidifiedByRef<E>(pub 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.
///
pub type ValidifyRejection<E> = ValidationRejection<ValidationErrors, E>;