1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-03 16:44:06 +02:00

more write work

This commit is contained in:
Robin Appelman 2021-07-15 22:44:37 +02:00
commit ac3c7ab32a
2 changed files with 60 additions and 1 deletions

View file

@ -1,5 +1,7 @@
use crate::{BitReadStream, BitWriteStream, Endianness, Result}; use crate::{BitReadStream, BitWriteStream, Endianness, Result};
use std::mem::size_of; use std::mem::size_of;
use std::rc::Rc;
use std::sync::Arc;
/// Trait for types that can be written to a stream without requiring the size to be configured /// Trait for types that can be written to a stream without requiring the size to be configured
pub trait BitWrite<E: Endianness> { pub trait BitWrite<E: Endianness> {
@ -81,6 +83,27 @@ impl<E: Endianness, T: BitWrite<E>, const N: usize> BitWrite<E> for [T; N] {
} }
} }
impl<T: BitWrite<E>, E: Endianness> BitWrite<E> for Box<T> {
#[inline]
fn write(&self, stream: &mut BitWriteStream<E>) -> Result<()> {
stream.write(self)
}
}
impl<T: BitWrite<E>, E: Endianness> BitWrite<E> for Rc<T> {
#[inline]
fn write(&self, stream: &mut BitWriteStream<E>) -> Result<()> {
stream.write(self)
}
}
impl<T: BitWrite<E>, E: Endianness> BitWrite<E> for Arc<T> {
#[inline]
fn write(&self, stream: &mut BitWriteStream<E>) -> Result<()> {
stream.write(self)
}
}
macro_rules! impl_write_tuple { macro_rules! impl_write_tuple {
($($i:tt: $type:ident),*) => { ($($i:tt: $type:ident),*) => {
impl<'a, E: Endianness, $($type: BitWrite<E>),*> BitWrite<E> for ($($type),*) { impl<'a, E: Endianness, $($type: BitWrite<E>),*> BitWrite<E> for ($($type),*) {
@ -133,11 +156,13 @@ impl_write_sized_int!(u16);
impl_write_sized_int!(u32); impl_write_sized_int!(u32);
impl_write_sized_int!(u64); impl_write_sized_int!(u64);
impl_write_sized_int!(u128); impl_write_sized_int!(u128);
impl_write_sized_int!(usize);
impl_write_sized_int!(i8); impl_write_sized_int!(i8);
impl_write_sized_int!(i16); impl_write_sized_int!(i16);
impl_write_sized_int!(i32); impl_write_sized_int!(i32);
impl_write_sized_int!(i64); impl_write_sized_int!(i64);
impl_write_sized_int!(i128); impl_write_sized_int!(i128);
impl_write_sized_int!(isize);
impl<E: Endianness> BitWriteSized<E> for BitReadStream<'_, E> { impl<E: Endianness> BitWriteSized<E> for BitReadStream<'_, E> {
#[inline] #[inline]
@ -156,3 +181,24 @@ impl<E: Endianness, T: BitWriteSized<E>, const N: usize> BitWriteSized<E> for [T
Ok(()) Ok(())
} }
} }
impl<T: BitWrite<E>, E: Endianness> BitWriteSized<E> for Box<T> {
#[inline]
fn write_sized(&self, stream: &mut BitWriteStream<E>, len: usize) -> Result<()> {
stream.write_sized(self, len)
}
}
impl<T: BitWrite<E>, E: Endianness> BitWriteSized<E> for Rc<T> {
#[inline]
fn write_sized(&self, stream: &mut BitWriteStream<E>, len: usize) -> Result<()> {
stream.write_sized(self, len)
}
}
impl<T: BitWrite<E>, E: Endianness> BitWriteSized<E> for Arc<T> {
#[inline]
fn write_sized(&self, stream: &mut BitWriteStream<E>, len: usize) -> Result<()> {
stream.write_sized(self, len)
}
}

View file

@ -287,11 +287,24 @@ where
/// Reserve some bits to be written later by splitting of two parts /// Reserve some bits to be written later by splitting of two parts
/// ///
/// This allows skipping a few bits to write later /// This allows skipping a few bits to write later
pub fn reserve(&mut self, count: usize) -> (BitWriteStream<E>, BitWriteStream<E>) { fn reserve(&mut self, count: usize) -> (BitWriteStream<E>, BitWriteStream<E>) {
let (head, tail) = self.buffer.reserve(count); let (head, tail) = self.buffer.reserve(count);
( (
BitWriteStream { buffer: head }, BitWriteStream { buffer: head },
BitWriteStream { buffer: tail }, BitWriteStream { buffer: tail },
) )
} }
/// Write the length of a section before the section
pub fn reserve_length<F: Fn(&mut BitWriteStream<E>) -> Result<()>>(
&mut self,
length_bit_size: usize,
body_fn: F,
) -> Result<()> {
let (mut head, mut tail) = self.reserve(length_bit_size);
let start = tail.bit_len();
body_fn(&mut tail)?;
let end = tail.bit_len();
head.write_sized(&(end - start), length_bit_size)
}
} }