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