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