use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt;
use core::fmt::Display;
use core::fmt::Formatter;
use core::ops::Deref;
use core::str::FromStr;
use arrayvec::ArrayString;
use miette::Diagnostic;
use serde::Deserialize;
use snafu::ensure;
use snafu::Backtrace;
use snafu::Snafu;
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(try_from = "String")]
pub struct Commodity {
pub(crate) name: ArrayString<24>,
}
impl AsRef<str> for Commodity {
fn as_ref(&self) -> &str {
self
}
}
impl Borrow<str> for Commodity {
fn borrow(&self) -> &str {
self
}
}
impl Deref for Commodity {
type Target = str;
#[inline]
fn deref(&self) -> &Self::Target {
&self.name
}
}
impl Display for Commodity {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.pad(&self.name)
}
}
impl From<&Self> for Commodity {
fn from(value: &Self) -> Self {
*value
}
}
impl FromStr for Commodity {
type Err = <Self as TryFrom<&'static str>>::Error;
fn from_str(name: &str) -> Result<Self, Self::Err> {
Self::try_from(name)
}
}
impl PartialEq<Commodity> for str {
fn eq(&self, other: &Commodity) -> bool {
other.eq(self)
}
}
impl PartialEq<str> for Commodity {
fn eq(&self, other: &str) -> bool {
self.partial_cmp(other).is_some_and(Ordering::is_eq)
}
}
impl PartialOrd<Commodity> for str {
fn partial_cmp(&self, other: &Commodity) -> Option<Ordering> {
other.partial_cmp(self)
}
}
impl PartialOrd<str> for Commodity {
fn partial_cmp(&self, other: &str) -> Option<Ordering> {
self.name.partial_cmp(other)
}
}
impl TryFrom<&str> for Commodity {
type Error = CommodityError;
fn try_from(name: &str) -> Result<Self, Self::Error> {
ensure!(
lazy_regex::regex_is_match!("^[A-Z](?:[-A-Z0-9._]{0,22}[A-Z0-9])?$", name),
CommoditySnafu { name }
);
let name = name.try_into().expect("length should fit");
Ok(Self { name })
}
}
impl TryFrom<String> for Commodity {
type Error = CommodityError;
fn try_from(value: String) -> Result<Self, Self::Error> {
Self::try_from(&*value)
}
}
#[derive(Debug, Diagnostic, Snafu)]
#[snafu(display("invalid commodity: {name:?}"))]
pub struct CommodityError {
pub(crate) name: String,
pub(crate) backtrace: Backtrace,
}