1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#![feature(optin_builtin_traits)]
use core::any::Any;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct SomeError;
pub auto trait NotSomeError {}
impl !NotSomeError for SomeError {}
impl Default for SomeError {
fn default() -> Self {
SomeError
}
}
impl<T: NotSomeError> From<T> for SomeError {
fn from(_: T) -> SomeError {
SomeError
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FormattedError(pub String);
pub auto trait NotFormattedError {}
impl !NotFormattedError for FormattedError {}
impl FormattedError {
pub fn new(string: &str) -> Self {
FormattedError(string.to_owned())
}
}
impl Default for FormattedError {
fn default() -> Self {
FormattedError::new("Default FormattedError")
}
}
impl<T: core::fmt::Debug + NotFormattedError> From<T> for FormattedError {
fn from(t: T) -> FormattedError {
FormattedError(format!("{:?}", t))
}
}
pub struct AnyError(pub Box<dyn Any>);
pub auto trait NotAnyError {}
impl !NotAnyError for AnyError {}
impl Default for AnyError {
fn default() -> Self {
().into()
}
}
impl<T: NotAnyError + Any> From<T> for AnyError {
fn from(t: T) -> AnyError {
AnyError(Box::new(t) as Box<dyn Any>)
}
}
impl AnyError {
pub fn downcast<T: Any>(self) -> Result<T, Self> {
match self.0.downcast::<T>() {
Ok(t) => Ok(*t),
Err(e) => Err(AnyError(e)),
}
}
}
#[cfg(test)]
mod test {
use crate::{AnyError, FormattedError, SomeError};
struct FormatableError;
impl core::fmt::Debug for FormatableError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "FormatableErrorDebug")
}
}
fn unit_or_formatable_error(ok: bool) -> Result<(), FormatableError> {
match ok {
true => Ok(()),
false => Err(FormatableError),
}
}
#[test]
fn some_test() {
let test = |ok| -> Result<(), SomeError> { Ok(unit_or_formatable_error(ok)?) };
assert_eq!(test(true), Ok(()));
assert_eq!(test(false), Err(SomeError));
}
#[test]
fn formatted_test() {
let test = |ok| -> Result<(), FormattedError> { Ok(unit_or_formatable_error(ok)?) };
assert_eq!(test(true), Ok(()));
assert_eq!(
test(false),
Err(FormattedError("FormatableErrorDebug".to_owned()))
);
}
#[test]
fn any_test() {
let test = |ok| -> Result<(), AnyError> { Ok(unit_or_formatable_error(ok)?) };
assert!(test(true).is_ok());
match test(false) {
Ok(_) => panic!("test(false) should never be Ok(_)"),
Err(error) => match error.0.downcast::<FormatableError>() {
Ok(downcasted) => println!("Successfully Downcasted: {:?}", downcasted),
Err(_) => panic!("Couldn't downcast after boxing in AnyError"),
},
}
}
}