108 lines
2.5 KiB
Rust
108 lines
2.5 KiB
Rust
use std::{fmt, str::FromStr};
|
|
|
|
use serde::{de, Deserialize, Serialize};
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct MacAddr {
|
|
octets: [u8; 6],
|
|
}
|
|
|
|
impl Serialize for MacAddr {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: serde::Serializer,
|
|
{
|
|
serializer.serialize_str(&self.to_string())
|
|
}
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for MacAddr {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
let s: String = Deserialize::deserialize(deserializer)?;
|
|
MacAddr::from_str(s.as_str()).map_err(de::Error::custom)
|
|
}
|
|
}
|
|
|
|
impl std::ops::Index<usize> for MacAddr {
|
|
type Output = u8;
|
|
|
|
fn index(&self, index: usize) -> &Self::Output {
|
|
&self.octets[index]
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
ParseError(std::num::ParseIntError),
|
|
SizeError(usize),
|
|
}
|
|
|
|
impl fmt::Display for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Self::ParseError(er) => write!(f, "Couldn't parse octets: {}", er),
|
|
Self::SizeError(sz) => write!(f, "Too many octets; expected 6, string had {}", sz),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for Error {}
|
|
|
|
impl fmt::Display for MacAddr {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
self.octets.map(|oct| format!("{:02x}", oct)).join(":")
|
|
)
|
|
}
|
|
}
|
|
|
|
impl FromStr for MacAddr {
|
|
type Err = Error;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
let octets = s
|
|
.split(':')
|
|
.map(|s| u8::from_str_radix(s, 16))
|
|
.collect::<Result<Vec<u8>, std::num::ParseIntError>>()
|
|
.map_err(Error::ParseError)?;
|
|
Ok(MacAddr {
|
|
octets: octets
|
|
.try_into()
|
|
.map_err(|v: Vec<u8>| Error::SizeError(v.len()))?,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl MacAddr {
|
|
pub fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> MacAddr {
|
|
MacAddr {
|
|
octets: [a, b, c, d, e, f],
|
|
}
|
|
}
|
|
|
|
pub fn invalid() -> MacAddr {
|
|
MacAddr { octets: [0u8; 6] }
|
|
}
|
|
|
|
pub fn from_bytes<T>(value: T) -> Result<MacAddr, Error>
|
|
where
|
|
T: AsRef<[u8]>,
|
|
{
|
|
let slice = value.as_ref();
|
|
if slice.len() < 6 {
|
|
Err(Error::SizeError(slice.len()))
|
|
} else {
|
|
Ok(MacAddr {
|
|
octets: slice[0..6].try_into().unwrap(),
|
|
})
|
|
}
|
|
}
|
|
|
|
pub fn octets(&self) -> [u8; 6] {
|
|
self.octets
|
|
}
|
|
}
|