dot15d4_frame/
addressing.rs

1//! Addressing fields readers and writers.
2
3use super::FrameControl;
4use super::FrameVersion;
5use super::{Error, Result};
6
7/// An IEEE 802.15.4 address.
8#[derive(Debug, PartialEq, Eq, Clone, Copy)]
9#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
10pub enum Address {
11    /// The address is absent.
12    Absent,
13    /// A short address.
14    Short([u8; 2]),
15    /// An extended address.
16    Extended([u8; 8]),
17}
18
19impl Address {
20    /// The broadcast address.
21    pub const BROADCAST: Address = Address::Short([0xff; 2]);
22
23    /// Query whether the address is an unicast address.
24    pub fn is_unicast(&self) -> bool {
25        !self.is_broadcast()
26    }
27
28    /// Query whether this address is the broadcast address.
29    pub fn is_broadcast(&self) -> bool {
30        *self == Self::BROADCAST
31    }
32
33    /// Create an [`Address`] from a slice of bytes.
34    pub fn from(a: &[u8]) -> Self {
35        if a.is_empty() {
36            Address::Absent
37        } else if a.len() == 2 {
38            let mut b = [0u8; 2];
39            b.copy_from_slice(a);
40            Address::Short(b)
41        } else if a.len() == 8 {
42            let mut b = [0u8; 8];
43            b.copy_from_slice(a);
44            Address::Extended(b)
45        } else {
46            unreachable!()
47        }
48    }
49
50    /// Return the address as a slice of bytes.
51    pub const fn as_bytes(&self) -> &[u8] {
52        match self {
53            Address::Absent => &[],
54            Address::Short(value) => value,
55            Address::Extended(value) => value,
56        }
57    }
58
59    /// Return the short address form of the address.
60    pub fn to_short(&self) -> Option<Self> {
61        match self {
62            short @ Address::Short(_) => Some(*short),
63            Address::Extended(value) => {
64                let mut raw = [0u8; 2];
65                raw.copy_from_slice(&value[..2]);
66                Some(Address::Short(raw))
67            }
68            _ => None,
69        }
70    }
71
72    /// Create a short [`Address`] from an array of 2 bytes.
73    const fn short_from_bytes(a: [u8; 2]) -> Self {
74        Self::Short(a)
75    }
76
77    /// Create an extended [`Address`] from an array of 8 bytes.
78    const fn extended_from_bytes(a: [u8; 8]) -> Self {
79        Self::Extended(a)
80    }
81
82    /// Return the length of the address in octets.
83    #[allow(clippy::len_without_is_empty)]
84    pub fn len(&self) -> usize {
85        match self {
86            Address::Absent => 0,
87            Address::Short(_) => 2,
88            Address::Extended(_) => 8,
89        }
90    }
91
92    /// Query whether the address is absent.
93    pub fn is_absent(&self) -> bool {
94        matches!(self, Address::Absent)
95    }
96
97    /// Query whether the address is short.
98    pub fn is_short(&self) -> bool {
99        matches!(self, Address::Short(_))
100    }
101
102    /// Query whether the address is extended.
103    pub fn is_extended(&self) -> bool {
104        matches!(self, Address::Extended(_))
105    }
106
107    /// Parse an address from a string.
108    #[cfg(any(feature = "std", test))]
109    pub fn parse(s: &str) -> Result<Self> {
110        if s.is_empty() {
111            return Ok(Address::Absent);
112        }
113
114        let parts: Vec<&str> = s.split(':').collect();
115        match parts.len() {
116            2 => {
117                let mut bytes = [0u8; 2];
118                for (i, part) in parts.iter().enumerate() {
119                    bytes[i] = u8::from_str_radix(part, 16).unwrap();
120                }
121                Ok(Address::Short(bytes))
122            }
123            8 => {
124                let mut bytes = [0u8; 8];
125                for (i, part) in parts.iter().enumerate() {
126                    bytes[i] = u8::from_str_radix(part, 16).unwrap();
127                }
128                Ok(Address::Extended(bytes))
129            }
130            _ => Err(Error),
131        }
132    }
133}
134
135impl From<Address> for AddressingMode {
136    fn from(value: Address) -> Self {
137        match value {
138            Address::Absent => AddressingMode::Absent,
139            Address::Short(_) => AddressingMode::Short,
140            Address::Extended(_) => AddressingMode::Extended,
141        }
142    }
143}
144
145impl core::fmt::Display for Address {
146    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
147        match self {
148            Address::Absent => write!(f, "absent"),
149            Address::Short(value) => write!(f, "{:02x}:{:02x}", value[0], value[1]),
150            Address::Extended(value) => write!(
151                f,
152                "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
153                value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7]
154            ),
155        }
156    }
157}
158
159/// IEEE 802.15.4 addressing mode.
160#[derive(Debug, Eq, PartialEq, Clone, Copy)]
161#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
162pub enum AddressingMode {
163    /// The address is absent.
164    Absent = 0b00,
165    /// The address is a short address.
166    Short = 0b10,
167    /// The address is an extended address.
168    Extended = 0b11,
169    /// Unknown addressing mode.
170    Unknown,
171}
172
173impl AddressingMode {
174    /// Return the size of the address in octets.
175    pub fn size(&self) -> usize {
176        match self {
177            Self::Absent => 0,
178            Self::Short => 2,
179            Self::Extended => 8,
180            Self::Unknown => 0,
181        }
182    }
183}
184
185impl From<u8> for AddressingMode {
186    fn from(value: u8) -> Self {
187        match value {
188            0b00 => Self::Absent,
189            0b10 => Self::Short,
190            0b11 => Self::Extended,
191            _ => Self::Unknown,
192        }
193    }
194}
195
196/// A reader/writer for the IEEE 802.15.4 Addressing Fields.
197pub struct AddressingFields<T: AsRef<[u8]>, FC: AsRef<[u8]>> {
198    buffer: T,
199    fc: FrameControl<FC>,
200}
201
202impl<T: AsRef<[u8]>, FC: AsRef<[u8]>> AddressingFields<T, FC> {
203    /// Create a new [`AddressingFields`] reader/writer from a given buffer.
204    ///
205    /// # Errors
206    ///
207    /// This function will check the length of the buffer to ensure it is large
208    /// enough to contain the addressing fields. If the buffer is too small,
209    /// an error will be returned.
210    pub fn new(buffer: T, fc: FrameControl<FC>) -> Result<Self> {
211        let af = Self::new_unchecked(buffer, fc);
212
213        if !af.check_len() {
214            return Err(Error);
215        }
216
217        Ok(af)
218    }
219
220    /// Check if the buffer is large enough to contain the addressing fields.
221    fn check_len(&self) -> bool {
222        let Some((dst_pan_id_present, dst_addr_mode, src_pan_id_present, src_addr_mode)) =
223            Self::address_present_flags(
224                self.fc.frame_version(),
225                self.fc.dst_addressing_mode(),
226                self.fc.src_addressing_mode(),
227                self.fc.pan_id_compression(),
228            )
229        else {
230            return false;
231        };
232
233        let expected_len = (if dst_pan_id_present { 2 } else { 0 })
234            + dst_addr_mode.size()
235            + (if src_pan_id_present { 2 } else { 0 })
236            + src_addr_mode.size();
237
238        self.buffer.as_ref().len() >= expected_len
239    }
240
241    /// Create a new [`AddressingFields`] reader/writer from a given buffer
242    /// without checking the length.
243    pub fn new_unchecked(buffer: T, fc: FrameControl<FC>) -> Self {
244        Self { buffer, fc }
245    }
246
247    /// Return the length of the Addressing Fields in octets.
248    #[allow(clippy::len_without_is_empty)]
249    pub fn len(&self) -> usize {
250        (match self.dst_pan_id() {
251            Some(_) => 2,
252            None => 0,
253        }) + match self.fc.dst_addressing_mode() {
254            AddressingMode::Absent => 0,
255            AddressingMode::Short => 2,
256            AddressingMode::Extended => 8,
257            _ => unreachable!(),
258        } + match self.src_pan_id() {
259            Some(_) => 2,
260            None => 0,
261        } + match self.fc.src_addressing_mode() {
262            AddressingMode::Absent => 0,
263            AddressingMode::Short => 2,
264            AddressingMode::Extended => 8,
265            _ => unreachable!(),
266        }
267    }
268
269    fn address_present_flags(
270        frame_version: FrameVersion,
271        dst_addr_mode: AddressingMode,
272        src_addr_mode: AddressingMode,
273        pan_id_compression: bool,
274    ) -> Option<(bool, AddressingMode, bool, AddressingMode)> {
275        use AddressingMode::*;
276        match frame_version {
277            FrameVersion::Ieee802154_2003 | FrameVersion::Ieee802154_2006 => {
278                match (dst_addr_mode, src_addr_mode, pan_id_compression) {
279                    // If both destination and source address information is present, and the
280                    // destination and source PAN IDs are identical, then the source PAN ID is
281                    // omitted.
282                    // In the following case, the destination and source PAN IDs are not identical,
283                    // and thus both are present.
284                    (dst @ (Short | Extended), src @ (Short | Extended), false) => {
285                        Some((true, dst, true, src))
286                    }
287                    // In the following case, the destination and source PAN IDs are identical, and
288                    // thus only the destination PAN ID is present.
289                    (dst @ (Short | Extended), src @ (Short | Extended), true) => {
290                        Some((true, dst, false, src))
291                    }
292
293                    // If either the destination or the source address is present, then the PAN ID
294                    // of the corresponding address is present and the PAN ID compression field is
295                    // set to 0.
296                    (Absent, src @ (Short | Extended), false) => Some((false, Absent, true, src)),
297                    (dst @ (Short | Extended), Absent, false) => Some((true, dst, false, Absent)),
298
299                    // All other cases are invalid.
300                    _ => None,
301                }
302            }
303            FrameVersion::Ieee802154_2020 => {
304                Some(match (dst_addr_mode, src_addr_mode, pan_id_compression) {
305                    (Absent, Absent, false) => (false, Absent, false, Absent),
306                    (Absent, Absent, true) => (true, Absent, false, Absent),
307                    (dst, Absent, false) if !matches!(dst, Absent) => (true, dst, false, Absent),
308                    (dst, Absent, true) if !matches!(dst, Absent) => (false, dst, false, Absent),
309                    (Absent, src, false) if !matches!(src, Absent) => (false, Absent, true, src),
310                    (Absent, src, true) if !matches!(src, Absent) => (false, Absent, false, src),
311                    (Extended, Extended, false) => (true, Extended, false, Extended),
312                    (Extended, Extended, true) => (false, Extended, false, Extended),
313                    (Short, Short, false) => (true, Short, true, Short),
314                    (Short, Extended, false) => (true, Short, true, Extended),
315                    (Extended, Short, false) => (true, Extended, true, Short),
316                    (Short, Extended, true) => (true, Short, false, Extended),
317                    (Extended, Short, true) => (true, Extended, false, Short),
318                    (Short, Short, true) => (true, Short, false, Short),
319                    _ => return None,
320                })
321            }
322            _ => None,
323        }
324    }
325
326    /// Return the IEEE 802.15.4 destination [`Address`] if not absent.
327    pub fn dst_address(&self) -> Option<Address> {
328        if let Some((dst_pan_id, dst_addr, _, _)) = Self::address_present_flags(
329            self.fc.frame_version(),
330            self.fc.dst_addressing_mode(),
331            self.fc.src_addressing_mode(),
332            self.fc.pan_id_compression(),
333        ) {
334            let offset = if dst_pan_id { 2 } else { 0 };
335
336            match dst_addr {
337                AddressingMode::Absent => Some(Address::Absent),
338                AddressingMode::Short => {
339                    let mut raw = [0u8; 2];
340                    raw.clone_from_slice(&self.buffer.as_ref()[offset..offset + 2]);
341                    raw.reverse();
342                    Some(Address::short_from_bytes(raw))
343                }
344                AddressingMode::Extended => {
345                    let mut raw = [0u8; 8];
346                    raw.clone_from_slice(&self.buffer.as_ref()[offset..offset + 8]);
347                    raw.reverse();
348                    Some(Address::extended_from_bytes(raw))
349                }
350                AddressingMode::Unknown => None,
351            }
352        } else {
353            None
354        }
355    }
356
357    /// Return the IEEE 802.15.4 source [`Address`] if not absent.
358    pub fn src_address(&self) -> Option<Address> {
359        if let Some((dst_pan_id, dst_addr, src_pan_id, src_addr)) = Self::address_present_flags(
360            self.fc.frame_version(),
361            self.fc.dst_addressing_mode(),
362            self.fc.src_addressing_mode(),
363            self.fc.pan_id_compression(),
364        ) {
365            let mut offset = if dst_pan_id { 2 } else { 0 };
366            offset += dst_addr.size();
367            offset += if src_pan_id { 2 } else { 0 };
368
369            match src_addr {
370                AddressingMode::Absent => Some(Address::Absent),
371                AddressingMode::Short => {
372                    let mut raw = [0u8; 2];
373                    raw.clone_from_slice(&self.buffer.as_ref()[offset..offset + 2]);
374                    raw.reverse();
375                    Some(Address::short_from_bytes(raw))
376                }
377                AddressingMode::Extended => {
378                    let mut raw = [0u8; 8];
379                    raw.clone_from_slice(&self.buffer.as_ref()[offset..offset + 8]);
380                    raw.reverse();
381                    Some(Address::extended_from_bytes(raw))
382                }
383                AddressingMode::Unknown => None,
384            }
385        } else {
386            None
387        }
388    }
389
390    /// Return the IEEE 802.15.4 destination PAN ID if not elided.
391    pub fn dst_pan_id(&self) -> Option<u16> {
392        if let Some((true, _, _, _)) = Self::address_present_flags(
393            self.fc.frame_version(),
394            self.fc.dst_addressing_mode(),
395            self.fc.src_addressing_mode(),
396            self.fc.pan_id_compression(),
397        ) {
398            let b = &self.buffer.as_ref()[..2];
399            Some(u16::from_le_bytes([b[0], b[1]]))
400        } else {
401            None
402        }
403    }
404
405    /// Return the IEEE 802.15.4 source PAN ID if not elided.
406    pub fn src_pan_id(&self) -> Option<u16> {
407        if let Some((dst_pan_id, dst_addr, true, _)) = Self::address_present_flags(
408            self.fc.frame_version(),
409            self.fc.dst_addressing_mode(),
410            self.fc.src_addressing_mode(),
411            self.fc.pan_id_compression(),
412        ) {
413            let mut offset = if dst_pan_id { 2 } else { 0 };
414            offset += dst_addr.size();
415
416            let b = &self.buffer.as_ref()[offset..][..2];
417            Some(u16::from_le_bytes([b[0], b[1]]))
418        } else {
419            None
420        }
421    }
422}
423
424impl<T: AsRef<[u8]>, FC: AsRef<[u8]>> core::fmt::Display for AddressingFields<T, FC> {
425    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
426        writeln!(f, "Addressing Fields")?;
427
428        if let Some(id) = self.dst_pan_id() {
429            writeln!(f, "  dst pan id: {:0x}", id)?;
430        }
431
432        if let Some(addr) = self.dst_address() {
433            writeln!(f, "  dst address: {}", addr)?;
434        }
435
436        if let Some(id) = self.src_pan_id() {
437            writeln!(f, "  src pan id: {:0x}", id)?;
438        }
439
440        if let Some(addr) = self.src_address() {
441            writeln!(f, "  src address: {}", addr)?;
442        }
443
444        Ok(())
445    }
446}
447
448impl<T: AsRef<[u8]> + AsMut<[u8]>, FC: AsRef<[u8]>> AddressingFields<T, FC> {
449    /// Write the addressing fields to the buffer.
450    pub fn write_fields(&mut self, fields: &super::repr::AddressingFieldsRepr) {
451        let mut offset = 0;
452
453        if let Some(id) = fields.dst_pan_id {
454            let b = &mut self.buffer.as_mut()[offset..][..2];
455            b.copy_from_slice(&id.to_le_bytes());
456            offset += 2;
457        }
458
459        if let Some(addr) = fields.dst_address {
460            let b = &mut self.buffer.as_mut()[offset..][..addr.len()];
461            match addr {
462                Address::Absent => {}
463                Address::Short(value) => {
464                    let mut addr = value;
465                    addr.reverse();
466                    b.copy_from_slice(&addr);
467                }
468                Address::Extended(value) => {
469                    let mut addr = value;
470                    addr.reverse();
471                    b.copy_from_slice(&addr);
472                }
473            }
474            offset += addr.len();
475        }
476
477        if let Some(id) = fields.src_pan_id {
478            let b = &mut self.buffer.as_mut()[offset..][..2];
479            b.copy_from_slice(&id.to_le_bytes());
480            offset += 2;
481        }
482
483        if let Some(addr) = fields.src_address {
484            let b = &mut self.buffer.as_mut()[offset..][..addr.len()];
485            match addr {
486                Address::Absent => {}
487                Address::Short(value) => {
488                    let mut addr = value;
489                    addr.reverse();
490                    b.copy_from_slice(&addr);
491                }
492                Address::Extended(value) => {
493                    let mut addr = value;
494                    addr.reverse();
495                    b.copy_from_slice(&addr);
496                }
497            }
498        }
499    }
500}
501
502#[cfg(test)]
503mod tests {
504    use super::*;
505
506    #[test]
507    fn address_type() {
508        assert!(Address::Absent.is_absent());
509        assert!(!Address::Absent.is_short());
510        assert!(!Address::Absent.is_extended());
511
512        assert!(!Address::Short([0xff, 0xff]).is_absent());
513        assert!(Address::Short([0xff, 0xff]).is_short());
514        assert!(!Address::Short([0xff, 0xff]).is_extended());
515
516        assert!(!Address::Extended([0xff; 8]).is_absent());
517        assert!(!Address::Extended([0xff; 8]).is_short());
518        assert!(Address::Extended([0xff; 8]).is_extended());
519
520        assert_eq!(Address::Absent.len(), 0);
521        assert_eq!(Address::Short([0xff, 0xff]).len(), 2);
522        assert_eq!(Address::Extended([0xff; 8]).len(), 8);
523    }
524
525    #[test]
526    fn addressing_mode() {
527        assert_eq!(AddressingMode::from(0b00), AddressingMode::Absent);
528        assert_eq!(AddressingMode::from(0b10), AddressingMode::Short);
529        assert_eq!(AddressingMode::from(0b11), AddressingMode::Extended);
530        assert_eq!(AddressingMode::from(0b01), AddressingMode::Unknown);
531
532        assert_eq!(AddressingMode::Unknown.size(), 0);
533        assert_eq!(AddressingMode::Absent.size(), 0);
534        assert_eq!(AddressingMode::Short.size(), 2);
535        assert_eq!(AddressingMode::Extended.size(), 8);
536    }
537
538    #[test]
539    fn is_broadcast() {
540        assert!(Address::BROADCAST.is_broadcast());
541        assert!(Address::Short([0xff, 0xff]).is_broadcast());
542        assert!(!Address::Short([0xff, 0xfe]).is_broadcast());
543
544        assert!(!Address::BROADCAST.is_unicast());
545        assert!(!Address::Short([0xff, 0xff]).is_unicast());
546        assert!(Address::Short([0xff, 0xfe]).is_unicast());
547    }
548
549    #[test]
550    fn as_bytes() {
551        assert_eq!(Address::BROADCAST.as_bytes(), &[0xff, 0xff]);
552        assert_eq!(Address::Short([0xff, 0xff]).as_bytes(), &[0xff, 0xff]);
553        assert_eq!(Address::Short([0xff, 0xfe]).as_bytes(), &[0xff, 0xfe]);
554        assert_eq!(Address::Extended([0xff; 8]).as_bytes(), &[0xff; 8]);
555        assert_eq!(Address::Extended([0x01; 8]).as_bytes(), &[0x01; 8]);
556        assert_eq!(Address::Absent.as_bytes(), &[]);
557    }
558
559    #[test]
560    fn from_bytes() {
561        assert_eq!(Address::from(&[0xff, 0xff]), Address::Short([0xff, 0xff]));
562        assert_eq!(Address::from(&[0xff, 0xfe]), Address::Short([0xff, 0xfe]));
563        assert_eq!(Address::from(&[0xff; 8]), Address::Extended([0xff; 8]));
564        assert_eq!(Address::from(&[0x01; 8]), Address::Extended([0x01; 8]));
565        assert_eq!(Address::from(&[]), Address::Absent);
566    }
567
568    #[test]
569    #[should_panic]
570    fn from_bytes_panic() {
571        Address::from(&[0xff, 0xff, 0xff]);
572    }
573
574    #[test]
575    fn address_present_flags() {
576        use AddressingMode::*;
577        use FrameVersion::*;
578
579        macro_rules! check {
580            (($version:ident, $dst:ident, $src:ident, $compression:literal) -> $expected:expr) => {
581                assert_eq!(
582                    AddressingFields::<&[u8], &[u8]>::address_present_flags(
583                        $version,
584                        $dst,
585                        $src,
586                        $compression
587                    ),
588                    $expected
589                );
590            };
591        }
592
593        check!((Ieee802154_2003, Short, Short, false) -> Some((true, Short, true, Short)));
594        check!((Ieee802154_2003, Short, Short, true) -> Some((true, Short, false, Short)));
595        check!((Ieee802154_2003, Extended, Extended, false) -> Some((true, Extended, true, Extended)));
596        check!((Ieee802154_2003, Extended, Extended, true) -> Some((true, Extended, false, Extended)));
597        check!((Ieee802154_2003, Short, Extended, false) -> Some((true, Short, true, Extended)));
598        check!((Ieee802154_2003, Short, Extended, true) -> Some((true, Short, false, Extended)));
599        check!((Ieee802154_2003, Extended, Short, false) -> Some((true, Extended, true, Short)));
600        check!((Ieee802154_2003, Extended, Short, true) -> Some((true, Extended, false, Short)));
601        check!((Ieee802154_2003, Absent, Short, false) -> Some((false, Absent, true, Short)));
602        check!((Ieee802154_2003, Absent, Extended, false) -> Some((false, Absent, true, Extended)));
603        check!((Ieee802154_2003, Short, Absent, false) -> Some((true, Short, false, Absent)));
604        check!((Ieee802154_2003, Extended, Absent, false) -> Some((true, Extended, false, Absent)));
605        check!((Ieee802154_2003, Absent, Short, true) -> None);
606        check!((Ieee802154_2003, Absent, Extended, true) -> None);
607        check!((Ieee802154_2003, Short, Absent, true) -> None);
608        check!((Ieee802154_2003, Extended, Absent, true) -> None);
609        check!((Ieee802154_2003, Absent, Absent, false) -> None);
610        check!((Ieee802154_2003, Absent, Absent, true) -> None);
611
612        check!((Ieee802154_2006, Short, Short, false) -> Some((true, Short, true, Short)));
613        check!((Ieee802154_2006, Short, Short, true) -> Some((true, Short, false, Short)));
614        check!((Ieee802154_2006, Extended, Extended, false) -> Some((true, Extended, true, Extended)));
615        check!((Ieee802154_2006, Extended, Extended, true) -> Some((true, Extended, false, Extended)));
616        check!((Ieee802154_2006, Short, Extended, false) -> Some((true, Short, true, Extended)));
617        check!((Ieee802154_2006, Short, Extended, true) -> Some((true, Short, false, Extended)));
618        check!((Ieee802154_2006, Extended, Short, false) -> Some((true, Extended, true, Short)));
619        check!((Ieee802154_2006, Extended, Short, true) -> Some((true, Extended, false, Short)));
620        check!((Ieee802154_2006, Absent, Short, false) -> Some((false, Absent, true, Short)));
621        check!((Ieee802154_2006, Absent, Extended, false) -> Some((false, Absent, true, Extended)));
622        check!((Ieee802154_2006, Short, Absent, false) -> Some((true, Short, false, Absent)));
623        check!((Ieee802154_2006, Extended, Absent, false) -> Some((true, Extended, false, Absent)));
624        check!((Ieee802154_2006, Absent, Short, true) -> None);
625        check!((Ieee802154_2006, Absent, Extended, true) -> None);
626        check!((Ieee802154_2006, Short, Absent, true) -> None);
627        check!((Ieee802154_2006, Extended, Absent, true) -> None);
628        check!((Ieee802154_2006, Absent, Absent, false) -> None);
629        check!((Ieee802154_2006, Absent, Absent, true) -> None);
630
631        check!((Ieee802154_2020, Short, Short, false) -> Some((true, Short, true, Short)));
632        check!((Ieee802154_2020, Short, Short, true) -> Some((true, Short, false, Short)));
633        check!((Ieee802154_2020, Extended, Extended, false) -> Some((true, Extended, false, Extended)));
634        check!((Ieee802154_2020, Extended, Extended, true) -> Some((false, Extended, false, Extended)));
635        check!((Ieee802154_2020, Short, Extended, false) -> Some((true, Short, true, Extended)));
636        check!((Ieee802154_2020, Short, Extended, true) -> Some((true, Short, false, Extended)));
637        check!((Ieee802154_2020, Extended, Short, false) -> Some((true, Extended, true, Short)));
638        check!((Ieee802154_2020, Extended, Short, true) -> Some((true, Extended, false, Short)));
639        check!((Ieee802154_2020, Absent, Short, false) -> Some((false, Absent, true, Short)));
640        check!((Ieee802154_2020, Absent, Extended, false) -> Some((false, Absent, true, Extended)));
641        check!((Ieee802154_2020, Short, Absent, false) -> Some((true, Short, false, Absent)));
642        check!((Ieee802154_2020, Extended, Absent, false) -> Some((true, Extended, false, Absent)));
643        check!((Ieee802154_2020, Absent, Short, true) -> Some((false, Absent, false, Short)));
644        check!((Ieee802154_2020, Absent, Extended, true) -> Some((false, Absent, false, Extended)));
645        check!((Ieee802154_2020, Short, Absent, true) -> Some((false, Short, false, Absent)));
646        check!((Ieee802154_2020, Extended, Absent, true) -> Some((false, Extended, false, Absent)));
647        check!((Ieee802154_2020, Absent, Absent, false) -> Some((false, Absent, false, Absent)));
648        check!((Ieee802154_2020, Absent, Absent, true) -> Some((true, Absent, false, Absent)));
649    }
650
651    #[test]
652    fn parse() {
653        let mut addresses = vec![
654            ("", Address::Absent),
655            ("ff:ff", Address::Short([0xff, 0xff])),
656            ("ff:fe", Address::Short([0xff, 0xfe])),
657            ("ff:ff:ff:ff:ff:ff:ff:ff", Address::Extended([0xff; 8])),
658            ("01:01:01:01:01:01:01:01", Address::Extended([0x01; 8])),
659            ("00:00:00:00:00:00:00:00", Address::Extended([0x00; 8])),
660            (
661                "00:00:00:00:00:00:00:01",
662                Address::Extended([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]),
663            ),
664        ];
665
666        for (s, expected) in addresses.drain(..) {
667            assert_eq!(Address::parse(s).unwrap(), expected);
668        }
669    }
670}