pub enum Validation<E, A> {
Valid(A),
Invalid(Accumulator<E>),
}Expand description
Applicative-style validation that accumulates many errors instead of failing fast.
Validation<E, A> represents a computation that either succeeds with a value of type A
or fails with one or more errors of type E. Unlike Result, which fails fast on the first
error, Validation accumulates all errors, making it ideal for form validation and other
scenarios where you want to collect all problems at once.
§Serde Support
Validation implements Serialize and Deserialize when E and A do.
This makes it easy to use in API responses or configuration files.
§Type Parameters
E- The error typeA- The success value type
§Variants
Valid(A)- Contains a successful valueInvalid(Accumulator<E>)- Contains one or more accumulated errors
§Examples
use error_rail::validation::Validation;
let valid = Validation::<&str, i32>::valid(42);
assert!(valid.is_valid());
let invalid = Validation::<&str, i32>::invalid("error");
assert!(invalid.is_invalid());Variants§
Valid(A)
Invalid(Accumulator<E>)
Implementations§
Source§impl<E, A> Validation<E, A>
impl<E, A> Validation<E, A>
Sourcepub fn invalid_many<I>(errors: I) -> Selfwhere
I: IntoIterator<Item = E>,
pub fn invalid_many<I>(errors: I) -> Selfwhere
I: IntoIterator<Item = E>,
Sourcepub fn is_valid(&self) -> bool
pub fn is_valid(&self) -> bool
Returns true if the validation contains a value.
§Examples
use error_rail::validation::Validation;
let v = Validation::<&str, i32>::valid(42);
assert!(v.is_valid());Sourcepub fn is_invalid(&self) -> bool
pub fn is_invalid(&self) -> bool
Returns true if the validation contains errors.
§Examples
use error_rail::validation::Validation;
let v = Validation::<&str, i32>::invalid("error");
assert!(v.is_invalid());Sourcepub fn map<B, F>(self, f: F) -> Validation<E, B>where
F: FnOnce(A) -> B,
pub fn map<B, F>(self, f: F) -> Validation<E, B>where
F: FnOnce(A) -> B,
Maps the valid value using the provided function.
If the validation is invalid, the errors are preserved unchanged.
§Arguments
f- A function that transforms the success value from typeAto typeB
§Examples
use error_rail::validation::Validation;
let v = Validation::<&str, i32>::valid(21);
let doubled = v.map(|x| x * 2);
assert_eq!(doubled.into_value(), Some(42));Sourcepub fn and_then<B, F>(self, f: F) -> Validation<E, B>where
F: FnOnce(A) -> Validation<E, B>,
pub fn and_then<B, F>(self, f: F) -> Validation<E, B>where
F: FnOnce(A) -> Validation<E, B>,
Chains computations that may produce additional validation errors.
Behaves like Result::and_then, propagating invalid states while
invoking f only when the current validation is valid.
§Arguments
f- Function producing the next validation step
§Examples
use error_rail::validation::Validation;
fn parse_even(input: i32) -> Validation<&'static str, i32> {
if input % 2 == 0 {
Validation::valid(input)
} else {
Validation::invalid("not even")
}
}
let result = Validation::valid(4).and_then(parse_even);
assert_eq!(result.into_value(), Some(4));
let invalid = Validation::valid(3).and_then(parse_even);
assert!(invalid.is_invalid());Sourcepub fn or_else<F>(self, op: F) -> Validation<E, A>
pub fn or_else<F>(self, op: F) -> Validation<E, A>
Calls op if the validation is invalid, otherwise returns the Valid value.
This function can be used for control flow based on validation results.
§Arguments
op- The function to call if the validation is invalid.
§Examples
use error_rail::validation::Validation;
let v = Validation::<&str, i32>::invalid("error");
let res = v.or_else(|_errs| Validation::valid(42));
assert_eq!(res.into_value(), Some(42));Sourcepub fn zip<B>(self, other: Validation<E, B>) -> Validation<E, (A, B)>
pub fn zip<B>(self, other: Validation<E, B>) -> Validation<E, (A, B)>
Combines two validations into a tuple, accumulating all errors.
If both validations are valid, returns a tuple of both values. If either or both are invalid, accumulates all errors from both.
§Arguments
other- Another validation to combine with this one
§Examples
use error_rail::validation::Validation;
let v1 = Validation::<&str, i32>::valid(42);
let v2 = Validation::<&str, i32>::valid(21);
let result = v1.zip(v2);
assert_eq!(result.into_value(), Some((42, 21)));
let v3 = Validation::<&str, i32>::invalid("error1");
let v4 = Validation::<&str, i32>::invalid("error2");
let result = v3.zip(v4);
assert_eq!(result.into_errors().unwrap().len(), 2);Sourcepub fn map_err<F, G>(self, f: F) -> Validation<G, A>where
F: Fn(E) -> G,
pub fn map_err<F, G>(self, f: F) -> Validation<G, A>where
F: Fn(E) -> G,
Maps each error while preserving the success branch.
Transforms all accumulated errors using the provided function, leaving valid values unchanged.
§Arguments
f- A function that transforms errors from typeEto typeG
§Examples
use error_rail::validation::Validation;
let v = Validation::<&str, i32>::invalid("error");
let mapped = v.map_err(|e| format!("Error: {}", e));
assert!(mapped.is_invalid());Sourcepub fn to_result(self) -> Result<A, ErrorVec<E>>
pub fn to_result(self) -> Result<A, ErrorVec<E>>
Converts into a Result, losing error accumulation if invalid.
The success value becomes Ok, and all accumulated errors become Err.
§Examples
use error_rail::validation::Validation;
let v = Validation::<&str, i32>::valid(42);
assert_eq!(v.to_result(), Ok(42));
let v = Validation::<&str, i32>::invalid("error");
assert!(v.to_result().is_err());Sourcepub fn from_result(result: Result<A, E>) -> Self
pub fn from_result(result: Result<A, E>) -> Self
Sourcepub fn into_errors(self) -> Option<ErrorVec<E>>
pub fn into_errors(self) -> Option<ErrorVec<E>>
Extracts the error list, if any.
Returns Some(errors) if invalid, None if valid.
§Examples
use error_rail::validation::Validation;
let v = Validation::<&str, i32>::invalid("error");
assert_eq!(v.into_errors().unwrap().len(), 1);Sourcepub fn into_value(self) -> Option<A>
pub fn into_value(self) -> Option<A>
Extracts the value, if valid.
Returns Some(value) if valid, None if invalid.
§Examples
use error_rail::validation::Validation;
let v = Validation::<&str, i32>::valid(42);
assert_eq!(v.into_value(), Some(42));Source§impl<E, A> Validation<E, A>
impl<E, A> Validation<E, A>
Sourcepub fn iter(&self) -> Iter<'_, A> ⓘ
pub fn iter(&self) -> Iter<'_, A> ⓘ
Returns an iterator over the valid value.
The iterator yields at most one item - the valid value if present. For invalid validations, the iterator yields nothing.
§Examples
use error_rail::validation::Validation;
let valid: Validation<String, i32> = Validation::Valid(5);
assert_eq!(valid.iter().next(), Some(&5));
let invalid: Validation<String, i32> = Validation::invalid("error".to_string());
assert_eq!(invalid.iter().next(), None);Sourcepub fn iter_mut(&mut self) -> IterMut<'_, A> ⓘ
pub fn iter_mut(&mut self) -> IterMut<'_, A> ⓘ
Returns a mutable iterator over the valid value.
The iterator yields at most one mutable reference - to the valid value if present. For invalid validations, the iterator yields nothing.
§Examples
use error_rail::validation::Validation;
let mut valid: Validation<String, i32> = Validation::Valid(5);
if let Some(value) = valid.iter_mut().next() {
*value = 10;
}
assert_eq!(valid, Validation::Valid(10));Sourcepub fn iter_errors(&self) -> ErrorsIter<'_, E> ⓘ
pub fn iter_errors(&self) -> ErrorsIter<'_, E> ⓘ
Returns an iterator over the errors.
For invalid validations, yields references to all accumulated errors. For valid validations, yields nothing.
§Examples
use error_rail::validation::Validation;
let valid: Validation<String, i32> = Validation::Valid(5);
assert_eq!(valid.iter_errors().next(), None);
let invalid: Validation<String, i32> = Validation::invalid("error".to_string());
assert_eq!(invalid.iter_errors().next(), Some(&"error".to_string()));
let multi_invalid: Validation<&str, i32> = Validation::invalid_many(["err1", "err2"]);
assert_eq!(multi_invalid.iter_errors().count(), 2);Sourcepub fn iter_errors_mut(&mut self) -> ErrorsIterMut<'_, E> ⓘ
pub fn iter_errors_mut(&mut self) -> ErrorsIterMut<'_, E> ⓘ
Returns a mutable iterator over the errors.
For invalid validations, yields mutable references to all accumulated errors. For valid validations, yields nothing.
§Examples
use error_rail::validation::Validation;
let mut invalid: Validation<String, i32> = Validation::invalid("error".to_string());
for error in invalid.iter_errors_mut() {
error.push_str(" [updated]");
}
assert_eq!(
invalid.iter_errors().next(),
Some(&"error [updated]".to_string())
);Trait Implementations§
Source§impl<E: Clone, A: Clone> Clone for Validation<E, A>
impl<E: Clone, A: Clone> Clone for Validation<E, A>
Source§fn clone(&self) -> Validation<E, A>
fn clone(&self) -> Validation<E, A>
1.0.0§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<'de, E, A> Deserialize<'de> for Validation<E, A>where
E: Deserialize<'de>,
A: Deserialize<'de>,
impl<'de, E, A> Deserialize<'de> for Validation<E, A>where
E: Deserialize<'de>,
A: Deserialize<'de>,
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl<E> ErrorCategory<E> for Validation<E, ()>
Implementation of ErrorCategory for Validation types.
impl<E> ErrorCategory<E> for Validation<E, ()>
Implementation of ErrorCategory for Validation types.
This allows Validation<E, ()> to act as an error category, where:
liftcreatesValidvalueshandle_errorcreatesInvalidvalues with a single error
§Examples
use error_rail::traits::ErrorCategory;
use error_rail::validation::Validation;
let valid: Validation<String, i32> = <Validation<String, ()>>::lift(42);
assert!(valid.is_valid());
let invalid: Validation<String, i32> = <Validation<String, ()>>::handle_error("error".to_string());
assert!(invalid.is_invalid());Source§type ErrorFunctor<T> = Validation<E, T>
type ErrorFunctor<T> = Validation<E, T>
T.Source§fn lift<T>(value: T) -> Validation<E, T>
fn lift<T>(value: T) -> Validation<E, T>
Source§fn handle_error<T>(error: E) -> Validation<E, T>
fn handle_error<T>(error: E) -> Validation<E, T>
Source§impl<E, A, C> FromIterator<Result<A, E>> for Validation<E, C>where
C: FromIterator<A>,
Collects an iterator of Results into a single Validation, aggregating all errors.
impl<E, A, C> FromIterator<Result<A, E>> for Validation<E, C>where
C: FromIterator<A>,
Collects an iterator of Results into a single Validation, aggregating all errors.
If all results are Ok, returns Valid with a collection of all success values.
If any results are Err, returns Invalid with all accumulated errors.
This is useful for validating multiple operations and collecting all failures instead of short-circuiting on the first error.
§Examples
use error_rail::validation::Validation;
let inputs = vec![Ok(1), Err("oops"), Ok(2)];
let collected: Validation<&str, Vec<i32>> = inputs.into_iter().collect();
assert!(collected.is_invalid());
assert_eq!(collected.into_errors().unwrap()[0], "oops");
let all_ok = vec![Ok(1), Ok(2), Ok(3)];
let collected: Validation<&str, Vec<i32>> = all_ok.into_iter().collect();
assert_eq!(collected, Validation::Valid(vec![1, 2, 3]));Source§impl<E, A, C> FromIterator<Validation<E, A>> for Validation<E, C>where
C: FromIterator<A>,
Collects an iterator of Validations into a single Validation, aggregating all errors.
impl<E, A, C> FromIterator<Validation<E, A>> for Validation<E, C>where
C: FromIterator<A>,
Collects an iterator of Validations into a single Validation, aggregating all errors.
If all validations are valid, returns Valid with a collection of all success values.
If any validations are invalid, returns Invalid with all accumulated errors from all
invalid validations.
This is the primary way to combine multiple validations while preserving all error information.
§Examples
use error_rail::validation::Validation;
let items = vec![Validation::valid(1), Validation::invalid("bad")];
let collected: Validation<&str, Vec<i32>> = items.into_iter().collect();
assert!(collected.is_invalid());Source§fn from_iter<T: IntoIterator<Item = Validation<E, A>>>(iter: T) -> Self
fn from_iter<T: IntoIterator<Item = Validation<E, A>>>(iter: T) -> Self
Source§impl<'a, E, A> IntoIterator for &'a Validation<E, A>
Converts a reference to a Validation into an iterator.
impl<'a, E, A> IntoIterator for &'a Validation<E, A>
Converts a reference to a Validation into an iterator.
This allows for convenient iteration over the valid value without consuming the validation.
§Examples
use error_rail::validation::Validation;
let valid: Validation<String, i32> = Validation::Valid(5);
for value in &valid {
assert_eq!(value, &5);
}
// valid is still usable hereSource§impl<'a, E, A> IntoIterator for &'a mut Validation<E, A>
Converts a mutable reference to a Validation into an iterator.
impl<'a, E, A> IntoIterator for &'a mut Validation<E, A>
Converts a mutable reference to a Validation into an iterator.
This allows for convenient mutable iteration over the valid value without consuming the validation.
§Examples
use error_rail::validation::Validation;
let mut valid: Validation<String, i32> = Validation::Valid(5);
for value in &mut valid {
*value *= 2;
}
assert_eq!(valid, Validation::Valid(10));Source§impl<E, A> IntoIterator for Validation<E, A>
Converts a Validation into an iterator over its valid value.
impl<E, A> IntoIterator for Validation<E, A>
Converts a Validation into an iterator over its valid value.
This consumes the validation and yields at most one item.
§Examples
use error_rail::validation::Validation;
let valid: Validation<String, i32> = Validation::Valid(42);
let values: Vec<_> = valid.into_iter().collect();
assert_eq!(values, vec![42]);
let invalid: Validation<String, i32> = Validation::invalid("error".to_string());
let values: Vec<_> = invalid.into_iter().collect();
assert!(values.is_empty());Source§impl<E: Ord, A: Ord> Ord for Validation<E, A>
impl<E: Ord, A: Ord> Ord for Validation<E, A>
Source§impl<E: PartialOrd, A: PartialOrd> PartialOrd for Validation<E, A>
impl<E: PartialOrd, A: PartialOrd> PartialOrd for Validation<E, A>
Source§impl<E, A> Serialize for Validation<E, A>
impl<E, A> Serialize for Validation<E, A>
Source§impl<T, E> WithError<E> for Validation<E, T>
Implementation of WithError for Validation types.
impl<T, E> WithError<E> for Validation<E, T>
Implementation of WithError for Validation types.
This allows transforming the error type of a validation while preserving the success value and accumulating all errors through the transformation.
§Examples
use error_rail::traits::WithError;
use error_rail::validation::Validation;
let validation: Validation<&str, i32> = Validation::invalid_many(vec!["err1", "err2"]);
let mapped = validation.fmap_error(|e| format!("Error: {}", e));
assert_eq!(mapped.iter_errors().count(), 2);
let valid: Validation<&str, i32> = Validation::valid(42);
let result = valid.to_result();
assert_eq!(result, Ok(42));Source§fn to_result_first(self) -> Result<Self::Success, E>
fn to_result_first(self) -> Result<Self::Success, E>
Converts the validation to a result, taking only the first error if invalid.
This method explicitly indicates that only the first error will be returned, potentially losing additional errors in multi-error scenarios.
§Returns
Ok(value)if validation is validErr(first_error)if validation is invalid (only the first error)
§Examples
use error_rail::validation::Validation;
use error_rail::traits::WithError;
let valid = Validation::<&str, i32>::valid(42);
assert_eq!(valid.to_result_first(), Ok(42));
let invalid = Validation::<&str, i32>::invalid_many(vec!["error1", "error2"]);
assert_eq!(invalid.to_result_first(), Err("error1"));Source§fn to_result_all(self) -> Result<Self::Success, ErrorVec<E>>
fn to_result_all(self) -> Result<Self::Success, ErrorVec<E>>
Converts the validation to a result, preserving all errors if invalid.
This method returns all accumulated errors in a Vec<E>, ensuring no error
information is lost during the conversion.
§Returns
Ok(value)if validation is validErr(all_errors)if validation is invalid (all errors in a Vec)
§Examples
use error_rail::validation::Validation;
use error_rail::traits::WithError;
let valid = Validation::<&str, i32>::valid(42);
assert_eq!(valid.to_result_all(), Ok(42));
let invalid = Validation::<&str, i32>::invalid_many(vec!["error1", "error2"]);
assert_eq!(invalid.to_result_all(), Err(vec!["error1", "error2"].into()));type Success = T
type ErrorOutput<G> = Validation<G, T>
Source§fn fmap_error<F, G>(self, f: F) -> Self::ErrorOutput<G>where
F: Fn(E) -> G,
fn fmap_error<F, G>(self, f: F) -> Self::ErrorOutput<G>where
F: Fn(E) -> G,
f, producing a new container with error type G.impl<E: Eq, A: Eq> Eq for Validation<E, A>
impl<E, A> StructuralPartialEq for Validation<E, A>
Auto Trait Implementations§
impl<E, A> Freeze for Validation<E, A>
impl<E, A> RefUnwindSafe for Validation<E, A>where
A: RefUnwindSafe,
E: RefUnwindSafe,
impl<E, A> Send for Validation<E, A>
impl<E, A> Sync for Validation<E, A>
impl<E, A> Unpin for Validation<E, A>
impl<E, A> UnwindSafe for Validation<E, A>
Blanket Implementations§
§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§unsafe fn clone_to_uninit(&self, dest: *mut u8)
unsafe fn clone_to_uninit(&self, dest: *mut u8)
clone_to_uninit)