use crate::currency::Currency;
use crate::language::FormKind;
use crate::max::Max;
use std::fmt;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Error {
InvalidNumber(String),
InvalidOrdinal(String),
OutOfRange {
max: Max,
},
UnknownOption {
key: String,
allowed: &'static [&'static str],
},
MissingOption {
key: &'static str,
},
InvalidOptionValue {
key: &'static str,
value: String,
allowed: Vec<&'static str>,
},
UnsupportedCurrency {
currency: Currency,
allowed: Vec<Currency>,
},
NoMinorUnit {
currency: Currency,
},
UnsupportedForm {
language: &'static str,
form: FormKind,
},
}
impl Error {
#[must_use]
pub fn is_malformed_argument(&self) -> bool {
matches!(
self,
Error::UnknownOption { .. }
| Error::MissingOption { .. }
| Error::UnsupportedForm { .. }
)
}
}
fn join<T: fmt::Display>(items: impl IntoIterator<Item = T>) -> String {
items
.into_iter()
.map(|i| i.to_string())
.collect::<Vec<_>>()
.join(", ")
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::InvalidNumber(msg) | Error::InvalidOrdinal(msg) => f.write_str(msg),
Error::OutOfRange { max } => write!(
f,
"Number too large to convert: the largest supported value is {}",
max.largest_display()
),
Error::UnknownOption { key, allowed: [] } => {
write!(f, "Unknown option \"{key}\": this form takes no options")
}
Error::UnknownOption { key, allowed } => {
write!(
f,
"Unknown option \"{key}\": expected one of: {}",
allowed.join(", ")
)
}
Error::MissingOption { key } => write!(
f,
"Option \"{key}\" is required: a bare language tag names a language, not a locale, \
so it has no default to fall back on; pass it explicitly or use a region-qualified code"
),
Error::InvalidOptionValue {
key,
value,
allowed,
} if allowed.is_empty() => {
write!(f, "Option \"{key}\" has an invalid value: {value:?}")
}
Error::InvalidOptionValue {
key,
value,
allowed,
} => write!(
f,
"Option \"{key}\" must be one of: {}; got {value:?}",
allowed.join(", ")
),
Error::UnsupportedCurrency { currency, allowed } => write!(
f,
"Option \"currency\" must be one of: {}; got {currency}",
join(allowed)
),
Error::NoMinorUnit { currency } => {
write!(
f,
"{currency} has no minor unit: fractional amounts aren't representable"
)
}
Error::UnsupportedForm { language, form } => {
write!(f, "{language} does not support the {form} form")
}
}
}
}
impl std::error::Error for Error {}