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}