-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove ValidationErrors type, generalize error utils
Summary: Per offline discussion w kassens this changes the `try_*` error utilities to deal with `Vec<E>` (where each instance can have a different error type) instead of the more narrow `ValidationErrors` type. This makes it possible to use the error utilities with lists of syntax or other error types. Reviewed By: kassens Differential Revision: D19958009 fbshipit-source-id: 639d5a4bea0a494feadbc6c9016a411e342ea8a3
- Loading branch information
1 parent
006be0a
commit 5d733bc
Showing
13 changed files
with
210 additions
and
255 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[project] | ||
name = "errors" | ||
version = "0.0.0" | ||
edition = "2018" | ||
|
||
[dependencies] | ||
rayon = "1.3.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
use rayon::prelude::*; | ||
|
||
// Helpers for unwrapping multiple Results to aggregate all success values or all error values. | ||
|
||
pub fn try2<T1, T2, E>(t1: Result<T1, Vec<E>>, t2: Result<T2, Vec<E>>) -> Result<(T1, T2), Vec<E>> { | ||
match (t1, t2) { | ||
(Ok(t1), Ok(t2)) => Ok((t1, t2)), | ||
(Ok(_), Err(errors)) => Err(errors), | ||
(Err(errors), Ok(_)) => Err(errors), | ||
(Err(mut errors1), Err(errors2)) => { | ||
errors1.extend(errors2); | ||
Err(errors1) | ||
} | ||
} | ||
} | ||
|
||
pub fn try3<T1, T2, T3, E>( | ||
t1: Result<T1, Vec<E>>, | ||
t2: Result<T2, Vec<E>>, | ||
t3: Result<T3, Vec<E>>, | ||
) -> Result<(T1, T2, T3), Vec<E>> { | ||
let mut errors = Vec::new(); | ||
let t1 = match t1 { | ||
Ok(t1) => Some(t1), | ||
Err(e) => { | ||
errors.extend(e); | ||
None | ||
} | ||
}; | ||
let t2 = match t2 { | ||
Ok(t2) => Some(t2), | ||
Err(e) => { | ||
errors.extend(e); | ||
None | ||
} | ||
}; | ||
let t3 = match t3 { | ||
Ok(t3) => Some(t3), | ||
Err(e) => { | ||
errors.extend(e); | ||
None | ||
} | ||
}; | ||
if !errors.is_empty() { | ||
Err(errors) | ||
} else { | ||
Ok((t1.unwrap(), t2.unwrap(), t3.unwrap())) | ||
} | ||
} | ||
|
||
pub fn try4<T1, T2, T3, T4, E>( | ||
t1: Result<T1, Vec<E>>, | ||
t2: Result<T2, Vec<E>>, | ||
t3: Result<T3, Vec<E>>, | ||
t4: Result<T4, Vec<E>>, | ||
) -> Result<(T1, T2, T3, T4), Vec<E>> { | ||
let mut errors = Vec::new(); | ||
let t1 = match t1 { | ||
Ok(t1) => Some(t1), | ||
Err(e) => { | ||
errors.extend(e); | ||
None | ||
} | ||
}; | ||
let t2 = match t2 { | ||
Ok(t2) => Some(t2), | ||
Err(e) => { | ||
errors.extend(e); | ||
None | ||
} | ||
}; | ||
let t3 = match t3 { | ||
Ok(t3) => Some(t3), | ||
Err(e) => { | ||
errors.extend(e); | ||
None | ||
} | ||
}; | ||
let t4 = match t4 { | ||
Ok(t4) => Some(t4), | ||
Err(e) => { | ||
errors.extend(e); | ||
None | ||
} | ||
}; | ||
if !errors.is_empty() { | ||
Err(errors) | ||
} else { | ||
Ok((t1.unwrap(), t2.unwrap(), t3.unwrap(), t4.unwrap())) | ||
} | ||
} | ||
|
||
/// Given an iterable of Result values, returns all the success values if all items are | ||
/// `Ok` or all the error values if one or more items were `Err`. | ||
pub fn try_all<T, E, I>(items: I) -> Result<Vec<T>, Vec<E>> | ||
where | ||
I: IntoIterator<Item = Result<T, Vec<E>>>, | ||
{ | ||
try_map(items, |x| x) | ||
} | ||
|
||
/// Transforms the items of a list with a fallible transform function, returning either | ||
/// all the transformed values if all items succeeded or a list of all errors if one or | ||
/// more items could not be tansformed. | ||
pub fn try_map<T, E, U, I, F>(items: I, mut f: F) -> Result<Vec<T>, Vec<E>> | ||
where | ||
I: IntoIterator<Item = U>, | ||
F: FnMut(U) -> Result<T, Vec<E>>, | ||
{ | ||
let iter = items.into_iter(); | ||
let mut errors = Vec::new(); | ||
let mut values = Vec::with_capacity(iter.size_hint().1.unwrap_or_default()); | ||
for item in iter { | ||
match f(item) { | ||
Ok(item_value) => values.push(item_value), | ||
Err(item_errors) => errors.extend(item_errors), | ||
} | ||
} | ||
if errors.is_empty() { | ||
Ok(values) | ||
} else { | ||
Err(errors) | ||
} | ||
} | ||
|
||
/// Similar to `try_map` but performs the transform in parallel. | ||
pub fn par_try_map<T: Sync + Send, E: Sync + Send, U: Sync + Send, I, F: Sync + Send>( | ||
items: I, | ||
f: F, | ||
) -> Result<Vec<T>, Vec<E>> | ||
where | ||
I: IntoParallelIterator<Item = U>, | ||
F: Fn(U) -> Result<T, Vec<E>>, | ||
{ | ||
let results: Vec<Result<T, Vec<E>>> = items.into_par_iter().map(f).collect(); | ||
let mut errors = Vec::new(); | ||
let mut values = Vec::with_capacity(results.len()); | ||
for result in results { | ||
match result { | ||
Ok(item_value) => values.push(item_value), | ||
Err(item_errors) => errors.extend(item_errors), | ||
} | ||
} | ||
if errors.is_empty() { | ||
Ok(values) | ||
} else { | ||
Err(errors) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
mod error_combinators; | ||
|
||
pub use error_combinators::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.