mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-04 00:54:07 +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::collections::HashMap;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::size_of;
|
use std::mem::{size_of, MaybeUninit};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
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);
|
||||||
impl_read_tuple!(T1, T2, T3, T4);
|
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
|
/// 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,
|
/// 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)
|
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
|
/// Trait for types that can be written to a stream, requiring the size to be configured
|
||||||
pub trait BitWriteSized<E: Endianness> {
|
pub trait BitWriteSized<E: Endianness> {
|
||||||
/// Write the type to stream
|
/// Write the type to stream
|
||||||
|
|
@ -120,3 +130,13 @@ impl<E: Endianness> BitWriteSized<E> for BitReadStream<'_, E> {
|
||||||
stream.write_bits(&bits)
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,3 +90,9 @@ fn test_field_enum() {
|
||||||
roundtrip(Enum::C(12.0));
|
roundtrip(Enum::C(12.0));
|
||||||
roundtrip(Enum::D(-12345));
|
roundtrip(Enum::D(-12345));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_array() {
|
||||||
|
roundtrip([1, 2, 3, 4, 5]);
|
||||||
|
roundtrip([String::from("asd"), String::from("foobar")]);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue