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]);