hardware_address/
mac.rs

1addr_ty!(
2  /// Represents a physical hardware address (MAC address).
3  #[doc(alias = "Eui48Addr")]
4  MacAddr[6]
5);
6
7#[cfg(test)]
8mod tests {
9  use super::*;
10  use crate::{ParseError, TestCase};
11
12  use std::{string::ToString, vec, vec::Vec};
13
14  const MAC_ADDRESS_SIZE: usize = 6;
15
16  fn test_cases() -> Vec<TestCase<MAC_ADDRESS_SIZE>> {
17    vec![
18      // RFC 7042, Section 2.1.1
19      TestCase {
20        input: "00:00:5e:00:53:01",
21        output: Some(vec![0x00, 0x00, 0x5e, 0x00, 0x53, 0x01]),
22        err: None,
23      },
24      TestCase {
25        input: "00-00-5e-00-53-01",
26        output: Some(vec![0x00, 0x00, 0x5e, 0x00, 0x53, 0x01]),
27        err: None,
28      },
29      TestCase {
30        input: "0000.5e00.5301",
31        output: Some(vec![0x00, 0x00, 0x5e, 0x00, 0x53, 0x01]),
32        err: None,
33      },
34      TestCase {
35        input: "ab:cd:ef:AB:CD:EF",
36        output: Some(vec![0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef]),
37        err: None,
38      },
39      // Invalid MAC-48 cases
40      TestCase {
41        input: "01.02.03.04.05.06",
42        output: None,
43        err: Some(ParseError::InvalidSeparator(b'.')),
44      },
45      TestCase {
46        input: "01:02:03:04:05:06:",
47        output: None,
48        err: Some(ParseError::InvalidLength(18)),
49      },
50      TestCase {
51        input: "x1:02:03:04:05:06",
52        output: None,
53        err: Some(ParseError::InvalidHexDigit([b'x', b'1'])),
54      },
55      TestCase {
56        input: "01-02:03:04:05:06",
57        output: None,
58        err: Some(ParseError::UnexpectedSeparator {
59          expected: b'-',
60          actual: b':',
61        }),
62      },
63    ]
64  }
65
66  #[test]
67  fn parse() {
68    let cases = test_cases();
69    for (i, test) in cases.iter().enumerate() {
70      let result = MacAddr::try_from(test.input);
71
72      match (result, &test.output) {
73        (Ok(out), Some(expected)) => {
74          assert_eq!(
75            expected.as_slice(),
76            out,
77            "Test case {}: MacAddr::parse({}) output mismatch",
78            i,
79            test.input
80          );
81
82          // Test round-trip if this was a valid case
83          if test.err.is_none() {
84            let formatted = out.to_string();
85            let round_trip = MacAddr::try_from(formatted.as_str());
86            assert!(
87              round_trip.is_ok(),
88              "Test case {}: Round-trip parse failed for {}",
89              i,
90              formatted
91            );
92            assert_eq!(
93              round_trip.unwrap(),
94              out,
95              "Test case {}: Round-trip value mismatch",
96              i
97            );
98          }
99        }
100        (Err(err), None) => {
101          assert_eq!(
102            Some(&err),
103            test.err.as_ref(),
104            "Test case {}: Expected error containing '{:?}', got '{:?}'",
105            i,
106            test.err,
107            err
108          );
109        }
110        (Ok(out), None) => {
111          panic!(
112            "Test case {}: Expected error '{:?}', got success: {:?}",
113            i, test.err, out
114          );
115        }
116        (Err(err), Some(expected)) => {
117          panic!(
118            "Test case {}: Expected {:?}, got error: {:?}",
119            i, expected, err
120          );
121        }
122      }
123    }
124  }
125
126  #[test]
127  fn test_default() {
128    let addr = MacAddr::default();
129    assert_eq!(addr.octets(), [0, 0, 0, 0, 0, 0]);
130  }
131
132  #[test]
133  fn formatted() {
134    let addr = MacAddr::try_from("00:00:5e:00:53:01").unwrap();
135    assert_eq!(addr.to_string(), "00:00:5e:00:53:01");
136    assert_eq!(addr.to_colon_separated(), "00:00:5e:00:53:01");
137
138    let dot = addr.to_dot_separated_array();
139    let dot_str = core::str::from_utf8(&dot).unwrap();
140    assert_eq!(dot_str, "0000.5e00.5301");
141    assert_eq!(addr.to_dot_separated(), "0000.5e00.5301");
142
143    let dashed = addr.to_hyphen_separated_array();
144    let dashed_str = core::str::from_utf8(&dashed).unwrap();
145    assert_eq!(dashed_str, "00-00-5e-00-53-01");
146    assert_eq!(addr.to_hyphen_separated(), "00-00-5e-00-53-01");
147  }
148
149  #[cfg(feature = "serde")]
150  #[test]
151  fn serde_human_readable() {
152    let addr = MacAddr::try_from("00:00:5e:00:53:01").unwrap();
153    let json = serde_json::to_string(&addr).unwrap();
154    assert_eq!(json, "\"00:00:5e:00:53:01\"");
155
156    let addr2: MacAddr = serde_json::from_str(&json).unwrap();
157    assert_eq!(addr, addr2);
158  }
159
160  #[cfg(feature = "serde")]
161  #[test]
162  fn serde_human_unreadable() {
163    let addr = MacAddr::try_from("00:00:5e:00:53:01").unwrap();
164    let json = bincode::serde::encode_to_vec(addr, bincode::config::standard()).unwrap();
165    assert_eq!(json, [0, 0, 94, 0, 83, 1]);
166    assert_eq!(addr.octets(), [0, 0, 94, 0, 83, 1]);
167
168    let addr2: MacAddr = bincode::serde::decode_from_slice(&json, bincode::config::standard())
169      .unwrap()
170      .0;
171    assert_eq!(addr, addr2);
172
173    let addr3 = MacAddr::from_raw([0, 0, 94, 0, 83, 1]);
174    assert_eq!(addr, addr3);
175
176    println!("{:?}", addr);
177  }
178}