Validation

Enum Validation 

Source
pub enum Validation<E, A> {
    Valid(A),
    Invalid(ErrorVec<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 type
  • A - The success value type

§Variants

  • Valid(A) - Contains a successful value
  • Invalid(ErrorVec<E>) - Contains one or more 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(ErrorVec<E>)

Implementations§

Source§

impl<E, A> Validation<E, A>

Source

pub fn valid(value: A) -> Self

Creates a valid value.

§Arguments
  • value - The success value to wrap
§Examples
use error_rail::validation::Validation;

let v = Validation::<&str, i32>::valid(42);
assert_eq!(v.into_value(), Some(42));
Source

pub fn invalid(error: E) -> Self

Creates an invalid value from a single error.

§Arguments
  • error - The error to wrap
§Examples
use error_rail::validation::Validation;

let v = Validation::<&str, ()>::invalid("missing field");
assert!(v.is_invalid());
Source

pub fn invalid_many<I>(errors: I) -> Self
where I: IntoIterator<Item = E>,

Creates an invalid value from an iterator of errors.

§Arguments
  • errors - An iterator of errors to collect
§Examples
use error_rail::validation::Validation;

let v = Validation::<&str, ()>::invalid_many(["missing", "invalid"]);
assert!(v.is_invalid());
assert_eq!(v.into_errors().unwrap().len(), 2);
Source

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());
Source

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());
Source

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 type A to type B
§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));
Source

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());
Source

pub fn or_else<F>(self, op: F) -> Validation<E, A>
where F: FnOnce(ErrorVec<E>) -> 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));
Source

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);
Source

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 type E to type G
§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());
Source

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());
Source

pub fn from_result(result: Result<A, E>) -> Self

Wraps a normal Result into a Validation, turning the error side into a singleton vec.

§Arguments
  • result - The result to convert
§Examples
use error_rail::validation::Validation;

let result: Result<i32, &str> = Ok(42);
let v = Validation::from_result(result);
assert!(v.is_valid());
Source

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);
Source

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>

Source

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);
Source

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));
Source

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);
Source

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>

Source§

fn clone(&self) -> Validation<E, A>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<E: Debug, A: Debug> Debug for Validation<E, A>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

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>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<E> ErrorCategory<E> for Validation<E, ()>

Implementation of ErrorCategory for Validation types.

This allows Validation<E, ()> to act as an error category, where:

  • lift creates Valid values
  • handle_error creates Invalid values 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>

The functor type that wraps values with error handling capability.
Source§

fn lift<T>(value: T) -> Validation<E, T>

Lifts a pure value into the error functor context. Read more
Source§

fn handle_error<T>(error: E) -> Validation<E, T>

Constructs an error case from an error value. Read more
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.

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§

fn from_iter<T: IntoIterator<Item = Result<A, E>>>(iter: T) -> Self

Creates a value from an iterator. Read more
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.

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

Creates a value from an iterator. Read more
Source§

impl<E: Hash, A: Hash> Hash for Validation<E, A>

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

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 here
Source§

type Item = &'a A

The type of the elements being iterated over.
Source§

type IntoIter = Iter<'a, A>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

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§

type Item = &'a mut A

The type of the elements being iterated over.
Source§

type IntoIter = IterMut<'a, A>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

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§

type Item = A

The type of the elements being iterated over.
Source§

type IntoIter = IntoIter<A>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<E: Ord, A: Ord> Ord for Validation<E, A>

Source§

fn cmp(&self, other: &Validation<E, A>) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl<E: PartialEq, A: PartialEq> PartialEq for Validation<E, A>

Source§

fn eq(&self, other: &Validation<E, A>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<E: PartialOrd, A: PartialOrd> PartialOrd for Validation<E, A>

Source§

fn partial_cmp(&self, other: &Validation<E, A>) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl<E, A> Serialize for Validation<E, A>
where E: Serialize, A: Serialize,

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

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(self) -> Result<Self::Success, E>

👎Deprecated since 0.6.0: Use to_result_first() or to_result_all() for explicit error handling

Converts the validation to a result, taking only the first error if invalid.

⚠️ DEPRECATED: Use to_result_first() or to_result_all() for explicit error handling. This method loses additional errors in multi-error scenarios.

§Returns
  • Ok(value) if validation is valid
  • Err(first_error) if validation is invalid (only the first error)
Source§

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 valid
  • Err(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>>

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 valid
  • Err(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()));
Source§

type Success = T

Source§

type ErrorOutput<G> = Validation<G, T>

Source§

fn fmap_error<F, G>(self, f: F) -> Self::ErrorOutput<G>
where F: Fn(E) -> G,

Maps the error value using f, producing a new container with error type G. Read more
Source§

impl<E: Eq, A: Eq> Eq for Validation<E, A>

Source§

impl<E, A> StructuralPartialEq for Validation<E, A>

Auto Trait Implementations§

§

impl<E, A> Freeze for Validation<E, A>
where A: Freeze, E: Freeze,

§

impl<E, A> RefUnwindSafe for Validation<E, A>

§

impl<E, A> Send for Validation<E, A>
where A: Send, E: Send,

§

impl<E, A> Sync for Validation<E, A>
where A: Sync, E: Sync,

§

impl<E, A> Unpin for Validation<E, A>
where A: Unpin, E: Unpin,

§

impl<E, A> UnwindSafe for Validation<E, A>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,