1use std::fmt;
2
3#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
6pub enum MacAddressFormat {
7 #[default]
8 Eui48,
9 Eui64,
10}
11
12impl MacAddressFormat {
13 pub fn accepts(self, mac: MacAddress) -> bool {
14 matches!(
15 (self, mac),
16 (Self::Eui48, MacAddress::Eui48(_)) | (Self::Eui64, MacAddress::Eui64(_))
17 )
18 }
19}
20
21#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
26pub enum MacAddress {
27 Eui48([u8; 6]),
28 Eui64([u8; 8]),
29}
30
31impl MacAddress {
32 pub const BROADCAST_EUI48: Self = Self::Eui48([0xff; 6]);
34 pub const BROADCAST_EUI64: Self = Self::Eui64([0xff; 8]);
36 pub const BROADCAST: Self = Self::BROADCAST_EUI48;
38
39 pub const fn new_eui48(octets: [u8; 6]) -> Self {
40 Self::Eui48(octets)
41 }
42
43 pub const fn new_eui64(octets: [u8; 8]) -> Self {
44 Self::Eui64(octets)
45 }
46
47 pub fn as_bytes(&self) -> &[u8] {
49 match self {
50 MacAddress::Eui48(o) => o,
51 MacAddress::Eui64(o) => o,
52 }
53 }
54
55 #[allow(clippy::len_without_is_empty)]
57 pub const fn len(&self) -> usize {
58 match self {
59 MacAddress::Eui48(_) => 6,
60 MacAddress::Eui64(_) => 8,
61 }
62 }
63
64 pub const fn is_eui48(&self) -> bool {
66 matches!(self, MacAddress::Eui48(_))
67 }
68
69 pub const fn is_eui64(&self) -> bool {
71 matches!(self, MacAddress::Eui64(_))
72 }
73}
74
75impl fmt::Debug for MacAddress {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 write!(f, "MacAddress({})", self)
78 }
79}
80
81impl fmt::Display for MacAddress {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 let mut first = true;
84 for byte in self.as_bytes() {
85 if first {
86 first = false;
87 } else {
88 write!(f, ":")?;
89 }
90 write!(f, "{byte:02x}")?;
91 }
92 Ok(())
93 }
94}
95
96impl From<[u8; 6]> for MacAddress {
97 fn from(v: [u8; 6]) -> Self {
98 Self::Eui48(v)
99 }
100}
101
102impl From<[u8; 8]> for MacAddress {
103 fn from(v: [u8; 8]) -> Self {
104 Self::Eui64(v)
105 }
106}