Skip to main content

options/validation/
error.rs

1use std::error;
2use std::fmt::{Display, Formatter, Result};
3use tracing::debug;
4
5/// Represents the result of options validation.
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct Error {
8    failures: Vec<String>,
9}
10
11impl Error {
12    /// Creates a new validation [Error].
13    ///
14    /// # Arguments
15    ///
16    /// `failure` - The failure message
17    #[inline]
18    pub fn new<S: AsRef<str>>(failure: S) -> Self {
19        Self::many([failure])
20    }
21
22    /// Creates a new validation [Error] for many reasons.
23    ///
24    /// # Arguments
25    ///
26    /// `failures` - The failure messages
27    pub fn many<S, I>(failures: I) -> Self
28    where
29        S: AsRef<str>,
30        I: IntoIterator<Item = S>,
31    {
32        Self {
33            failures: failures
34                .into_iter()
35                .map(|failure| {
36                    let failure = failure.as_ref().to_owned();
37                    debug!("{failure}");
38                    failure
39                })
40                .collect(),
41        }
42    }
43
44    /// Gets the full list of validation failures.
45    #[inline]
46    pub fn failures(&self) -> &[String] {
47        &self.failures
48    }
49}
50
51impl Display for Error {
52    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
53        let mut failures = self.failures.iter();
54
55        if let Some(failure) = failures.next() {
56            failure.fmt(f)?;
57
58            for failure in failures {
59                f.write_str("; ")?;
60                failure.fmt(f)?;
61            }
62        }
63
64        Ok(())
65    }
66}
67
68impl error::Error for Error {}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn new_should_return_message() {
76        // arrange
77        let result = Error::new("Failed");
78
79        // act
80        let message = result.to_string();
81
82        // assert
83        assert_eq!(message, "Failed");
84    }
85
86    #[test]
87    fn many_should_return_joined_message() {
88        // arrange
89        let failures = ["Failure 1", "Failure 2"];
90        let result = Error::many(failures);
91
92        // act
93        let message = result.to_string();
94
95        // assert
96        assert_eq!(message, "Failure 1; Failure 2");
97    }
98
99    #[test]
100    fn many_should_return_failures() {
101        // arrange
102        let expected = ["Failure 1", "Failure 2"];
103        let result = Error::many(&expected);
104
105        // act
106        let failures = result.failures();
107
108        // assert
109        assert_eq!(failures, &expected[..]);
110    }
111}