http_types/
status.rs
1use crate::{Error, StatusCode};
2use core::convert::{Infallible, TryInto};
3use std::error::Error as StdError;
4use std::fmt::Debug;
5
6pub trait Status<T, E>: private::Sealed {
10 fn status<S>(self, status: S) -> Result<T, Error>
12 where
13 S: TryInto<StatusCode>,
14 S::Error: Debug;
15
16 fn with_status<S, F>(self, f: F) -> Result<T, Error>
19 where
20 S: TryInto<StatusCode>,
21 S::Error: Debug,
22 F: FnOnce() -> S;
23}
24
25impl<T, E> Status<T, E> for Result<T, E>
26where
27 E: StdError + Send + Sync + 'static,
28{
29 fn status<S>(self, status: S) -> Result<T, Error>
38 where
39 S: TryInto<StatusCode>,
40 S::Error: Debug,
41 {
42 self.map_err(|error| {
43 let status = status
44 .try_into()
45 .expect("Could not convert into a valid `StatusCode`");
46 Error::new(status, error)
47 })
48 }
49
50 fn with_status<S, F>(self, f: F) -> Result<T, Error>
60 where
61 S: TryInto<StatusCode>,
62 S::Error: Debug,
63 F: FnOnce() -> S,
64 {
65 self.map_err(|error| {
66 let status = f()
67 .try_into()
68 .expect("Could not convert into a valid `StatusCode`");
69 Error::new(status, error)
70 })
71 }
72}
73
74impl<T> Status<T, Infallible> for Option<T> {
75 fn status<S>(self, status: S) -> Result<T, Error>
84 where
85 S: TryInto<StatusCode>,
86 S::Error: Debug,
87 {
88 self.ok_or_else(|| {
89 let status = status
90 .try_into()
91 .expect("Could not convert into a valid `StatusCode`");
92 Error::from_str(status, "NoneError")
93 })
94 }
95
96 fn with_status<S, F>(self, f: F) -> Result<T, Error>
106 where
107 S: TryInto<StatusCode>,
108 S::Error: Debug,
109 F: FnOnce() -> S,
110 {
111 self.ok_or_else(|| {
112 let status = f()
113 .try_into()
114 .expect("Could not convert into a valid `StatusCode`");
115 Error::from_str(status, "NoneError")
116 })
117 }
118}
119
120pub(crate) mod private {
121 pub trait Sealed {}
122
123 impl<T, E> Sealed for Result<T, E> {}
124 impl<T> Sealed for Option<T> {}
125}
126
127#[cfg(test)]
128mod test {
129 use super::Status;
130
131 #[test]
132 fn construct_shorthand_with_valid_status_code() {
133 let _res = Some(()).status(200).unwrap();
134 }
135
136 #[test]
137 #[should_panic(expected = "Could not convert into a valid `StatusCode`")]
138 fn construct_shorthand_with_invalid_status_code() {
139 let res: Result<(), std::io::Error> =
140 Err(std::io::Error::new(std::io::ErrorKind::Other, "oh no!"));
141 let _res = res.status(600).unwrap();
142 }
143}