1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use bytes::buf::UninitSlice;
use crate::prelude::*;
use super::{chain::Chain, limit::Limit};
pub trait BitBufMut {
/// Advance the internal cursor of the BitBufMut by `count` bits.
///
/// The next call to chunk_mut will return a slice starting `count` bits further into the
/// underlying buffer.
fn advance_mut_bits(&mut self, count: usize);
/// Advance the internal cursor of the BitBufMut by `count` bytes.
///
/// The next call to chunk_mut will return a slice starting `count` bytes further into the
/// underlying buffer.
fn advance_mut_bytes(&mut self, count: usize) {
self.advance_mut_bits(count * 8);
}
/// Returns a mutable `BitSlice` starting at the current `BitBufMut` position and of length
/// between 0 and BitBufMut::remaining_mut(). Note that this can be shorter than the whole
/// remainder of the buffer (this allows non-continuous implementation).
///
/// This is a lower level function. Most operations are done with other functions.
///
/// The returned byte slice may represent uninitialized memory and should not be read from.
fn chunk_mut_bits(&mut self) -> &mut BitSlice;
/// Returns a mutable `UninitSlice` starting at the current `BitBufMut` position and of length
/// between 0 and BitBufMut::remaining_mut(). Note that this can be shorter than the whole
/// remainder of the buffer (this allows non-continuous implementation). This `BitBufMut`
/// must be fully byte-aligned for this to work: caller should check `byte_aligned` before
/// calling.
///
/// This is a lower level function. Most operations are done with other functions.
///
/// The returned byte slice may represent uninitialized memory and should not be read from.
fn chunk_mut_bytes(&mut self) -> &mut UninitSlice;
/// Returns the number of bits that can be written from the current position until the end of
/// the buffer is reached. Note that the returned value may under-represent the remainin
/// amount: we are returning the value in bits but if the underlying storage is in bytes then
/// the result here will be under-represented by a factor of 8. `remaining_mut_bytes` will
/// give a more accurate view of how much space (in bytes) is remaining.
///
/// This value is greater than or equal to the length of the slice returned by chunk_mut().
///
/// Writing to a BitBufMut may involve allocating more memory on the fly. Implementations may
/// fail before reaching the number of bytes indicated by this method if they encounter an
/// allocation failure.
fn remaining_mut_bits(&self) -> usize;
/// Creates an adaptor which can write at most `limit` bits to `self`
fn limit_bits(self, limit: usize) -> Limit<Self>
where
Self: Sized,
{
Limit::new(self, limit)
}
/// Creates an adaptor which can write at most `limit` bytes to `self`
fn limit_bytes(self, limit: usize) -> Limit<Self>
where
Self: Sized,
{
Limit::new(self, limit * 8)
}
/// Returns true if there is space in self for more bits.
///
/// This is equivalent to calling `self.remaining_mut_bits() > 0`
fn has_remaining_mut_bits(&self) -> bool {
self.remaining_mut_bits() > 0
}
/// Returns the number of _full_ bytes that can be written from the current position until the
/// end of the buffer is reached.
///
/// This value is greater than or equal to the length of the slice returned by chunk_mut().
///
/// Writing to a BitBufMut may involve allocating more memory on the fly. Implementations may
/// fail before reaching the number of bytes indicated by this method if they encounter an
/// allocation failure.
fn remaining_mut_bytes(&self) -> usize {
self.remaining_mut_bits() / 8
}
/// Returns true if there is space in self for more bytes.
///
/// This is equivalent to calling `self.remaining_mut_bytes() > 0`
fn has_reminaing_mut_bytes(&self) -> bool {
self.remaining_mut_bytes() > 0
}
/// Creates an adaptor which will chain this buffer to another.
///
/// The returned `BitBufMut` instance will first write to all bytes from `self`. Afterwards it
/// will write to `next`.
fn chain_mut<U: BitBufMut>(self, next: U) -> Chain<Self, U>
where
Self: Sized,
{
Chain::new(self, next)
}
/// Transfer bits into `self` from `src` and advance the cursor by the number of bits written.
///
/// `self` must have enough remaining capacity to contain all of `src`.
fn put_bit_slice(&mut self, src: &BitSlice) {
self.try_put_bit_slice(src).unwrap()
}
/// Try to transfer bits info `self` from `src` and advance the cursor by the number of bits
/// written.
///
/// Returns an error if `self` doesn't have enough remaining capacity to contain all of `src`.
fn try_put_bit_slice(&mut self, mut src: &BitSlice) -> std::io::Result<()> {
if self.remaining_mut_bits() < src.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
format!(
"Remaining bits ({}) are less than the size of the source ({})",
self.remaining_mut_bits(),
src.len()
),
));
}
while !src.is_empty() {
let dest = self.chunk_mut_bits();
let count = usize::min(src.len(), dest.len());
dest[..count].copy_from_bitslice(&src[..count]);
src = &src[count..];
self.advance_mut_bits(count);
}
Ok(())
}
fn try_put_slice_bytes(&mut self, mut src: &[u8]) -> std::io::Result<()> {
if !self.byte_aligned_mut() {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"BitBuf beginning and end must both be byte-aligned",
));
}
if self.remaining_mut_bytes() < src.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
format!(
"Remaining bytes ({}) are less than the size of the source ({})",
self.remaining_mut_bytes(),
src.len()
),
));
}
while !src.is_empty() {
let dest = self.chunk_mut_bytes();
let count = usize::min(src.len(), dest.len());
dest[..count].copy_from_slice(&src[..count]);
src = &src[count..];
self.advance_mut_bytes(count);
}
Ok(())
}
/// Returns whether or not this `BitBufMut` is fully byte-aligned (beginning and end) with the
/// underlying storage.
fn byte_aligned_mut(&self) -> bool;
}