hardware_address/
eui64.rs

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