| 1 | //! Component range error |
| 2 | |
| 3 | use core::fmt; |
| 4 | |
| 5 | use 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, PartialEq, Eq, Hash)] |
| 11 | pub 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_range: bool, |
| 23 | } |
| 24 | |
| 25 | impl 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_range |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | impl fmt::Display for ComponentRange { |
| 39 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 40 | write!( |
| 41 | f, |
| 42 | " {} must be in the range {}..= {}" , |
| 43 | self.name, self.minimum, self.maximum |
| 44 | )?; |
| 45 | |
| 46 | if self.conditional_range { |
| 47 | f.write_str(data:", given values of other parameters" )?; |
| 48 | } |
| 49 | |
| 50 | Ok(()) |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | impl From<ComponentRange> for crate::Error { |
| 55 | fn from(original: ComponentRange) -> Self { |
| 56 | Self::ComponentRange(original) |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | impl TryFrom<crate::Error> for ComponentRange { |
| 61 | type Error = error::DifferentVariant; |
| 62 | |
| 63 | fn try_from(err: crate::Error) -> Result<Self, Self::Error> { |
| 64 | match err { |
| 65 | crate::Error::ComponentRange(err: ComponentRange) => Ok(err), |
| 66 | _ => Err(error::DifferentVariant), |
| 67 | } |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | /// **This trait implementation is deprecated and will be removed in a future breaking release.** |
| 72 | #[cfg (feature = "serde" )] |
| 73 | impl serde::de::Expected for ComponentRange { |
| 74 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 75 | write!( |
| 76 | f, |
| 77 | "a value in the range {}..={}" , |
| 78 | self.minimum, self.maximum |
| 79 | ) |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | #[cfg (feature = "serde" )] |
| 84 | impl ComponentRange { |
| 85 | /// Convert the error to a deserialization error. |
| 86 | pub(crate) fn into_de_error<E: serde::de::Error>(self) -> E { |
| 87 | E::invalid_value(serde::de::Unexpected::Signed(self.value), &self) |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | #[cfg (feature = "std" )] |
| 92 | #[allow (clippy::std_instead_of_core)] |
| 93 | impl std::error::Error for ComponentRange {} |
| 94 | |