time/error/
component_range.rs

1//! Component range error
2
3use core::{fmt, hash};
4
5use crate::error;
6
7/// An error type indicating that a component provided to a method was out of range, causing a
8/// failure.
9// i64 is the narrowest type fitting all use cases. This eliminates the need for a type parameter.
10#[derive(Debug, Clone, Copy, Eq)]
11pub struct ComponentRange {
12    /// Name of the component.
13    pub(crate) name: &'static str,
14    /// Minimum allowed value, inclusive.
15    pub(crate) minimum: i64,
16    /// Maximum allowed value, inclusive.
17    pub(crate) maximum: i64,
18    /// Value that was provided.
19    pub(crate) value: i64,
20    /// The minimum and/or maximum value is conditional on the value of other
21    /// parameters.
22    pub(crate) conditional_message: Option<&'static str>,
23}
24
25impl ComponentRange {
26    /// Obtain the name of the component whose value was out of range.
27    pub const fn name(self) -> &'static str {
28        self.name
29    }
30
31    /// Whether the value's permitted range is conditional, i.e. whether an input with this
32    /// value could have succeeded if the values of other components were different.
33    pub const fn is_conditional(self) -> bool {
34        self.conditional_message.is_some()
35    }
36}
37
38impl PartialEq for ComponentRange {
39    fn eq(&self, other: &Self) -> bool {
40        self.name == other.name
41        && self.minimum == other.minimum
42        && self.maximum == other.maximum
43        && self.value == other.value
44        // Skip the contents of the message when comparing for equality.
45        && self.conditional_message.is_some() == other.conditional_message.is_some()
46    }
47}
48
49impl hash::Hash for ComponentRange {
50    fn hash<H: hash::Hasher>(&self, state: &mut H) {
51        self.name.hash(state);
52        self.minimum.hash(state);
53        self.maximum.hash(state);
54        self.value.hash(state);
55        // Skip the contents of the message when comparing for equality.
56        self.conditional_message.is_some().hash(state);
57    }
58}
59
60impl fmt::Display for ComponentRange {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        write!(
63            f,
64            "{} must be in the range {}..={}",
65            self.name, self.minimum, self.maximum
66        )?;
67
68        if let Some(message) = self.conditional_message {
69            write!(f, " {message}")?;
70        }
71
72        Ok(())
73    }
74}
75
76impl From<ComponentRange> for crate::Error {
77    fn from(original: ComponentRange) -> Self {
78        Self::ComponentRange(original)
79    }
80}
81
82impl TryFrom<crate::Error> for ComponentRange {
83    type Error = error::DifferentVariant;
84
85    fn try_from(err: crate::Error) -> Result<Self, Self::Error> {
86        match err {
87            crate::Error::ComponentRange(err) => Ok(err),
88            _ => Err(error::DifferentVariant),
89        }
90    }
91}
92
93/// **This trait implementation is deprecated and will be removed in a future breaking release.**
94#[cfg(feature = "serde")]
95impl serde::de::Expected for ComponentRange {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        write!(
98            f,
99            "a value in the range {}..={}",
100            self.minimum, self.maximum
101        )
102    }
103}
104
105#[cfg(feature = "serde")]
106impl ComponentRange {
107    /// Convert the error to a deserialization error.
108    pub(crate) fn into_de_error<E: serde::de::Error>(self) -> E {
109        E::invalid_value(serde::de::Unexpected::Signed(self.value), &self)
110    }
111}
112
113#[cfg(feature = "std")]
114impl std::error::Error for ComponentRange {}