valust/error/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! Human-readable error produced by `valust`.

pub mod display;
pub mod transform;
pub mod validate;

use std::fmt::{self, Debug, Display, Write};

use sealed::sealed;
use transform::TransformError;
use validate::ValidateError;

/// Display-able error trait.
///
/// You don't need to manually implement this trait as this trait
/// has been implemented for all `Debug + Display` types.
pub trait ErrorShow: Debug + Display {}

impl<T: Debug + Display> ErrorShow for T {}

/// Any validation error.
#[derive(Debug, Default)]
pub struct ValidationError {
    /// Error produced by validators.
    pub validates: Vec<ValidateError>,
    /// Error produced by transformers.
    pub transforms: Vec<TransformError>,
}

impl ValidationError {
    /// Create an empty error set.
    pub fn new() -> Self {
        Self::default()
    }

    /// Check if the error set contains any error instance.
    pub fn check(self) -> Result<(), ValidationError> {
        if self.validates.is_empty() && self.transforms.is_empty() {
            Ok(())
        } else {
            Err(self)
        }
    }

    /// Push a validator error to the set.
    pub fn push_validate_error(&mut self, err: ValidateError) {
        self.validates.push(err);
    }

    /// Push a transformer error to the set.
    pub fn push_transform_error(&mut self, err: TransformError) {
        self.transforms.push(err);
    }

    /// Extend the set.
    ///
    /// This will modify original set's `path` field.
    pub fn extend_error(&mut self, parent: &str, rhs: Self) {
        self.validates
            .extend(rhs.validates.into_iter().map(|mut x| {
                x.path = format!("{}.{}", parent, x.path);
                x
            }));
        self.transforms
            .extend(rhs.transforms.into_iter().map(|mut x| {
                x.path = format!("{}.{}", parent, x.path);
                x
            }));
    }
}

#[sealed]
impl display::ErrorDisplay for ValidationError {
    fn full_display(&self, w: &mut impl Write) -> fmt::Result {
        self.validates.iter().try_for_each(|t| t.full_display(w))?;
        self.transforms.iter().try_for_each(|t| t.full_display(w))?;

        Ok(())
    }

    fn brief_display(&self, w: &mut impl Write) -> fmt::Result {
        self.validates.iter().try_for_each(|t| t.brief_display(w))?;
        self.transforms
            .iter()
            .try_for_each(|t| t.brief_display(w))?;

        Ok(())
    }
}