1use anyhow::Result;
2#[cfg(feature = "serde")]
3use serde::Serialize;
4
5#[derive(Debug, PartialEq, Eq, Clone)]
6#[cfg_attr(feature = "serde", derive(Serialize))]
7pub enum CFList {
8 Channels(CFListChannels),
9 ChannelMask(CFListChannelMasks),
10}
11
12impl CFList {
13 pub fn from_bytes(b: [u8; 16]) -> Result<Self> {
14 let mut bb: [u8; 15] = [0; 15];
15 bb.clone_from_slice(&b[..15]);
16
17 match b[15] {
19 0x00 => Ok(CFList::Channels(CFListChannels::from_bytes(bb))),
20 0x01 => Ok(CFList::ChannelMask(CFListChannelMasks::from_bytes(bb))),
21 _ => Err(anyhow!("unexpected CFListType")),
22 }
23 }
24
25 pub fn to_bytes(&self) -> Result<[u8; 16]> {
26 let mut b: [u8; 16] = [0; 16];
27
28 match self {
29 CFList::Channels(v) => {
30 b[..15].clone_from_slice(&v.to_bytes()?);
31 b[15] = 0x00;
32 }
33 CFList::ChannelMask(v) => {
34 b[..15].clone_from_slice(&v.to_bytes()?);
35 b[15] = 0x01;
36 }
37 }
38
39 Ok(b)
40 }
41}
42
43#[derive(Debug, PartialEq, Eq, Clone)]
44#[cfg_attr(feature = "serde", derive(Serialize))]
45pub struct CFListChannels([u32; 5]);
46
47impl CFListChannels {
48 pub fn new(channels: [u32; 5]) -> Self {
49 CFListChannels(channels)
50 }
51
52 pub fn from_slice(channels: &[u32]) -> Result<Self> {
53 let mut channels_array: [u32; 5] = [0; 5];
54 if channels.len() > channels_array.len() {
55 return Err(anyhow!(
56 "Max number of channels is {}",
57 channels_array.len()
58 ));
59 }
60
61 for (i, c) in channels.iter().enumerate() {
62 channels_array[i] = *c;
63 }
64
65 Ok(Self::new(channels_array))
66 }
67
68 pub fn from_bytes(b: [u8; 15]) -> Self {
69 let mut channels: [u32; 5] = [0; 5];
70
71 for (i, ch) in channels.iter_mut().enumerate() {
72 let index = i * 3;
73 *ch = u32::from_le_bytes([b[index], b[index + 1], b[index + 2], 0x00]) * 100;
74 }
75
76 CFListChannels(channels)
77 }
78
79 pub fn to_bytes(&self) -> Result<[u8; 15]> {
80 let mut b: [u8; 15] = [0; 15];
81
82 for (i, f) in self.0.iter().enumerate() {
83 if f % 100 != 0 {
84 return Err(anyhow!("frequency must be a multiple of 100"));
85 }
86
87 let f = f / 100;
88 if f > (1 << 24) - 1 {
89 return Err(anyhow!("max value of frequency is 2^24-1"));
90 }
91
92 let index = i * 3;
93 b[index..index + 3].clone_from_slice(&f.to_le_bytes()[..3]);
94 }
95
96 Ok(b)
97 }
98
99 pub fn iter(&self) -> std::slice::Iter<'_, u32> {
100 self.0.iter()
101 }
102}
103
104#[derive(Debug, PartialEq, Eq, Clone)]
105#[cfg_attr(feature = "serde", derive(Serialize))]
106pub struct CFListChannelMasks(Vec<ChMask>);
107
108impl CFListChannelMasks {
109 pub fn new(masks: Vec<ChMask>) -> Self {
110 CFListChannelMasks(masks)
111 }
112
113 pub fn from_bytes(b: [u8; 15]) -> Self {
114 let b = b[..14].to_vec(); let mut masks: Vec<ChMask> = Vec::with_capacity(b.len() / 3);
117 let mut pending: Vec<ChMask> = Vec::with_capacity(b.len() / 2);
118
119 for i in (0..b.len()).step_by(2) {
120 pending.push(ChMask::from_bytes([b[i], b[i + 1]]));
121
122 if b[i..i + 2] != vec![0x00, 0x00] {
123 masks.append(&mut pending);
124 }
125 }
126
127 CFListChannelMasks(masks)
128 }
129
130 pub fn to_bytes(&self) -> Result<[u8; 15]> {
131 if self.0.len() > 6 {
132 return Err(anyhow!("max number of channel-masks is 6"));
133 }
134
135 let mut b: [u8; 15] = [0; 15];
136
137 for (i, mask) in self.0.iter().enumerate() {
138 let index = i * 2;
139 b[index..index + 2].clone_from_slice(&mask.to_bytes());
140 }
141
142 Ok(b)
143 }
144
145 pub fn iter(&self) -> std::slice::Iter<'_, ChMask> {
146 self.0.iter()
147 }
148}
149
150#[derive(Debug, PartialEq, Eq, Clone, Copy)]
153#[cfg_attr(feature = "serde", derive(Serialize))]
154pub struct ChMask([bool; 16]);
155
156impl ChMask {
157 const SIZE: usize = 2;
158
159 pub fn new(mask: [bool; 16]) -> Self {
160 ChMask(mask)
161 }
162
163 pub fn set(&mut self, i: usize, v: bool) {
164 self.0[i] = v
165 }
166
167 pub fn from_slice(mask: &[bool]) -> Result<Self> {
168 let mut mask_array: [bool; 16] = [false; 16];
169
170 if mask.len() > mask_array.len() {
171 return Err(anyhow!("Max number of masks is {}", mask_array.len()));
172 }
173
174 for (i, m) in mask.iter().enumerate() {
175 mask_array[i] = *m;
176 }
177
178 Ok(Self::new(mask_array))
179 }
180
181 pub fn from_bytes(b: [u8; Self::SIZE]) -> Self {
182 let mut mask: [bool; 16] = [false; 16];
183
184 let n = u16::from_le_bytes(b);
185 for (i, m) in mask.iter_mut().enumerate() {
186 *m = n & (1 << i) != 0;
187 }
188
189 ChMask(mask)
190 }
191
192 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
193 let mut n: u16 = 0;
194 for i in 0..16 {
195 if self.0[i] {
196 n |= 1 << i;
197 }
198 }
199
200 n.to_le_bytes()
201 }
202}
203
204impl IntoIterator for ChMask {
205 type Item = bool;
206 type IntoIter = std::vec::IntoIter<Self::Item>;
207
208 #[allow(clippy::unnecessary_to_owned)]
209 fn into_iter(self) -> Self::IntoIter {
210 self.0.to_vec().into_iter()
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 struct Test {
219 cflist: CFList,
220 bytes: [u8; 16],
221 }
222
223 fn tests() -> Vec<Test> {
224 vec![
225 Test {
226 cflist: CFList::ChannelMask(CFListChannelMasks::new(vec![ChMask::new([
227 true, true, true, true, true, true, true, true, false, false, false, false,
228 false, false, false, false,
229 ])])),
230 bytes: [
231 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x01,
233 ],
234 },
235 Test {
236 cflist: CFList::ChannelMask(CFListChannelMasks::new(vec![
237 ChMask::new([false; 16]),
238 ChMask::new([
239 true, true, true, true, true, true, true, true, false, false, false, false,
240 false, false, false, false,
241 ]),
242 ])),
243 bytes: [
244 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x01,
246 ],
247 },
248 Test {
249 cflist: CFList::Channels(CFListChannels::new([
250 867100000, 867300000, 867500000, 867700000, 867900000,
251 ])),
252 bytes: [
253 0x18, 0x4f, 0x84, 0xe8, 0x56, 0x84, 0xb8, 0x5e, 0x84, 0x88, 0x66, 0x84, 0x58,
254 0x6e, 0x84, 0x0,
255 ],
256 },
257 ]
258 }
259
260 #[test]
261 fn test_to_bytes() {
262 for tst in tests() {
263 assert_eq!(tst.bytes, tst.cflist.to_bytes().unwrap());
264 }
265 }
266
267 #[test]
268 fn test_from_bytes() {
269 for tst in tests() {
270 assert_eq!(tst.cflist, CFList::from_bytes(tst.bytes).unwrap());
271 }
272 }
273}