mac6 1.2.0

Convenient MAC data type
Documentation
#[cfg(feature = "serde")]
use serde_with::{DeserializeFromStr, SerializeDisplay};
use std::{error::Error, fmt, str::FromStr};

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(DeserializeFromStr, SerializeDisplay))]
pub struct Mac(pub [u8; 6]);

#[derive(Debug, PartialEq, Eq)]
pub struct MacParseError;

impl fmt::Display for MacParseError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "invalid mac address")
    }
}

impl Error for MacParseError {}

impl From<u64> for Mac {
    fn from(value: u64) -> Self {
        let x = value.to_be_bytes();
        Self([x[2], x[3], x[4], x[5], x[6], x[7]])
    }
}

impl From<Mac> for u64 {
    fn from(value: Mac) -> Self {
        let b = value.0;
        let x = [0, 0, b[0], b[1], b[2], b[3], b[4], b[5]];
        u64::from_be_bytes(x)
    }
}

impl FromStr for Mac {
    type Err = MacParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut mac = [0u8; 6];

        let parts = s.chars().filter(|x| *x == ':').count() + 1;

        match s.len() {
            12 if parts == 1 => {
                for i in 0..6 {
                    let j = i * 2;
                    let d = &s[j..=(j + 1)];
                    mac[i] = u8::from_str_radix(d, 16).map_err(|_| MacParseError)?;
                }
            }
            11..=17 if parts == 6 => {
                for (i, d) in s.split(':').enumerate() {
                    mac[i] = u8::from_str_radix(d, 16).map_err(|_| MacParseError)?;
                }
            }
            _ => return Err(MacParseError),
        }

        Ok(Self(mac))
    }
}

impl fmt::Display for Mac {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let b = self.0;
        write!(
            f,
            "{:<02X}:{:<02X}:{:<02X}:{:<02X}:{:<02X}:{:<02X}",
            b[0], b[1], b[2], b[3], b[4], b[5]
        )
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn u64() {
        let mac = Mac::from(78187493530);
        assert_eq!(mac, Mac([0x00, 0x12, 0x34, 0x56, 0x78, 0x9a]));
        assert_eq!(u64::from(mac), 78187493530);
    }

    #[test]
    fn from_str() {
        assert_eq!(
            Mac::from_str("123456789abc"),
            Ok(Mac([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc]))
        );
        assert_eq!(
            Mac::from_str("12:34:56:78:9a:bc"),
            Ok(Mac([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc]))
        );
        assert_eq!(
            Mac::from_str("1:2:3:a:b:c"),
            Ok(Mac([0x1, 0x2, 0x3, 0xa, 0xb, 0xc]))
        );
        assert_eq!(
            Mac::from_str("12:3:0:ab:c:0"),
            Ok(Mac([0x12, 0x3, 0x0, 0xab, 0xc, 0x0]))
        );
        assert_eq!(Mac::from_str(""), Err(MacParseError));
    }
}