Skip to content

Commit 82e791a

Browse files
authored
update: changed source field of Err to use Option (#9)
1 parent 3c18fb9 commit 82e791a

File tree

2 files changed

+89
-26
lines changed

2 files changed

+89
-26
lines changed

src/errs.rs

+4-18
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::ptr;
1414
/// the error.
1515
pub struct Err {
1616
reason_container: ptr::NonNull<ReasonContainer>,
17-
source: Box<dyn error::Error>,
17+
source: Option<Box<dyn error::Error>>,
1818
}
1919

2020
impl Err {
@@ -38,7 +38,7 @@ impl Err {
3838
let ptr = ptr::NonNull::from(Box::leak(boxed)).cast::<ReasonContainer>();
3939
Self {
4040
reason_container: ptr,
41-
source: Box::new(NoSource {}),
41+
source: None,
4242
}
4343
}
4444

@@ -67,7 +67,7 @@ impl Err {
6767
let ptr = ptr::NonNull::from(Box::leak(boxed)).cast::<ReasonContainer>();
6868
Self {
6969
reason_container: ptr,
70-
source: Box::new(source),
70+
source: Some(Box::new(source)),
7171
}
7272
}
7373

@@ -194,10 +194,7 @@ impl fmt::Display for Err {
194194

195195
impl error::Error for Err {
196196
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
197-
match self.source.downcast_ref::<NoSource>() {
198-
Some(_) => None,
199-
None => Some(&(*self.source)),
200-
}
197+
self.source.as_deref()
201198
}
202199
}
203200

@@ -267,17 +264,6 @@ where
267264
any::TypeId::of::<R>() == type_id
268265
}
269266

270-
#[derive(Debug)]
271-
struct NoSource {}
272-
273-
impl error::Error for NoSource {}
274-
275-
impl fmt::Display for NoSource {
276-
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
277-
Ok(())
278-
}
279-
}
280-
281267
#[cfg(test)]
282268
mod tests_of_err_without_source {
283269
use super::*;

tests/errs_test.rs

+85-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#[cfg(test)]
22
mod integration_tests_of_err {
33
use sabi;
4+
use std::error::Error;
45

56
#[derive(Debug)]
67
enum IoErrs {
78
FileNotFound { path: String },
89
NoPermission { path: String, r#mod: (u8, u8, u8) },
10+
DueToSomeError { path: String },
911
}
1012

1113
fn find_file() -> Result<(), sabi::Err> {
@@ -15,14 +17,21 @@ mod integration_tests_of_err {
1517
Err(err)
1618
}
1719

18-
fn write_file() -> Result<(), sabi::Err> {
20+
fn read_file() -> Result<(), sabi::Err> {
1921
let err = sabi::Err::new(IoErrs::NoPermission {
2022
path: "/aaa/bbb/ccc".to_string(),
21-
r#mod: (6, 6, 6),
23+
r#mod: (4, 4, 4),
2224
});
2325
Err(err)
2426
}
2527

28+
fn write_file() -> Result<(), sabi::Err> {
29+
let path = "/aaa/bbb/ccc".to_string();
30+
let source = std::io::Error::new(std::io::ErrorKind::AlreadyExists, path.clone());
31+
let err = sabi::Err::with_source(IoErrs::DueToSomeError { path }, source);
32+
Err(err)
33+
}
34+
2635
#[test]
2736
fn should_create_err_and_identify_reason() {
2837
match find_file() {
@@ -31,21 +40,43 @@ mod integration_tests_of_err {
3140
Ok(r) => match r {
3241
IoErrs::FileNotFound { path } => {
3342
assert_eq!(path, "/aaa/bbb/ccc");
43+
assert!(err.source().is_none());
3444
}
3545
IoErrs::NoPermission { path: _, r#mod: _ } => panic!(),
46+
IoErrs::DueToSomeError { path: _ } => panic!(),
3647
},
3748
_ => panic!(),
3849
},
3950
}
4051

41-
match write_file() {
52+
match read_file() {
4253
Ok(_) => panic!(),
4354
Err(err) => match err.reason::<IoErrs>() {
4455
Ok(r) => match r {
4556
IoErrs::FileNotFound { path: _ } => panic!(),
4657
IoErrs::NoPermission { path, r#mod } => {
4758
assert_eq!(path, "/aaa/bbb/ccc");
48-
assert_eq!(*r#mod, (6, 6, 6));
59+
assert_eq!(*r#mod, (4, 4, 4));
60+
assert!(err.source().is_none());
61+
}
62+
IoErrs::DueToSomeError { path: _ } => panic!(),
63+
},
64+
_ => panic!(),
65+
},
66+
}
67+
68+
match write_file() {
69+
Ok(_) => panic!(),
70+
Err(err) => match err.reason::<IoErrs>() {
71+
Ok(r) => match r {
72+
IoErrs::FileNotFound { path: _ } => panic!(),
73+
IoErrs::NoPermission { path: _, r#mod: _ } => panic!(),
74+
IoErrs::DueToSomeError { path } => {
75+
assert_eq!(path, "/aaa/bbb/ccc");
76+
let source = err.source().unwrap();
77+
let io_err = source.downcast_ref::<std::io::Error>().unwrap();
78+
assert_eq!(io_err.kind(), std::io::ErrorKind::AlreadyExists);
79+
assert_eq!(io_err.to_string(), "/aaa/bbb/ccc");
4980
}
5081
},
5182
_ => panic!(),
@@ -62,16 +93,29 @@ mod integration_tests_of_err {
6293
assert_eq!(path, "/aaa/bbb/ccc");
6394
}
6495
IoErrs::NoPermission { path: _, r#mod: _ } => panic!(),
96+
IoErrs::DueToSomeError { path: _ } => panic!(),
6597
}),
6698
};
6799

68-
match write_file() {
100+
match read_file() {
69101
Ok(_) => panic!(),
70102
Err(err) => err.match_reason::<IoErrs>(|r| match r {
71103
IoErrs::FileNotFound { path: _ } => panic!(),
72104
IoErrs::NoPermission { path, r#mod } => {
73105
assert_eq!(path, "/aaa/bbb/ccc");
74-
assert_eq!(*r#mod, (6, 6, 6));
106+
assert_eq!(*r#mod, (4, 4, 4));
107+
}
108+
IoErrs::DueToSomeError { path: _ } => panic!(),
109+
}),
110+
};
111+
112+
match write_file() {
113+
Ok(_) => panic!(),
114+
Err(err) => err.match_reason::<IoErrs>(|r| match r {
115+
IoErrs::FileNotFound { path: _ } => panic!(),
116+
IoErrs::NoPermission { path: _, r#mod: _ } => panic!(),
117+
IoErrs::DueToSomeError { path } => {
118+
assert_eq!(path, "/aaa/bbb/ccc");
75119
}
76120
}),
77121
};
@@ -83,6 +127,10 @@ mod integration_tests_of_err {
83127
assert!(err.is_reason::<IoErrs>());
84128
assert!(!err.is_reason::<String>());
85129

130+
let err = read_file().unwrap_err();
131+
assert!(err.is_reason::<IoErrs>());
132+
assert!(!err.is_reason::<String>());
133+
86134
let err = write_file().unwrap_err();
87135
assert!(err.is_reason::<IoErrs>());
88136
assert!(!err.is_reason::<String>());
@@ -94,9 +142,13 @@ mod integration_tests_of_err {
94142
//println!("{err:?}");
95143
assert_eq!(format!("{err:?}"), "sabi::errs::Err { reason: errs_test::integration_tests_of_err::IoErrs FileNotFound { path: \"/aaa/bbb/ccc\" } }");
96144

145+
let err = read_file().unwrap_err();
146+
//println!("{err:?}");
147+
assert_eq!(format!("{err:?}"), "sabi::errs::Err { reason: errs_test::integration_tests_of_err::IoErrs NoPermission { path: \"/aaa/bbb/ccc\", mod: (4, 4, 4) } }");
148+
97149
let err = write_file().unwrap_err();
98150
//println!("{err:?}");
99-
assert_eq!(format!("{err:?}"), "sabi::errs::Err { reason: errs_test::integration_tests_of_err::IoErrs NoPermission { path: \"/aaa/bbb/ccc\", mod: (6, 6, 6) } }");
151+
assert_eq!(format!("{err:?}"), "sabi::errs::Err { reason: errs_test::integration_tests_of_err::IoErrs DueToSomeError { path: \"/aaa/bbb/ccc\" } }");
100152
}
101153

102154
#[test]
@@ -105,13 +157,38 @@ mod integration_tests_of_err {
105157
//println!("{err}");
106158
assert_eq!(format!("{err}"), "FileNotFound { path: \"/aaa/bbb/ccc\" }");
107159

160+
let err = read_file().unwrap_err();
161+
//println!("{err}");
162+
assert_eq!(
163+
format!("{err}"),
164+
"NoPermission { path: \"/aaa/bbb/ccc\", mod: (4, 4, 4) }"
165+
);
166+
108167
let err = write_file().unwrap_err();
109168
//println!("{err}");
110169
assert_eq!(
111170
format!("{err}"),
112-
"NoPermission { path: \"/aaa/bbb/ccc\", mod: (6, 6, 6) }"
171+
"DueToSomeError { path: \"/aaa/bbb/ccc\" }"
113172
);
114173
}
174+
175+
#[test]
176+
fn should_get_source_of_err() {
177+
let err = find_file().unwrap_err();
178+
assert!(err.source().is_none());
179+
180+
let err = read_file().unwrap_err();
181+
assert!(err.source().is_none());
182+
183+
let err = write_file().unwrap_err();
184+
if let Some(source) = err.source() {
185+
let io_err = source.downcast_ref::<std::io::Error>().unwrap();
186+
assert_eq!(io_err.kind(), std::io::ErrorKind::AlreadyExists);
187+
assert_eq!(io_err.to_string(), "/aaa/bbb/ccc");
188+
} else {
189+
panic!();
190+
}
191+
}
115192
}
116193

117194
#[test]

0 commit comments

Comments
 (0)