mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 08:34:07 +02:00
remove branch from hot code
This commit is contained in:
parent
65f3280b1b
commit
ffe2f350fb
1 changed files with 29 additions and 17 deletions
|
|
@ -12,7 +12,6 @@ use crate::num_traits::{IsSigned, UncheckedPrimitiveFloat, UncheckedPrimitiveInt
|
||||||
use crate::{BitError, Result};
|
use crate::{BitError, Result};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::slice::SliceIndex;
|
|
||||||
|
|
||||||
const USIZE_SIZE: usize = size_of::<usize>();
|
const USIZE_SIZE: usize = size_of::<usize>();
|
||||||
const USIZE_BIT_SIZE: usize = USIZE_SIZE * 8;
|
const USIZE_BIT_SIZE: usize = USIZE_SIZE * 8;
|
||||||
|
|
@ -34,10 +33,6 @@ impl<'a> Data<'a> {
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.as_slice().len()
|
self.as_slice().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn get_unchecked<I: SliceIndex<[u8]>>(&self, index: I) -> &I::Output {
|
|
||||||
self.as_slice().get_unchecked(index)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Index<Range<usize>> for Data<'a> {
|
impl<'a> Index<Range<usize>> for Data<'a> {
|
||||||
|
|
@ -99,6 +94,7 @@ where
|
||||||
bytes: Data<'a>,
|
bytes: Data<'a>,
|
||||||
bit_len: usize,
|
bit_len: usize,
|
||||||
endianness: PhantomData<E>,
|
endianness: PhantomData<E>,
|
||||||
|
slice: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E> BitReadBuffer<'a, E>
|
impl<'a, E> BitReadBuffer<'a, E>
|
||||||
|
|
@ -125,6 +121,7 @@ where
|
||||||
bytes: Data::Borrowed(bytes),
|
bytes: Data::Borrowed(bytes),
|
||||||
bit_len: byte_len * 8,
|
bit_len: byte_len * 8,
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
|
slice: bytes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -148,11 +145,19 @@ where
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new_owned(bytes: Vec<u8>, _endianness: E) -> Self {
|
pub fn new_owned(bytes: Vec<u8>, _endianness: E) -> Self {
|
||||||
let byte_len = bytes.len();
|
let byte_len = bytes.len();
|
||||||
|
let bytes = Data::Owned(Rc::new(bytes));
|
||||||
|
|
||||||
|
// this is safe because
|
||||||
|
// - the slice can only be access trough this struct
|
||||||
|
// - this struct keeps the vec the slice comes from alive
|
||||||
|
// - this struct doesn't allow mutation
|
||||||
|
let slice = unsafe { std::slice::from_raw_parts(bytes.as_slice().as_ptr(), bytes.len()) };
|
||||||
|
|
||||||
BitReadBuffer {
|
BitReadBuffer {
|
||||||
bytes: Data::Owned(Rc::new(bytes)),
|
bytes,
|
||||||
bit_len: byte_len * 8,
|
bit_len: byte_len * 8,
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
|
slice,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,16 +195,16 @@ where
|
||||||
unsafe fn read_usize_bytes(&self, byte_index: usize, end: bool) -> [u8; USIZE_SIZE] {
|
unsafe fn read_usize_bytes(&self, byte_index: usize, end: bool) -> [u8; USIZE_SIZE] {
|
||||||
if end {
|
if end {
|
||||||
let mut bytes = [0; USIZE_SIZE];
|
let mut bytes = [0; USIZE_SIZE];
|
||||||
let count = min(USIZE_SIZE, self.bytes.len() - byte_index);
|
let count = min(USIZE_SIZE, self.slice.len() - byte_index);
|
||||||
bytes[0..count]
|
bytes[0..count]
|
||||||
.copy_from_slice(self.bytes.get_unchecked(byte_index..byte_index + count));
|
.copy_from_slice(self.slice.get_unchecked(byte_index..byte_index + count));
|
||||||
bytes
|
bytes
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(byte_index + USIZE_SIZE <= self.bytes.len());
|
debug_assert!(byte_index + USIZE_SIZE <= self.slice.len());
|
||||||
// this is safe because all calling paths check that byte_index is less than the unpadded
|
// this is safe because all calling paths check that byte_index is less than the unpadded
|
||||||
// length (because they check based on bit_len), so with padding byte_index + USIZE_SIZE is
|
// length (because they check based on bit_len), so with padding byte_index + USIZE_SIZE is
|
||||||
// always within bounds
|
// always within bounds
|
||||||
self.bytes
|
self.slice
|
||||||
.get_unchecked(byte_index..byte_index + USIZE_SIZE)
|
.get_unchecked(byte_index..byte_index + USIZE_SIZE)
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -259,7 +264,7 @@ where
|
||||||
let bit_offset = position & 7;
|
let bit_offset = position & 7;
|
||||||
|
|
||||||
if position < self.bit_len() {
|
if position < self.bit_len() {
|
||||||
let byte = self.bytes[byte_index];
|
let byte = self.slice[byte_index];
|
||||||
if E::is_le() {
|
if E::is_le() {
|
||||||
let shifted = byte >> bit_offset as u8;
|
let shifted = byte >> bit_offset as u8;
|
||||||
Ok(shifted & 1u8 == 1)
|
Ok(shifted & 1u8 == 1)
|
||||||
|
|
@ -281,7 +286,7 @@ where
|
||||||
let byte_index = position / 8;
|
let byte_index = position / 8;
|
||||||
let bit_offset = position & 7;
|
let bit_offset = position & 7;
|
||||||
|
|
||||||
let byte = self.bytes.get_unchecked(byte_index);
|
let byte = self.slice.get_unchecked(byte_index);
|
||||||
let shifted = byte >> bit_offset;
|
let shifted = byte >> bit_offset;
|
||||||
shifted & 1u8 == 1
|
shifted & 1u8 == 1
|
||||||
}
|
}
|
||||||
|
|
@ -482,7 +487,7 @@ where
|
||||||
|
|
||||||
if shift == 0 {
|
if shift == 0 {
|
||||||
let byte_pos = position / 8;
|
let byte_pos = position / 8;
|
||||||
return self.bytes[byte_pos..byte_pos + byte_count].to_vec();
|
return self.slice[byte_pos..byte_pos + byte_count].to_vec();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut data = Vec::with_capacity(byte_count);
|
let mut data = Vec::with_capacity(byte_count);
|
||||||
|
|
@ -559,9 +564,9 @@ where
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn find_null_byte(&self, byte_index: usize) -> usize {
|
fn find_null_byte(&self, byte_index: usize) -> usize {
|
||||||
memchr::memchr(0, &self.bytes[byte_index..])
|
memchr::memchr(0, &self.slice[byte_index..])
|
||||||
.map(|index| index + byte_index)
|
.map(|index| index + byte_index)
|
||||||
.unwrap_or(self.bytes.len()) // due to padding we always have 0 bytes at the end
|
.unwrap_or(self.slice.len()) // due to padding we always have 0 bytes at the end
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -569,7 +574,7 @@ where
|
||||||
let shift = position & 7;
|
let shift = position & 7;
|
||||||
if shift == 0 {
|
if shift == 0 {
|
||||||
let byte_index = position / 8;
|
let byte_index = position / 8;
|
||||||
Ok(self.bytes[byte_index..self.find_null_byte(byte_index)].to_vec())
|
Ok(self.slice[byte_index..self.find_null_byte(byte_index)].to_vec())
|
||||||
} else {
|
} else {
|
||||||
let mut acc = Vec::with_capacity(32);
|
let mut acc = Vec::with_capacity(32);
|
||||||
let mut byte_index = position / 8;
|
let mut byte_index = position / 8;
|
||||||
|
|
@ -685,6 +690,7 @@ where
|
||||||
bytes: self.bytes.clone(),
|
bytes: self.bytes.clone(),
|
||||||
bit_len,
|
bit_len,
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
|
slice: self.slice,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -696,6 +702,7 @@ impl<'a, E: Endianness> From<&'a [u8]> for BitReadBuffer<'a, E> {
|
||||||
bytes: Data::Borrowed(bytes),
|
bytes: Data::Borrowed(bytes),
|
||||||
bit_len: byte_len * 8,
|
bit_len: byte_len * 8,
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
|
slice: bytes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -703,10 +710,14 @@ impl<'a, E: Endianness> From<&'a [u8]> for BitReadBuffer<'a, E> {
|
||||||
impl<'a, E: Endianness> From<Vec<u8>> for BitReadBuffer<'a, E> {
|
impl<'a, E: Endianness> From<Vec<u8>> for BitReadBuffer<'a, E> {
|
||||||
fn from(bytes: Vec<u8>) -> Self {
|
fn from(bytes: Vec<u8>) -> Self {
|
||||||
let byte_len = bytes.len();
|
let byte_len = bytes.len();
|
||||||
|
let bytes = Data::Owned(Rc::new(bytes));
|
||||||
|
let slice = unsafe { std::slice::from_raw_parts(bytes.as_slice().as_ptr(), bytes.len()) };
|
||||||
|
|
||||||
BitReadBuffer {
|
BitReadBuffer {
|
||||||
bytes: Data::Owned(Rc::new(bytes)),
|
bytes,
|
||||||
bit_len: byte_len * 8,
|
bit_len: byte_len * 8,
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
|
slice,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -717,6 +728,7 @@ impl<'a, E: Endianness> Clone for BitReadBuffer<'a, E> {
|
||||||
bytes: self.bytes.clone(),
|
bytes: self.bytes.clone(),
|
||||||
bit_len: self.bit_len(),
|
bit_len: self.bit_len(),
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
|
slice: self.slice,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue