1#[cfg(feature = "std")]
10use std::error::Error;
11
12use core::fmt;
13use core::str::FromStr;
14
15#[cfg(feature = "serde")]
16use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
17
18pub const ETHER_ADDR_LEN: usize = 6;
20
21type EtherAddr = [u8; ETHER_ADDR_LEN];
23
24const LOCAL_ADDR_BIT: u8 = 0x02;
25const MULTICAST_ADDR_BIT: u8 = 0x01;
26
27#[derive(PartialEq, Eq, Clone, Copy, Default, Hash, Ord, PartialOrd)]
29pub struct MacAddr(pub u8, pub u8, pub u8, pub u8, pub u8, pub u8);
30
31impl MacAddr {
32 pub fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> MacAddr {
34 MacAddr(a, b, c, d, e, f)
35 }
36
37 pub fn zero() -> MacAddr {
39 Default::default()
40 }
41
42 pub fn broadcast() -> MacAddr {
44 [0xff; ETHER_ADDR_LEN].into()
45 }
46
47 pub fn is_zero(&self) -> bool {
49 *self == Self::zero()
50 }
51
52 pub fn is_universal(&self) -> bool {
54 !self.is_local()
55 }
56
57 pub fn is_local(&self) -> bool {
59 (self.0 & LOCAL_ADDR_BIT) == LOCAL_ADDR_BIT
60 }
61
62 pub fn is_unicast(&self) -> bool {
64 !self.is_multicast()
65 }
66
67 pub fn is_multicast(&self) -> bool {
69 (self.0 & MULTICAST_ADDR_BIT) == MULTICAST_ADDR_BIT
70 }
71
72 pub fn is_broadcast(&self) -> bool {
74 *self == Self::broadcast()
75 }
76
77 pub fn octets(&self) -> [u8; 6] {
79 [self.0, self.1, self.2, self.3, self.4, self.5]
80 }
81}
82
83impl From<EtherAddr> for MacAddr {
84 fn from(addr: EtherAddr) -> MacAddr {
85 MacAddr(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
86 }
87}
88
89impl From<MacAddr> for EtherAddr {
90 fn from(addr: MacAddr) -> Self {
91 [addr.0, addr.1, addr.2, addr.3, addr.4, addr.5]
92 }
93}
94
95impl PartialEq<EtherAddr> for MacAddr {
96 fn eq(&self, other: &EtherAddr) -> bool {
97 *self == MacAddr::from(*other)
98 }
99}
100
101impl fmt::Display for MacAddr {
102 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
103 write!(
104 fmt,
105 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
106 self.0, self.1, self.2, self.3, self.4, self.5
107 )
108 }
109}
110
111#[cfg(feature = "serde")]
112impl Serialize for MacAddr {
113 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
118 if serializer.is_human_readable() {
119 serializer.collect_str(self)
120 } else {
121 serializer.serialize_bytes(&[self.0, self.1, self.2, self.3, self.4, self.5])
122 }
123 }
124}
125
126#[cfg(feature = "serde")]
127impl<'de> Deserialize<'de> for MacAddr {
128 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
134 struct MacAddrVisitor;
135 impl<'de> de::Visitor<'de> for MacAddrVisitor {
136 type Value = MacAddr;
137
138 fn visit_str<E: de::Error>(self, value: &str) -> Result<MacAddr, E> {
139 value.parse().map_err(|err| E::custom(err))
140 }
141
142 fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<MacAddr, E> {
143 if v.len() == 6 {
144 Ok(MacAddr::new(v[0], v[1], v[2], v[3], v[4], v[5]))
145 } else {
146 Err(E::invalid_length(v.len(), &self))
147 }
148 }
149
150 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
151 write!(
152 formatter,
153 "either a string representation of a MAC address or 6-element byte array"
154 )
155 }
156 }
157
158 if deserializer.is_human_readable() {
160 deserializer.deserialize_str(MacAddrVisitor)
161 } else {
162 deserializer.deserialize_bytes(MacAddrVisitor)
163 }
164 }
165}
166
167impl fmt::Debug for MacAddr {
168 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
169 fmt::Display::fmt(self, fmt)
170 }
171}
172
173#[derive(Copy, Debug, PartialEq, Eq, Clone)]
175pub enum ParseMacAddrErr {
176 TooManyComponents,
178 TooFewComponents,
180 InvalidComponent,
182}
183
184#[cfg(feature = "std")]
185impl Error for ParseMacAddrErr {}
186
187impl ParseMacAddrErr {
188 fn description(&self) -> &str {
189 match *self {
190 ParseMacAddrErr::TooManyComponents => "Too many components in a MAC address string",
191 ParseMacAddrErr::TooFewComponents => "Too few components in a MAC address string",
192 ParseMacAddrErr::InvalidComponent => "Invalid component in a MAC address string",
193 }
194 }
195}
196
197impl fmt::Display for ParseMacAddrErr {
198 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199 write!(f, "{}", self.description())
200 }
201}
202
203impl FromStr for MacAddr {
204 type Err = ParseMacAddrErr;
205 fn from_str(s: &str) -> Result<MacAddr, ParseMacAddrErr> {
206 let mut parts = [0u8; 6];
207 let splits = s.split(':');
208 let mut i = 0;
209 for split in splits {
210 if i == 6 {
211 return Err(ParseMacAddrErr::TooManyComponents);
212 }
213 match u8::from_str_radix(split, 16) {
214 Ok(b) if split.len() != 0 => parts[i] = b,
215 _ => return Err(ParseMacAddrErr::InvalidComponent),
216 }
217 i += 1;
218 }
219
220 if i == 6 {
221 Ok(MacAddr(
222 parts[0], parts[1], parts[2], parts[3], parts[4], parts[5],
223 ))
224 } else {
225 Err(ParseMacAddrErr::TooFewComponents)
226 }
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use super::*;
233
234 #[test]
235 fn mac_addr_from_str() {
236 assert_eq!("00:00:00:00:00:00".parse(), Ok(MacAddr::zero()));
237 assert_eq!("ff:ff:ff:ff:ff:ff".parse(), Ok(MacAddr::broadcast()));
238 assert_eq!(
239 "12:34:56:78:90:ab".parse(),
240 Ok(MacAddr(0x12, 0x34, 0x56, 0x78, 0x90, 0xAB))
241 );
242 assert_eq!(
243 "::::::".parse::<MacAddr>(),
244 Err(ParseMacAddrErr::InvalidComponent)
245 );
246 assert_eq!(
247 "0::::::".parse::<MacAddr>(),
248 Err(ParseMacAddrErr::InvalidComponent)
249 );
250 assert_eq!(
251 "::::0::".parse::<MacAddr>(),
252 Err(ParseMacAddrErr::InvalidComponent)
253 );
254 assert_eq!(
255 "12:34:56:78".parse::<MacAddr>(),
256 Err(ParseMacAddrErr::TooFewComponents)
257 );
258 assert_eq!(
259 "12:34:56:78:".parse::<MacAddr>(),
260 Err(ParseMacAddrErr::InvalidComponent)
261 );
262 assert_eq!(
263 "12:34:56:78:90".parse::<MacAddr>(),
264 Err(ParseMacAddrErr::TooFewComponents)
265 );
266 assert_eq!(
267 "12:34:56:78:90:".parse::<MacAddr>(),
268 Err(ParseMacAddrErr::InvalidComponent)
269 );
270 assert_eq!(
271 "12:34:56:78:90:00:00".parse::<MacAddr>(),
272 Err(ParseMacAddrErr::TooManyComponents)
273 );
274 assert_eq!(
275 "xx:xx:xx:xx:xx:xx".parse::<MacAddr>(),
276 Err(ParseMacAddrErr::InvalidComponent)
277 );
278 }
279
280 #[test]
281 fn str_from_mac_addr() {
282 assert_eq!(format!("{}", MacAddr::zero()), "00:00:00:00:00:00");
283 assert_eq!(format!("{}", MacAddr::broadcast()), "ff:ff:ff:ff:ff:ff");
284 assert_eq!(
285 format!("{}", MacAddr(0x12, 0x34, 0x56, 0x78, 0x09, 0xAB)),
286 "12:34:56:78:09:ab"
287 );
288 }
289
290 #[test]
291 fn fixed_size_slice_from_mac_addr() {
292 assert_eq!(
293 MacAddr(0x00, 0x01, 0x02, 0x03, 0x04, 0x05).octets(),
294 [0x00, 0x01, 0x02, 0x03, 0x04, 0x05]
295 );
296 }
297
298 #[test]
299 fn type_of_addr() {
300 assert!(MacAddr::zero().is_zero());
301 assert!(MacAddr::broadcast().is_broadcast());
302
303 let mac = MacAddr(0x12, 0x34, 0x56, 0x78, 0x90, 0xAB);
304 assert!(mac.is_local());
305 assert!(mac.is_unicast());
306
307 let mac = MacAddr(0xac, 0x87, 0xa3, 0x07, 0x32, 0xb8);
308 assert!(mac.is_universal());
309 assert!(mac.is_unicast());
310 }
311
312 #[test]
313 fn conversion() {
314 let mac = MacAddr(0x12, 0x34, 0x56, 0x78, 0x90, 0xAB);
315 let addr = [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB];
316
317 assert_eq!(mac, MacAddr::from(addr));
318 assert_eq!(addr, EtherAddr::from(mac));
319 assert!(mac == addr);
320 }
321
322 #[cfg(feature = "serde")]
323 mod serde {
324 extern crate serde_test;
325 use self::serde_test::{
326 assert_de_tokens, assert_de_tokens_error, assert_tokens, Compact, Configure, Readable,
327 Token,
328 };
329 use super::*;
330
331 #[test]
332 fn string() {
333 let mac = MacAddr::new(0x11, 0x22, 0x33, 0x44, 0x55, 0x66);
334 assert_tokens(&mac.readable(), &[Token::Str("11:22:33:44:55:66")]);
335 assert_de_tokens(&mac.readable(), &[Token::String("11:22:33:44:55:66")]);
336 assert_de_tokens(&mac.readable(), &[Token::BorrowedStr("11:22:33:44:55:66")]);
337 assert_de_tokens_error::<Readable<MacAddr>>(
338 &[Token::Str("not an address")],
339 "Invalid component in a MAC address string",
340 );
341 assert_de_tokens(
343 &mac.readable(),
344 &[Token::Bytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66])],
345 );
346 }
347
348 #[test]
349 fn bytes() {
350 let mac = MacAddr::new(0x11, 0x22, 0x33, 0x44, 0x55, 0x66);
351 assert_tokens(
352 &mac.compact(),
353 &[Token::Bytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66])],
354 );
355 assert_de_tokens(
356 &mac.compact(),
357 &[Token::BorrowedBytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66])],
358 );
359 let err = "invalid length 2, expected either a string representation of a MAC address or 6-element byte array";
360 assert_de_tokens_error::<Compact<MacAddr>>(&[Token::Bytes(&[0x11, 0x33])], err);
361 let err = "invalid length 7, expected either a string representation of a MAC address or 6-element byte array";
362 assert_de_tokens_error::<Compact<MacAddr>>(
363 &[Token::Bytes(&[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77])],
364 err,
365 );
366 assert_de_tokens(&mac.compact(), &[Token::Str("11:22:33:44:55:66")]);
368 }
369 }
370}