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]);