predawn_core/
either.rs

1use std::{
2    collections::{BTreeMap, BTreeSet},
3    error::Error,
4    fmt,
5};
6
7use http::StatusCode;
8
9use crate::{
10    error::BoxError,
11    error_ext::{ErrorExt, NextError},
12    location::Location,
13    openapi::{self, merge_responses, Schema},
14    response::Response,
15    response_error::ResponseError,
16};
17
18#[derive(Debug)]
19pub enum Either<L, R> {
20    Left(L),
21    Right(R),
22}
23
24impl<L, R> fmt::Display for Either<L, R>
25where
26    L: fmt::Display,
27    R: fmt::Display,
28{
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        match self {
31            Either::Left(l) => fmt::Display::fmt(l, f),
32            Either::Right(r) => fmt::Display::fmt(r, f),
33        }
34    }
35}
36
37impl<L, R> Error for Either<L, R>
38where
39    L: Error,
40    R: Error,
41{
42    fn source(&self) -> Option<&(dyn Error + 'static)> {
43        match self {
44            Either::Left(l) => l.source(),
45            Either::Right(r) => r.source(),
46        }
47    }
48}
49
50impl<L, R> ErrorExt for Either<L, R>
51where
52    L: ErrorExt,
53    R: ErrorExt,
54{
55    fn entry(&self) -> (Location, NextError<'_>) {
56        match self {
57            Either::Left(l) => l.entry(),
58            Either::Right(r) => r.entry(),
59        }
60    }
61}
62
63impl<L, R> ResponseError for Either<L, R>
64where
65    L: ResponseError,
66    R: ResponseError,
67{
68    fn as_status(&self) -> StatusCode {
69        match self {
70            Either::Left(l) => l.as_status(),
71            Either::Right(r) => r.as_status(),
72        }
73    }
74
75    fn status_codes(codes: &mut BTreeSet<StatusCode>) {
76        L::status_codes(codes);
77        R::status_codes(codes);
78    }
79
80    fn as_response(&self) -> Response {
81        match self {
82            Either::Left(l) => l.as_response(),
83            Either::Right(r) => r.as_response(),
84        }
85    }
86
87    fn responses(
88        schemas: &mut BTreeMap<String, Schema>,
89        schemas_in_progress: &mut Vec<String>,
90    ) -> BTreeMap<StatusCode, openapi::Response> {
91        let mut responses = L::responses(schemas, schemas_in_progress);
92        merge_responses(&mut responses, R::responses(schemas, schemas_in_progress));
93        responses
94    }
95
96    #[doc(hidden)]
97    fn inner(self) -> BoxError {
98        match self {
99            Either::Left(l) => l.inner(),
100            Either::Right(r) => r.inner(),
101        }
102    }
103}