1use super::*;
6use anyhow::Context;
7use byteorder::{BigEndian, ByteOrder, LittleEndian, WriteBytesExt};
8use core::hash::Hash;
9use std::collections::HashSet;
10
11macro_rules! impl_try_array_unpack_sized(
12 ($self:ty, $lifetime:lifetime) => {
13 fn try_array_unpack(iter: &mut std::slice::Iter<$lifetime, u8>) -> anyhow::Result<<$self>::Unpacked> {
14 let data: &[u8] = TryUnpackAs::<SpinelDataWlen>::try_unpack_as(iter)?;
15 Self::try_unpack_from_slice(data)
16 }
17 }
18);
19
20macro_rules! impl_try_array_owned_unpack_sized(
21 ($self:ty) => {
22 fn try_array_owned_unpack(iter: &mut std::slice::Iter<'_, u8>) -> anyhow::Result<<$self>::Unpacked> {
23 let data: &[u8] = TryUnpackAs::<SpinelDataWlen>::try_unpack_as(iter)?;
24 Self::try_owned_unpack_from_slice(data)
25 }
26 }
27);
28
29macro_rules! impl_try_pack_unpack_as_data(
30 (u8) => {
31 };
33 ($self:ty) => {
34 impl<'a> TryUnpackAs<'a, [u8]> for $self {
35 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
36 Self::try_unpack(iter)
37 }
38 }
39 impl<'a> TryUnpackAs<'a, SpinelDataWlen> for $self {
40 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
41 let buffer: &'a[u8] = TryUnpackAs::<SpinelDataWlen>::try_unpack_as(iter)?;
43
44 TryUnpackAs::<[u8]>::try_unpack_as(&mut buffer.iter())
46 }
47 }
48 impl TryPackAs<[u8]> for $self {
49 fn pack_as_len(&self) -> io::Result<usize> {
50 self.pack_len()
51 }
52
53 fn try_pack_as<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
54 self.try_pack(buffer)
55 }
56 }
57 impl TryPackAs<SpinelDataWlen> for $self {
58 fn pack_as_len(&self) -> io::Result<usize> {
59 self.pack_len().map(|x|x+2)
60 }
61
62 fn try_pack_as<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
63 let mut len = TryPackAs::<[u8]>::pack_as_len(self)?;
65
66 len += TryPackAs::<u16>::try_pack_as(&(len as u16), buffer)?;
69
70 TryPackAs::<[u8]>::try_pack_as(self, buffer)?;
72
73 Ok(len)
74 }
75 }
76 };
77 ($self:ty $(,$next:ty)*,) => {
78 impl_try_pack_unpack_as_data!($self $(,$next)*);
79 };
80 ($self:ty $(,$next:ty)*) => {
81 impl_try_pack_unpack_as_data!($self);
82 impl_try_pack_unpack_as_data!($($next,)*);
83 };
84);
85
86macro_rules! def_fixed_len(
89 ($t:ty, $len:expr, |$pack_buf:ident, $pack_var:ident| $pack_block:expr, | $unpack_buf:ident | $unpack_block:expr) => {
90 def_fixed_len!($t, $len, $t, |$pack_buf, $pack_var|$pack_block, | $unpack_buf | $unpack_block);
91 };
92 ($t:ty, $len:expr, $pack_as:ty, |$pack_buf:ident, $pack_var:ident| $pack_block:expr, | $unpack_buf:ident | $unpack_block:expr) => {
93 impl_try_pack_unpack_as_data!($t);
94 impl TryPackAs<$pack_as> for $t {
95 fn pack_as_len(&self) -> io::Result<usize> {
96 Ok(<$t>::FIXED_LEN)
97 }
98
99 fn try_pack_as<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
100 let pack = | $pack_buf: &mut T, $pack_var: $t | $pack_block;
101 pack (buffer, *self).map(|_|<$t>::FIXED_LEN)
104 }
105 }
106
107 impl SpinelFixedLen for $t {
108 const FIXED_LEN: usize = $len;
109 }
110
111 impl TryPack for $t {
112 fn pack_len(&self) -> io::Result<usize> {
113 TryPackAs::<$pack_as>::pack_as_len(self)
114 }
115
116 fn try_pack<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
117 TryPackAs::<$pack_as>::try_pack_as(self, buffer)
118 }
119 }
120
121 impl<'a> TryUnpackAs<'a, $pack_as> for $t {
122 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
123 let unpack_fn = | $unpack_buf: &[u8] | $unpack_block;
124
125 if iter.len() < <$t>::FIXED_LEN {
126 Err(UnpackingError::InvalidInternalLength)?
127 }
128
129 let result: Result<$t,UnpackingError> = unpack_fn(iter.as_slice());
130 *iter = iter.as_slice()[<$t>::FIXED_LEN..].iter();
131 Ok(result?)
132 }
133 }
134
135 impl_try_unpack_for_owned! {
136 impl TryOwnedUnpack for $t {
137 type Unpacked = Self;
138 fn try_owned_unpack(iter: &mut std::slice::Iter<'_, u8>) -> anyhow::Result<Self::Unpacked> {
139 TryUnpackAs::<$pack_as>::try_unpack_as(iter)
140 }
141 }
142 }
143 };
144);
145
146def_fixed_len!(u8, 1, |b, v| b.write_u8(v), |buffer| Ok(buffer[0]));
147
148def_fixed_len!(i8, 1, |b, v| b.write_i8(v), |buffer| Ok(buffer[0] as i8));
149
150def_fixed_len!(u16, 2, |b, v| b.write_u16::<LittleEndian>(v), |buffer| Ok(LittleEndian::read_u16(
151 buffer
152)));
153
154def_fixed_len!(i16, 2, |b, v| b.write_i16::<LittleEndian>(v), |buffer| Ok(LittleEndian::read_i16(
155 buffer
156)));
157
158def_fixed_len!(u32, 4, |b, v| b.write_u32::<LittleEndian>(v), |buffer| Ok(LittleEndian::read_u32(
159 buffer
160)));
161
162def_fixed_len!(i32, 4, |b, v| b.write_i32::<LittleEndian>(v), |buffer| Ok(LittleEndian::read_i32(
163 buffer
164)));
165
166def_fixed_len!(u64, 8, |b, v| b.write_u64::<LittleEndian>(v), |buffer| Ok(LittleEndian::read_u64(
167 buffer
168)));
169
170def_fixed_len!(i64, 8, |b, v| b.write_i64::<LittleEndian>(v), |buffer| Ok(LittleEndian::read_i64(
171 buffer
172)));
173
174def_fixed_len!(bool, 1, |b, v| b.write_u8(v as u8), |buffer| match buffer[0] {
175 0 => Ok(false),
176 1 => Ok(true),
177 _ => Err(UnpackingError::InvalidValue),
178});
179
180def_fixed_len!((), 0, |_b, _v| { Ok(()) }, |_b| Ok(()));
181
182def_fixed_len!(std::net::Ipv6Addr, 16, |b, v| b.write_u128::<BigEndian>(v.into()), |b| Ok(
183 BigEndian::read_u128(b).into()
184));
185
186def_fixed_len!(EUI64, 8, |b, v| b.write_all((&v).into()), |b| Ok(EUI64([
187 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]
188])));
189
190def_fixed_len!(EUI48, 6, |b, v| b.write_all((&v).into()), |b| Ok(EUI48([
191 b[0], b[1], b[2], b[3], b[4], b[5]
192])));
193
194impl TryPack for str {
195 fn pack_len(&self) -> io::Result<usize> {
196 TryPackAs::<str>::pack_as_len(self)
197 }
198
199 fn try_pack<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
200 TryPackAs::<str>::try_pack_as(self, buffer)
201 }
202}
203
204impl TryPack for &str {
205 fn pack_len(&self) -> io::Result<usize> {
206 TryPackAs::<str>::pack_as_len(*self)
207 }
208
209 fn try_pack<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
210 TryPackAs::<str>::try_pack_as(*self, buffer)
211 }
212}
213
214impl TryPack for String {
215 fn pack_len(&self) -> io::Result<usize> {
216 TryPackAs::<str>::pack_as_len(self.as_str())
217 }
218
219 fn try_pack<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
220 TryPackAs::<str>::try_pack_as(self.as_str(), buffer)
221 }
222}
223
224impl TryPackAs<str> for str {
225 fn pack_as_len(&self) -> io::Result<usize> {
226 Ok(self.len() + 1)
227 }
228
229 fn try_pack_as<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
230 let bytes = self.as_bytes();
231 let len = bytes.len() + 1;
232
233 if len > u16::MAX as usize {
234 Err(io::ErrorKind::InvalidInput.into())
235 } else if buffer.write(bytes)? != bytes.len() || buffer.write(&[0u8; 1])? != 1 {
236 Err(io::ErrorKind::Other.into())
237 } else {
238 Ok(len)
239 }
240 }
241}
242
243impl TryPackAs<str> for &str {
244 fn pack_as_len(&self) -> io::Result<usize> {
245 TryPackAs::<str>::pack_as_len(*self)
246 }
247
248 fn try_pack_as<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
249 TryPackAs::<str>::try_pack_as(*self, buffer)
250 }
251}
252
253impl TryPackAs<str> for String {
254 fn pack_as_len(&self) -> io::Result<usize> {
255 TryPackAs::<str>::pack_as_len(self.as_str())
256 }
257
258 fn try_pack_as<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
259 TryPackAs::<str>::try_pack_as(self.as_str(), buffer)
260 }
261}
262
263impl TryPackAs<str> for &[u8] {
264 fn pack_as_len(&self) -> io::Result<usize> {
265 Ok(self.len() + 1)
266 }
267
268 fn try_pack_as<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
269 let string = std::str::from_utf8(self)
270 .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
271 TryPackAs::<str>::try_pack_as(string, buffer)
272 }
273}
274
275impl TryPackAs<str> for Vec<u8> {
276 fn pack_as_len(&self) -> io::Result<usize> {
277 TryPackAs::<str>::pack_as_len(&self.as_slice())
278 }
279
280 fn try_pack_as<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> io::Result<usize> {
281 TryPackAs::<str>::try_pack_as(&self.as_slice(), buffer)
282 }
283}
284
285impl<T: TryPack> TryPack for Vec<T>
286where
287 for<'a> &'a [T]: TryPack,
288{
289 fn pack_len(&self) -> io::Result<usize> {
290 self.as_slice().pack_len()
291 }
292
293 fn try_pack<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
294 self.as_slice().try_pack(buffer)
295 }
296
297 fn array_pack_len(&self) -> io::Result<usize> {
298 self.as_slice().array_pack_len()
299 }
300
301 fn try_array_pack<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
302 self.as_slice().try_array_pack(buffer)
303 }
304}
305
306impl<T: TryPack> TryPack for &[T] {
307 fn pack_len(&self) -> io::Result<usize> {
308 let mut len: usize = 0;
309 for iter in self.iter() {
310 len += iter.array_pack_len()?;
311 }
312 Ok(len)
313 }
314
315 fn try_pack<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
316 let mut len: usize = 0;
317
318 for iter in self.iter() {
320 len += iter.try_array_pack(buffer)?;
321 }
322
323 Ok(len)
324 }
325
326 fn array_pack_len(&self) -> io::Result<usize> {
327 self.pack_len().map(|len| len + 2)
328 }
329
330 fn try_array_pack<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
331 let pack_len = self.pack_len()?;
332
333 let pack_len: u16 =
335 pack_len.try_into().map_err(|_| io::Error::from(io::ErrorKind::InvalidInput))?;
336
337 TryPackAs::<u16>::try_pack_as(&pack_len, buffer)?;
338
339 self.try_pack(buffer).map(|len| len + 2)
340 }
341}
342
343impl<T: TryPack> TryPack for HashSet<T> {
344 fn pack_len(&self) -> io::Result<usize> {
345 let mut len: usize = 0;
346 for iter in self.iter() {
347 len += iter.array_pack_len()?;
348 }
349 Ok(len)
350 }
351
352 fn try_pack<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
353 let mut len: usize = 0;
354
355 for iter in self.iter() {
357 len += iter.try_array_pack(buffer)?;
358 }
359
360 Ok(len)
361 }
362
363 fn array_pack_len(&self) -> io::Result<usize> {
364 self.pack_len().map(|len| len + 2)
365 }
366
367 fn try_array_pack<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
368 let pack_len = self.pack_len()?;
369
370 let pack_len: u16 =
372 pack_len.try_into().map_err(|_| io::Error::from(io::ErrorKind::InvalidInput))?;
373
374 TryPackAs::<u16>::try_pack_as(&pack_len, buffer)?;
375
376 self.try_pack(buffer).map(|len| len + 2)
377 }
378}
379
380impl<'a> TryUnpack<'a> for &'a EUI64 {
382 type Unpacked = Self;
383 fn try_unpack(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self::Unpacked> {
384 if iter.len() < std::mem::size_of::<EUI64>() {
385 Err(UnpackingError::InvalidInternalLength)?
386 }
387
388 let ret = &iter.as_slice()[..std::mem::size_of::<EUI64>()];
390
391 *iter = ret[ret.len()..].iter();
393
394 Ok(ret.try_into().unwrap())
395 }
396}
397
398impl<'a> TryUnpack<'a> for &'a EUI48 {
400 type Unpacked = Self;
401 fn try_unpack(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self::Unpacked> {
402 if iter.len() < std::mem::size_of::<EUI48>() {
403 Err(UnpackingError::InvalidInternalLength)?
404 }
405
406 let ret = &iter.as_slice()[..std::mem::size_of::<EUI48>()];
408
409 *iter = ret[ret.len()..].iter();
411
412 Ok(ret.try_into().unwrap())
413 }
414}
415
416impl<'a> TryUnpack<'a> for &'a [u8] {
417 type Unpacked = Self;
418 fn try_unpack(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self::Unpacked> {
419 let ret = iter.as_slice();
421
422 *iter = ret[ret.len()..].iter();
424
425 Ok(ret)
426 }
427 impl_try_array_unpack_sized!(Self, 'a);
428}
429
430impl<'a> TryUnpackAs<'a, [u8]> for &'a [u8] {
431 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
432 Self::try_unpack(iter)
433 }
434}
435
436impl<'a> TryUnpackAs<'a, SpinelDataWlen> for &'a [u8] {
437 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
438 let len = u16::try_unpack(iter)? as usize;
439
440 let ret = iter.as_slice();
441
442 if ret.len() < len {
443 Err(UnpackingError::InvalidInternalLength)?
444 }
445
446 *iter = ret[len..].iter();
448
449 Ok(&ret[..len])
450 }
451}
452
453impl<'a> TryUnpack<'a> for &'a str {
454 type Unpacked = Self;
455 fn try_unpack(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self::Unpacked> {
456 TryUnpackAs::<str>::try_unpack_as(iter)
457 }
458}
459
460impl<'a> TryUnpackAs<'a, str> for &'a str {
461 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
462 let mut split = iter.as_slice().splitn(2, |c| *c == 0);
463
464 let str_bytes: &[u8] = split.next().ok_or(UnpackingError::UnterminatedString)?;
465
466 *iter = split.next().ok_or(UnpackingError::UnterminatedString)?.iter();
467
468 std::str::from_utf8(str_bytes).context(UnpackingError::InvalidValue)
469 }
470}
471
472impl<'a> TryUnpackAs<'a, str> for String {
473 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
474 <&str>::try_unpack(iter).map(ToString::to_string)
475 }
476}
477
478impl<'a> TryUnpackAs<'a, str> for &'a [u8] {
479 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
480 <&str as TryUnpackAs<str>>::try_unpack_as(iter).map(str::as_bytes)
481 }
482}
483
484impl<'a> TryUnpackAs<'a, str> for Vec<u8> {
485 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
486 <&[u8] as TryUnpackAs<str>>::try_unpack_as(iter).map(<[u8]>::to_vec)
487 }
488}
489
490impl_try_unpack_for_owned! {
491 impl TryOwnedUnpack for String {
492 type Unpacked = Self;
493 fn try_owned_unpack(iter: &mut std::slice::Iter<'_, u8>) -> anyhow::Result<Self::Unpacked> {
494 <&str>::try_unpack(iter).map(ToString::to_string)
495 }
496 }
497}
498
499impl TryPackAs<SpinelUint> for u32 {
500 fn pack_as_len(&self) -> std::io::Result<usize> {
501 if *self < (1 << 7) {
502 Ok(1)
503 } else if *self < (1 << 14) {
504 Ok(2)
505 } else if *self < (1 << 21) {
506 Ok(3)
507 } else if *self < (1 << 28) {
508 Ok(4)
509 } else {
510 Ok(5)
511 }
512 }
513
514 fn try_pack_as<T: std::io::Write + ?Sized>(&self, buffer: &mut T) -> std::io::Result<usize> {
515 let len = TryPackAs::<SpinelUint>::pack_as_len(self)?;
516
517 let mut value = *self;
518 let mut inner_buffer = [0u8; 5];
519
520 #[allow(clippy::needless_range_loop)]
521 for i in 0..(len - 1) {
522 inner_buffer[i] = ((value & 0x7F) | 0x80) as u8;
523 value >>= 7;
524 }
525
526 inner_buffer[len - 1] = (value & 0x7F) as u8;
527
528 buffer.write_all(&inner_buffer[..len])?;
529
530 Ok(len)
531 }
532}
533
534impl<'a> TryUnpackAs<'a, SpinelUint> for u32 {
535 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
536 let mut len: usize = 0;
537 let mut value: u32 = 0;
538 let mut i = 0;
539
540 loop {
541 if len >= 5 {
542 return Err(UnpackingError::InvalidValue.into());
543 }
544
545 let byte = iter.next().ok_or(UnpackingError::InvalidInternalLength)?;
546
547 len += 1;
548
549 value |= ((byte & 0x7F) as u32) << i;
550
551 if byte & 0x80 != 0x80 {
552 break;
553 }
554
555 i += 7;
556 }
557
558 Ok(value)
559 }
560}
561
562impl_try_unpack_for_owned! {
563 impl TryOwnedUnpack for SpinelUint {
564 type Unpacked = u32;
565 fn try_owned_unpack(iter: &mut std::slice::Iter<'_, u8>) -> anyhow::Result<Self::Unpacked> {
566 TryUnpackAs::<SpinelUint>::try_unpack_as(iter)
567 }
568 }
569}
570
571impl<T> TryOwnedUnpack for [T]
572where
573 T: TryOwnedUnpack,
574{
575 type Unpacked = Vec<T::Unpacked>;
576 fn try_owned_unpack(iter: &mut std::slice::Iter<'_, u8>) -> anyhow::Result<Self::Unpacked> {
577 let mut ret: Self::Unpacked = Vec::with_capacity(iter.size_hint().0);
578
579 while iter.len() != 0 {
580 ret.push(T::try_array_owned_unpack(iter)?);
581 }
582
583 Ok(ret)
584 }
585 impl_try_array_owned_unpack_sized!(Self);
586}
587
588impl<T> TryOwnedUnpack for Vec<T>
589where
590 T: TryOwnedUnpack,
591{
592 type Unpacked = Vec<T::Unpacked>;
593 fn try_owned_unpack(iter: &mut std::slice::Iter<'_, u8>) -> anyhow::Result<Self::Unpacked> {
594 let mut ret: Self::Unpacked = Vec::with_capacity(iter.size_hint().0);
595
596 while iter.len() != 0 {
597 ret.push(T::try_array_owned_unpack(iter)?);
598 }
599
600 Ok(ret)
601 }
602 impl_try_array_owned_unpack_sized!(Self);
603}
604
605impl<'a, T, const N: usize> TryUnpack<'a> for [T; N]
606where
607 T: TryUnpack<'a>,
608{
609 type Unpacked = [T::Unpacked; N];
610 fn try_unpack(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self::Unpacked> {
611 let mut ret: Vec<T::Unpacked> = Vec::with_capacity(iter.size_hint().0);
612
613 while iter.len() != 0 {
614 ret.push(T::try_array_unpack(iter)?);
615 }
616
617 ret.try_into().map_err(|vec: Vec<_>| {
618 anyhow::anyhow!("incorrect number of elements {} vs {}", vec.len(), N)
619 })
620 }
621 impl_try_array_unpack_sized!(Self, 'a);
622}
623
624impl<'a, T> TryUnpack<'a> for Vec<T>
625where
626 T: TryUnpack<'a>,
627{
628 type Unpacked = Vec<T::Unpacked>;
629 fn try_unpack(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self::Unpacked> {
630 let mut ret: Self::Unpacked = Vec::with_capacity(iter.size_hint().0);
631
632 while iter.len() != 0 {
633 ret.push(T::try_array_unpack(iter)?);
634 }
635
636 Ok(ret)
637 }
638 impl_try_array_unpack_sized!(Self, 'a);
639}
640
641impl<T> TryOwnedUnpack for HashSet<T>
642where
643 T: TryOwnedUnpack,
644 T::Unpacked: Eq + Hash,
645{
646 type Unpacked = HashSet<T::Unpacked>;
647 fn try_owned_unpack(iter: &mut std::slice::Iter<'_, u8>) -> anyhow::Result<Self::Unpacked> {
648 let mut ret: Self::Unpacked = Default::default();
649
650 while iter.len() != 0 {
651 ret.insert(T::try_array_owned_unpack(iter)?);
652 }
653
654 Ok(ret)
655 }
656 impl_try_array_owned_unpack_sized!(Self);
657}
658
659impl<'a, T> TryUnpack<'a> for HashSet<T>
660where
661 T: TryUnpack<'a>,
662 T::Unpacked: Eq + Hash,
663{
664 type Unpacked = HashSet<T::Unpacked>;
665 fn try_unpack(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self::Unpacked> {
666 let mut ret: Self::Unpacked = Default::default();
667
668 while iter.len() != 0 {
669 ret.insert(T::try_array_unpack(iter)?);
670 }
671
672 Ok(ret)
673 }
674 impl_try_array_unpack_sized!(Self, 'a);
675}
676
677impl<'a, T, const N: usize> TryUnpackAs<'a, [u8]> for [T; N]
678where
679 Self: TryUnpack<'a, Unpacked = Self>,
680{
681 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
682 Self::try_unpack(iter)
683 }
684}
685
686impl<'a, T> TryUnpackAs<'a, [u8]> for Vec<T>
687where
688 Self: TryUnpack<'a, Unpacked = Self>,
689{
690 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
691 Self::try_unpack(iter)
692 }
693}
694
695impl<'a, T, const N: usize> TryUnpackAs<'a, SpinelDataWlen> for [T; N]
696where
697 Self: TryUnpackAs<'a, [u8]>,
698{
699 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
700 let buffer: &'a [u8] = TryUnpackAs::<SpinelDataWlen>::try_unpack_as(iter)?;
702
703 TryUnpackAs::<[u8]>::try_unpack_as(&mut buffer.iter())
705 }
706}
707
708impl<'a, T> TryUnpackAs<'a, SpinelDataWlen> for Vec<T>
709where
710 Self: TryUnpackAs<'a, [u8]>,
711{
712 fn try_unpack_as(iter: &mut std::slice::Iter<'a, u8>) -> anyhow::Result<Self> {
713 let buffer: &'a [u8] = TryUnpackAs::<SpinelDataWlen>::try_unpack_as(iter)?;
715
716 TryUnpackAs::<[u8]>::try_unpack_as(&mut buffer.iter())
718 }
719}
720
721impl<T> TryPackAs<[u8]> for Vec<T>
722where
723 for<'a> &'a [T]: TryPackAs<[u8]>,
724{
725 fn pack_as_len(&self) -> io::Result<usize> {
726 TryPackAs::<[u8]>::pack_as_len(&self.as_slice())
727 }
728
729 fn try_pack_as<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
730 TryPackAs::<[u8]>::try_pack_as(&self.as_slice(), buffer)
731 }
732}
733
734impl<T> TryPackAs<[u8]> for &[T]
735where
736 Self: TryPack,
737{
738 fn pack_as_len(&self) -> io::Result<usize> {
739 self.pack_len()
740 }
741
742 fn try_pack_as<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
743 self.try_pack(buffer)
744 }
745}
746
747impl<T, const N: usize> TryPackAs<SpinelDataWlen> for [T; N]
748where
749 for<'a> &'a [T]: TryPackAs<SpinelDataWlen>,
750{
751 fn pack_as_len(&self) -> io::Result<usize> {
752 TryPackAs::<SpinelDataWlen>::pack_as_len(&self.as_slice())
753 }
754
755 fn try_pack_as<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
756 TryPackAs::<SpinelDataWlen>::try_pack_as(&self.as_slice(), buffer)
757 }
758}
759
760impl<T> TryPackAs<SpinelDataWlen> for Vec<T>
761where
762 for<'a> &'a [T]: TryPackAs<SpinelDataWlen>,
763{
764 fn pack_as_len(&self) -> io::Result<usize> {
765 TryPackAs::<SpinelDataWlen>::pack_as_len(&self.as_slice())
766 }
767
768 fn try_pack_as<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
769 TryPackAs::<SpinelDataWlen>::try_pack_as(&self.as_slice(), buffer)
770 }
771}
772
773impl<T> TryPackAs<SpinelDataWlen> for &[T]
774where
775 Self: TryPackAs<[u8]>,
776{
777 fn pack_as_len(&self) -> io::Result<usize> {
778 TryPackAs::<[u8]>::pack_as_len(self).map(|x| x + 2)
779 }
780
781 fn try_pack_as<B: std::io::Write + ?Sized>(&self, buffer: &mut B) -> io::Result<usize> {
782 let mut len = TryPackAs::<[u8]>::pack_as_len(self)?;
784
785 len += TryPackAs::<u16>::try_pack_as(&(len as u16), buffer)?;
788
789 TryPackAs::<[u8]>::try_pack_as(self, buffer)?;
791
792 Ok(len)
793 }
794}
795
796#[cfg(test)]
797mod tests {
798 use super::*;
799 use assert_matches::assert_matches;
800
801 #[allow(unused)]
804 #[spinel_packed("dD")]
805 #[derive(Debug, Hash, Clone, Eq, PartialEq)]
806 pub struct NetworkPacket<'a> {
807 pub packet: &'a [u8],
808 pub metadata: &'a [u8],
809 }
810
811 #[test]
812 fn test_uint_pack() {
813 let mut buffer = [0u8; 500];
814
815 let mut tmp_buffer = &mut buffer[..];
816
817 assert_eq!(TryPackAs::<SpinelUint>::try_pack_as(&0u32, &mut tmp_buffer).unwrap(), 1,);
818 assert_eq!(&tmp_buffer[0..1], &[0x00]);
819 assert_matches!(
820 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut tmp_buffer[0..1].iter()),
821 Ok(0u32)
822 );
823
824 let mut tmp_buffer = &mut buffer[..];
825 assert_eq!(TryPackAs::<SpinelUint>::try_pack_as(&127u32, &mut tmp_buffer).unwrap(), 1,);
826 assert_eq!(&buffer[0..1], &[0x7F]);
827 assert_matches!(
828 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut buffer[0..1].iter()),
829 Ok(127u32)
830 );
831
832 let mut tmp_buffer = &mut buffer[..];
833 assert_eq!(TryPackAs::<SpinelUint>::try_pack_as(&128u32, &mut tmp_buffer).unwrap(), 2,);
834 assert_eq!(&buffer[0..2], &[0x80, 0x01]);
835 assert_matches!(
836 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut buffer[0..2].iter()),
837 Ok(128u32)
838 );
839
840 let mut tmp_buffer = &mut buffer[..];
841 assert_eq!(TryPackAs::<SpinelUint>::try_pack_as(&16383u32, &mut tmp_buffer).unwrap(), 2,);
842 assert_eq!(&buffer[0..2], &[0xFF, 0x7F]);
843 assert_matches!(
844 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut buffer[0..2].iter()),
845 Ok(16383u32)
846 );
847
848 let mut tmp_buffer = &mut buffer[..];
849 assert_eq!(TryPackAs::<SpinelUint>::try_pack_as(&16384u32, &mut tmp_buffer).unwrap(), 3,);
850 assert_eq!(&buffer[0..3], &[0x80, 0x80, 0x01]);
851 assert_matches!(
852 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut buffer[0..3].iter()),
853 Ok(16384u32)
854 );
855
856 let mut tmp_buffer = &mut buffer[..];
857 assert_eq!(TryPackAs::<SpinelUint>::try_pack_as(&2097151u32, &mut tmp_buffer).unwrap(), 3,);
858 assert_eq!(&buffer[0..3], &[0xFF, 0xFF, 0x7F]);
859 assert_matches!(
860 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut buffer[0..3].iter()),
861 Ok(2097151u32)
862 );
863
864 let mut tmp_buffer = &mut buffer[..];
865 assert_eq!(TryPackAs::<SpinelUint>::try_pack_as(&2097152u32, &mut tmp_buffer).unwrap(), 4,);
866 assert_eq!(&buffer[0..4], &[0x80, 0x80, 0x80, 0x01]);
867 assert_matches!(
868 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut buffer[0..4].iter()),
869 Ok(2097152u32)
870 );
871
872 let mut tmp_buffer = &mut buffer[..];
873 assert_eq!(
874 TryPackAs::<SpinelUint>::try_pack_as(&268435455u32, &mut tmp_buffer).unwrap(),
875 4,
876 );
877 assert_eq!(&buffer[0..4], &[0xFF, 0xFF, 0xFF, 0x7F]);
878 assert_matches!(
879 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut buffer[0..4].iter()),
880 Ok(268435455u32)
881 );
882
883 let mut tmp_buffer = &mut buffer[..];
884 assert_eq!(
885 TryPackAs::<SpinelUint>::try_pack_as(&268435456u32, &mut tmp_buffer).unwrap(),
886 5,
887 );
888 assert_eq!(&buffer[0..5], &[0x80, 0x80, 0x80, 0x80, 0x01]);
889 assert_matches!(
890 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut buffer[0..5].iter()),
891 Ok(268435456u32)
892 );
893
894 let mut tmp_buffer = &mut buffer[..];
895 assert_eq!(
896 TryPackAs::<SpinelUint>::try_pack_as(&4294967295u32, &mut tmp_buffer).unwrap(),
897 5,
898 );
899 assert_eq!(&buffer[0..5], &[0xFF, 0xFF, 0xFF, 0xFF, 0x0F]);
900 assert_matches!(
901 TryUnpackAs::<SpinelUint>::try_unpack_as(&mut buffer[0..5].iter()),
902 Ok(4294967295u32)
903 );
904 }
905
906 #[test]
907 fn test_vec_owned_unpack() {
908 let buffer: &[u8] = &[0x34, 0x12, 0xcd, 0xab];
909
910 let out = Vec::<u16>::try_owned_unpack_from_slice(buffer).unwrap();
911
912 assert_eq!(out.as_slice(), &[0x1234, 0xabcd]);
913 }
914
915 #[test]
916 fn test_vec_unpack() {
917 let buffer: &[u8] = &[0x31, 0x32, 0x33, 0x00, 0x34, 0x35, 0x36, 0x00];
918
919 let out = Vec::<&str>::try_unpack_from_slice(buffer).unwrap();
920
921 assert_eq!(out.as_slice(), &["123", "456"]);
922 }
923
924 #[test]
925 fn test_string_as_vec() {
926 let buffer: &[u8] = &[0x31, 0x32, 0x33, 0x00];
927
928 let out = <&[u8] as TryUnpackAs<str>>::try_unpack_as_from_slice(buffer).unwrap();
929
930 assert_eq!(out, &[0x31, 0x32, 0x33]);
931 }
932
933 #[test]
934 fn test_hashset_owned_unpack() {
935 let buffer: &[u8] = &[0x34, 0x12, 0xcd, 0xab];
936
937 let out = HashSet::<u16>::try_owned_unpack_from_slice(buffer).unwrap();
938
939 assert!(out.contains(&0x1234));
940 assert!(out.contains(&0xabcd));
941 }
942
943 #[test]
944 fn test_hashset_unpack() {
945 let buffer: &[u8] = &[0x31, 0x32, 0x33, 0x00, 0x34, 0x35, 0x36, 0x00];
946
947 let out = HashSet::<&str>::try_unpack_from_slice(buffer).unwrap();
948
949 assert!(out.contains("123"));
950 assert!(out.contains("456"));
951 }
952
953 #[test]
954 fn test_u32_as_data_unpack() {
955 let buffer: &[u8] = &[0x67, 0x45, 0x23, 0x01, 0xfe, 0x0f, 0xdc, 0xba];
956
957 let out = Vec::<u32>::try_unpack_from_slice(buffer).unwrap();
958
959 assert_eq!(out, &[0x01234567, 0xbadc0ffe]);
960 }
961
962 #[test]
963 fn test_u32_as_data_unpack_wlen() {
964 let buffer: &[u8] = &[0x08, 0x00, 0x67, 0x45, 0x23, 0x01, 0xfe, 0x0f, 0xdc, 0xba];
965
966 let out = Vec::<u32>::try_array_unpack(&mut buffer.iter()).unwrap();
967
968 assert_eq!(out, &[0x01234567, 0xbadc0ffe]);
969 }
970
971 #[test]
972 fn test_u32_as_data_pack() {
973 let v: Vec<u32> = vec![0x01234567, 0xbadc0ffe];
974 let buffer: &[u8] = &[0x67, 0x45, 0x23, 0x01, 0xfe, 0x0f, 0xdc, 0xba];
975
976 let mut packed = Vec::with_capacity(v.pack_len().unwrap());
977 v.try_pack(&mut packed).unwrap();
978
979 assert_eq!(buffer, packed);
980 }
981
982 #[test]
983 fn test_u32_as_data_pack_wlen() {
984 let v: Vec<u32> = vec![0x01234567, 0xbadc0ffe];
985 let buffer: &[u8] = &[0x08, 0x00, 0x67, 0x45, 0x23, 0x01, 0xfe, 0x0f, 0xdc, 0xba];
986
987 let mut packed = Vec::with_capacity(v.array_pack_len().unwrap());
988 v.try_array_pack(&mut packed).unwrap();
989
990 assert_eq!(buffer, packed);
991 }
992
993 #[test]
994 fn test_u32_as_data_pack_struct() {
995 #[spinel_packed("d")]
996 #[derive(Debug, Hash, Clone, Eq, PartialEq)]
997 struct Blah {
998 v: Vec<u32>,
999 }
1000 let v = Blah { v: vec![0x01234567, 0xbadc0ffe] };
1001 let buffer: &[u8] = &[0x08, 0x00, 0x67, 0x45, 0x23, 0x01, 0xfe, 0x0f, 0xdc, 0xba];
1002
1003 let mut packed = Vec::with_capacity(v.pack_len().unwrap());
1004 v.try_pack(&mut packed).unwrap();
1005
1006 assert_eq!(buffer, packed);
1007 }
1008
1009 #[test]
1010 fn test_container_pack_unpack() {
1011 #[spinel_packed("6CLL")]
1012 #[derive(Debug, Hash, Clone, Eq, PartialEq)]
1013 pub struct AddressTableEntry {
1014 pub addr: std::net::Ipv6Addr,
1015 pub prefix_len: u8,
1016 pub lifetime_a: u32,
1017 pub lifetime_b: u32,
1018 }
1019
1020 let buffer: &[u8] = &[
1021 0x19, 0x0, 0xfd, 0xde, 0xad, 0x0, 0xbe, 0xef, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0,
1022 0xfc, 0x0, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0, 0xfd, 0xde,
1023 0xad, 0x0, 0xbe, 0xef, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0, 0x44, 0x0, 0x40, 0xff,
1024 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x19, 0x0, 0xfd, 0xde, 0xad, 0x0, 0xbe, 0xef,
1025 0x0, 0x0, 0xec, 0x2c, 0xb9, 0xec, 0xa5, 0x14, 0x96, 0xc, 0x40, 0xff, 0xff, 0xff, 0xff,
1026 0xff, 0xff, 0xff, 0xff, 0x19, 0x0, 0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28,
1027 0x3f, 0xf, 0x66, 0x3e, 0xa7, 0x4d, 0x33, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1028 0xff, 0xff,
1029 ];
1030
1031 let out = Vec::<AddressTableEntry>::try_unpack_from_slice(buffer).unwrap();
1032
1033 assert!(out.contains(&AddressTableEntry {
1034 addr: "fdde:ad00:beef::ff:fe00:4400".parse().unwrap(),
1035 prefix_len: 64,
1036 lifetime_a: 0xFFFFFFFF,
1037 lifetime_b: 0xFFFFFFFF,
1038 }));
1039 assert!(out.contains(&AddressTableEntry {
1040 addr: "fdde:ad00:beef::ff:fe00:fc00".parse().unwrap(),
1041 prefix_len: 64,
1042 lifetime_a: 0xFFFFFFFF,
1043 lifetime_b: 0xFFFFFFFF,
1044 }));
1045 assert!(out.contains(&AddressTableEntry {
1046 addr: "fdde:ad00:beef::ec2c:b9ec:a514:960c".parse().unwrap(),
1047 prefix_len: 64,
1048 lifetime_a: 0xFFFFFFFF,
1049 lifetime_b: 0xFFFFFFFF,
1050 }));
1051 assert!(out.contains(&AddressTableEntry {
1052 addr: "fe80::283f:f66:3ea7:4d33".parse().unwrap(),
1053 prefix_len: 64,
1054 lifetime_a: 0xFFFFFFFF,
1055 lifetime_b: 0xFFFFFFFF,
1056 }));
1057
1058 let buffer_pack = out.try_packed().expect("packing failed");
1059
1060 assert_eq!(buffer_pack.as_slice(), buffer);
1061 }
1062}