use core::{
fmt::{Debug, Display, Formatter},
hash::Hash,
str::FromStr,
};
use std::borrow::Cow;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MonType(Cow<'static, str>);
impl Display for MonType {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
Display::fmt(self.0.as_ref(), f)
}
}
impl MonType {
pub const WINDOWS_IPHLPAPI: Self = Self::new_static("win32_iphlpapi");
pub const RTNETLINK: Self = Self::new_static("rtnetlink");
pub const AF_ROUTE: Self = Self::new_static("af_route");
pub const fn new_static(ty: &'static str) -> Self {
Self::new(Cow::Borrowed(ty))
}
pub const fn new(ty: Cow<'static, str>) -> Self {
let s = match &ty {
Cow::Borrowed(s) => *s,
Cow::Owned(s) => s.as_str(),
};
if !s.is_ascii() {
panic!("id types must be ascii")
}
let t = s.as_bytes();
let mut i = 0;
while i < t.len() {
if t[i] == b':' {
panic!("id type may not contain ':'");
}
i += 1;
}
Self(ty)
}
}
impl AsRef<str> for MonType {
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct InterfaceId {
ty: MonType,
value: u64,
}
impl InterfaceId {
pub const fn new(ty: MonType, value: u64) -> Self {
InterfaceId { ty, value }
}
pub const fn ty(&self) -> &MonType {
&self.ty
}
pub const fn value(&self) -> u64 {
self.value
}
}
impl Debug for InterfaceId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "InterfaceId({})", self)
}
}
impl Display for InterfaceId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.ty, self.value)
}
}
impl FromStr for InterfaceId {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (ty, value) = s.split_once(':').ok_or(())?;
Ok(InterfaceId::new(
MonType::new(ty.to_owned().into()),
value.parse().map_err(|_| ())?,
))
}
}