mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
cow data
This commit is contained in:
parent
0c8d2ebe18
commit
9f5a9c5391
1 changed files with 75 additions and 6 deletions
|
|
@ -3,7 +3,7 @@ use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
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, Index, Range, RangeFrom};
|
||||||
|
|
||||||
use num_traits::{Float, PrimInt};
|
use num_traits::{Float, PrimInt};
|
||||||
|
|
||||||
|
|
@ -11,10 +11,68 @@ use crate::endianness::Endianness;
|
||||||
use crate::num_traits::{IsSigned, UncheckedPrimitiveFloat, UncheckedPrimitiveInt};
|
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::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;
|
||||||
|
|
||||||
|
// Cow<[u8]> but with cheap clones using Rc
|
||||||
|
enum Data<'a> {
|
||||||
|
Borrowed(&'a [u8]),
|
||||||
|
Owned(Rc<Vec<u8>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Data<'a> {
|
||||||
|
pub fn as_slice(&self) -> &[u8] {
|
||||||
|
match self {
|
||||||
|
Data::Borrowed(bytes) => *bytes,
|
||||||
|
Data::Owned(bytes) => bytes.as_slice(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
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> {
|
||||||
|
type Output = [u8];
|
||||||
|
|
||||||
|
fn index(&self, index: Range<usize>) -> &Self::Output {
|
||||||
|
self.as_slice().index(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Index<RangeFrom<usize>> for Data<'a> {
|
||||||
|
type Output = [u8];
|
||||||
|
|
||||||
|
fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
|
||||||
|
self.as_slice().index(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Index<usize> for Data<'a> {
|
||||||
|
type Output = u8;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
self.as_slice().index(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Clone for Data<'a> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Data::Borrowed(bytes) => Data::Borrowed(*bytes),
|
||||||
|
Data::Owned(bytes) => Data::Owned(Rc::clone(bytes)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Buffer that allows reading integers of arbitrary bit length and non byte-aligned integers
|
/// Buffer that allows reading integers of arbitrary bit length and non byte-aligned integers
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
|
@ -38,7 +96,7 @@ pub struct BitReadBuffer<'a, E>
|
||||||
where
|
where
|
||||||
E: Endianness,
|
E: Endianness,
|
||||||
{
|
{
|
||||||
bytes: &'a [u8],
|
bytes: Data<'a>,
|
||||||
bit_len: usize,
|
bit_len: usize,
|
||||||
endianness: PhantomData<E>,
|
endianness: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +122,7 @@ where
|
||||||
let byte_len = bytes.len();
|
let byte_len = bytes.len();
|
||||||
|
|
||||||
BitReadBuffer {
|
BitReadBuffer {
|
||||||
bytes,
|
bytes: Data::Borrowed(bytes),
|
||||||
bit_len: byte_len * 8,
|
bit_len: byte_len * 8,
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
}
|
}
|
||||||
|
|
@ -596,7 +654,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(BitReadBuffer {
|
Ok(BitReadBuffer {
|
||||||
bytes: self.bytes,
|
bytes: self.bytes.clone(),
|
||||||
bit_len,
|
bit_len,
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
})
|
})
|
||||||
|
|
@ -607,7 +665,18 @@ impl<'a, E: Endianness> From<&'a [u8]> for BitReadBuffer<'a, E> {
|
||||||
fn from(bytes: &'a [u8]) -> Self {
|
fn from(bytes: &'a [u8]) -> Self {
|
||||||
let byte_len = bytes.len();
|
let byte_len = bytes.len();
|
||||||
BitReadBuffer {
|
BitReadBuffer {
|
||||||
bytes,
|
bytes: Data::Borrowed(bytes),
|
||||||
|
bit_len: byte_len * 8,
|
||||||
|
endianness: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E: Endianness> From<Vec<u8>> for BitReadBuffer<'a, E> {
|
||||||
|
fn from(bytes: Vec<u8>) -> Self {
|
||||||
|
let byte_len = bytes.len();
|
||||||
|
BitReadBuffer {
|
||||||
|
bytes: Data::Owned(Rc::new(bytes)),
|
||||||
bit_len: byte_len * 8,
|
bit_len: byte_len * 8,
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
}
|
}
|
||||||
|
|
@ -617,7 +686,7 @@ impl<'a, E: Endianness> From<&'a [u8]> for BitReadBuffer<'a, E> {
|
||||||
impl<'a, E: Endianness> Clone for BitReadBuffer<'a, E> {
|
impl<'a, E: Endianness> Clone for BitReadBuffer<'a, E> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
BitReadBuffer {
|
BitReadBuffer {
|
||||||
bytes: self.bytes,
|
bytes: self.bytes.clone(),
|
||||||
bit_len: self.bit_len(),
|
bit_len: self.bit_len(),
|
||||||
endianness: PhantomData,
|
endianness: PhantomData,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue