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 {
|
||||
fn into_bytes(self) -> Vec<u8>;
|
||||
type Iter: DoubleEndedIterator<Item = u8> + ExactSizeIterator;
|
||||
|
||||
fn into_bytes(self) -> Self::Iter;
|
||||
}
|
||||
|
||||
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 {
|
||||
type Iter = $iter;
|
||||
|
||||
#[inline(always)]
|
||||
fn into_bytes(self) -> Vec<u8> {
|
||||
self.to_le_bytes().to_vec()
|
||||
fn into_bytes(self) -> Self::Iter {
|
||||
<$iter>::new(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -223,15 +277,15 @@ impl_is_signed!(i64, true);
|
|||
impl_is_signed!(i128, true);
|
||||
impl_is_signed!(isize, true);
|
||||
|
||||
impl_into_bytes!(u8);
|
||||
impl_into_bytes!(u16);
|
||||
impl_into_bytes!(u32);
|
||||
impl_into_bytes!(u64);
|
||||
impl_into_bytes!(u128);
|
||||
impl_into_bytes!(usize);
|
||||
impl_into_bytes!(i8);
|
||||
impl_into_bytes!(i16);
|
||||
impl_into_bytes!(i32);
|
||||
impl_into_bytes!(i64);
|
||||
impl_into_bytes!(i128);
|
||||
impl_into_bytes!(isize);
|
||||
impl_into_bytes!(u8, BytesIterU8);
|
||||
impl_into_bytes!(u16, BytesIterU16);
|
||||
impl_into_bytes!(u32, BytesIterU32);
|
||||
impl_into_bytes!(u64, BytesIterU64);
|
||||
impl_into_bytes!(u128, BytesIterU128);
|
||||
impl_into_bytes!(usize, BytesIterUsize);
|
||||
impl_into_bytes!(i8, BytesIterI8);
|
||||
impl_into_bytes!(i16, BytesIterI16);
|
||||
impl_into_bytes!(i32, BytesIterI32);
|
||||
impl_into_bytes!(i64, BytesIterI64);
|
||||
impl_into_bytes!(i128, BytesIterI128);
|
||||
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::mem::size_of;
|
||||
use std::ops::{BitOrAssign, BitXor};
|
||||
|
||||
use num_traits::{Float, PrimInt};
|
||||
|
||||
use crate::endianness::Endianness;
|
||||
use crate::num_traits::{IntoBytes, IsSigned, UncheckedPrimitiveFloat, UncheckedPrimitiveInt};
|
||||
use crate::readbuffer::get_bits_from_usize;
|
||||
use crate::{LittleEndian, ReadError, Result};
|
||||
use std::iter::{once, repeat};
|
||||
use crate::{ReadError, Result};
|
||||
|
||||
const USIZE_SIZE: usize = size_of::<usize>();
|
||||
const USIZE_BITS: usize = USIZE_SIZE * 8;
|
||||
|
|
@ -77,20 +74,20 @@ where
|
|||
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);
|
||||
let counts = repeat(8)
|
||||
.take(bits.len() - 1)
|
||||
.chain(once(count - (bits.len() - 1) * 8));
|
||||
if E::is_le() {
|
||||
bits.iter()
|
||||
.copied()
|
||||
.zip(counts)
|
||||
bits.zip(counts)
|
||||
.for_each(|(chunk, count)| self.push_bits(chunk as usize, count))
|
||||
} else {
|
||||
bits.iter()
|
||||
.rev()
|
||||
.copied()
|
||||
bits.rev()
|
||||
.zip(counts)
|
||||
.for_each(|(chunk, count)| self.push_bits(chunk as usize, count))
|
||||
}
|
||||
|
|
@ -176,7 +173,7 @@ where
|
|||
self.push_bits(value.into_usize_unchecked(), count);
|
||||
}
|
||||
} else {
|
||||
self.push_non_fit_bits(&value.into_bytes(), count)
|
||||
self.push_non_fit_bits(value.into_bytes(), count)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -207,10 +204,10 @@ where
|
|||
if size_of::<T>() < USIZE_SIZE {
|
||||
self.push_bits(value.to_f32().unwrap().to_bits() as usize, 32);
|
||||
} 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 {
|
||||
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(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue