aide/helpers/
use_api.rs

1use std::{
2    marker::PhantomData,
3    ops::{Deref, DerefMut},
4};
5
6use serde::{Deserialize, Serialize};
7
8use crate::generate::GenContext;
9use crate::openapi::{Operation, Response};
10use crate::{OperationInput, OperationOutput};
11
12/// helper trait to allow simplified use of [`UseApi`] in responses
13pub trait IntoApi {
14    /// into [`UseApi`]
15    fn into_api<A>(self) -> UseApi<Self, A>
16    where
17        Self: Sized;
18}
19
20impl<T> IntoApi for T {
21    fn into_api<A>(self) -> UseApi<Self, A>
22    where
23        Self: Sized,
24    {
25        self.into()
26    }
27}
28
29/// Allows non [`OperationInput`] or [`OperationOutput`] types to be used in aide handlers with the api documentation of [A].
30///
31/// For types that already implement [`OperationInput`] or [`OperationOutput`] it overrides the documentation with the provided one.
32#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)]
33pub struct UseApi<T, A>(pub T, pub PhantomData<A>);
34
35impl<T, A> UseApi<T, A> {
36    /// Unwraps [Self] into its inner type
37    pub fn into_inner(self) -> T {
38        self.0
39    }
40}
41
42impl<T, A> Deref for UseApi<T, A> {
43    type Target = T;
44
45    fn deref(&self) -> &Self::Target {
46        &self.0
47    }
48}
49
50impl<T, A> DerefMut for UseApi<T, A> {
51    fn deref_mut(&mut self) -> &mut Self::Target {
52        &mut self.0
53    }
54}
55
56impl<T, A> AsRef<T> for UseApi<T, A> {
57    fn as_ref(&self) -> &T {
58        &self.0
59    }
60}
61
62impl<T, A> AsMut<T> for UseApi<T, A> {
63    fn as_mut(&mut self) -> &mut T {
64        &mut self.0
65    }
66}
67
68impl<T, A> From<T> for UseApi<T, A> {
69    fn from(value: T) -> Self {
70        Self(value, Default::default())
71    }
72}
73
74impl<T, A> OperationInput for UseApi<T, A>
75where
76    A: OperationInput,
77{
78    fn operation_input(ctx: &mut GenContext, operation: &mut Operation) {
79        A::operation_input(ctx, operation);
80    }
81
82    fn inferred_early_responses(
83        ctx: &mut GenContext,
84        operation: &mut Operation,
85    ) -> Vec<(Option<u16>, Response)> {
86        A::inferred_early_responses(ctx, operation)
87    }
88}
89
90impl<T, A> OperationOutput for UseApi<T, A>
91where
92    A: OperationOutput,
93{
94    type Inner = A::Inner;
95
96    fn operation_response(ctx: &mut GenContext, operation: &mut Operation) -> Option<Response> {
97        A::operation_response(ctx, operation)
98    }
99
100    fn inferred_responses(
101        ctx: &mut GenContext,
102        operation: &mut Operation,
103    ) -> Vec<(Option<u16>, Response)> {
104        A::inferred_responses(ctx, operation)
105    }
106}
107
108#[cfg(feature = "axum")]
109mod axum {
110    use axum::body::Body;
111    use axum::extract::{FromRequest, FromRequestParts};
112    use axum::response::{IntoResponse, IntoResponseParts, Response, ResponseParts};
113    use http::request::Parts;
114    use http::Request;
115
116    use crate::UseApi;
117
118    impl<T, A> IntoResponse for UseApi<T, A>
119    where
120        T: IntoResponse,
121    {
122        fn into_response(self) -> Response {
123            self.0.into_response()
124        }
125    }
126
127    impl<T, A> IntoResponseParts for UseApi<T, A>
128    where
129        T: IntoResponseParts,
130    {
131        type Error = T::Error;
132
133        fn into_response_parts(self, res: ResponseParts) -> Result<ResponseParts, Self::Error> {
134            self.0.into_response_parts(res)
135        }
136    }
137
138    impl<T, A, S> FromRequestParts<S> for UseApi<T, A>
139    where
140        T: FromRequestParts<S>,
141        S: Send + Sync,
142    {
143        type Rejection = T::Rejection;
144
145        async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
146            Ok(Self(
147                T::from_request_parts(parts, state).await?,
148                Default::default(),
149            ))
150        }
151    }
152
153    impl<T, A, S> FromRequest<S> for UseApi<T, A>
154    where
155        T: FromRequest<S>,
156        S: Send + Sync,
157    {
158        type Rejection = T::Rejection;
159
160        async fn from_request(req: Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
161            Ok(Self(T::from_request(req, state).await?, Default::default()))
162        }
163    }
164}