1use super::*;
5use crate::error::*;
6
7#[cfg_attr(all(feature = "defmt", target_os = "none"), derive(defmt::Format))]
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Data<'d> {
11 pub(crate) data: RawData<'d>,
12 pub(crate) quantity: usize,
13}
14
15impl<'d> Data<'d> {
16 pub fn from_words(words: &[u16], target: &'d mut [u8]) -> Result<Self, Error> {
18 if (words.len() * 2 > target.len()) || words.is_empty() {
19 return Err(Error::BufferSize);
20 }
21 for (i, w) in words.iter().enumerate() {
22 BigEndian::write_u16(&mut target[i * 2..], *w);
23 }
24 Ok(Data {
25 data: target,
26 quantity: words.len(),
27 })
28 }
29 pub(crate) fn copy_to(&self, buf: &mut [u8]) {
31 let cnt = self.quantity * 2;
32 debug_assert!(buf.len() >= cnt);
33 (0..cnt).for_each(|idx| {
34 buf[idx] = self.data[idx];
35 });
36 }
37 #[must_use]
39 pub const fn len(&self) -> usize {
40 self.quantity
41 }
42 #[must_use]
44 pub const fn is_empty(&self) -> bool {
45 self.quantity == 0
46 }
47 #[must_use]
49 pub fn get(&self, idx: usize) -> Option<Word> {
50 if idx + 1 > self.quantity {
51 return None;
52 }
53 let idx = idx * 2;
54 Some(BigEndian::read_u16(&self.data[idx..idx + 2]))
55 }
56
57 #[must_use]
58 pub const fn payload(&self) -> &[u8] {
59 self.data
60 }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65pub struct DataFromBufferError;
66
67impl<'buffer> TryFrom<&'buffer [u8]> for Data<'buffer> {
68 type Error = DataFromBufferError;
69
70 fn try_from(value: &'buffer [u8]) -> Result<Self, Self::Error> {
71 if value.is_empty() || value.len() % 2 != 0 {
72 Err(DataFromBufferError)
73 } else {
74 Ok(Self {
75 data: value,
76 quantity: value.len() / 2,
77 })
78 }
79 }
80}
81
82macro_rules! derive_from_for_data {
83 ($($buffer_length: literal)+) => {
84 $(
85 impl<'buffer> From<&'buffer [u8; $buffer_length]> for Data<'buffer> {
86 fn from(value: &'buffer [u8; $buffer_length]) -> Self {
87 Self {
88 data: value,
89 quantity: $buffer_length / 2,
90 }
91 }
92 }
93 )+
94 };
95}
96derive_from_for_data!(2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32);
97
98#[cfg_attr(all(feature = "defmt", target_os = "none"), derive(defmt::Format))]
101#[derive(Debug, Clone, PartialEq, Eq)]
102pub struct DataIter<'d> {
103 cnt: usize,
104 data: Data<'d>,
105}
106
107impl Iterator for DataIter<'_> {
108 type Item = Word;
109
110 fn next(&mut self) -> Option<Self::Item> {
111 let result = self.data.get(self.cnt);
112 self.cnt += 1;
113 result
114 }
115}
116
117impl<'d> IntoIterator for Data<'d> {
118 type Item = Word;
119 type IntoIter = DataIter<'d>;
120
121 fn into_iter(self) -> Self::IntoIter {
122 DataIter { cnt: 0, data: self }
123 }
124}
125
126#[cfg(test)]
127mod tests {
128
129 use super::*;
130
131 #[test]
132 fn from_word_slice() {
133 let words: &[u16] = &[0xABCD, 0xEF00, 0x1234];
134 let buff: &mut [u8] = &mut [0; 5];
135 assert!(Data::from_words(words, buff).is_err());
136 let buff: &mut [u8] = &mut [0; 6];
137 let data = Data::from_words(words, buff).unwrap();
138 assert_eq!(data.len(), 3);
139 let mut iter = data.into_iter();
140 assert_eq!(iter.next(), Some(0xABCD));
141 assert_eq!(iter.next(), Some(0xEF00));
142 assert_eq!(iter.next(), Some(0x1234));
143 assert_eq!(iter.next(), None);
144 }
145
146 #[test]
147 fn data_len() {
148 let data = Data {
149 data: &[0, 1, 2],
150 quantity: 5,
151 };
152 assert_eq!(data.len(), 5);
153 }
154
155 #[test]
156 fn data_empty() {
157 let data = Data {
158 data: &[0, 1, 2],
159 quantity: 0,
160 };
161 assert!(data.is_empty());
162 }
163
164 #[test]
165 fn data_get() {
166 let data = Data {
167 data: &[0xAB, 0xBC, 0x12],
168 quantity: 1,
169 };
170 assert_eq!(data.get(0), Some(0xABBC));
171 assert_eq!(data.get(1), None);
172
173 let data = Data {
174 data: &[0xFF, 0xAB, 0xCD, 0xEF, 0x33],
175 quantity: 2,
176 };
177 assert_eq!(data.get(0), Some(0xFFAB));
178 assert_eq!(data.get(1), Some(0xCDEF));
179 assert_eq!(data.get(2), None);
180 }
181
182 #[test]
183 fn data_iter() {
184 let data = Data {
185 data: &[0x01, 0x02, 0x03, 0x04, 0xAA, 0xBB],
186 quantity: 3,
187 };
188 let mut data_iter = DataIter { cnt: 0, data };
189 assert_eq!(data_iter.next(), Some(0x0102));
190 assert_eq!(data_iter.next(), Some(0x0304));
191 assert_eq!(data_iter.next(), Some(0xAABB));
192 assert_eq!(data_iter.next(), None);
193 }
194
195 #[test]
196 fn data_into_iter() {
197 let data = Data {
198 data: &[0x01, 0x02, 0x03, 0x04, 0xAA, 0xBB],
199 quantity: 3,
200 };
201 let mut data_iter = data.into_iter();
202 assert!(data_iter.next().is_some());
203 assert!(data_iter.next().is_some());
204 assert!(data_iter.next().is_some());
205 assert!(data_iter.next().is_none());
206 }
207
208 #[test]
209 fn data_try_from() {
210 assert_eq!(
211 Data::try_from(&[] as &[u8]),
212 Err(DataFromBufferError),
213 "Data from empty buffer is not allowed"
214 );
215 assert_eq!(
216 Data::try_from(&[0u8] as &[u8]),
217 Err(DataFromBufferError),
218 "Data from buffer with length that is not a multiple of 2 is not allowed"
219 );
220 assert_eq!(
221 Data::try_from(&[0u8, 1, 2] as &[u8]),
222 Err(DataFromBufferError),
223 "Data from buffer with length that is not a multiple of 2 is not allowed"
224 );
225 assert_eq!(
226 Data::try_from(&[0u8, 1] as &[u8]),
227 Ok(Data {
228 data: &[0, 1],
229 quantity: 1
230 }),
231 "Data from buffer with even length must succeed"
232 );
233 assert_eq!(
234 Data::try_from(&0x1234_5678_u64.to_be_bytes() as &[u8]),
235 Ok(Data {
236 data: &0x1234_5678_u64.to_be_bytes(),
237 quantity: 4
238 }),
239 "Data from buffer with even length must succeed"
240 );
241 }
242
243 #[test]
244 fn data_from() {
245 assert_eq!(
246 Data::from(&[0u8, 1]),
247 Data {
248 data: &[0, 1],
249 quantity: 1
250 },
251 "Data from buffer with even length must succeed"
252 );
253 assert_eq!(
254 Data::from(&0x1234_5678_u64.to_be_bytes()),
255 Data {
256 data: &0x1234_5678_u64.to_be_bytes(),
257 quantity: 4
258 },
259 "Data from buffer with even length must succeed"
260 );
261 }
262}