spinel_pack/
primitives.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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        // We skip u8.
32    };
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                // Get a reference to the buffer.
42                let buffer: &'a[u8] = TryUnpackAs::<SpinelDataWlen>::try_unpack_as(iter)?;
43
44                // Unpack using that buffer.
45                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                // Start with the length of the encoding
64                let mut len = TryPackAs::<[u8]>::pack_as_len(self)?;
65
66                // Encode the length of the buffer and add the
67                // length of that to our total length.
68                len += TryPackAs::<u16>::try_pack_as(&(len as u16), buffer)?;
69
70                // Encode the rest of the object into the buffer.
71                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
86/// Private convenience macro for defining the appropriate
87/// traits for primitive types with fixed encoding lengths.
88macro_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                //let pack: dyn Fn(&mut T, $t) -> io::Result<()> = $pack_block;
102
103                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        // Write out the elements of the data
319        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        // Write out the length of the data
334        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        // Write out the elements of the data
356        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        // Write out the length of the data
371        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
380/// Borrowed unpack for EUI64
381impl<'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        // Convert the iterator into a slice.
389        let ret = &iter.as_slice()[..std::mem::size_of::<EUI64>()];
390
391        // Move the iterator to the end.
392        *iter = ret[ret.len()..].iter();
393
394        Ok(ret.try_into().unwrap())
395    }
396}
397
398/// Borrowed unpack for EUI48
399impl<'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        // Convert the iterator into a slice.
407        let ret = &iter.as_slice()[..std::mem::size_of::<EUI48>()];
408
409        // Move the iterator to the end.
410        *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        // Convert the iterator into a slice.
420        let ret = iter.as_slice();
421
422        // Move the iterator to the end.
423        *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        // Move the iterator to the end.
447        *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        // Get a reference to the buffer.
701        let buffer: &'a [u8] = TryUnpackAs::<SpinelDataWlen>::try_unpack_as(iter)?;
702
703        // Unpack using that buffer.
704        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        // Get a reference to the buffer.
714        let buffer: &'a [u8] = TryUnpackAs::<SpinelDataWlen>::try_unpack_as(iter)?;
715
716        // Unpack using that buffer.
717        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        // Start with the length of the encoding
783        let mut len = TryPackAs::<[u8]>::pack_as_len(self)?;
784
785        // Encode the length of the buffer and add the
786        // length of that to our total length.
787        len += TryPackAs::<u16>::try_pack_as(&(len as u16), buffer)?;
788
789        // Encode the rest of the object into the buffer.
790        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    /// A verification that Spinel structs with
802    /// both `d` and `D` fields compile correctly.
803    #[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}