rama_error/ext/
wrapper.rs1use crate::BoxError;
2use std::fmt::{self, Debug, Display};
3
4#[repr(transparent)]
5pub struct OpaqueError(BoxError);
12
13impl OpaqueError {
14 pub fn from_std(error: impl std::error::Error + Send + Sync + 'static) -> Self {
16 Self(Box::new(error))
17 }
18
19 pub fn from_display(msg: impl Display + Debug + Send + Sync + 'static) -> Self {
21 Self::from_std(MessageError(msg))
22 }
23
24 #[must_use]
26 pub fn from_boxed(inner: BoxError) -> Self {
27 Self(inner)
28 }
29
30 #[must_use]
32 pub fn is<T>(&self) -> bool
33 where
34 T: std::error::Error + 'static,
35 {
36 self.0.is::<T>()
37 }
38
39 #[must_use]
41 pub fn into_boxed(self) -> BoxError {
42 self.0
43 }
44
45 pub fn downcast<T>(self) -> Result<T, Self>
47 where
48 T: std::error::Error + 'static,
49 {
50 match self.0.downcast::<T>() {
51 Ok(error) => Ok(*error),
52 Err(inner) => Err(Self(inner)),
53 }
54 }
55
56 #[must_use]
59 pub fn downcast_ref<T>(&self) -> Option<&T>
60 where
61 T: std::error::Error + 'static,
62 {
63 self.0.downcast_ref()
64 }
65
66 pub fn downcast_mut<T>(&mut self) -> Option<&mut T>
69 where
70 T: std::error::Error + 'static,
71 {
72 self.0.downcast_mut()
73 }
74}
75
76impl Debug for OpaqueError {
77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 Debug::fmt(&self.0, f)
79 }
80}
81
82impl Display for OpaqueError {
83 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84 Display::fmt(&self.0, f)
85 }
86}
87
88impl std::error::Error for OpaqueError {
89 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
90 if let Some(err) = self.0.source() {
91 return Some(err);
92 }
93 let err = self.0.as_ref();
94 Some(err as &(dyn std::error::Error + 'static))
95 }
96}
97
98impl From<BoxError> for OpaqueError {
99 fn from(error: BoxError) -> Self {
100 Self(error)
101 }
102}
103
104#[repr(transparent)]
105pub(crate) struct MessageError<M>(pub(crate) M);
107
108impl<M> Debug for MessageError<M>
109where
110 M: Display + Debug,
111{
112 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113 Debug::fmt(&self.0, f)
114 }
115}
116
117impl<M> Display for MessageError<M>
118where
119 M: Display + Debug,
120{
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 Display::fmt(&self.0, f)
123 }
124}
125
126impl<M> std::error::Error for MessageError<M> where M: Display + Debug + 'static {}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[derive(Debug)]
133 struct CustomError(usize);
134
135 impl Display for CustomError {
136 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137 write!(f, "Custom error ({})", self.0)
138 }
139 }
140
141 impl std::error::Error for CustomError {}
142
143 #[test]
144 fn opaque_error_is() {
145 let error = OpaqueError::from_std(CustomError(1));
146 assert!(error.is::<CustomError>());
147 }
148
149 #[test]
150 fn opaque_error_is_not() {
151 let error = OpaqueError::from_display("hello");
152 assert!(!error.is::<CustomError>());
153 }
154
155 #[test]
156 fn opaque_error_downcast() {
157 let error = OpaqueError::from_std(CustomError(2));
158 let custom_error = error.downcast::<CustomError>().unwrap();
159 assert_eq!(custom_error.0, 2);
160 }
161
162 #[test]
163 fn opaque_error_downcast_fail() {
164 let error = OpaqueError::from_display("hello");
165 assert!(error.downcast::<CustomError>().is_err());
166 }
167
168 #[test]
169 fn opaque_error_downcast_ref() {
170 let error = OpaqueError::from_std(CustomError(3));
171 let custom_error = error.downcast_ref::<CustomError>().unwrap();
172 assert_eq!(custom_error.0, 3);
173 }
174
175 #[test]
176 fn opaque_error_downcast_ref_fail() {
177 let error = OpaqueError::from_display("hello");
178 assert!(error.downcast_ref::<CustomError>().is_none());
179 }
180
181 #[test]
182 fn opaque_error_downcast_mut() {
183 let error = {
184 let mut error = OpaqueError::from_std(CustomError(4));
185 error.downcast_mut::<CustomError>().unwrap().0 = 42;
186 error
187 };
188
189 let custom_error = error.downcast_ref::<CustomError>().unwrap();
190 assert_eq!(custom_error.0, 42);
191 }
192
193 #[test]
194 fn opaque_error_downcast_mut_fail() {
195 let mut error = OpaqueError::from_display("hello");
196 assert!(error.downcast_mut::<CustomError>().is_none());
197 }
198}