mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
read/write array
This commit is contained in:
parent
b7fa549e79
commit
1fadf092cf
3 changed files with 119 additions and 1 deletions
94
src/read.rs
94
src/read.rs
|
|
@ -6,7 +6,7 @@ use std::cmp::min;
|
|||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::size_of;
|
||||
use std::mem::{size_of, MaybeUninit};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
@ -349,6 +349,50 @@ impl_read_tuple!(T1, T2);
|
|||
impl_read_tuple!(T1, T2, T3);
|
||||
impl_read_tuple!(T1, T2, T3, T4);
|
||||
|
||||
impl<'a, E: Endianness, T: BitRead<'a, E>, const N: usize> BitRead<'a, E> for [T; N] {
|
||||
#[inline]
|
||||
fn read(stream: &mut BitReadStream<'a, E>) -> Result<Self> {
|
||||
match T::bit_size() {
|
||||
Some(bit_size) => {
|
||||
let end = stream.check_read(bit_size * N)?;
|
||||
unsafe { Self::read_unchecked(stream, end) }
|
||||
}
|
||||
None => {
|
||||
// SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
|
||||
let mut array =
|
||||
unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() };
|
||||
for i in 0..N {
|
||||
unsafe {
|
||||
// length is already checked
|
||||
let val = stream.read()?;
|
||||
array[i].as_mut_ptr().write(val)
|
||||
}
|
||||
}
|
||||
unsafe { Ok((&array as *const _ as *const [T; N]).read()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn read_unchecked(stream: &mut BitReadStream<'a, E>, end: bool) -> Result<Self> {
|
||||
// SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
|
||||
let mut array = MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init();
|
||||
|
||||
for i in 0..N {
|
||||
// length is already checked
|
||||
let val = stream.read_unchecked(end)?;
|
||||
array[i].as_mut_ptr().write(val);
|
||||
}
|
||||
|
||||
Ok((&array as *const _ as *const [T; N]).read())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bit_size() -> Option<usize> {
|
||||
T::bit_size().map(|size| size * N)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for types that can be read from a stream, requiring the size to be configured
|
||||
///
|
||||
/// The meaning of the set sized depends on the type being read (e.g, number of bits for integers,
|
||||
|
|
@ -710,3 +754,51 @@ impl<'a, T: BitReadSized<'a, E>, E: Endianness> BitReadSized<'a, E> for LazyBitR
|
|||
T::bit_size_sized(size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Endianness, T: BitReadSized<'a, E>, const N: usize> BitReadSized<'a, E> for [T; N] {
|
||||
#[inline]
|
||||
fn read(stream: &mut BitReadStream<'a, E>, size: usize) -> Result<Self> {
|
||||
match T::bit_size_sized(size) {
|
||||
Some(bit_size) => {
|
||||
let end = stream.check_read(bit_size * N)?;
|
||||
unsafe { Self::read_unchecked(stream, size, end) }
|
||||
}
|
||||
None => {
|
||||
// SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
|
||||
let mut array =
|
||||
unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() };
|
||||
for i in 0..N {
|
||||
unsafe {
|
||||
// length is already checked
|
||||
let val = stream.read_sized(size)?;
|
||||
array[i].as_mut_ptr().write(val)
|
||||
}
|
||||
}
|
||||
unsafe { Ok((&array as *const _ as *const [T; N]).read()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn read_unchecked(
|
||||
stream: &mut BitReadStream<'a, E>,
|
||||
size: usize,
|
||||
end: bool,
|
||||
) -> Result<Self> {
|
||||
// SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
|
||||
let mut array = MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init();
|
||||
|
||||
for i in 0..N {
|
||||
// length is already checked
|
||||
let val = stream.read_sized_unchecked(size, end)?;
|
||||
array[i].as_mut_ptr().write(val);
|
||||
}
|
||||
|
||||
Ok((&array as *const _ as *const [T; N]).read())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bit_size_sized(size: usize) -> Option<usize> {
|
||||
T::bit_size_sized(size).map(|size| size * N)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
20
src/write.rs
20
src/write.rs
|
|
@ -71,6 +71,16 @@ impl<E: Endianness> BitWrite<E> for BitReadStream<'_, E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Endianness, T: BitWrite<E>, const N: usize> BitWrite<E> for [T; N] {
|
||||
#[inline]
|
||||
fn write(&self, stream: &mut BitWriteStream<E>) -> Result<()> {
|
||||
for element in self.iter() {
|
||||
stream.write(element)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for types that can be written to a stream, requiring the size to be configured
|
||||
pub trait BitWriteSized<E: Endianness> {
|
||||
/// Write the type to stream
|
||||
|
|
@ -120,3 +130,13 @@ impl<E: Endianness> BitWriteSized<E> for BitReadStream<'_, E> {
|
|||
stream.write_bits(&bits)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Endianness, T: BitWriteSized<E>, const N: usize> BitWriteSized<E> for [T; N] {
|
||||
#[inline]
|
||||
fn write_sized(&self, stream: &mut BitWriteStream<E>, len: usize) -> Result<()> {
|
||||
for element in self.iter() {
|
||||
stream.write_sized(element, len)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue