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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
//! Rust iterators return `Option<Item>`, but what happens if `Item` is a `Result` that could possibly be `Err`? This crate supplies iterator adapters to simplify working with so-called "fallible" iterators. The supplied adapters are independent of each other; you can use the whole crate with `use resultit::*;` or just the iterator adapter traits you want with (for instance) `use resultit::FlattenResults`. You are also free to take individual files (e.g. flatten_results.rs) and use them in your own source tree without depending on this crate. //! //! Example: //! //! ``` //! # struct Error1; //! # impl std::fmt::Display for Error1 { //! # fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { //! # write!(f, "Error1") //! # } //! # } //! # impl std::fmt::Debug for Error1 { //! # fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { //! # <Error1 as std::fmt::Display>::fmt(self, f) //! # } //! # } //! # impl std::error::Error for Error1 { } //! # //! # struct Error2; //! # impl std::fmt::Display for Error2 { //! # fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { //! # write!(f, "Error2") //! # } //! # } //! # impl std::fmt::Debug for Error2 { //! # fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { //! # <Error2 as std::fmt::Display>::fmt(self, f) //! # } //! # } //! # impl std::error::Error for Error2 { } //! # //! // Use the flatten_results() and stop_after_error() iterator adapters. //! use resultit::FlattenResults; //! use resultit::StopAfterError; //! //! // Use the TryError convenience/shorthand type. //! use resultit::TryResult; //! //! // Nested vector of results with different error types. //! let v: Vec<Result<Vec<Result<i32, Error2>>, Error1>> = vec![ //! Ok(vec![Ok(1), Ok(2)]), //! Ok(vec![Ok(3), Ok(4)]), //! Ok(vec![Err(Error2{}), Ok(5)]), //! Ok(vec![Ok(6), Ok(7)]) //! ]; //! //! // Flatten v, stopping after the first error. //! let v: Vec<TryResult<i32>> = v.into_iter() //! // Flatten the inner vectors. //! .flatten_results() //! // Flatten/erase error types by converting //! // Result<Result<i32, Error2>, Error1> to Result<i32, E> //! // where E is a boxed error trait object. //! .map(|res| -> TryResult<_> { Ok(res??) } ) //! // Stop iterating after the first error is encountered. //! .stop_after_error() //! // Collect into vector v for this example. //! // Could just as easily have done try_for_each() or any other adapter. //! .collect(); //! //! println!("{:?}", v); //! // [Ok(1), Ok(2), Ok(3), Ok(4), Err(Error2)] //! # assert_eq!(v.len(), 5); //! # assert_eq!(*v[0].as_ref().unwrap(), 1); //! # assert_eq!(*v[1].as_ref().unwrap(), 2); //! # assert_eq!(*v[2].as_ref().unwrap(), 3); //! # assert_eq!(*v[3].as_ref().unwrap(), 4); //! # assert_eq!(v[4].is_err(), true); //! # //! # // Additional testing embedded in rustdoc. //! # let v: Vec<Result<Vec<Result<i32, Error2>>, Error1>> = vec![ //! # Ok(vec![Ok(1), Ok(2)]), //! # Ok(vec![Ok(3), Ok(4)]), //! # Err(Error1{}), //! # Ok(vec![Ok(5), Ok(6)]) //! # ]; //! # let v: Vec<TryResult<i32>> = v.into_iter() //! # .flatten_results() //! # .map(|res| -> TryResult<_> { Ok(res??) } ) //! # .stop_after_error() //! # .collect(); //! # println!("{:?}", v); //! # // [Ok(1), Ok(2), Ok(3), Ok(4), Err(Error1)] //! # assert_eq!(v.len(), 5); //! # assert_eq!(*v[0].as_ref().unwrap(), 1); //! # assert_eq!(*v[1].as_ref().unwrap(), 2); //! # assert_eq!(*v[2].as_ref().unwrap(), 3); //! # assert_eq!(*v[3].as_ref().unwrap(), 4); //! # assert_eq!(v[4].is_err(), true); //! # //! # let v: Vec<Result<Vec<Result<i32, Error2>>, Error1>> = vec![ //! # Ok(vec![Ok(1), Ok(2)]), //! # Ok(vec![Ok(3), Ok(4)]), //! # Ok(vec![Ok(5), Err(Error2{})]), //! # Ok(vec![Ok(6), Ok(7)]) //! # ]; //! # let v: Vec<TryResult<i32>> = v.into_iter() //! # .flatten_results() //! # .map(|res| -> TryResult<_> { Ok(res??) } ) //! # .stop_after_error() //! # .collect(); //! # println!("{:?}", v); //! # // [Ok(1), Ok(2), Ok(3), Ok(4), Ok(5), Err(Error2)] //! # assert_eq!(v.len(), 6); //! # assert_eq!(*v[0].as_ref().unwrap(), 1); //! # assert_eq!(*v[1].as_ref().unwrap(), 2); //! # assert_eq!(*v[2].as_ref().unwrap(), 3); //! # assert_eq!(*v[3].as_ref().unwrap(), 4); //! # assert_eq!(*v[4].as_ref().unwrap(), 5); //! # assert_eq!(v[5].is_err(), true); //! ``` // Re-export iterator adapter traits from submodules. pub mod flatten_results; pub use flatten_results::FlattenResults; pub mod stop_after_error; pub use stop_after_error::StopAfterError; /// Shorthand for a Result with a boxed error trait. /// Provided for convenience, not a dependency of any submodule. /// /// Particularly useful for flattening iterators of nested results by /// flattening/combining/erasing the error types. See the the /// [crate level documentation](crate) for an example of how to do this. A /// simpler example of what this type does follows below: /// /// ``` /// // Trivial case in which we return just one error type. /// fn parse1(num: &str) -> Result<i32, <i32 as std::str::FromStr>::Err> { /// return num.parse(); /// } /// /// // What if our function can return more than one error type? /// // We can return a boxed error trait to erase the type of the error. /// // We can use then use the ? (aka try) operator to propagate errors. /// // For maximum compatibility with threaded programs, /// // the error should also implement send and sync. /// fn parse2(num: &str) -> Result<i32, std::boxed::Box< /// dyn std::error::Error /// + std::marker::Send /// + std::marker::Sync /// >> { /// // do_something_fallible()?; /// let parsed_num = (num.parse())?; /// return Ok(parsed_num); /// } /// /// // Same as parse2() but using TryResult<i32> as shorthand. /// fn parse3(num: &str) -> resultit::TryResult<i32> { /// // do_something_fallible()?; /// let parsed_num = (num.parse())?; /// return Ok(parsed_num); /// } /// # assert_eq!(parse1("42").unwrap(), 42); /// # assert_eq!(parse2("42").unwrap(), 42); /// # assert_eq!(parse3("42").unwrap(), 42); /// ``` pub type TryResult<T> = std::result::Result< T, std::boxed::Box< dyn std::error::Error // must implement Error to satisfy Try + std::marker::Send // needed to move errors between threads + std::marker::Sync // needed to move errors between threads > >;