predawn_core/
api_request.rs

1use std::collections::BTreeMap;
2
3use bytes::Bytes;
4use http::{HeaderMap, Method, Uri, Version};
5
6use crate::{
7    body::RequestBody,
8    media_type::MultiRequestMediaType,
9    openapi::{self, Parameter, Schema},
10    private::{ViaRequest, ViaRequestHead},
11    request::{BodyLimit, Head, LocalAddr, OriginalUri, RemoteAddr},
12};
13
14pub trait ApiRequestHead {
15    fn parameters(
16        schemas: &mut BTreeMap<String, Schema>,
17        schemas_in_progress: &mut Vec<String>,
18    ) -> Option<Vec<Parameter>>;
19}
20
21pub trait ApiRequest<M = ViaRequest> {
22    fn parameters(
23        schemas: &mut BTreeMap<String, Schema>,
24        schemas_in_progress: &mut Vec<String>,
25    ) -> Option<Vec<Parameter>>;
26
27    fn request_body(
28        schemas: &mut BTreeMap<String, Schema>,
29        schemas_in_progress: &mut Vec<String>,
30    ) -> Option<openapi::RequestBody>;
31}
32
33impl<T> ApiRequest<ViaRequestHead> for T
34where
35    T: ApiRequestHead,
36{
37    fn parameters(
38        schemas: &mut BTreeMap<String, Schema>,
39        schemas_in_progress: &mut Vec<String>,
40    ) -> Option<Vec<Parameter>> {
41        T::parameters(schemas, schemas_in_progress)
42    }
43
44    fn request_body(
45        _: &mut BTreeMap<String, Schema>,
46        _: &mut Vec<String>,
47    ) -> Option<openapi::RequestBody> {
48        None
49    }
50}
51
52impl ApiRequest for RequestBody {
53    fn parameters(_: &mut BTreeMap<String, Schema>, _: &mut Vec<String>) -> Option<Vec<Parameter>> {
54        None
55    }
56
57    fn request_body(
58        _: &mut BTreeMap<String, Schema>,
59        _: &mut Vec<String>,
60    ) -> Option<openapi::RequestBody> {
61        None
62    }
63}
64
65macro_rules! some_api_request_impl {
66    ($($ty:ty),+ $(,)?) => {
67        $(
68            impl ApiRequest for $ty {
69                fn parameters(_: &mut BTreeMap<String, Schema>, _: &mut Vec<String>) -> Option<Vec<Parameter>> {
70                    None
71                }
72
73                fn request_body(schemas: &mut BTreeMap<String, Schema>, schemas_in_progress: &mut Vec<String>) -> Option<openapi::RequestBody> {
74                    Some(openapi::RequestBody {
75                        content: <$ty as MultiRequestMediaType>::content(schemas, schemas_in_progress),
76                        required: true,
77                        ..Default::default()
78                    })
79                }
80            }
81        )+
82    };
83}
84
85some_api_request_impl![Bytes, Vec<u8>, String];
86
87macro_rules! some_api_request_head_impl {
88    ($($ty:ty),+ $(,)?) => {
89        $(
90            impl ApiRequestHead for $ty {
91                fn parameters(_: &mut BTreeMap<String, Schema>, _: &mut Vec<String>) -> Option<Vec<Parameter>> {
92                    None
93                }
94            }
95        )+
96    };
97}
98
99some_api_request_head_impl![
100    Uri,
101    Method,
102    HeaderMap,
103    OriginalUri,
104    Version,
105    LocalAddr,
106    RemoteAddr,
107    BodyLimit,
108    Head,
109];
110
111macro_rules! optional_parameters {
112    ($ty:ty) => {
113        fn parameters(
114            schemas: &mut BTreeMap<String, Schema>,
115            schemas_in_progress: &mut Vec<String>,
116        ) -> Option<Vec<Parameter>> {
117            let mut parameters = <$ty>::parameters(schemas, schemas_in_progress)?;
118
119            parameters.iter_mut().for_each(|parameter| match parameter {
120                Parameter::Query { parameter_data, .. } => parameter_data.required = false,
121                Parameter::Header { parameter_data, .. } => parameter_data.required = false,
122                Parameter::Path { parameter_data, .. } => parameter_data.required = false,
123                Parameter::Cookie { parameter_data, .. } => parameter_data.required = false,
124            });
125
126            Some(parameters)
127        }
128    };
129}
130
131impl<T: ApiRequestHead> ApiRequestHead for Option<T> {
132    optional_parameters!(T);
133}
134
135impl<T: ApiRequest> ApiRequest for Option<T> {
136    optional_parameters!(T);
137
138    fn request_body(
139        schemas: &mut BTreeMap<String, Schema>,
140        schemas_in_progress: &mut Vec<String>,
141    ) -> Option<openapi::RequestBody> {
142        let mut request_body = T::request_body(schemas, schemas_in_progress)?;
143        request_body.required = false;
144        Some(request_body)
145    }
146}
147
148impl<T, E> ApiRequestHead for Result<T, E>
149where
150    T: ApiRequestHead,
151{
152    fn parameters(
153        schemas: &mut BTreeMap<String, Schema>,
154        schemas_in_progress: &mut Vec<String>,
155    ) -> Option<Vec<Parameter>> {
156        T::parameters(schemas, schemas_in_progress)
157    }
158}
159
160impl<T, E> ApiRequest for Result<T, E>
161where
162    T: ApiRequest,
163{
164    fn parameters(
165        schemas: &mut BTreeMap<String, Schema>,
166        schemas_in_progress: &mut Vec<String>,
167    ) -> Option<Vec<Parameter>> {
168        T::parameters(schemas, schemas_in_progress)
169    }
170
171    fn request_body(
172        schemas: &mut BTreeMap<String, Schema>,
173        schemas_in_progress: &mut Vec<String>,
174    ) -> Option<openapi::RequestBody> {
175        T::request_body(schemas, schemas_in_progress)
176    }
177}