bin_proto/impls/
array.rs

1use bitstream_io::{BitRead, BitWrite, Endianness};
2
3use crate::{util, BitDecode, BitEncode, Result};
4use core::mem::MaybeUninit;
5
6struct PartialGuard<T> {
7    ptr: *mut T,
8    len: usize,
9}
10
11impl<T> Drop for PartialGuard<T> {
12    fn drop(&mut self) {
13        unsafe {
14            core::ptr::drop_in_place(core::ptr::slice_from_raw_parts_mut(self.ptr, self.len));
15        }
16    }
17}
18
19impl<Ctx, T, const N: usize> BitDecode<Ctx> for [T; N]
20where
21    T: BitDecode<Ctx>,
22{
23    fn decode<R, E>(read: &mut R, ctx: &mut Ctx, (): ()) -> Result<Self>
24    where
25        R: BitRead,
26        E: Endianness,
27    {
28        let mut array: MaybeUninit<[T; N]> = MaybeUninit::uninit();
29        let mut guard = PartialGuard {
30            ptr: array.as_mut_ptr().cast::<T>(),
31            len: 0,
32        };
33        while guard.len < N {
34            let item = T::decode::<_, E>(read, ctx, ())?;
35            unsafe {
36                guard.ptr.add(guard.len).write(item);
37            }
38            guard.len += 1;
39        }
40        core::mem::forget(guard);
41        Ok(unsafe { array.assume_init() })
42    }
43}
44
45impl<Ctx, T, const N: usize> BitEncode<Ctx> for [T; N]
46where
47    T: BitEncode<Ctx> + Sized,
48{
49    fn encode<W, E>(&self, write: &mut W, ctx: &mut Ctx, (): ()) -> Result<()>
50    where
51        W: BitWrite,
52        E: Endianness,
53    {
54        util::encode_items::<_, E, _, _>(self.iter(), write, ctx)
55    }
56}
57
58test_codec!([u8; 4]; [0, 1, 2, 3] => [0x00, 0x01, 0x02, 0x03]);
59test_roundtrip!([u8; 4]);