Skip to main content

twine_codec/dataset/
components.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
8bitflags::bitflags! {
9    /// Represents the presence of different components in an Active or Pending Operational Dataset
10    #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
11    pub struct Components: u16 {
12        const ACTIVE = 1;
13        const PENDING = 1 << 1;
14        const NETWORK_KEY = 1 << 2;
15        const NETWORK_NAME = 1 << 3;
16        const EXTENDED_PAN_ID = 1 << 4;
17        const MESH_LOCAL_PREFIX = 1 << 5;
18        const DELAY = 1 << 6;
19        const PAN_ID = 1 << 7;
20        const CHANNEL = 1 << 8;
21        const PSKC = 1 << 9;
22        const SECURITY_POLICY = 1 << 10;
23        const CHANNEL_MASK = 1 << 11;
24    }
25}
26
27impl Components {
28    pub fn active(&self) -> bool {
29        self.contains(Self::ACTIVE)
30    }
31
32    pub fn pending(&self) -> bool {
33        self.contains(Self::PENDING)
34    }
35
36    pub fn network_key(&self) -> bool {
37        self.contains(Self::NETWORK_KEY)
38    }
39
40    pub fn network_name(&self) -> bool {
41        self.contains(Self::NETWORK_NAME)
42    }
43
44    pub fn extended_pan_id(&self) -> bool {
45        self.contains(Self::EXTENDED_PAN_ID)
46    }
47
48    pub fn mesh_local_prefix(&self) -> bool {
49        self.contains(Self::MESH_LOCAL_PREFIX)
50    }
51
52    pub fn delay(&self) -> bool {
53        self.contains(Self::DELAY)
54    }
55
56    pub fn pan_id(&self) -> bool {
57        self.contains(Self::PAN_ID)
58    }
59
60    pub fn channel(&self) -> bool {
61        self.contains(Self::CHANNEL)
62    }
63
64    pub fn pskc(&self) -> bool {
65        self.contains(Self::PSKC)
66    }
67
68    pub fn security_policy(&self) -> bool {
69        self.contains(Self::SECURITY_POLICY)
70    }
71
72    pub fn channel_mask(&self) -> bool {
73        self.contains(Self::CHANNEL_MASK)
74    }
75}
76
77impl From<u16> for Components {
78    fn from(value: u16) -> Self {
79        Self::from_bits_truncate(value)
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86    use std::sync::LazyLock;
87
88    static ALL_COMPONENTS: LazyLock<Components> = LazyLock::new(|| {
89        Components::ACTIVE
90            | Components::PENDING
91            | Components::NETWORK_KEY
92            | Components::NETWORK_NAME
93            | Components::EXTENDED_PAN_ID
94            | Components::MESH_LOCAL_PREFIX
95            | Components::DELAY
96            | Components::PAN_ID
97            | Components::CHANNEL
98            | Components::PSKC
99            | Components::SECURITY_POLICY
100            | Components::CHANNEL_MASK
101    });
102
103    /// Helper function to test only a single bitflag being set
104    fn helper_contains_single_bitflag(bits: u16) {
105        let components = Components::from(bits);
106
107        if components == Components::ACTIVE {
108            assert!(components.active());
109            assert!(ALL_COMPONENTS.active());
110        } else {
111            assert!(!components.active());
112        }
113
114        if components == Components::PENDING {
115            assert!(components.pending());
116            assert!(ALL_COMPONENTS.pending());
117        } else {
118            assert!(!components.pending());
119        }
120
121        if components == Components::NETWORK_KEY {
122            assert!(components.network_key());
123            assert!(ALL_COMPONENTS.network_key());
124        } else {
125            assert!(!components.network_key());
126        }
127
128        if components == Components::NETWORK_NAME {
129            assert!(components.network_name());
130            assert!(ALL_COMPONENTS.network_name());
131        } else {
132            assert!(!components.network_name());
133        }
134
135        if components == Components::EXTENDED_PAN_ID {
136            assert!(components.extended_pan_id());
137            assert!(ALL_COMPONENTS.extended_pan_id());
138        } else {
139            assert!(!components.extended_pan_id());
140        }
141
142        if components == Components::MESH_LOCAL_PREFIX {
143            assert!(components.mesh_local_prefix());
144            assert!(ALL_COMPONENTS.mesh_local_prefix());
145        } else {
146            assert!(!components.mesh_local_prefix());
147        }
148
149        if components == Components::DELAY {
150            assert!(components.delay());
151            assert!(ALL_COMPONENTS.delay());
152        } else {
153            assert!(!components.delay());
154        }
155
156        if components == Components::PAN_ID {
157            assert!(components.pan_id());
158            assert!(ALL_COMPONENTS.pan_id());
159        } else {
160            assert!(!components.pan_id());
161        }
162
163        if components == Components::CHANNEL {
164            assert!(components.channel());
165            assert!(ALL_COMPONENTS.channel());
166        } else {
167            assert!(!components.channel());
168        }
169
170        if components == Components::PSKC {
171            assert!(components.pskc());
172            assert!(ALL_COMPONENTS.pskc());
173        } else {
174            assert!(!components.pskc());
175        }
176
177        if components == Components::SECURITY_POLICY {
178            assert!(components.security_policy());
179            assert!(ALL_COMPONENTS.security_policy());
180        } else {
181            assert!(!components.security_policy());
182        }
183
184        if components == Components::CHANNEL_MASK {
185            assert!(components.channel_mask());
186            assert!(ALL_COMPONENTS.channel_mask());
187        } else {
188            assert!(!components.channel_mask());
189        }
190    }
191
192    #[test]
193    fn contains_active() {
194        helper_contains_single_bitflag(Components::ACTIVE.bits());
195
196        let active = Components::from(Components::ACTIVE.bits());
197        assert!(active.active());
198    }
199
200    #[test]
201    fn contains_pending() {
202        helper_contains_single_bitflag(Components::PENDING.bits());
203
204        let pending = Components::from(Components::PENDING.bits());
205        assert!(pending.pending());
206    }
207
208    #[test]
209    fn contains_network_key() {
210        helper_contains_single_bitflag(Components::NETWORK_KEY.bits());
211
212        let network_key = Components::from(Components::NETWORK_KEY.bits());
213        assert!(network_key.network_key());
214    }
215
216    #[test]
217    fn contains_network_name() {
218        helper_contains_single_bitflag(Components::NETWORK_NAME.bits());
219
220        let network_name = Components::from(Components::NETWORK_NAME.bits());
221        assert!(network_name.network_name());
222    }
223
224    #[test]
225    fn contains_extended_pan_id() {
226        helper_contains_single_bitflag(Components::EXTENDED_PAN_ID.bits());
227
228        let extended_pan_id = Components::from(Components::EXTENDED_PAN_ID.bits());
229        assert!(extended_pan_id.extended_pan_id());
230    }
231
232    #[test]
233    fn contains_mesh_local_prefix() {
234        helper_contains_single_bitflag(Components::MESH_LOCAL_PREFIX.bits());
235
236        let mesh_local_prefix = Components::from(Components::MESH_LOCAL_PREFIX.bits());
237        assert!(mesh_local_prefix.mesh_local_prefix());
238    }
239
240    #[test]
241    fn contains_delay() {
242        helper_contains_single_bitflag(Components::DELAY.bits());
243
244        let delay = Components::from(Components::DELAY.bits());
245        assert!(delay.delay());
246    }
247
248    #[test]
249    fn contains_pan_id() {
250        helper_contains_single_bitflag(Components::PAN_ID.bits());
251
252        let pan_id = Components::from(Components::PAN_ID.bits());
253        assert!(pan_id.pan_id());
254    }
255
256    #[test]
257    fn contains_channel() {
258        helper_contains_single_bitflag(Components::CHANNEL.bits());
259
260        let channel = Components::from(Components::CHANNEL.bits());
261        assert!(channel.channel());
262    }
263
264    #[test]
265    fn contains_pskc() {
266        helper_contains_single_bitflag(Components::PSKC.bits());
267
268        let pskc = Components::from(Components::PSKC.bits());
269        assert!(pskc.pskc());
270    }
271
272    #[test]
273    fn contains_security_policy() {
274        helper_contains_single_bitflag(Components::SECURITY_POLICY.bits());
275
276        let security_policy = Components::from(Components::SECURITY_POLICY.bits());
277        assert!(security_policy.security_policy());
278    }
279
280    #[test]
281    fn contains_channel_mask() {
282        helper_contains_single_bitflag(Components::CHANNEL_MASK.bits());
283
284        let channel_mask = Components::from(Components::CHANNEL_MASK.bits());
285        assert!(channel_mask.channel_mask());
286    }
287}