1#![doc(
14 html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
15 html_favicon_url = "https://www.rust-lang.org/favicon.ico",
16 html_root_url = "https://doc.rust-lang.org/eui48/"
17)]
18
19extern crate regex;
20#[cfg(feature = "rustc-serialize")]
21extern crate rustc_serialize;
22#[cfg(feature = "serde")]
23extern crate serde;
24#[cfg(feature = "serde_json")]
25extern crate serde_json;
26
27use std::default::Default;
28use std::error::Error;
29use std::fmt;
30use std::str::FromStr;
31
32use regex::Regex;
33#[cfg(feature = "rustc-serialize")]
34use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
35#[cfg(feature = "serde")]
36use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
37
38pub const EUI48LEN: usize = 6;
40pub type Eui48 = [u8; EUI48LEN];
41
42pub const EUI64LEN: usize = 8;
44pub type Eui64 = [u8; EUI64LEN];
45
46#[repr(C)]
48#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
49pub struct MacAddress {
50 eui: Eui48,
52}
53
54#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
55pub enum MacAddressFormat {
57 Canonical,
59 HexString,
61 DotNotation,
63 Hexadecimal,
65}
66
67#[derive(PartialEq, Eq, Copy, Clone, Debug, Ord, PartialOrd, Hash)]
68pub enum ParseError {
70 InvalidLength(usize),
72 InvalidByteCount(usize, Eui48),
74}
75
76impl MacAddress {
77 pub const fn new(eui: Eui48) -> MacAddress {
79 MacAddress { eui }
80 }
81
82 pub fn from_bytes(bytes: &[u8]) -> Result<Self, ParseError> {
86 if bytes.len() != EUI48LEN {
87 return Err(ParseError::InvalidLength(bytes.len()));
88 }
89 let mut input: [u8; EUI48LEN] = Default::default();
90 input[..EUI48LEN].clone_from_slice(&bytes[..EUI48LEN]);
91 Ok(Self::new(input))
92 }
93
94 pub fn nil() -> MacAddress {
96 MacAddress { eui: [0; EUI48LEN] }
97 }
98
99 pub fn broadcast() -> MacAddress {
101 MacAddress {
102 eui: [0xFF; EUI48LEN],
103 }
104 }
105
106 pub fn is_nil(&self) -> bool {
108 self.eui.iter().all(|&b| b == 0)
109 }
110
111 pub fn is_broadcast(&self) -> bool {
113 self.eui.iter().all(|&b| b == 0xFF)
114 }
115
116 pub fn is_unicast(&self) -> bool {
118 self.eui[0] & 1 == 0
119 }
120
121 pub fn is_multicast(&self) -> bool {
123 self.eui[0] & 1 == 1
124 }
125
126 pub fn is_universal(&self) -> bool {
128 self.eui[0] & 1 << 1 == 0
129 }
130
131 pub fn is_local(&self) -> bool {
133 self.eui[0] & 1 << 1 == 2
134 }
135
136 pub fn to_canonical(&self) -> String {
138 format!(
139 "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}",
140 self.eui[0], self.eui[1], self.eui[2], self.eui[3], self.eui[4], self.eui[5]
141 )
142 }
143
144 pub fn to_hex_string(&self) -> String {
146 format!(
147 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
148 self.eui[0], self.eui[1], self.eui[2], self.eui[3], self.eui[4], self.eui[5]
149 )
150 }
151
152 pub fn to_dot_string(&self) -> String {
154 format!(
155 "{:02x}{:02x}.{:02x}{:02x}.{:02x}{:02x}",
156 self.eui[0], self.eui[1], self.eui[2], self.eui[3], self.eui[4], self.eui[5]
157 )
158 }
159
160 pub fn to_hexadecimal(&self) -> String {
162 format!(
163 "0x{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
164 self.eui[0], self.eui[1], self.eui[2], self.eui[3], self.eui[4], self.eui[5]
165 )
166 }
167
168 pub fn to_interfaceid(&self) -> String {
170 format!(
171 "{:02x}{:02x}:{:02x}ff:fe{:02x}:{:02x}{:02x}",
172 (self.eui[0] ^ 0x02),
173 self.eui[1],
174 self.eui[2],
175 self.eui[3],
176 self.eui[4],
177 self.eui[5]
178 )
179 }
180
181 pub fn to_link_local(&self) -> String {
183 format!(
184 "fe80::{:02x}{:02x}:{:02x}ff:fe{:02x}:{:02x}{:02x}",
185 (self.eui[0] ^ 0x02),
186 self.eui[1],
187 self.eui[2],
188 self.eui[3],
189 self.eui[4],
190 self.eui[5]
191 )
192 }
193
194 pub fn to_string(&self, fmt: MacAddressFormat) -> String {
196 match fmt {
197 MacAddressFormat::Canonical => self.to_canonical(),
198 MacAddressFormat::HexString => self.to_hex_string(),
199 MacAddressFormat::DotNotation => self.to_dot_string(),
200 MacAddressFormat::Hexadecimal => self.to_hexadecimal(),
201 }
202 }
203
204 pub fn parse_str(s: &str) -> Result<MacAddress, ParseError> {
206 let re = Regex::new("(0x)?([0-9a-fA-F]{1,2})[:.-]?").unwrap();
207 let mut eui: Eui48 = [0; EUI48LEN];
208
209 match s.len() {
210 11..=17 => {}
211 _ => {
212 return Err(ParseError::InvalidLength(s.len()));
213 }
214 }
215
216 let mut i = 0;
217 for caps in re.captures_iter(s) {
218 if i < EUI48LEN {
220 let matched_byte = caps.get(2).unwrap().as_str();
221 eui[i] = u8::from_str_radix(matched_byte, 16).unwrap();
222 }
223 i += 1;
224 }
225
226 if i != EUI48LEN {
227 return Err(ParseError::InvalidByteCount(i, eui));
228 }
229
230 Ok(MacAddress::new(eui))
231 }
232
233 pub fn as_bytes(&self) -> &[u8] {
235 &self.eui
236 }
237
238 pub fn to_array(&self) -> Eui48 {
240 self.eui
241 }
242
243 pub fn get_display_format() -> MacAddressFormat {
245 if cfg!(feature = "disp_hexstring") {
246 MacAddressFormat::HexString
247 } else {
248 MacAddressFormat::Canonical
249 }
250 }
251}
252
253impl FromStr for MacAddress {
254 type Err = ParseError;
255 fn from_str(us: &str) -> Result<MacAddress, ParseError> {
257 MacAddress::parse_str(us)
258 }
259}
260
261impl Default for MacAddress {
262 fn default() -> MacAddress {
264 MacAddress::nil()
265 }
266}
267
268impl fmt::Debug for MacAddress {
269 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
271 write!(
272 f,
273 "MacAddress(\"{}\")",
274 self.to_string(MacAddressFormat::HexString)
275 )
276 }
277}
278
279impl fmt::Display for MacAddress {
280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
282 let disp_fmt = MacAddress::get_display_format();
283 write!(f, "{}", self.to_string(disp_fmt))
284 }
285}
286
287impl fmt::Display for ParseError {
288 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
290 match *self {
291 ParseError::InvalidLength(found) => write!(
292 f,
293 "Invalid length; expecting 11 to 17 chars, found {}",
294 found
295 ),
296 ParseError::InvalidByteCount(found, eui) => write!(
297 f,
298 "Invalid byte count; Matched `{}` bytes ({:?})",
299 found,
300 &eui[..found]
301 ),
302 }
303 }
304}
305
306impl Error for ParseError {
307 fn description(&self) -> &str {
309 "MacAddress parse error"
310 }
311}
312
313#[cfg(feature = "rustc-serialize")]
314impl Encodable for MacAddress {
315 fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
317 let disp_fmt = MacAddress::get_display_format();
318 e.emit_str(&self.to_string(disp_fmt))
319 }
320}
321
322#[cfg(feature = "rustc-serialize")]
323impl Decodable for MacAddress {
324 fn decode<D: Decoder>(d: &mut D) -> Result<MacAddress, D::Error> {
326 let string = d.read_str()?;
327 string.parse().map_err(|err| d.error(&format!("{}", err)))
328 }
329}
330
331#[cfg(all(feature = "serde", not(feature = "serde_bytes")))]
332impl Serialize for MacAddress {
333 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
335 let disp_fmt = MacAddress::get_display_format();
336 serializer.serialize_str(&self.to_string(disp_fmt))
337 }
338}
339
340#[cfg(feature = "serde_bytes")]
341impl Serialize for MacAddress {
342 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
344 serializer.serialize_bytes(self.as_bytes())
345 }
346}
347
348#[cfg(all(feature = "serde", not(feature = "serde_bytes")))]
349impl<'de> Deserialize<'de> for MacAddress {
350 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
352 struct MacAddressVisitor;
353 impl<'de> de::Visitor<'de> for MacAddressVisitor {
354 type Value = MacAddress;
355
356 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
357 write!(formatter, "a string representation of a MAC address")
358 }
359
360 fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
361 value.parse().map_err(|err| E::custom(&format!("{}", err)))
362 }
363 }
364 deserializer.deserialize_str(MacAddressVisitor)
365 }
366}
367
368#[cfg(feature = "serde_bytes")]
369impl<'de> Deserialize<'de> for MacAddress {
370 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
372 struct MacAddressVisitor;
373 impl<'de> de::Visitor<'de> for MacAddressVisitor {
374 type Value = MacAddress;
375
376 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
377 write!(formatter, "6-element byte array")
378 }
379
380 fn visit_bytes<E: de::Error>(self, value: &[u8]) -> Result<Self::Value, E> {
381 MacAddress::from_bytes(value).map_err(|_| E::invalid_length(value.len(), &self))
382 }
383 }
384 deserializer.deserialize_bytes(MacAddressVisitor)
385 }
386}
387
388#[cfg(test)]
390mod tests {
391 use super::{Eui48, MacAddress, MacAddressFormat, ParseError};
392
393 #[test]
394 fn test_new() {
395 let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
396 let mac = MacAddress::new(eui);
397
398 assert!(mac.eui[0..5] == eui[0..5]);
399 }
400
401 #[test]
402 fn test_from_bytes() {
403 assert_eq!(
404 "12:34:56:ab:cd:ef",
405 MacAddress::from_bytes(&[0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF])
406 .unwrap()
407 .to_hex_string()
408 );
409 assert!(MacAddress::from_bytes(&[0x12, 0x34, 0x56, 0xAB, 0xCD]).is_err());
410 }
411
412 #[test]
413 fn test_nil() {
414 let nil = MacAddress::nil();
415 let not_nil = MacAddress::broadcast();
416 assert_eq!("00:00:00:00:00:00", nil.to_hex_string());
417 assert!(nil.is_nil());
418 assert!(!not_nil.is_nil());
419 }
420
421 #[test]
422 fn test_default() {
423 let default = MacAddress::default();
424 assert!(default.is_nil());
425 }
426
427 #[test]
428 fn test_broadcast() {
429 let broadcast = MacAddress::broadcast();
430 let not_broadcast = MacAddress::nil();
431 assert_eq!("ff:ff:ff:ff:ff:ff", broadcast.to_hex_string());
432 assert!(broadcast.is_broadcast());
433 assert!(!not_broadcast.is_broadcast());
434 }
435
436 #[test]
437 fn test_is_nil() {
438 let nil = MacAddress::nil();
439 let not_nil = MacAddress::parse_str("01:00:5E:AB:CD:EF").unwrap();
440 assert!(nil.is_nil());
441 assert!(!not_nil.is_nil());
442 }
443
444 #[test]
445 fn test_is_broadcast() {
446 let broadcast = MacAddress::broadcast();
447 let not_broadcast = MacAddress::parse_str("01:00:5E:AB:CD:EF").unwrap();
448 assert!(broadcast.is_broadcast());
449 assert!(!not_broadcast.is_broadcast());
450 }
451
452 #[test]
453 fn test_is_unicast() {
454 let mac_u = MacAddress::parse_str("FE:00:5E:AB:CD:EF").unwrap();
455 let mac_m = MacAddress::parse_str("01:00:5E:AB:CD:EF").unwrap();
456 assert!(mac_u.is_unicast());
457 assert!(!mac_m.is_unicast());
458 assert_eq!("fe:00:5e:ab:cd:ef", mac_u.to_hex_string()); let mac = MacAddress::parse_str("FF:00:5E:AB:CD:EF").unwrap();
460 assert!(!mac.is_unicast());
461 assert_eq!("ff:00:5e:ab:cd:ef", mac.to_hex_string()); assert!(MacAddress::nil().is_unicast());
463 assert!(!MacAddress::broadcast().is_unicast());
464 }
465
466 #[test]
467 fn test_is_multicast() {
468 let mac_u = MacAddress::parse_str("FE:00:5E:AB:CD:EF").unwrap();
469 let mac_m = MacAddress::parse_str("01:00:5E:AB:CD:EF").unwrap();
470 assert!(!mac_u.is_multicast());
471 assert!(mac_m.is_multicast());
472 assert!(!MacAddress::nil().is_multicast());
473 assert_eq!("01:00:5e:ab:cd:ef", mac_m.to_hex_string()); let mac = MacAddress::parse_str("F0:00:5E:AB:CD:EF").unwrap();
475 assert!(!mac.is_multicast());
476 assert_eq!("f0:00:5e:ab:cd:ef", mac.to_hex_string()); assert!(MacAddress::broadcast().is_multicast());
478 }
479
480 #[test]
481 fn test_is_universal() {
482 let universal = MacAddress::parse_str("11:24:56:AB:CD:EF").unwrap();
483 let not_universal = MacAddress::parse_str("12:24:56:AB:CD:EF").unwrap();
484 assert!(universal.is_universal());
485 assert!(!not_universal.is_universal());
486 assert_eq!("11:24:56:ab:cd:ef", universal.to_hex_string()); }
488
489 #[test]
490 fn test_is_local() {
491 let local = MacAddress::parse_str("06:34:56:AB:CD:EF").unwrap();
492 let not_local = MacAddress::parse_str("00:34:56:AB:CD:EF").unwrap();
493 assert!(local.is_local());
494 assert!(!not_local.is_local());
495 assert_eq!("06:34:56:ab:cd:ef", local.to_hex_string()); }
497
498 #[test]
499 fn test_to_canonical() {
500 let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
501 let mac = MacAddress::new(eui);
502 assert_eq!("12-34-56-ab-cd-ef", mac.to_canonical());
503 }
504
505 #[test]
506 fn test_to_hex_string() {
507 let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
508 let mac = MacAddress::new(eui);
509 assert_eq!("12:34:56:ab:cd:ef", mac.to_hex_string());
510 }
511
512 #[test]
513 fn test_to_dot_string() {
514 let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
515 let mac = MacAddress::new(eui);
516 assert_eq!("1234.56ab.cdef", mac.to_dot_string());
517 }
518
519 #[test]
520 fn test_to_hexadecimal() {
521 let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
522 let mac = MacAddress::new(eui);
523 assert_eq!("0x123456abcdef", mac.to_hexadecimal());
524 }
525
526 #[test]
527 fn test_to_interfaceid() {
528 let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
529 let mac = MacAddress::new(eui);
530 assert_eq!("1034:56ff:feab:cdef", mac.to_interfaceid());
531 }
532
533 #[test]
534 fn test_to_link_local() {
535 let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
536 let mac = MacAddress::new(eui);
537 assert_eq!("fe80::1034:56ff:feab:cdef", mac.to_link_local());
538 }
539
540 #[test]
541 fn test_to_string() {
542 let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
543 let mac = MacAddress::new(eui);
544 assert_eq!(
545 "0x123456abcdef",
546 mac.to_string(MacAddressFormat::Hexadecimal)
547 );
548 assert_eq!(
549 "1234.56ab.cdef",
550 mac.to_string(MacAddressFormat::DotNotation)
551 );
552 assert_eq!(
553 "12:34:56:ab:cd:ef",
554 mac.to_string(MacAddressFormat::HexString)
555 );
556 assert_eq!(
557 "12-34-56-ab-cd-ef",
558 mac.to_string(MacAddressFormat::Canonical)
559 );
560 }
561
562 #[test]
563 fn test_parse_str() {
564 use super::ParseError::*;
565
566 assert_eq!(
567 "0x123456abcdef",
568 MacAddress::parse_str("0x123456ABCDEF")
569 .unwrap()
570 .to_hexadecimal()
571 );
572 assert_eq!(
573 "1234.56ab.cdef",
574 MacAddress::parse_str("1234.56AB.CDEF")
575 .unwrap()
576 .to_dot_string()
577 );
578 assert_eq!(
579 "12:34:56:ab:cd:ef",
580 MacAddress::parse_str("12:34:56:AB:CD:EF")
581 .unwrap()
582 .to_hex_string()
583 );
584 assert_eq!(
585 "12-34-56-ab-cd-ef",
586 MacAddress::parse_str("12-34-56-AB-CD-EF")
587 .unwrap()
588 .to_canonical()
589 );
590 assert_eq!(
591 "12-34-56-78-90-0a",
592 MacAddress::parse_str("0x1234567890A")
593 .unwrap()
594 .to_canonical()
595 );
596 assert_eq!(
597 "12-34-56-ab-cd-ef",
598 MacAddress::parse_str("123456ABCDEF")
599 .unwrap()
600 .to_canonical()
601 );
602 assert_eq!(
603 "00-00-00-00-00-00",
604 MacAddress::parse_str("!0x00000000000")
605 .unwrap()
606 .to_canonical()
607 );
608 assert_eq!(
609 "00-00-00-00-00-00",
610 MacAddress::parse_str("0x00000000000!")
611 .unwrap()
612 .to_canonical()
613 );
614 assert_eq!(MacAddress::parse_str(""), Err(InvalidLength(0)));
616 assert_eq!(MacAddress::parse_str("0"), Err(InvalidLength(1)));
617 assert_eq!(
618 MacAddress::parse_str("1234567890ABCD"),
619 Err(InvalidByteCount(7, [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB]))
620 );
621 assert_eq!(
622 MacAddress::parse_str("1234567890ABCDEF"),
623 Err(InvalidByteCount(8, [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB]))
624 );
625 assert_eq!(
626 MacAddress::parse_str("01234567890ABCDEF"),
627 Err(InvalidByteCount(9, [0x01, 0x23, 0x45, 0x67, 0x89, 0x0A]))
628 );
629 assert_eq!(
630 MacAddress::parse_str("0x1234567890ABCDE"),
631 Err(InvalidByteCount(8, [0x12, 0x34, 0x56, 0x78, 0x90, 0xAB]))
632 );
633 assert_eq!(
634 MacAddress::parse_str("0x00:01:02:03:"),
635 Err(InvalidByteCount(4, [0, 1, 2, 3, 0, 0]))
636 );
637 assert_eq!(
638 MacAddress::parse_str("0x00:01:02:03:04:"),
639 Err(InvalidByteCount(5, [0, 1, 2, 3, 4, 0]))
640 );
641 assert_eq!(
642 MacAddress::parse_str("::::::::::::::"),
643 Err(InvalidByteCount(0, [0, 0, 0, 0, 0, 0]))
644 );
645 assert_eq!(
646 MacAddress::parse_str(":::::::::::::::::"),
647 Err(InvalidByteCount(0, [0, 0, 0, 0, 0, 0]))
648 );
649 assert_eq!(
650 MacAddress::parse_str("0x0x0x0x0x0x0x"),
651 Err(InvalidByteCount(4, [0, 0, 0, 0, 0, 0]))
652 );
653 }
654
655 #[test]
656 fn test_as_bytes() {
657 let mac = MacAddress::broadcast();
658 let bytes = mac.as_bytes();
659
660 assert!(bytes.len() == 6);
661 assert!(bytes.iter().all(|&b| b == 0xFF));
662 }
663
664 #[test]
665 fn test_compare() {
666 let m1 = MacAddress::nil();
667 let m2 = MacAddress::broadcast();
668 assert_eq!(m1, m1);
669 assert_eq!(m2, m2);
670 assert_ne!(m1, m2);
671 assert_ne!(m2, m1);
672 }
673
674 #[test]
675 fn test_clone() {
676 let m1 = MacAddress::parse_str("12:34:56:AB:CD:EF").unwrap();
677 let m2 = m1;
678 assert_eq!(m1, m1);
679 assert_eq!(m2, m2);
680 assert_eq!(m1, m2);
681 assert_eq!(m2, m1);
682 }
683
684 #[test]
685 fn test_serialize() {
686 use rustc_serialize::json;
687
688 let mac = MacAddress::parse_str("12:34:56:AB:CD:EF").unwrap();
689 if cfg!(feature = "disp_hexstring") {
691 assert_eq!("\"12:34:56:ab:cd:ef\"", json::encode(&mac).unwrap());
692 } else {
693 assert_eq!("\"12-34-56-ab-cd-ef\"", json::encode(&mac).unwrap());
694 }
695 }
696
697 #[test]
698 fn test_deserialize() {
699 use rustc_serialize::json;
700
701 let mac = MacAddress::parse_str("12:34:56:AB:CD:EF").unwrap();
702
703 if cfg!(feature = "disp_hexstring") {
704 let d = "\"12:34:56:AB:CD:EF\"";
705 assert_eq!(mac, json::decode(&d).unwrap());
706 } else {
707 let d = "\"12-34-56-AB-CD-EF\"";
708 assert_eq!(mac, json::decode(&d).unwrap());
709 }
710 }
711
712 #[test]
713 fn test_serialize_roundtrip() {
714 use rustc_serialize::json;
715
716 let m1 = MacAddress::parse_str("12:34:56:AB:CD:EF").unwrap();
717 let s = json::encode(&m1).unwrap();
718 let m2 = json::decode(&s).unwrap();
719 assert_eq!(m1, m2);
720 }
721
722 #[test]
723 fn test_fmt_debug() {
724 let mac = MacAddress::parse_str("12:34:56:AB:CD:EF").unwrap();
725 assert_eq!(
726 "MacAddress(\"12:34:56:ab:cd:ef\")".to_owned(),
727 format!("{:?}", mac)
728 );
729 }
730
731 #[test]
732 fn test_fmt() {
733 let mac = MacAddress::parse_str("0x123456ABCDEF").unwrap();
734 match MacAddress::get_display_format() {
735 MacAddressFormat::HexString => {
736 assert_eq!("12:34:56:ab:cd:ef".to_owned(), format!("{}", mac))
737 }
738 _ => assert_eq!("12-34-56-ab-cd-ef".to_owned(), format!("{}", mac)),
739 };
740 }
741
742 #[test]
743 fn test_fmt_parse_errors() {
744 assert_eq!(
745 "Err(InvalidByteCount(7, [18, 52, 86, 171, 205, 239]))".to_owned(),
746 format!("{:?}", MacAddress::parse_str("123456ABCDEF1"))
747 );
748 assert_eq!(
749 "Err(InvalidLength(19))",
750 format!("{:?}", MacAddress::parse_str("12##45#67#89#AB#C#D"))
751 );
752 }
753
754 #[test]
755 #[cfg(feature = "serde_json")]
756 fn test_serde_json_serialize() {
757 use serde_json;
758 let serialized =
759 serde_json::to_string(&MacAddress::parse_str("12:34:56:AB:CD:EF").unwrap()).unwrap();
760 if cfg!(feature = "disp_hexstring") {
761 assert_eq!("\"12:34:56:ab:cd:ef\"", serialized);
762 } else {
763 assert_eq!("\"12-34-56-ab-cd-ef\"", serialized);
764 }
765 }
766
767 #[test]
768 #[cfg(feature = "serde_json")]
769 fn test_serde_json_deserialize() {
770 use serde_json;
771 let mac = MacAddress::parse_str("12:34:56:AB:CD:EF").unwrap();
772 let deserialized: MacAddress = serde_json::from_str("\"12-34-56-AB-CD-EF\"").unwrap();
773 assert_eq!(deserialized, mac);
774 }
775
776 #[test]
777 #[should_panic(expected = "Invalid length; expecting 11 to 17 chars, found 2")]
778 #[cfg(feature = "serde_json")]
779 fn test_serde_json_deserialize_panic() {
780 let _should_panic: MacAddress = serde_json::from_str("\"12\"").unwrap();
781 }
782
783 #[test]
784 #[cfg(feature = "serde_bytes")]
785 fn test_serde_bytes_serialization_roundtrip() {
786 use bincode;
787 let mac = MacAddress::parse_str("12:34:56:AB:CD:EF").unwrap();
788 let mut buffer = Vec::new();
789 bincode::serialize_into(&mut buffer, &mac).unwrap();
790 let deserialized: MacAddress = bincode::deserialize_from(&*buffer).unwrap();
791 assert_eq!(deserialized, mac);
792 }
793
794 #[test]
795 fn test_macaddressformat_derive() {
796 assert_eq!(MacAddressFormat::HexString, MacAddressFormat::HexString);
797 assert_ne!(MacAddressFormat::HexString, MacAddressFormat::Canonical);
798 }
799
800 #[test]
801 fn test_parseerror_fmt() {
802 assert_eq!(
803 "Invalid length; expecting 11 to 17 chars, found 2".to_owned(),
804 format!("{}", ParseError::InvalidLength(2))
805 );
806 assert_eq!(
807 "Invalid length; expecting 11 to 17 chars, found 2".to_owned(),
808 ParseError::InvalidLength(2).to_string()
809 );
810 }
811
812 #[test]
813 fn test_to_array() {
814 let eui: Eui48 = [0x12, 0x34, 0x56, 0xAB, 0xCD, 0xEF];
815 let mac = MacAddress::new(eui);
816 assert_eq!(eui, MacAddress::new(eui).to_array());
817 assert_eq!(mac, MacAddress::new(mac.to_array()));
818 }
819}