1use std::{error, iter::FromIterator, marker::PhantomData};
18
19use bytes::Bytes;
20use conjure_error::{Error, InvalidArgument};
21use conjure_object::FromPlain;
22use futures_core::Stream;
23use http::{header::CONTENT_TYPE, HeaderMap, HeaderValue, Response};
24use serde::{de::DeserializeOwned, Serialize};
25
26use crate::private::APPLICATION_OCTET_STREAM;
27
28use super::{
29 AsyncDeserializeRequest, AsyncResponseBody, AsyncSerializeResponse, AsyncWriteBody,
30 ConjureRuntime, DecodeHeader, DecodeParam, DeserializeRequest, EmptyResponseSerializer,
31 ResponseBody, SerializeResponse, StdRequestDeserializer, StdResponseSerializer, WriteBody,
32};
33
34pub enum OptionalRequestDeserializer {}
36
37impl<T, R> DeserializeRequest<Option<T>, R> for OptionalRequestDeserializer
38where
39 T: DeserializeOwned,
40 R: Iterator<Item = Result<Bytes, Error>>,
41{
42 fn deserialize(
43 runtime: &ConjureRuntime,
44 headers: &HeaderMap,
45 body: R,
46 ) -> Result<Option<T>, Error> {
47 if !headers.contains_key(CONTENT_TYPE) {
48 return Ok(None);
49 }
50
51 <StdRequestDeserializer as DeserializeRequest<_, _>>::deserialize(runtime, headers, body)
52 }
53}
54
55impl<T, R> AsyncDeserializeRequest<Option<T>, R> for OptionalRequestDeserializer
56where
57 T: DeserializeOwned,
58 R: Stream<Item = Result<Bytes, Error>> + Send,
59{
60 async fn deserialize(
61 runtime: &ConjureRuntime,
62 headers: &HeaderMap,
63 body: R,
64 ) -> Result<Option<T>, Error> {
65 if !headers.contains_key(CONTENT_TYPE) {
66 return Ok(None);
67 }
68
69 <StdRequestDeserializer as AsyncDeserializeRequest<_, _>>::deserialize(
70 runtime, headers, body,
71 )
72 .await
73 }
74}
75
76pub enum BinaryRequestDeserializer {}
78
79impl BinaryRequestDeserializer {
80 fn deserialize_inner<R>(headers: &HeaderMap, body: R) -> Result<R, Error> {
81 if headers.get(CONTENT_TYPE) != Some(&APPLICATION_OCTET_STREAM) {
82 return Err(Error::service_safe(
83 "unexpected Content-Type",
84 InvalidArgument::new(),
85 ));
86 }
87
88 Ok(body)
89 }
90}
91
92impl<R> DeserializeRequest<R, R> for BinaryRequestDeserializer {
93 fn deserialize(_runtime: &ConjureRuntime, headers: &HeaderMap, body: R) -> Result<R, Error> {
94 Self::deserialize_inner(headers, body)
95 }
96}
97
98impl<R> AsyncDeserializeRequest<R, R> for BinaryRequestDeserializer
99where
100 R: Send,
101{
102 async fn deserialize(
103 _runtime: &ConjureRuntime,
104 headers: &HeaderMap,
105 body: R,
106 ) -> Result<R, Error> {
107 Self::deserialize_inner(headers, body)
108 }
109}
110
111pub enum CollectionResponseSerializer {}
113
114impl<T, W> SerializeResponse<T, W> for CollectionResponseSerializer
115where
116 T: Serialize + PartialEq + Default,
117{
118 fn serialize(
119 runtime: &ConjureRuntime,
120 request_headers: &HeaderMap,
121 value: T,
122 ) -> Result<Response<ResponseBody<W>>, Error> {
123 if value == T::default() {
124 <EmptyResponseSerializer as SerializeResponse<_, _>>::serialize(
125 runtime,
126 request_headers,
127 (),
128 )
129 } else {
130 <StdResponseSerializer as SerializeResponse<_, _>>::serialize(
131 runtime,
132 request_headers,
133 value,
134 )
135 }
136 }
137}
138
139impl<T, W> AsyncSerializeResponse<T, W> for CollectionResponseSerializer
140where
141 T: Serialize + PartialEq + Default,
142{
143 fn serialize(
144 runtime: &ConjureRuntime,
145 request_headers: &HeaderMap,
146 value: T,
147 ) -> Result<Response<AsyncResponseBody<W>>, Error> {
148 if value == T::default() {
149 <EmptyResponseSerializer as AsyncSerializeResponse<_, _>>::serialize(
150 runtime,
151 request_headers,
152 (),
153 )
154 } else {
155 <StdResponseSerializer as AsyncSerializeResponse<_, _>>::serialize(
156 runtime,
157 request_headers,
158 value,
159 )
160 }
161 }
162}
163
164pub enum BinaryResponseSerializer {}
166
167impl BinaryResponseSerializer {
168 fn serialize_inner<B>(body: B) -> Result<Response<B>, Error> {
169 let mut response = Response::new(body);
170
171 response
172 .headers_mut()
173 .insert(CONTENT_TYPE, APPLICATION_OCTET_STREAM);
174 Ok(response)
175 }
176}
177
178impl<T, W> SerializeResponse<T, W> for BinaryResponseSerializer
179where
180 T: WriteBody<W> + 'static,
181{
182 fn serialize(
183 _runtime: &ConjureRuntime,
184 _request_headers: &HeaderMap,
185 value: T,
186 ) -> Result<Response<ResponseBody<W>>, Error> {
187 Self::serialize_inner(ResponseBody::Streaming(Box::new(value)))
188 }
189}
190
191impl<T, W> AsyncSerializeResponse<T, W> for BinaryResponseSerializer
192where
193 T: AsyncWriteBody<W> + 'static + Send,
194{
195 fn serialize(
196 _runtime: &ConjureRuntime,
197 _request_headers: &HeaderMap,
198 value: T,
199 ) -> Result<Response<AsyncResponseBody<W>>, Error> {
200 Self::serialize_inner(AsyncResponseBody::Streaming(super::BoxAsyncWriteBody::new(
201 value,
202 )))
203 }
204}
205
206pub enum OptionalBinaryResponseSerializer {}
208
209impl<T, W> SerializeResponse<Option<T>, W> for OptionalBinaryResponseSerializer
210where
211 T: WriteBody<W> + 'static,
212{
213 fn serialize(
214 runtime: &ConjureRuntime,
215 request_headers: &HeaderMap,
216 value: Option<T>,
217 ) -> Result<Response<ResponseBody<W>>, Error> {
218 match value {
219 Some(value) => <BinaryResponseSerializer as SerializeResponse<_, _>>::serialize(
220 runtime,
221 request_headers,
222 value,
223 ),
224 None => <EmptyResponseSerializer as SerializeResponse<_, _>>::serialize(
225 runtime,
226 request_headers,
227 (),
228 ),
229 }
230 }
231}
232
233impl<T, W> AsyncSerializeResponse<Option<T>, W> for OptionalBinaryResponseSerializer
234where
235 T: AsyncWriteBody<W> + 'static + Send,
236{
237 fn serialize(
238 runtime: &ConjureRuntime,
239 request_headers: &HeaderMap,
240 value: Option<T>,
241 ) -> Result<Response<AsyncResponseBody<W>>, Error> {
242 match value {
243 Some(value) => <BinaryResponseSerializer as AsyncSerializeResponse<_, _>>::serialize(
244 runtime,
245 request_headers,
246 value,
247 ),
248 None => <EmptyResponseSerializer as AsyncSerializeResponse<_, _>>::serialize(
249 runtime,
250 request_headers,
251 (),
252 ),
253 }
254 }
255}
256
257pub enum FromPlainDecoder {}
259
260impl<T> DecodeHeader<T> for FromPlainDecoder
261where
262 T: FromPlain,
263 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
264{
265 fn decode<'a, I>(_: &ConjureRuntime, headers: I) -> Result<T, Error>
266 where
267 I: IntoIterator<Item = &'a HeaderValue>,
268 {
269 T::from_plain(
270 super::only_item(headers)?
271 .to_str()
272 .map_err(|e| Error::service(e, InvalidArgument::new()))?,
273 )
274 .map_err(|e| Error::service(e, InvalidArgument::new()))
275 }
276}
277
278impl<T> DecodeParam<T> for FromPlainDecoder
279where
280 T: FromPlain,
281 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
282{
283 fn decode<I>(_: &ConjureRuntime, params: I) -> Result<T, Error>
284 where
285 I: IntoIterator,
286 I::Item: AsRef<str>,
287 {
288 T::from_plain(super::only_item(params)?.as_ref())
289 .map_err(|e| Error::service(e, InvalidArgument::new()))
290 }
291}
292
293pub enum FromPlainOptionDecoder {}
295
296impl<T> DecodeHeader<Option<T>> for FromPlainOptionDecoder
297where
298 T: FromPlain,
299 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
300{
301 fn decode<'a, I>(_: &ConjureRuntime, headers: I) -> Result<Option<T>, Error>
302 where
303 I: IntoIterator<Item = &'a HeaderValue>,
304 {
305 let Some(header) = super::optional_item(headers)? else {
306 return Ok(None);
307 };
308 let value = T::from_plain(
309 header
310 .to_str()
311 .map_err(|e| Error::service(e, InvalidArgument::new()))?,
312 )
313 .map_err(|e| Error::service(e, InvalidArgument::new()))?;
314 Ok(Some(value))
315 }
316}
317
318impl<T> DecodeParam<Option<T>> for FromPlainOptionDecoder
319where
320 T: FromPlain,
321 T::Err: Into<Box<dyn error::Error + Sync + Send>>,
322{
323 fn decode<I>(_: &ConjureRuntime, params: I) -> Result<Option<T>, Error>
324 where
325 I: IntoIterator,
326 I::Item: AsRef<str>,
327 {
328 let Some(param) = super::optional_item(params)? else {
329 return Ok(None);
330 };
331 let value =
332 T::from_plain(param.as_ref()).map_err(|e| Error::service(e, InvalidArgument::new()))?;
333 Ok(Some(value))
334 }
335}
336
337pub struct FromPlainSeqDecoder<U> {
340 _p: PhantomData<U>,
341}
342
343impl<T, U> DecodeParam<T> for FromPlainSeqDecoder<U>
344where
345 T: FromIterator<U>,
346 U: FromPlain,
347 U::Err: Into<Box<dyn error::Error + Sync + Send>>,
348{
349 fn decode<I>(_: &ConjureRuntime, params: I) -> Result<T, Error>
350 where
351 I: IntoIterator,
352 I::Item: AsRef<str>,
353 {
354 params
355 .into_iter()
356 .map(|s| {
357 U::from_plain(s.as_ref()).map_err(|e| Error::service(e, InvalidArgument::new()))
358 })
359 .collect()
360 }
361}