mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
some 32bit optimizations
This commit is contained in:
parent
0fe7c04ece
commit
f09b56b36a
3 changed files with 62 additions and 28 deletions
|
|
@ -256,19 +256,50 @@ macro_rules! impl_is_signed {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoBytes: Sized {
|
pub trait IntoBytes: Sized {
|
||||||
type Iter: DoubleEndedIterator<Item = u8> + ExactSizeIterator;
|
type BytesIter: DoubleEndedIterator<Item = u8> + ExactSizeIterator;
|
||||||
|
type U16Iter: DoubleEndedIterator<Item = u16> + ExactSizeIterator;
|
||||||
|
|
||||||
fn into_bytes(self) -> Self::Iter;
|
fn into_bytes(self) -> Self::BytesIter;
|
||||||
|
|
||||||
|
fn into_u16(self) -> Self::U16Iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_into_bytes {
|
macro_rules! impl_into_bytes {
|
||||||
($type:ty, $bytes:expr) => {
|
($type:ty, $bytes:expr, 1 ) => {
|
||||||
impl IntoBytes for $type {
|
impl IntoBytes for $type {
|
||||||
type Iter = std::array::IntoIter<u8, $bytes>;
|
type BytesIter = std::array::IntoIter<u8, $bytes>;
|
||||||
|
type U16Iter = std::array::IntoIter<u16, 1>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn into_bytes(self) -> Self::Iter {
|
fn into_bytes(self) -> Self::BytesIter {
|
||||||
Self::Iter::new(self.to_le_bytes())
|
Self::BytesIter::new(self.to_le_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn into_u16(self) -> Self::U16Iter {
|
||||||
|
Self::U16Iter::new([self as u16])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($type:ty, $bytes:expr, $shorts:expr ) => {
|
||||||
|
impl IntoBytes for $type {
|
||||||
|
type BytesIter = std::array::IntoIter<u8, $bytes>;
|
||||||
|
type U16Iter = std::array::IntoIter<u16, { $shorts }>;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn into_bytes(self) -> Self::BytesIter {
|
||||||
|
Self::BytesIter::new(self.to_le_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn into_u16(self) -> Self::U16Iter {
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
let bytes = self.to_le_bytes();
|
||||||
|
let (head, aligned, tail) = unsafe { bytes[..].align_to::<u16>() };
|
||||||
|
debug_assert_eq!(0, head.len());
|
||||||
|
debug_assert_eq!(0, tail.len());
|
||||||
|
Self::U16Iter::new(aligned.try_into().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -287,24 +318,24 @@ impl_is_signed!(i64, true);
|
||||||
impl_is_signed!(i128, true);
|
impl_is_signed!(i128, true);
|
||||||
impl_is_signed!(isize, true);
|
impl_is_signed!(isize, true);
|
||||||
|
|
||||||
impl_into_bytes!(u8, 1);
|
impl_into_bytes!(u8, 1, 1);
|
||||||
impl_into_bytes!(u16, 2);
|
impl_into_bytes!(u16, 2, 1);
|
||||||
impl_into_bytes!(u32, 4);
|
impl_into_bytes!(u32, 4, 2);
|
||||||
impl_into_bytes!(u64, 8);
|
impl_into_bytes!(u64, 8, 4);
|
||||||
impl_into_bytes!(u128, 16);
|
impl_into_bytes!(u128, 16, 8);
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
impl_into_bytes!(usize, 8);
|
impl_into_bytes!(usize, 8, 4);
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
impl_into_bytes!(usize, 4);
|
impl_into_bytes!(usize, 4, 2);
|
||||||
|
|
||||||
impl_into_bytes!(i8, 1);
|
impl_into_bytes!(i8, 1, 1);
|
||||||
impl_into_bytes!(i16, 2);
|
impl_into_bytes!(i16, 2, 1);
|
||||||
impl_into_bytes!(i32, 4);
|
impl_into_bytes!(i32, 4, 2);
|
||||||
impl_into_bytes!(i64, 8);
|
impl_into_bytes!(i64, 8, 4);
|
||||||
impl_into_bytes!(i128, 16);
|
impl_into_bytes!(i128, 16, 8);
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
impl_into_bytes!(isize, 8);
|
impl_into_bytes!(isize, 8, 4);
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
impl_into_bytes!(isize, 4);
|
impl_into_bytes!(isize, 4, 2);
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,14 @@ impl<'a, E: Endianness> WriteBuffer<'a, E> {
|
||||||
pub fn push_non_fit_bits<I>(&mut self, bits: I, count: usize)
|
pub fn push_non_fit_bits<I>(&mut self, bits: I, count: usize)
|
||||||
where
|
where
|
||||||
I: ExactSizeIterator,
|
I: ExactSizeIterator,
|
||||||
I: DoubleEndedIterator<Item = u8>,
|
I: DoubleEndedIterator<Item = u16>,
|
||||||
{
|
{
|
||||||
let full_bytes = min(bits.len() - 1, count / 8);
|
let chunk_bits = u16::BITS as usize;
|
||||||
|
let full_bytes = min(bits.len() - 1, count / chunk_bits);
|
||||||
|
|
||||||
let counts = repeat(8)
|
let counts = repeat(chunk_bits)
|
||||||
.take(full_bytes)
|
.take(full_bytes)
|
||||||
.chain(once(count - full_bytes * 8));
|
.chain(once(count - full_bytes * chunk_bits));
|
||||||
if E::is_le() {
|
if E::is_le() {
|
||||||
bits.zip(counts)
|
bits.zip(counts)
|
||||||
.for_each(|(chunk, count)| self.push_bits(chunk as usize, count))
|
.for_each(|(chunk, count)| self.push_bits(chunk as usize, count))
|
||||||
|
|
@ -52,12 +53,14 @@ impl<'a, E: Endianness> WriteBuffer<'a, E> {
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debug_assert!(count < USIZE_BITS - 8);
|
|
||||||
|
|
||||||
// ensure there are no stray bits
|
// ensure there are no stray bits
|
||||||
let bits = bits & (usize::MAX >> (USIZE_BITS - count));
|
let bits = bits & (usize::MAX >> (USIZE_BITS - count));
|
||||||
|
|
||||||
let bit_offset = self.bit_len & 7;
|
let bit_offset = self.bit_len & 7;
|
||||||
|
|
||||||
|
debug_assert!(count <= USIZE_BITS - bit_offset);
|
||||||
|
|
||||||
let last_written_byte = if bit_offset > 0 {
|
let last_written_byte = if bit_offset > 0 {
|
||||||
self.bytes.pop().unwrap_or(0)
|
self.bytes.pop().unwrap_or(0)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ where
|
||||||
fn push_non_fit_bits<I>(&mut self, bits: I, count: usize)
|
fn push_non_fit_bits<I>(&mut self, bits: I, count: usize)
|
||||||
where
|
where
|
||||||
I: ExactSizeIterator,
|
I: ExactSizeIterator,
|
||||||
I: DoubleEndedIterator<Item = u8>,
|
I: DoubleEndedIterator<Item = u16>,
|
||||||
{
|
{
|
||||||
self.buffer.push_non_fit_bits(bits, count)
|
self.buffer.push_non_fit_bits(bits, count)
|
||||||
}
|
}
|
||||||
|
|
@ -142,10 +142,10 @@ where
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if type_bit_size < USIZE_BITS || count < USIZE_BITS {
|
if type_bit_size < USIZE_BITS || count <= (USIZE_BITS - (self.bit_len() % 8)) {
|
||||||
self.push_bits(value.into_usize_unchecked(), count);
|
self.push_bits(value.into_usize_unchecked(), count);
|
||||||
} else {
|
} else {
|
||||||
self.push_non_fit_bits(value.into_bytes(), count)
|
self.push_non_fit_bits(value.into_u16(), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue