1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::{
    collections::{BTreeMap, HashSet},
    convert::Infallible,
    error::Error,
};

use http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use mime::TEXT_PLAIN_UTF_8;

use crate::{
    media_type::MultiResponseMediaType,
    openapi::{self, Components},
    response::Response,
};

pub trait ResponseError: Error + Send + Sync + 'static {
    fn as_status(&self) -> StatusCode;

    fn status_codes() -> HashSet<StatusCode>;

    fn as_response(&self) -> Response {
        Response::builder()
            .status(self.as_status())
            .header(
                CONTENT_TYPE,
                HeaderValue::from_static(TEXT_PLAIN_UTF_8.as_ref()),
            )
            .body(self.to_string().into())
            .unwrap()
    }

    fn responses(components: &mut Components) -> BTreeMap<StatusCode, openapi::Response> {
        Self::status_codes()
            .into_iter()
            .map(|status| {
                (
                    status,
                    openapi::Response {
                        description: status.canonical_reason().unwrap_or_default().to_string(),
                        content: <String as MultiResponseMediaType>::content(components),
                        ..Default::default()
                    },
                )
            })
            .collect()
    }
}

impl ResponseError for Infallible {
    fn as_status(&self) -> StatusCode {
        match *self {}
    }

    fn status_codes() -> HashSet<StatusCode> {
        HashSet::new()
    }

    fn as_response(&self) -> Response {
        match *self {}
    }

    fn responses(_: &mut Components) -> BTreeMap<StatusCode, openapi::Response> {
        BTreeMap::new()
    }
}