macro_rules! string_codes {
($(
$ty:ty
$(, aliases = [$( ($alias:literal, $to:expr) ),+ $(,)?])?
);+ $(;)?) => {$(
impl $ty {
/// Every accepted code, in the same order as `ALL`.
///
/// Computed from `ALL`, so it cannot fall out of step with it —
/// which is what a database `CHECK` constraint generated from this
/// list depends on. Lenient input aliases are deliberately absent:
/// this is the set of strings the type *writes*.
pub const CODES: &'static [&'static str] = &Self::CODE_ARRAY;
/// Backing storage for [`CODES`](Self::CODES). The array length is
const CODE_ARRAY: [&'static str; <$ty>::ALL.len()] = {
let all = Self::ALL;
let mut out = [""; <$ty>::ALL.len()];
let mut i = 0;
while i < out.len() {
out[i] = all[i].as_str();
i += 1;
}
out
};
}
impl ::std::fmt::Display for $ty {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.pad(self.as_str())
}
}
impl ::std::str::FromStr for $ty {
type Err = $crate::error::ParseError;
fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
let trimmed = s.trim();
$($(
if trimmed.eq_ignore_ascii_case($alias)
|| trimmed.to_uppercase() == $alias
{
return Ok($to);
}
)+)?
let upper = trimmed.to_uppercase();
Self::ALL
.into_iter()
.find(|v| v.as_str() == upper)
.ok_or_else(|| {
$crate::error::ParseError::one_of(stringify!($ty), s, Self::CODES)
})
}
}
)+};
}
pub(crate) use string_codes;