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