use core::fmt;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum PrimitiveErrorKind {
Empty,
TooShort,
TooLong,
OutOfRange,
InvalidFormat,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PrimitiveError {
Empty,
TooShort {
min: usize,
actual: usize,
},
TooLong {
max: usize,
actual: usize,
},
OutOfRange {
min: u128,
max: u128,
actual: u128,
},
Invalid {
message: &'static str,
},
}
pub type PrimitiveResult<T> = Result<T, PrimitiveError>;
impl PrimitiveError {
pub const fn kind(&self) -> PrimitiveErrorKind {
match self {
Self::Empty => PrimitiveErrorKind::Empty,
Self::TooShort { .. } => PrimitiveErrorKind::TooShort,
Self::TooLong { .. } => PrimitiveErrorKind::TooLong,
Self::OutOfRange { .. } => PrimitiveErrorKind::OutOfRange,
Self::Invalid { .. } => PrimitiveErrorKind::InvalidFormat,
}
}
}
impl fmt::Display for PrimitiveError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Empty => f.write_str("value must not be empty"),
Self::TooShort { min, actual } => {
write!(
f,
"value is too short: minimum is {min}, actual is {actual}"
)
}
Self::TooLong { max, actual } => {
write!(f, "value is too long: maximum is {max}, actual is {actual}")
}
Self::OutOfRange { min, max, actual } => {
write!(
f,
"value is out of range: expected {min}..={max}, actual is {actual}"
)
}
Self::Invalid { message } => write!(f, "invalid value: {message}"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for PrimitiveError {}
#[cfg(test)]
mod tests {
use super::{PrimitiveError, PrimitiveErrorKind};
use alloc::string::ToString;
#[test]
fn display_empty() {
assert_eq!(PrimitiveError::Empty.to_string(), "value must not be empty");
}
#[test]
fn display_too_short() {
assert_eq!(
PrimitiveError::TooShort { min: 3, actual: 1 }.to_string(),
"value is too short: minimum is 3, actual is 1"
);
}
#[test]
fn display_too_long() {
assert_eq!(
PrimitiveError::TooLong { max: 5, actual: 8 }.to_string(),
"value is too long: maximum is 5, actual is 8"
);
}
#[test]
fn display_out_of_range() {
assert_eq!(
PrimitiveError::OutOfRange {
min: 1,
max: 100,
actual: 200
}
.to_string(),
"value is out of range: expected 1..=100, actual is 200"
);
}
#[test]
fn display_invalid() {
assert_eq!(
PrimitiveError::Invalid {
message: "bad format"
}
.to_string(),
"invalid value: bad format"
);
}
#[test]
fn kind_returns_stable_error_category() {
assert_eq!(PrimitiveError::Empty.kind(), PrimitiveErrorKind::Empty);
assert_eq!(
PrimitiveError::TooShort { min: 3, actual: 1 }.kind(),
PrimitiveErrorKind::TooShort
);
assert_eq!(
PrimitiveError::TooLong { max: 5, actual: 8 }.kind(),
PrimitiveErrorKind::TooLong
);
assert_eq!(
PrimitiveError::OutOfRange {
min: 1,
max: 100,
actual: 200
}
.kind(),
PrimitiveErrorKind::OutOfRange
);
assert_eq!(
PrimitiveError::Invalid {
message: "bad format"
}
.kind(),
PrimitiveErrorKind::InvalidFormat
);
}
}