1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(all(not(feature = "std"), feature = "alloc"))]
4extern crate alloc;
5
6#[cfg(all(not(feature = "std"), feature = "alloc"))]
7use alloc::format;
8
9use core::fmt;
10use core::str::FromStr;
11
12#[cfg(feature = "serde")]
13use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
14
15#[cfg(all(feature = "std", not(feature = "alloc")))]
16use std as alloc_mod;
17#[cfg(all(feature = "alloc", not(feature = "std")))]
18use alloc as alloc_mod;
19
20#[cfg(any(feature = "std", feature = "alloc"))]
21use alloc_mod::string::String;
22
23#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Default, Debug)]
26pub struct MacAddr(pub u8, pub u8, pub u8, pub u8, pub u8, pub u8);
27
28impl MacAddr {
29 #[inline]
31 pub fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> MacAddr {
32 MacAddr(a, b, c, d, e, f)
33 }
34
35 #[inline]
37 pub fn from_octets(octets: [u8; 6]) -> MacAddr {
38 MacAddr(octets[0], octets[1], octets[2], octets[3], octets[4], octets[5])
39 }
40
41 #[inline]
43 pub fn octets(&self) -> [u8; 6] {
44 [self.0, self.1, self.2, self.3, self.4, self.5]
45 }
46
47 #[cfg(any(feature = "std", feature = "alloc"))]
49 #[inline]
50 pub fn address(&self) -> String {
51 format!(
52 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
53 self.0, self.1, self.2, self.3, self.4, self.5
54 )
55 }
56
57 #[inline]
59 pub fn zero() -> MacAddr {
60 MacAddr(0, 0, 0, 0, 0, 0)
61 }
62
63 #[inline]
65 pub fn broadcast() -> MacAddr {
66 MacAddr(0xff, 0xff, 0xff, 0xff, 0xff, 0xff)
67 }
68
69 #[inline]
71 pub fn from_hex_format(hex_mac_addr: &str) -> MacAddr {
72 if hex_mac_addr.len() != 17 {
73 return MacAddr::zero();
74 }
75 let mut fields = hex_mac_addr.split(':');
76 let o1 = u8::from_str_radix(fields.next().unwrap_or_default(), 16).unwrap_or(0);
77 let o2 = u8::from_str_radix(fields.next().unwrap_or_default(), 16).unwrap_or(0);
78 let o3 = u8::from_str_radix(fields.next().unwrap_or_default(), 16).unwrap_or(0);
79 let o4 = u8::from_str_radix(fields.next().unwrap_or_default(), 16).unwrap_or(0);
80 let o5 = u8::from_str_radix(fields.next().unwrap_or_default(), 16).unwrap_or(0);
81 let o6 = u8::from_str_radix(fields.next().unwrap_or_default(), 16).unwrap_or(0);
82 MacAddr(o1, o2, o3, o4, o5, o6)
83 }
84
85 #[inline]
87 pub fn is_multicast(&self) -> bool {
88 self.0 & 0x01 == 0x01
89 }
90
91 #[inline]
93 pub fn is_unicast(&self) -> bool {
94 !self.is_multicast()
95 }
96
97 #[inline]
99 pub fn is_locally_administered(&self) -> bool {
100 self.0 & 0x02 == 0x02
101 }
102
103 #[inline]
105 pub fn is_universal(&self) -> bool {
106 !self.is_locally_administered()
107 }
108
109 #[inline]
111 pub fn oui(&self) -> [u8; 3] {
112 [self.0, self.1, self.2]
113 }
114}
115
116impl fmt::Display for MacAddr {
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119 let _ = write!(
120 f,
121 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
122 self.0, self.1, self.2, self.3, self.4, self.5
123 );
124 Ok(())
125 }
126}
127
128#[derive(Copy, Debug, PartialEq, Eq, Clone)]
130pub enum ParseMacAddrError {
131 TooManyComponents,
133 TooFewComponents,
135 InvalidComponent,
137}
138
139impl fmt::Display for ParseMacAddrError {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 let s = match *self {
142 ParseMacAddrError::TooManyComponents => "Too many components in a MAC address string",
143 ParseMacAddrError::TooFewComponents => "Too few components in a MAC address string",
144 ParseMacAddrError::InvalidComponent => "Invalid component in a MAC address string",
145 };
146 f.write_str(s)
147 }
148}
149
150#[cfg(feature = "std")]
151impl std::error::Error for ParseMacAddrError {}
152
153impl FromStr for MacAddr {
154 type Err = ParseMacAddrError;
155
156 fn from_str(s: &str) -> Result<MacAddr, ParseMacAddrError> {
157 let mut parts = [0u8; 6];
158 let mut i = 0;
159 for split in s.split(':') {
160 if i == 6 {
161 return Err(ParseMacAddrError::TooManyComponents);
162 }
163 match u8::from_str_radix(split, 16) {
164 Ok(b) if !split.is_empty() => parts[i] = b,
165 _ => return Err(ParseMacAddrError::InvalidComponent),
166 }
167 i += 1;
168 }
169 if i == 6 {
170 Ok(MacAddr(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5]))
171 } else {
172 Err(ParseMacAddrError::TooFewComponents)
173 }
174 }
175}
176
177#[cfg(feature = "serde")]
178impl Serialize for MacAddr {
179 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
180 if serializer.is_human_readable() {
181 serializer.collect_str(self)
182 } else {
183 serializer.serialize_bytes(&[self.0, self.1, self.2, self.3, self.4, self.5])
184 }
185 }
186}
187
188#[cfg(feature = "serde")]
189impl<'de> Deserialize<'de> for MacAddr {
190 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
191 struct MacAddrVisitor;
192 impl<'de> de::Visitor<'de> for MacAddrVisitor {
193 type Value = MacAddr;
194
195 fn visit_str<E: de::Error>(self, value: &str) -> Result<MacAddr, E> {
196 value.parse().map_err(E::custom)
197 }
198 fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<MacAddr, E> {
199 if v.len() == 6 {
200 Ok(MacAddr::new(v[0], v[1], v[2], v[3], v[4], v[5]))
201 } else {
202 Err(E::invalid_length(v.len(), &self))
203 }
204 }
205 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
206 f.write_str("either a string MAC address or 6-byte array")
207 }
208 }
209
210 if deserializer.is_human_readable() {
211 deserializer.deserialize_str(MacAddrVisitor)
212 } else {
213 deserializer.deserialize_bytes(MacAddrVisitor)
214 }
215 }
216}
217
218impl From<[u8; 6]> for MacAddr {
219 #[inline]
220 fn from(v: [u8; 6]) -> Self { MacAddr::from_octets(v) }
221}
222
223impl From<MacAddr> for [u8; 6] {
224 #[inline]
225 fn from(m: MacAddr) -> Self { m.octets() }
226}
227
228impl AsRef<[u8; 6]> for MacAddr {
229 #[inline]
233 fn as_ref(&self) -> &[u8; 6] {
234 unsafe { &*(self as *const MacAddr as *const [u8; 6]) }
235 }
236}