mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
better IntoBytes
This commit is contained in:
parent
123223f479
commit
bce35aeb32
2 changed files with 83 additions and 32 deletions
|
|
@ -196,15 +196,69 @@ macro_rules! impl_is_signed {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoBytes: Sized {
|
pub trait IntoBytes: Sized {
|
||||||
fn into_bytes(self) -> Vec<u8>;
|
type Iter: DoubleEndedIterator<Item = u8> + ExactSizeIterator;
|
||||||
|
|
||||||
|
fn into_bytes(self) -> Self::Iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_into_bytes {
|
macro_rules! impl_into_bytes {
|
||||||
($type:ty) => {
|
($type:ty, $iter:ident) => {
|
||||||
|
// once std::array:IntoIter is stabilized we can get rid of this iterator
|
||||||
|
// https://github.com/rust-lang/rust/issues/65798
|
||||||
|
pub struct $iter {
|
||||||
|
data: [u8; std::mem::size_of::<$type>()],
|
||||||
|
start: usize,
|
||||||
|
end: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $iter {
|
||||||
|
pub fn new(int: $type) -> Self {
|
||||||
|
$iter {
|
||||||
|
data: int.to_le_bytes(),
|
||||||
|
start: 0,
|
||||||
|
end: std::mem::size_of::<$type>(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for $iter {
|
||||||
|
type Item = u8;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.start < self.end {
|
||||||
|
let byte = self.data[self.start];
|
||||||
|
self.start += 1;
|
||||||
|
Some(byte)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let size = self.end - self.start;
|
||||||
|
(size, Some(size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::iter::DoubleEndedIterator for $iter {
|
||||||
|
fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.end > self.start {
|
||||||
|
self.end -= 1;
|
||||||
|
Some(self.data[self.end])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::iter::ExactSizeIterator for $iter {}
|
||||||
|
|
||||||
impl IntoBytes for $type {
|
impl IntoBytes for $type {
|
||||||
|
type Iter = $iter;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn into_bytes(self) -> Vec<u8> {
|
fn into_bytes(self) -> Self::Iter {
|
||||||
self.to_le_bytes().to_vec()
|
<$iter>::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -223,15 +277,15 @@ 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);
|
impl_into_bytes!(u8, BytesIterU8);
|
||||||
impl_into_bytes!(u16);
|
impl_into_bytes!(u16, BytesIterU16);
|
||||||
impl_into_bytes!(u32);
|
impl_into_bytes!(u32, BytesIterU32);
|
||||||
impl_into_bytes!(u64);
|
impl_into_bytes!(u64, BytesIterU64);
|
||||||
impl_into_bytes!(u128);
|
impl_into_bytes!(u128, BytesIterU128);
|
||||||
impl_into_bytes!(usize);
|
impl_into_bytes!(usize, BytesIterUsize);
|
||||||
impl_into_bytes!(i8);
|
impl_into_bytes!(i8, BytesIterI8);
|
||||||
impl_into_bytes!(i16);
|
impl_into_bytes!(i16, BytesIterI16);
|
||||||
impl_into_bytes!(i32);
|
impl_into_bytes!(i32, BytesIterI32);
|
||||||
impl_into_bytes!(i64);
|
impl_into_bytes!(i64, BytesIterI64);
|
||||||
impl_into_bytes!(i128);
|
impl_into_bytes!(i128, BytesIterI128);
|
||||||
impl_into_bytes!(isize);
|
impl_into_bytes!(isize, BytesIterIsize);
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,12 @@
|
||||||
use std::cmp::min;
|
use num_traits::{Float, PrimInt};
|
||||||
|
use std::iter::{once, repeat};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::ops::{BitOrAssign, BitXor};
|
use std::ops::{BitOrAssign, BitXor};
|
||||||
|
|
||||||
use num_traits::{Float, PrimInt};
|
|
||||||
|
|
||||||
use crate::endianness::Endianness;
|
use crate::endianness::Endianness;
|
||||||
use crate::num_traits::{IntoBytes, IsSigned, UncheckedPrimitiveFloat, UncheckedPrimitiveInt};
|
use crate::num_traits::{IntoBytes, IsSigned, UncheckedPrimitiveFloat, UncheckedPrimitiveInt};
|
||||||
use crate::readbuffer::get_bits_from_usize;
|
use crate::{ReadError, Result};
|
||||||
use crate::{LittleEndian, ReadError, Result};
|
|
||||||
use std::iter::{once, repeat};
|
|
||||||
|
|
||||||
const USIZE_SIZE: usize = size_of::<usize>();
|
const USIZE_SIZE: usize = size_of::<usize>();
|
||||||
const USIZE_BITS: usize = USIZE_SIZE * 8;
|
const USIZE_BITS: usize = USIZE_SIZE * 8;
|
||||||
|
|
@ -77,20 +74,20 @@ where
|
||||||
self.bytes.len()
|
self.bytes.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_non_fit_bits(&mut self, bits: &[u8], count: usize) {
|
fn push_non_fit_bits<I>(&mut self, bits: I, count: usize)
|
||||||
|
where
|
||||||
|
I: ExactSizeIterator,
|
||||||
|
I: DoubleEndedIterator<Item = u8>,
|
||||||
|
{
|
||||||
debug_assert!(bits.len() == count / 8);
|
debug_assert!(bits.len() == count / 8);
|
||||||
let counts = repeat(8)
|
let counts = repeat(8)
|
||||||
.take(bits.len() - 1)
|
.take(bits.len() - 1)
|
||||||
.chain(once(count - (bits.len() - 1) * 8));
|
.chain(once(count - (bits.len() - 1) * 8));
|
||||||
if E::is_le() {
|
if E::is_le() {
|
||||||
bits.iter()
|
bits.zip(counts)
|
||||||
.copied()
|
|
||||||
.zip(counts)
|
|
||||||
.for_each(|(chunk, count)| self.push_bits(chunk as usize, count))
|
.for_each(|(chunk, count)| self.push_bits(chunk as usize, count))
|
||||||
} else {
|
} else {
|
||||||
bits.iter()
|
bits.rev()
|
||||||
.rev()
|
|
||||||
.copied()
|
|
||||||
.zip(counts)
|
.zip(counts)
|
||||||
.for_each(|(chunk, count)| self.push_bits(chunk as usize, count))
|
.for_each(|(chunk, count)| self.push_bits(chunk as usize, count))
|
||||||
}
|
}
|
||||||
|
|
@ -176,7 +173,7 @@ where
|
||||||
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_bytes(), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -207,10 +204,10 @@ where
|
||||||
if size_of::<T>() < USIZE_SIZE {
|
if size_of::<T>() < USIZE_SIZE {
|
||||||
self.push_bits(value.to_f32().unwrap().to_bits() as usize, 32);
|
self.push_bits(value.to_f32().unwrap().to_bits() as usize, 32);
|
||||||
} else {
|
} else {
|
||||||
self.push_non_fit_bits(&value.to_f32().unwrap().to_le_bytes(), 32)
|
self.push_non_fit_bits(value.to_f32().unwrap().to_bits().into_bytes(), 32)
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
self.push_non_fit_bits(&value.to_f64().unwrap().to_le_bytes(), 64)
|
self.push_non_fit_bits(value.to_f64().unwrap().to_bits().into_bytes(), 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue