Skip to main content

twine_codec/dataset/
xpan.rs

1// Copyright (c) 2025 Jake Swensen
2// SPDX-License-Identifier: MPL-2.0
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8use twine_rs_macros::Tlv;
9
10pub(crate) const EXT_PAN_ID_SIZE: usize = 8;
11
12/// IEEE 802.15.4 Extended PAN ID
13#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Tlv)]
14#[tlv(tlv_type = 0x02, tlv_length = 8, derive_inner)]
15pub struct ExtendedPanId([u8; EXT_PAN_ID_SIZE]);
16
17impl ExtendedPanId {
18    pub fn random() -> Self {
19        let mut bytes = [0u8; EXT_PAN_ID_SIZE];
20        crate::fill_random_bytes(&mut bytes);
21        Self(bytes)
22    }
23}
24
25impl From<ExtendedPanId> for u64 {
26    fn from(value: ExtendedPanId) -> Self {
27        u64::from_be_bytes(value.0)
28    }
29}
30
31impl From<u64> for ExtendedPanId {
32    fn from(id: u64) -> Self {
33        Self(id.to_be_bytes())
34    }
35}
36
37impl From<ExtendedPanId> for [u8; EXT_PAN_ID_SIZE] {
38    fn from(value: ExtendedPanId) -> Self {
39        value.0
40    }
41}
42
43impl From<[u8; EXT_PAN_ID_SIZE]> for ExtendedPanId {
44    fn from(value: [u8; EXT_PAN_ID_SIZE]) -> Self {
45        Self(value)
46    }
47}
48
49impl core::fmt::Display for ExtendedPanId {
50    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51        for byte in &self.0 {
52            write!(f, "{:02x}", byte)?;
53        }
54
55        Ok(())
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use alloc::format;
62
63    use twine_tlv::prelude::*;
64
65    use super::*;
66
67    const TEST_VALUE: u64 = 0x1122334455667788;
68
69    #[test]
70    fn xpan_transform_u64() {
71        let test = TEST_VALUE;
72        let xpan = ExtendedPanId::from(test);
73        let result = u64::from(xpan);
74        assert_eq!(test, result);
75    }
76
77    #[test]
78    fn xpan_transform_array() {
79        let test = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88];
80        let xpan = ExtendedPanId::from(test);
81        let result: [u8; EXT_PAN_ID_SIZE] = xpan.into();
82        assert_eq!(test, result);
83        assert_eq!(TEST_VALUE, xpan.into());
84    }
85
86    #[test]
87    fn xpan_encode_decode_tlv() {
88        let test = TEST_VALUE;
89        let xpan = ExtendedPanId::from(test);
90        let mut collection = TlvCollection::<16>::default();
91        collection.push(xpan).unwrap();
92        insta::assert_debug_snapshot!(format!("{:02x?}", collection));
93        let result = collection.decode_type_unchecked::<ExtendedPanId>().unwrap();
94        assert_eq!(xpan, result);
95    }
96}