1pub fn zip<A, B, E>(result1: Result<A, E>, result2: Result<B, E>) -> Result<(A, B), E> {
7 result1.and_then(|a| result2.map(|b| (a, b)))
8}
9
10pub fn zip_with<A, B, Z, E, F>(
13 result1: Result<A, E>,
14 result2: Result<B, E>,
15 transform: F,
16) -> Result<Z, E>
17where
18 F: FnOnce(A, B) -> Z,
19{
20 zip(result1, result2).map(|(a, b)| transform(a, b))
21}
22
23pub fn zip3<A, B, C, E>(
25 result1: Result<A, E>,
26 result2: Result<B, E>,
27 result3: Result<C, E>,
28) -> Result<(A, B, C), E> {
29 result1.and_then(|a| result2.and_then(|b| result3.map(|c| (a, b, c))))
30}
31
32pub fn zip3_with<A, B, C, Z, E, F>(
34 result1: Result<A, E>,
35 result2: Result<B, E>,
36 result3: Result<C, E>,
37 transform: F,
38) -> Result<Z, E>
39where
40 F: FnOnce(A, B, C) -> Z,
41{
42 zip3(result1, result2, result3).map(|(a, b, c)| transform(a, b, c))
43}
44
45pub fn zip4<A, B, C, D, E>(
47 result1: Result<A, E>,
48 result2: Result<B, E>,
49 result3: Result<C, E>,
50 result4: Result<D, E>,
51) -> Result<(A, B, C, D), E> {
52 result1.and_then(|a| result2.and_then(|b| result3.and_then(|c| result4.map(|d| (a, b, c, d)))))
53}
54
55pub fn zip4_with<A, B, C, D, Z, E, F>(
57 result1: Result<A, E>,
58 result2: Result<B, E>,
59 result3: Result<C, E>,
60 result4: Result<D, E>,
61 transform: F,
62) -> Result<Z, E>
63where
64 F: FnOnce(A, B, C, D) -> Z,
65{
66 zip4(result1, result2, result3, result4).map(|(a, b, c, d)| transform(a, b, c, d))
67}
68
69pub fn sequence<A, E>(results: Vec<Result<A, E>>) -> Result<Vec<A>, E> {
72 let mut values = Vec::with_capacity(results.len());
73 for result in results {
74 values.push(result?);
75 }
76 Ok(values)
77}
78
79pub fn flat_map<A, B, E, F>(result: Result<A, E>, transform: F) -> Result<B, E>
82where
83 F: FnOnce(A) -> Result<B, E>,
84{
85 result.and_then(transform)
86}
87
88pub fn map<A, B, E, F>(result: Result<A, E>, transform: F) -> Result<B, E>
91where
92 F: FnOnce(A) -> B,
93{
94 result.map(transform)
95}
96
97pub fn map_error<A, E, F, G>(result: Result<A, E>, transform: F) -> Result<A, F>
100where
101 F: FnOnce(E) -> F,
102{
103 result.map_err(transform)
104}
105
106pub fn get_or_else<A, E, F>(result: Result<A, E>, default: F) -> A
109where
110 F: FnOnce() -> A,
111{
112 result.unwrap_or_else(|_| default())
113}
114
115pub fn get_or_default<A, E>(result: Result<A, E>) -> A
117where
118 A: Default,
119{
120 result.unwrap_or_default()
121}
122
123pub fn from_option<A, E>(option: Option<A>, error: E) -> Result<A, E> {
125 option.ok_or(error)
126}
127
128pub fn to_option<A, E>(result: Result<A, E>) -> Option<A> {
130 result.ok()
131}
132
133pub fn or<A, E>(result1: Result<A, E>, result2: Result<A, E>) -> Result<A, E> {
135 match result1 {
136 Ok(value) => Ok(value),
137 Err(_) => result2,
138 }
139}
140
141pub fn or_else<A, E, F>(result: Result<A, E>, fallback: F) -> Result<A, E>
143where
144 F: FnOnce() -> Result<A, E>,
145{
146 match result {
147 Ok(value) => Ok(value),
148 Err(_) => fallback(),
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155
156 #[test]
157 fn test_zip() {
158 let result1: Result<i32, &str> = Ok(5);
159 let result2: Result<String, &str> = Ok("hello".to_string());
160
161 let zipped = zip(result1, result2);
162 assert_eq!(zipped, Ok((5, "hello".to_string())));
163
164 let error_result: Result<i32, &str> = Err("error");
165 let zipped_error = zip(error_result, result2);
166 assert_eq!(zipped_error, Err("error"));
167 }
168
169 #[test]
170 fn test_zip_with() {
171 let result1: Result<i32, &str> = Ok(5);
172 let result2: Result<i32, &str> = Ok(3);
173
174 let zipped = zip_with(result1, result2, |a, b| a + b);
175 assert_eq!(zipped, Ok(8));
176 }
177
178 #[test]
179 fn test_zip3() {
180 let result1: Result<i32, &str> = Ok(1);
181 let result2: Result<i32, &str> = Ok(2);
182 let result3: Result<i32, &str> = Ok(3);
183
184 let zipped = zip3(result1, result2, result3);
185 assert_eq!(zipped, Ok((1, 2, 3)));
186 }
187
188 #[test]
189 fn test_zip3_with() {
190 let result1: Result<i32, &str> = Ok(1);
191 let result2: Result<i32, &str> = Ok(2);
192 let result3: Result<i32, &str> = Ok(3);
193
194 let zipped = zip3_with(result1, result2, result3, |a, b, c| a + b + c);
195 assert_eq!(zipped, Ok(6));
196 }
197
198 #[test]
199 fn test_sequence() {
200 let results = vec![Ok(1), Ok(2), Ok(3)];
201 let sequenced = sequence(results);
202 assert_eq!(sequenced, Ok(vec![1, 2, 3]));
203
204 let error_results = vec![Ok(1), Err("error"), Ok(3)];
205 let sequenced_error = sequence(error_results);
206 assert_eq!(sequenced_error, Err("error"));
207 }
208
209 #[test]
210 fn test_flat_map() {
211 let result: Result<i32, &str> = Ok(5);
212 let mapped = flat_map(result, |x| Ok(x * 2));
213 assert_eq!(mapped, Ok(10));
214
215 let error_result: Result<i32, &str> = Err("error");
216 let mapped_error = flat_map(error_result, |x| Ok(x * 2));
217 assert_eq!(mapped_error, Err("error"));
218 }
219
220 #[test]
221 fn test_map() {
222 let result: Result<i32, &str> = Ok(5);
223 let mapped = map(result, |x| x * 2);
224 assert_eq!(mapped, Ok(10));
225 }
226
227 #[test]
228 fn test_map_error() {
229 let result: Result<i32, &str> = Err("error");
230 let mapped = map_error(result, |e| format!("Error: {}", e));
231 assert_eq!(mapped, Err("Error: error".to_string()));
232 }
233
234 #[test]
235 fn test_get_or_else() {
236 let result: Result<i32, &str> = Ok(5);
237 let value = get_or_else(result, || 0);
238 assert_eq!(value, 5);
239
240 let error_result: Result<i32, &str> = Err("error");
241 let value_error = get_or_else(error_result, || 0);
242 assert_eq!(value_error, 0);
243 }
244
245 #[test]
246 fn test_from_option() {
247 let some_option = Some(5);
248 let result = from_option(some_option, "error");
249 assert_eq!(result, Ok(5));
250
251 let none_option: Option<i32> = None;
252 let result_none = from_option(none_option, "error");
253 assert_eq!(result_none, Err("error"));
254 }
255
256 #[test]
257 fn test_to_option() {
258 let result: Result<i32, &str> = Ok(5);
259 let option = to_option(result);
260 assert_eq!(option, Some(5));
261
262 let error_result: Result<i32, &str> = Err("error");
263 let option_error = to_option(error_result);
264 assert_eq!(option_error, None);
265 }
266
267 #[test]
268 fn test_or() {
269 let result1: Result<i32, &str> = Ok(5);
270 let result2: Result<i32, &str> = Ok(10);
271 let combined = or(result1, result2);
272 assert_eq!(combined, Ok(5));
273
274 let error_result1: Result<i32, &str> = Err("error1");
275 let result2: Result<i32, &str> = Ok(10);
276 let combined_error = or(error_result1, result2);
277 assert_eq!(combined_error, Ok(10));
278 }
279
280 #[test]
281 fn test_or_else() {
282 let result: Result<i32, &str> = Ok(5);
283 let fallback = or_else(result, || Ok(10));
284 assert_eq!(fallback, Ok(5));
285
286 let error_result: Result<i32, &str> = Err("error");
287 let fallback_error = or_else(error_result, || Ok(10));
288 assert_eq!(fallback_error, Ok(10));
289 }
290}