Skip to main content

reliakit_primitives/
error.rs

1use core::fmt;
2
3/// Error returned when a primitive value fails validation.
4#[non_exhaustive]
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum PrimitiveError {
7    /// The value was empty or contained only whitespace.
8    Empty,
9    /// The value was shorter than the minimum allowed length.
10    TooShort {
11        /// Minimum allowed length.
12        min: usize,
13        /// Actual observed length.
14        actual: usize,
15    },
16    /// The value was longer than the maximum allowed length.
17    TooLong {
18        /// Maximum allowed length.
19        max: usize,
20        /// Actual observed length.
21        actual: usize,
22    },
23    /// The value was outside the inclusive allowed range.
24    OutOfRange {
25        /// Minimum allowed value.
26        min: u128,
27        /// Maximum allowed value.
28        max: u128,
29        /// Actual observed value.
30        actual: u128,
31    },
32    /// The value did not match the expected format or pattern.
33    Invalid {
34        /// Static validation message describing why the value is invalid.
35        message: &'static str,
36    },
37}
38
39/// Result alias used by Reliakit primitive constructors.
40pub type PrimitiveResult<T> = Result<T, PrimitiveError>;
41
42impl fmt::Display for PrimitiveError {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        match self {
45            Self::Empty => f.write_str("value must not be empty"),
46            Self::TooShort { min, actual } => {
47                write!(
48                    f,
49                    "value is too short: minimum is {min}, actual is {actual}"
50                )
51            }
52            Self::TooLong { max, actual } => {
53                write!(f, "value is too long: maximum is {max}, actual is {actual}")
54            }
55            Self::OutOfRange { min, max, actual } => {
56                write!(
57                    f,
58                    "value is out of range: expected {min}..={max}, actual is {actual}"
59                )
60            }
61            Self::Invalid { message } => write!(f, "invalid value: {message}"),
62        }
63    }
64}
65
66#[cfg(feature = "std")]
67impl std::error::Error for PrimitiveError {}
68
69#[cfg(test)]
70mod tests {
71    use super::PrimitiveError;
72    use alloc::string::ToString;
73
74    #[test]
75    fn display_empty() {
76        assert_eq!(PrimitiveError::Empty.to_string(), "value must not be empty");
77    }
78
79    #[test]
80    fn display_too_short() {
81        assert_eq!(
82            PrimitiveError::TooShort { min: 3, actual: 1 }.to_string(),
83            "value is too short: minimum is 3, actual is 1"
84        );
85    }
86
87    #[test]
88    fn display_too_long() {
89        assert_eq!(
90            PrimitiveError::TooLong { max: 5, actual: 8 }.to_string(),
91            "value is too long: maximum is 5, actual is 8"
92        );
93    }
94
95    #[test]
96    fn display_out_of_range() {
97        assert_eq!(
98            PrimitiveError::OutOfRange {
99                min: 1,
100                max: 100,
101                actual: 200
102            }
103            .to_string(),
104            "value is out of range: expected 1..=100, actual is 200"
105        );
106    }
107
108    #[test]
109    fn display_invalid() {
110        assert_eq!(
111            PrimitiveError::Invalid {
112                message: "bad format"
113            }
114            .to_string(),
115            "invalid value: bad format"
116        );
117    }
118}