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}