55A error library that supports tracking the call-site location of errors. Also features an anyhow-style ` AnyError ` .
66
77``` rust
8- use n0_error :: {e, add_meta , StackError , Result , StackResultExt , StdResultExt };
8+ use n0_error :: {err, stack_error , StackError , Result , StackResultExt , StdResultExt };
99
10- // Adds a `meta` field to all variants to track call-site error location .
11- #[add_meta]
12- // Derives the various impls for our error.
13- #[derive(StackError )]
14- // Automatically create From impls from the error sources
15- #[error( from_sources)]
10+ /// The `stack_error` macro controls how to turn our enum into a `StackError` .
11+ ///
12+ /// * `add_meta` adds a field to all variants to track the call-site error location
13+ /// * `derive` adds ` #[derive(StackError)]`
14+ /// * `from_sources` creates ` From` impls for the error sources
15+ #[stack_error(derive, add_meta, from_sources)]
1616enum MyError {
17- // A custom validation error
18- #[error(" bad input: {count}" )]
17+ /// We can define the error message with the `error` attribute
18+ #[error(" bad input ( {count}) " )]
1919 BadInput { count : usize },
20- // Wrap a std::io::Error as a source (std error)
21- #[error(" IO error " )]
20+ /// Or we can define a variant as `transparent`, which forwards the Display impl to the error source
21+ #[error(transparent )]
2222 Io {
23+ /// For sources that do not implement `StackError`, we have to mark the source as `std_err`.
2324 #[error(std_err)]
2425 source : std :: io :: Error ,
2526 },
2627}
2728
28- // A function that returns a std io::Error
29+ // A function that returns a std:: io::Error
2930fn fail_io () -> std :: io :: Result <()> {
3031 Err (std :: io :: Error :: other (" io failed" ))
3132}
3233
3334// An outer function returning our custom MyError
3435fn some_fn (count : usize ) -> Result <(), MyError > {
3536 if count == 13 {
36- return Err (e! (MyError :: BadInput { count }));
37+ // The `err` macro constructs a `StackError` while automatically adding the `meta` field.
38+ return Err (err! (MyError :: BadInput { count }));
3739 }
38- // We have a From impl for std::io::Error on our error.
40+ // We have a ` From` impl for ` std::io::Error` on our error.
3941 fail_io ()? ;
4042 // Without the From impl, we'd need to forward the error manually.
41- // The `e ` macro can assist here, so that we don't have to declare the `meta` field manually.
42- fail_io (). map_err (| source | e ! (MyError :: Io , source ))? ;
43+ // The `err ` macro can assist here, so that we don't have to declare the `meta` field manually.
44+ fail_io (). map_err (| source | err ! (MyError :: Io , source ))? ;
4345 Ok (())
4446}
4547
@@ -54,27 +56,21 @@ fn run() -> Result<()> {
5456}
5557
5658fn main () -> Result <()> {
57- let res = run ();
58- if let Err (err ) = run () {
59- println! (" {err}" );
60- // This prints:
61- // Error: failed at some_fn
62- // Caused by:
63- // 0: bad input: 0
64- }
59+ let err = run (). unwrap_err ();
60+ assert_eq! (
61+ format! (" {err:#}" ),
62+ " failed at some_fn: bad input (13)"
63+ );
6564 Ok (())
6665}
6766
68- // You can also use the macros with tuple structs or enums.
69- // In this case the meta field will be added as the last field.
70-
71- #[add_meta]
72- #[derive(StackError )]
67+ /// You can also use the macros with tuple structs or enums.
68+ /// In this case the meta field will be added as the last field.
69+ #[stack_error(derive, add_meta)]
7370#[error(" tuple fail ({_0})" )]
7471struct TupleStruct (u32 );
7572
76- #[add_meta]
77- #[derive(StackError )]
73+ #[stack_error(derive, add_meta)]
7874enum TupleEnum {
7975 #[error(" io failed" )]
8076 Io (#[error(source, std_err)] std :: io :: Error ),
0 commit comments