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}