options/
validate.rs

1use std::fmt::{Display, Formatter, Result as FormatResult};
2
3/// Represents the result of [`Options`](crate::Options) validation.
4#[derive(Clone, Debug)]
5pub struct ValidateOptionsResult {
6    succeeded: bool,
7    skipped: bool,
8    failed: bool,
9    failures: Vec<String>,
10}
11
12impl ValidateOptionsResult {
13    /// Gets a value indicating whether the validation was successful.
14    pub fn succeeded(&self) -> bool {
15        self.succeeded
16    }
17
18    /// Gets a value indicating whether the validation was skipped.
19    pub fn skipped(&self) -> bool {
20        self.skipped
21    }
22
23    /// Gets a value indicating whether the validation failed.
24    pub fn failed(&self) -> bool {
25        self.failed
26    }
27
28    /// Gets the validation failure description.
29    pub fn failure_message(&self) -> String {
30        if self.failures.is_empty() {
31            String::new()
32        } else {
33            self.failures.join("; ")
34        }
35    }
36
37    /// Gets the full list of validation failures.
38    pub fn failures(&self) -> &[String] {
39        &self.failures
40    }
41
42    /// Creates a result when validation was skipped due to not matching.
43    pub fn skip() -> Self {
44        Self {
45            succeeded: false,
46            skipped: true,
47            failed: false,
48            failures: Vec::with_capacity(0),
49        }
50    }
51
52    /// Creates a result when validation was successful.
53    pub fn success() -> Self {
54        Self {
55            succeeded: true,
56            skipped: false,
57            failed: false,
58            failures: Vec::with_capacity(0),
59        }
60    }
61
62    /// Creates a result when validation failed.
63    ///
64    /// # Arguments
65    ///
66    /// `failure` - The failure message
67    pub fn fail<S: AsRef<str>>(failure: S) -> Self {
68        Self::fail_many([failure].iter())
69    }
70
71    /// Creates a result when validation failed for many reasons.
72    pub fn fail_many<S, I>(failures: I) -> Self
73    where
74        S: AsRef<str>,
75        I: Iterator<Item = S>,
76    {
77        Self {
78            succeeded: false,
79            skipped: false,
80            failed: true,
81            failures: failures.map(|f| f.as_ref().to_owned()).collect(),
82        }
83    }
84}
85
86impl Display for ValidateOptionsResult {
87    fn fmt(&self, formatter: &mut Formatter<'_>) -> FormatResult {
88        formatter.write_str(&self.failure_message())
89    }
90}
91
92/// Defines the behavior of an object that validates configuration options.
93pub trait ValidateOptions<T> {
94    /// Validates named options or all options if no name is specified.
95    ///
96    /// # Arguments
97    ///
98    /// * `name` - The optional name of the options to validate
99    /// * `options` - The options to validate
100    fn validate(&self, name: Option<&str>, options: &T) -> ValidateOptionsResult;
101}
102
103#[cfg(test)]
104mod tests {
105
106    use super::*;
107
108    #[test]
109    fn success_should_indicate_succeed() {
110        // arrange
111        let result = ValidateOptionsResult::success();
112
113        // act
114        let succeeded = result.succeeded();
115
116        // assert
117        assert!(succeeded);
118    }
119
120    #[test]
121    fn skip_should_indicate_skipped() {
122        // arrange
123        let result = ValidateOptionsResult::skip();
124
125        // act
126        let skipped = result.skipped();
127
128        // assert
129        assert!(skipped);
130    }
131
132    #[test]
133    fn fail_should_return_failed() {
134        // arrange
135        let result = ValidateOptionsResult::fail("");
136
137        // act
138        let failed = result.failed();
139
140        // assert
141        assert!(failed);
142    }
143
144    #[test]
145    fn fail_should_return_message() {
146        // arrange
147        let result = ValidateOptionsResult::fail("Failed");
148
149        // act
150        let message = result.failure_message();
151
152        // assert
153        assert_eq!(&message, "Failed");
154    }
155
156    #[test]
157    fn fail_many_should_return_joined_message() {
158        // arrange
159        let failures = ["Failure 1", "Failure 2"];
160        let result = ValidateOptionsResult::fail_many(failures.iter());
161
162        // act
163        let message = result.failure_message();
164
165        // assert
166        assert_eq!(&message, "Failure 1; Failure 2");
167    }
168
169    #[test]
170    fn fail_many_should_return_failures() {
171        // arrange
172        let expected = ["Failure 1", "Failure 2"];
173        let result = ValidateOptionsResult::fail_many(expected.iter());
174
175        // act
176        let failures = result.failures();
177
178        // assert
179        assert_eq!(failures, &expected[..]);
180    }
181
182    #[test]
183    fn to_string_should_return_message() {
184        // arrange
185        let result = ValidateOptionsResult::fail("Failed");
186        let message = result.failure_message();
187
188        // act
189        let string = result.to_string();
190
191        // assert
192        assert_eq!(string, message);
193    }
194}