hardware_address/
eui64.rs

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