predawn_core/
response.rs

1use std::{borrow::Cow, collections::BTreeMap};
2
3use bytes::{Bytes, BytesMut};
4use http::StatusCode;
5
6use crate::{
7    body::ResponseBody,
8    media_type::MultiResponseMediaType,
9    openapi::{self, Schema},
10};
11
12pub type Response<T = ResponseBody> = http::Response<T>;
13
14pub trait SingleResponse {
15    const STATUS_CODE: u16 = 200;
16
17    fn response(
18        schemas: &mut BTreeMap<String, Schema>,
19        schemas_in_progress: &mut Vec<String>,
20    ) -> openapi::Response;
21}
22
23pub trait MultiResponse {
24    fn responses(
25        schemas: &mut BTreeMap<String, Schema>,
26        schemas_in_progress: &mut Vec<String>,
27    ) -> BTreeMap<StatusCode, openapi::Response>;
28}
29
30impl<T: SingleResponse> MultiResponse for T {
31    fn responses(
32        schemas: &mut BTreeMap<String, Schema>,
33        schemas_in_progress: &mut Vec<String>,
34    ) -> BTreeMap<StatusCode, openapi::Response> {
35        let mut map = BTreeMap::new();
36
37        map.insert(
38            StatusCode::from_u16(T::STATUS_CODE).unwrap_or_else(|_| {
39                panic!(
40                    "`<{} as SingleResponse>::STATUS_CODE` is {}, which is not a valid status code",
41                    std::any::type_name::<T>(),
42                    T::STATUS_CODE
43                )
44            }),
45            T::response(schemas, schemas_in_progress),
46        );
47
48        map
49    }
50}
51
52impl SingleResponse for () {
53    fn response(_: &mut BTreeMap<String, Schema>, _: &mut Vec<String>) -> openapi::Response {
54        openapi::Response::default()
55    }
56}
57
58macro_rules! some_impl {
59    ($ty:ty; $($desc:tt)+) => {
60        impl $($desc)+
61        {
62            fn response(schemas: &mut BTreeMap<String, Schema>, schemas_in_progress: &mut Vec<String>) -> openapi::Response {
63                openapi::Response {
64                    content: <$ty as MultiResponseMediaType>::content(schemas, schemas_in_progress),
65                    ..Default::default()
66                }
67            }
68        }
69    };
70}
71
72some_impl!(String; SingleResponse for &'static str);
73some_impl!(String; SingleResponse for Cow<'static, str>);
74some_impl!(String; SingleResponse for String);
75some_impl!(String; SingleResponse for Box<str>);
76
77some_impl!(Vec<u8>; SingleResponse for &'static [u8]);
78some_impl!(Vec<u8>; SingleResponse for Cow<'static, [u8]>);
79some_impl!(Vec<u8>; SingleResponse for Vec<u8>);
80some_impl!(Vec<u8>; SingleResponse for Bytes);
81some_impl!(Vec<u8>; SingleResponse for BytesMut);
82some_impl!(Vec<u8>; SingleResponse for Box<[u8]>);
83
84some_impl!([u8; N]; <const N: usize> SingleResponse for [u8; N]);
85some_impl!([u8; N]; <const N: usize> SingleResponse for &'static [u8; N]);