error_rail/validation/
traits.rs

1use crate::traits::ErrorCategory;
2use crate::traits::WithError;
3use crate::validation::core::Validation;
4
5/// Implementation of `ErrorCategory` for `Validation` types.
6///
7/// This allows `Validation<E, ()>` to act as an error category, where:
8/// - `lift` creates `Valid` values
9/// - `handle_error` creates `Invalid` values with a single error
10///
11/// # Examples
12///
13/// ```
14/// use error_rail::traits::ErrorCategory;
15/// use error_rail::validation::Validation;
16///
17/// let valid: Validation<String, i32> = <Validation<String, ()>>::lift(42);
18/// assert!(valid.is_valid());
19///
20/// let invalid: Validation<String, i32> = <Validation<String, ()>>::handle_error("error".to_string());
21/// assert!(invalid.is_invalid());
22/// ```
23impl<E> ErrorCategory<E> for Validation<E, ()> {
24    type ErrorFunctor<T> = Validation<E, T>;
25
26    #[inline]
27    fn lift<T>(value: T) -> Validation<E, T> {
28        Validation::Valid(value)
29    }
30
31    #[inline]
32    fn handle_error<T>(error: E) -> Validation<E, T> {
33        Validation::invalid(error)
34    }
35}
36
37/// Implementation of `WithError` for `Validation` types.
38///
39/// This allows transforming the error type of a validation while preserving
40/// the success value and accumulating all errors through the transformation.
41///
42/// # Examples
43///
44/// ```
45/// use error_rail::traits::WithError;
46/// use error_rail::validation::Validation;
47///
48/// let validation: Validation<&str, i32> = Validation::invalid_many(["err1", "err2"]);
49/// let mapped = validation.fmap_error(|e| format!("Error: {}", e));
50/// assert_eq!(mapped.iter_errors().count(), 2);
51///
52/// let valid: Validation<&str, i32> = Validation::valid(42);
53/// let result = valid.to_result();
54/// assert_eq!(result, Ok(42));
55/// ```
56impl<T, E> WithError<E> for Validation<E, T> {
57    type Success = T;
58    type ErrorOutput<G> = Validation<G, T>;
59
60    fn fmap_error<F, G>(self, f: F) -> Self::ErrorOutput<G>
61    where
62        F: Fn(E) -> G,
63    {
64        match self {
65            Validation::Valid(t) => Validation::Valid(t),
66            Validation::Invalid(e) => Validation::Invalid(e.into_iter().map(f).collect()),
67        }
68    }
69
70    fn to_result(self) -> Result<Self::Success, E> {
71        match self {
72            Validation::Valid(t) => Ok(t),
73            Validation::Invalid(e) => Err(e.into_iter().next().unwrap()),
74        }
75    }
76}