resultit/
lib.rs

1//! 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.
2//! 
3//! Example:
4//! 
5//! ```
6//! # struct Error1;
7//! # impl std::fmt::Display for Error1 {
8//! # 	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9//! # 		write!(f, "Error1")
10//! # 	}
11//! # }
12//! # impl std::fmt::Debug for Error1 {
13//! # 	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14//! # 		<Error1 as std::fmt::Display>::fmt(self, f)
15//! # 	}
16//! # }
17//! # impl std::error::Error for Error1 { }
18//! #
19//! # struct Error2;
20//! # impl std::fmt::Display for Error2 {
21//! # 	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22//! # 		write!(f, "Error2")
23//! # 	}
24//! # }
25//! # impl std::fmt::Debug for Error2 {
26//! # 	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27//! # 		<Error2 as std::fmt::Display>::fmt(self, f)
28//! # 	}
29//! # }
30//! # impl std::error::Error for Error2 { }
31//! #
32//! // Use the flatten_results() and stop_after_error() iterator adapters.
33//! use resultit::FlattenResults;
34//! use resultit::StopAfterError;
35//!
36//! // Use the TryError convenience/shorthand type.
37//! use resultit::TryResult;
38//! 
39//! // Nested vector of results with different error types.
40//! let v: Vec<Result<Vec<Result<i32, Error2>>, Error1>> = vec![
41//! 	Ok(vec![Ok(1), Ok(2)]),
42//! 	Ok(vec![Ok(3), Ok(4)]),
43//! 	Ok(vec![Err(Error2{}), Ok(5)]),
44//! 	Ok(vec![Ok(6), Ok(7)])
45//! ];
46//! 
47//! // Flatten v, stopping after the first error.
48//! let v: Vec<TryResult<i32>> = v.into_iter()
49//! 	// Flatten the inner vectors.
50//! 	.flatten_results()
51//! 	// Flatten/erase error types by converting
52//! 	// Result<Result<i32, Error2>, Error1> to Result<i32, E>
53//! 	// where E is a boxed error trait object.
54//! 	.map(|res| -> TryResult<_> { Ok(res??) } )
55//! 	// Stop iterating after the first error is encountered.
56//! 	.stop_after_error()
57//! 	// Collect into vector v for this example.
58//! 	// Could just as easily have done try_for_each() or any other adapter.
59//! 	.collect();
60//!
61//! println!("{:?}", v);
62//! // [Ok(1), Ok(2), Ok(3), Ok(4), Err(Error2)]
63//! # assert_eq!(v.len(), 5);
64//! # assert_eq!(*v[0].as_ref().unwrap(), 1);
65//! # assert_eq!(*v[1].as_ref().unwrap(), 2);
66//! # assert_eq!(*v[2].as_ref().unwrap(), 3);
67//! # assert_eq!(*v[3].as_ref().unwrap(), 4);
68//! # assert_eq!(v[4].is_err(), true);
69//! #
70//! # // Additional testing embedded in rustdoc.
71//! # let v: Vec<Result<Vec<Result<i32, Error2>>, Error1>> = vec![
72//! # 	Ok(vec![Ok(1), Ok(2)]),
73//! # 	Ok(vec![Ok(3), Ok(4)]),
74//! # 	Err(Error1{}),
75//! # 	Ok(vec![Ok(5), Ok(6)])
76//! # ];
77//! # let v: Vec<TryResult<i32>> = v.into_iter()
78//! # 	.flatten_results()
79//! # 	.map(|res| -> TryResult<_> { Ok(res??) } )
80//! # 	.stop_after_error()
81//! # 	.collect();
82//! # println!("{:?}", v);
83//! # // [Ok(1), Ok(2), Ok(3), Ok(4), Err(Error1)]
84//! # assert_eq!(v.len(), 5);
85//! # assert_eq!(*v[0].as_ref().unwrap(), 1);
86//! # assert_eq!(*v[1].as_ref().unwrap(), 2);
87//! # assert_eq!(*v[2].as_ref().unwrap(), 3);
88//! # assert_eq!(*v[3].as_ref().unwrap(), 4);
89//! # assert_eq!(v[4].is_err(), true);
90//! #
91//! # let v: Vec<Result<Vec<Result<i32, Error2>>, Error1>> = vec![
92//! # 	Ok(vec![Ok(1), Ok(2)]),
93//! # 	Ok(vec![Ok(3), Ok(4)]),
94//! # 	Ok(vec![Ok(5), Err(Error2{})]),
95//! # 	Ok(vec![Ok(6), Ok(7)])
96//! # ];
97//! # let v: Vec<TryResult<i32>> = v.into_iter()
98//! # 	.flatten_results()
99//! # 	.map(|res| -> TryResult<_> { Ok(res??) } )
100//! # 	.stop_after_error()
101//! # 	.collect();
102//! # println!("{:?}", v);
103//! # // [Ok(1), Ok(2), Ok(3), Ok(4), Ok(5), Err(Error2)]
104//! # assert_eq!(v.len(), 6);
105//! # assert_eq!(*v[0].as_ref().unwrap(), 1);
106//! # assert_eq!(*v[1].as_ref().unwrap(), 2);
107//! # assert_eq!(*v[2].as_ref().unwrap(), 3);
108//! # assert_eq!(*v[3].as_ref().unwrap(), 4);
109//! # assert_eq!(*v[4].as_ref().unwrap(), 5);
110//! # assert_eq!(v[5].is_err(), true);
111//! ```
112
113// Re-export iterator adapter traits from submodules.
114pub mod flatten_results;
115pub use flatten_results::FlattenResults;
116pub mod stop_after_error;
117pub use stop_after_error::StopAfterError;
118
119/// Shorthand for a Result with a boxed error trait.
120/// Provided for convenience, not a dependency of any submodule.
121///
122/// Particularly useful for flattening iterators of nested results by
123/// flattening/combining/erasing the error types.  See the the
124/// [crate level documentation](crate) for an example of how to do this.  A
125/// simpler example of what this type does follows below:
126/// 
127/// ```
128/// // Trivial case in which we return just one error type.
129/// fn parse1(num: &str) -> Result<i32, <i32 as std::str::FromStr>::Err> {
130/// 	return num.parse();
131/// }
132///
133/// // What if our function can return more than one error type?
134/// // We can return a boxed error trait to erase the type of the error.
135/// // We can use then use the ? (aka try) operator to propagate errors.
136/// // For maximum compatibility with threaded programs,
137/// // the error should also implement send and sync.
138/// fn parse2(num: &str) -> Result<i32, std::boxed::Box<
139/// 	dyn std::error::Error
140/// 	+ std::marker::Send
141/// 	+ std::marker::Sync
142/// >> {
143/// 	// do_something_fallible()?;
144/// 	let parsed_num = (num.parse())?;
145///		return Ok(parsed_num);
146/// }
147/// 
148/// // Same as parse2() but using TryResult<i32> as shorthand.
149/// fn parse3(num: &str) -> resultit::TryResult<i32> {
150/// 	// do_something_fallible()?;
151/// 	let parsed_num = (num.parse())?;
152///		return Ok(parsed_num);
153/// }
154/// # assert_eq!(parse1("42").unwrap(), 42);
155/// # assert_eq!(parse2("42").unwrap(), 42);
156/// # assert_eq!(parse3("42").unwrap(), 42);
157/// ```
158pub type TryResult<T> = std::result::Result<
159	T,
160	std::boxed::Box< dyn
161		std::error::Error   // must implement Error to satisfy Try
162		+ std::marker::Send // needed to move errors between threads
163		+ std::marker::Sync // needed to move errors between threads
164	>
165>;