#![warn(missing_docs)]
#![doc(html_root_url = "https://docs.rs/validated/0.4.1")]
use crate::Validated::{Fail, Good};
use std::iter::{FromIterator, Sum};
use std::ops::{Deref, DerefMut};
use nonempty_collections::{nev, NEVec, NonEmptyIterator};
#[cfg(feature = "rayon")]
use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator};
#[cfg(feature = "rayon")]
use std::sync::Mutex;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum Validated<T, E> {
Good(T),
Fail(NEVec<E>),
}
impl<T, E> Validated<T, E> {
pub fn fail(e: E) -> Validated<T, E> {
Fail(nev![e])
}
pub fn as_mut(&mut self) -> Validated<&mut T, &mut E> {
match self {
Good(ref mut t) => Good(t),
Fail(ref mut e) => {
let ne = e.nonempty_iter_mut().collect();
Fail(ne)
}
}
}
pub fn as_ref(&self) -> Validated<&T, &E> {
match self {
Good(ref t) => Good(t),
Fail(e) => {
let ne = e.nonempty_iter().collect();
Fail(ne)
}
}
}
pub fn expect(self, msg: &str) -> T {
match self {
Good(t) => t,
Fail(_) => panic!("{}", msg),
}
}
pub fn is_good(&self) -> bool {
matches!(self, Good(_))
}
pub fn is_fail(&self) -> bool {
matches!(self, Fail(_))
}
pub fn iter(&self) -> Iter<'_, T> {
Iter {
inner: self.as_ref().ok().ok(),
}
}
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
inner: self.as_mut().ok().ok(),
}
}
pub fn map<U, F>(self, op: F) -> Validated<U, E>
where
F: FnOnce(T) -> U,
{
match self {
Good(t) => Good(op(t)),
Fail(e) => Fail(e),
}
}
pub fn map_err<R, F>(self, op: F) -> Validated<T, R>
where
F: FnOnce(NEVec<E>) -> NEVec<R>,
{
match self {
Good(t) => Good(t),
Fail(e) => Fail(op(e)),
}
}
pub fn map2<U, Z, F>(self, vu: Validated<U, E>, f: F) -> Validated<Z, E>
where
F: FnOnce(T, U) -> Z,
{
match (self, vu) {
(Good(t), Good(u)) => Good(f(t, u)),
(Good(_), Fail(e)) => Fail(e),
(Fail(e), Good(_)) => Fail(e),
(Fail(mut e0), Fail(e1)) => {
e0.extend(e1);
Fail(e0)
}
}
}
pub fn map3<U, V, Z, F>(self, vu: Validated<U, E>, vv: Validated<V, E>, f: F) -> Validated<Z, E>
where
F: FnOnce(T, U, V) -> Z,
{
match (self, vu, vv) {
(Good(t), Good(u), Good(v)) => Good(f(t, u, v)),
(Good(_), Good(_), Fail(e)) => Fail(e),
(Good(_), Fail(e), Good(_)) => Fail(e),
(Fail(e), Good(_), Good(_)) => Fail(e),
(Good(_), Fail(e0), Fail(e1)) => Fail(nons(e0, Some(e1).into_iter())),
(Fail(e0), Good(_), Fail(e1)) => Fail(nons(e0, Some(e1).into_iter())),
(Fail(e0), Fail(e1), Good(_)) => Fail(nons(e0, Some(e1).into_iter())),
(Fail(e0), Fail(e1), Fail(e2)) => Fail(nons(e0, vec![e1, e2].into_iter())),
}
}
pub fn map4<U, V, W, Z, F>(
self,
vu: Validated<U, E>,
vv: Validated<V, E>,
vw: Validated<W, E>,
f: F,
) -> Validated<Z, E>
where
F: FnOnce(T, U, V, W) -> Z,
{
match (self, vu, vv, vw) {
(Good(t), Good(u), Good(v), Good(w)) => Good(f(t, u, v, w)),
(Good(_), Good(_), Good(_), Fail(e)) => Fail(e),
(Good(_), Good(_), Fail(e), Good(_)) => Fail(e),
(Good(_), Fail(e), Good(_), Good(_)) => Fail(e),
(Fail(e), Good(_), Good(_), Good(_)) => Fail(e),
(Good(_), Good(_), Fail(e0), Fail(e1)) => Fail(nons(e0, Some(e1).into_iter())),
(Good(_), Fail(e0), Good(_), Fail(e1)) => Fail(nons(e0, Some(e1).into_iter())),
(Good(_), Fail(e0), Fail(e1), Good(_)) => Fail(nons(e0, Some(e1).into_iter())),
(Fail(e0), Good(_), Good(_), Fail(e1)) => Fail(nons(e0, Some(e1).into_iter())),
(Fail(e0), Fail(e1), Good(_), Good(_)) => Fail(nons(e0, Some(e1).into_iter())),
(Fail(e0), Good(_), Fail(e1), Good(_)) => Fail(nons(e0, Some(e1).into_iter())),
(Good(_), Fail(e0), Fail(e1), Fail(e2)) => Fail(nons(e0, vec![e1, e2].into_iter())),
(Fail(e0), Good(_), Fail(e1), Fail(e2)) => Fail(nons(e0, vec![e1, e2].into_iter())),
(Fail(e0), Fail(e1), Good(_), Fail(e2)) => Fail(nons(e0, vec![e1, e2].into_iter())),
(Fail(e0), Fail(e1), Fail(e2), Good(_)) => Fail(nons(e0, vec![e1, e2].into_iter())),
(Fail(e0), Fail(e1), Fail(e2), Fail(e3)) => {
Fail(nons(e0, vec![e1, e2, e3].into_iter()))
}
}
}
pub fn ok(self) -> Result<T, NEVec<E>> {
match self {
Good(t) => Ok(t),
Fail(e) => Err(e),
}
}
pub fn unwrap(self) -> T {
match self {
Good(t) => t,
Fail(_) => panic!("called `Validated::unwrap` on a `Fail` value"),
}
}
pub fn unwrap_or(self, default: T) -> T {
match self {
Good(t) => t,
Fail(_) => default,
}
}
pub fn unwrap_or_else<F>(self, op: F) -> T
where
F: FnOnce(NEVec<E>) -> T,
{
match self {
Good(t) => t,
Fail(e) => op(e),
}
}
}
impl<T: Default, E> Validated<T, E> {
pub fn unwrap_or_default(self) -> T {
match self {
Good(t) => t,
Fail(_) => Default::default(),
}
}
}
impl<T: Deref, E> Validated<T, E> {
pub fn as_deref(&self) -> Validated<&T::Target, &E> {
self.as_ref().map(|t| t.deref())
}
}
impl<T: DerefMut, E> Validated<T, E> {
pub fn as_deref_mut(&mut self) -> Validated<&mut T::Target, &mut E> {
self.as_mut().map(|t| t.deref_mut())
}
}
impl<T, E> From<Result<T, E>> for Validated<T, E> {
fn from(r: Result<T, E>) -> Self {
match r {
Ok(t) => Good(t),
Err(e) => Fail(NEVec::new(e)),
}
}
}
impl<T, U, E> FromIterator<Result<T, E>> for Validated<U, E>
where
U: FromIterator<T>,
{
fn from_iter<I: IntoIterator<Item = Result<T, E>>>(iter: I) -> Self {
let mut errors = Vec::new();
let result = iter
.into_iter()
.filter_map(|item| match item {
Ok(t) => Some(t),
Err(e) => {
errors.push(e);
None
}
})
.collect();
match NEVec::try_from_vec(errors) {
None => Good(result),
Some(e) => Fail(e),
}
}
}
impl<T, U, E> FromIterator<Validated<T, E>> for Validated<U, E>
where
U: FromIterator<T>,
{
fn from_iter<I: IntoIterator<Item = Validated<T, E>>>(iter: I) -> Self {
let mut errors = Vec::new();
let result = iter
.into_iter()
.filter_map(|item| match item {
Good(t) => Some(t),
Fail(e) => {
errors.extend(e);
None
}
})
.collect();
match NEVec::try_from_vec(errors) {
None => Good(result),
Some(e) => Fail(e),
}
}
}
#[cfg(feature = "rayon")]
impl<T, U, E> FromParallelIterator<Result<T, E>> for Validated<U, E>
where
T: Send,
E: Send,
U: FromParallelIterator<T>,
{
fn from_par_iter<I>(par_iter: I) -> Validated<U, E>
where
I: IntoParallelIterator<Item = Result<T, E>>,
{
let errors = Mutex::new(Vec::new());
let result = par_iter
.into_par_iter()
.filter_map(|item| match item {
Ok(t) => Some(t),
Err(e) => {
errors.lock().unwrap().push(e);
None
}
})
.collect();
match NEVec::try_from_vec(errors.into_inner().unwrap()) {
None => Good(result),
Some(e) => Fail(e),
}
}
}
#[cfg(feature = "rayon")]
impl<T, U, E> FromParallelIterator<Validated<T, E>> for Validated<U, E>
where
T: Send,
E: Send,
U: FromParallelIterator<T>,
{
fn from_par_iter<I>(par_iter: I) -> Validated<U, E>
where
I: IntoParallelIterator<Item = Validated<T, E>>,
{
let errors = Mutex::new(Vec::new());
let result = par_iter
.into_par_iter()
.filter_map(|item| match item {
Good(t) => Some(t),
Fail(e) => {
errors.lock().unwrap().extend(e);
None
}
})
.collect();
match NEVec::try_from_vec(errors.into_inner().unwrap()) {
None => Good(result),
Some(e) => Fail(e),
}
}
}
impl<T, E> IntoIterator for Validated<T, E> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
inner: self.ok().ok(),
}
}
}
impl<'a, T, E> IntoIterator for &'a Validated<T, E> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
impl<'a, T, E> IntoIterator for &'a mut Validated<T, E> {
type Item = &'a mut T;
type IntoIter = IterMut<'a, T>;
fn into_iter(self) -> IterMut<'a, T> {
self.iter_mut()
}
}
impl<T, U, E> Sum<Validated<U, E>> for Validated<T, E>
where
T: Sum<U>,
{
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Validated<U, E>>,
{
let mut errors = Vec::new();
let result = iter
.filter_map(|item| match item {
Good(n) => Some(n),
Fail(e) => {
errors.extend(e);
None
}
})
.sum();
match NEVec::try_from_vec(errors) {
None => Good(result),
Some(e) => Fail(e),
}
}
}
impl<T, U, E> Sum<Result<U, E>> for Validated<T, E>
where
T: Sum<U>,
{
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Result<U, E>>,
{
let mut errors = Vec::new();
let result = iter
.filter_map(|item| match item {
Ok(n) => Some(n),
Err(e) => {
errors.push(e);
None
}
})
.sum();
match NEVec::try_from_vec(errors) {
None => Good(result),
Some(e) => Fail(e),
}
}
}
#[derive(Debug)]
pub struct Iter<'a, T: 'a> {
inner: Option<&'a T>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.take()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let n = if self.inner.is_some() { 1 } else { 0 };
(n, Some(n))
}
}
impl<T> DoubleEndedIterator for Iter<'_, T> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.take()
}
}
impl<T> ExactSizeIterator for Iter<'_, T> {}
#[derive(Debug)]
pub struct IterMut<'a, T: 'a> {
inner: Option<&'a mut T>,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
#[inline]
fn next(&mut self) -> Option<&'a mut T> {
self.inner.take()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let n = if self.inner.is_some() { 1 } else { 0 };
(n, Some(n))
}
}
impl<T> DoubleEndedIterator for IterMut<'_, T> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.inner.take()
}
}
impl<T> ExactSizeIterator for IterMut<'_, T> {}
#[derive(Clone, Debug)]
pub struct IntoIter<T> {
inner: Option<T>,
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
self.inner.take()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let n = if self.inner.is_some() { 1 } else { 0 };
(n, Some(n))
}
}
fn nons<E, I>(mut a: NEVec<E>, rest: I) -> NEVec<E>
where
I: Iterator<Item = NEVec<E>>,
{
for i in rest {
a.extend(i);
}
a
}