Skip to content

Commit dea6b4a

Browse files
read side
0 parents  commit dea6b4a

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[package]
2+
name = "bitbuf"
3+
version = "0.1.0"
4+
authors = ["Izzy Swart <[email protected]>"]
5+
edition = "2018"

src/lib.rs

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use core::borrow::Borrow;
2+
3+
#[derive(Debug)]
4+
pub struct Insufficient;
5+
6+
#[derive(Debug)]
7+
pub enum CopyError {
8+
Insufficient(Insufficient),
9+
Overflow,
10+
}
11+
12+
impl From<Insufficient> for CopyError {
13+
fn from(input: Insufficient) -> Self {
14+
CopyError::Insufficient(input)
15+
}
16+
}
17+
18+
#[derive(Debug)]
19+
pub struct BitBuf<'a> {
20+
data: &'a [u8],
21+
prefix: u8,
22+
}
23+
24+
impl<'a> BitBuf<'a> {
25+
pub fn new(data: &'a [u8]) -> Self {
26+
BitBuf { data, prefix: 0 }
27+
}
28+
29+
pub fn advance(&mut self, bits: usize) -> Result<(), Insufficient> {
30+
self.prefix += (bits & 7) as u8;
31+
if self.prefix >= 8 {
32+
self.prefix -= 8;
33+
self.data = &self
34+
.data
35+
.borrow()
36+
.get((bits / 8) + 1..)
37+
.ok_or(Insufficient)?;
38+
} else {
39+
self.data = &self.data.borrow().get(bits / 8..).ok_or(Insufficient)?;
40+
}
41+
Ok(())
42+
}
43+
44+
pub fn byte_at_offset(&self, offset: usize) -> Option<u8> {
45+
let len = self.len();
46+
if offset == 0 {
47+
if len == 0 {
48+
return None;
49+
}
50+
Some(self.data[0])
51+
} else if len < 8 || offset > len - 8 {
52+
None
53+
} else {
54+
let offset_bytes = offset / 8;
55+
let offset_rem = offset & 7;
56+
if offset_rem == 0 {
57+
Some(self.data[offset_bytes])
58+
} else {
59+
let offset_rem_inv = 8 - offset_rem;
60+
Some(
61+
((self.data[offset_bytes] & (255 >> offset_rem)) << offset_rem)
62+
+ ((self.data[(offset_bytes) + 1] & (255 << offset_rem_inv))
63+
>> offset_rem_inv),
64+
)
65+
}
66+
}
67+
}
68+
69+
pub fn copy_to_slice(&mut self, dst: &mut [u8], bits: usize) -> Result<(), CopyError> {
70+
let bytes = bits / 8;
71+
let len = dst.len();
72+
if len < bytes {
73+
return Err(CopyError::Overflow);
74+
}
75+
for i in 0..bytes {
76+
dst[i] = self
77+
.byte_at_offset(i * 8)
78+
.ok_or(CopyError::Insufficient(Insufficient))?;
79+
}
80+
let rem = bits & 7;
81+
if rem > 0 {
82+
if len < bytes + 1 {
83+
return Err(CopyError::Overflow);
84+
}
85+
let byte = self
86+
.byte_at_offset(bytes * 8)
87+
.ok_or(CopyError::Insufficient(Insufficient))?
88+
& (255 << (8 - rem));
89+
dst[bytes] |= byte;
90+
dst[bytes] &= byte;
91+
}
92+
self.advance(bits)?;
93+
Ok(())
94+
}
95+
96+
pub fn pop(&mut self) -> Option<bool> {
97+
let byte = self.byte_at_offset(0)?;
98+
self.advance(1).unwrap();
99+
Some(byte & 1 != 0)
100+
}
101+
102+
pub fn len(&self) -> usize {
103+
self.data.len() * 8 - self.prefix as usize
104+
}
105+
}
106+
107+
pub struct BitBufMut {}

0 commit comments

Comments
 (0)