use std::{
fmt::{Debug, Display, Formatter},
str::FromStr,
};
use serde_with::{DeserializeFromStr, SerializeDisplay};
use utoipa::ToSchema;
use crate::{
core::{macros::impl_from, read::FromUnalignedRead},
scion::address::AddressParseError,
};
#[derive(
Copy,
Clone,
Eq,
PartialEq,
Hash,
PartialOrd,
Ord,
SerializeDisplay,
DeserializeFromStr,
ToSchema,
)]
#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
#[repr(transparent)]
pub struct Isd(pub u16);
impl Isd {
pub const WILDCARD: Self = Self(0);
pub const MAX: Self = Self::new(u16::MAX);
pub const BITS: u32 = u16::BITS;
pub const fn new(id: u16) -> Self {
Self(id)
}
pub const fn to_u16(&self) -> u16 {
self.0
}
pub const fn is_wildcard(&self) -> bool {
self.0 == Self::WILDCARD.0
}
pub const fn matches(&self, other: Isd) -> bool {
self.is_wildcard() || other.is_wildcard() || self.0 == other.0
}
pub fn matches_any_in<'a>(&self, collection: impl IntoIterator<Item = &'a Isd>) -> bool {
collection.into_iter().any(|other| self.matches(*other))
}
}
impl Debug for Isd {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
<Self as Display>::fmt(self, f)
}
}
impl Display for Isd {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl FromStr for Isd {
type Err = AddressParseError;
fn from_str(string: &str) -> Result<Self, Self::Err> {
u16::from_str(string)
.map(Isd::new)
.or(Err(AddressParseError::Isd))
}
}
impl_from!(u16, Isd, |v| Isd::new(v));
impl_from!(Isd, u16, |v| v.to_u16());
impl FromUnalignedRead for Isd {
fn from_unaligned_read(v: u128) -> Self {
Isd::new(u16::from_unaligned_read(v))
}
}
#[cfg(test)]
mod tests {
use super::*;
mod display {
use super::*;
#[test]
fn wildcard() {
assert_eq!(Isd::WILDCARD.to_string(), "0");
}
}
}