1 #[allow(unused_imports)]
2 use alloc::vec::Vec;
3 
4 use crate::fastcpy::slice_copy;
5 
6 /// Returns a Sink implementation appropriate for outputing up to `required_capacity`
7 /// bytes at `vec[offset..offset+required_capacity]`.
8 /// It can be either a `SliceSink` (pre-filling the vec with zeroes if necessary)
9 /// when the `safe-decode` feature is enabled, or `VecSink` otherwise.
10 /// The argument `pos` defines the initial output position in the Sink.
11 #[inline]
12 #[cfg(feature = "frame")]
vec_sink_for_compression( vec: &mut Vec<u8>, offset: usize, pos: usize, required_capacity: usize, ) -> SliceSink13 pub fn vec_sink_for_compression(
14     vec: &mut Vec<u8>,
15     offset: usize,
16     pos: usize,
17     required_capacity: usize,
18 ) -> SliceSink {
19     return {
20         vec.resize(offset + required_capacity, 0);
21         SliceSink::new(&mut vec[offset..], pos)
22     };
23 }
24 
25 /// Returns a Sink implementation appropriate for outputing up to `required_capacity`
26 /// bytes at `vec[offset..offset+required_capacity]`.
27 /// It can be either a `SliceSink` (pre-filling the vec with zeroes if necessary)
28 /// when the `safe-decode` feature is enabled, or `VecSink` otherwise.
29 /// The argument `pos` defines the initial output position in the Sink.
30 #[cfg(feature = "frame")]
31 #[inline]
vec_sink_for_decompression( vec: &mut Vec<u8>, offset: usize, pos: usize, required_capacity: usize, ) -> SliceSink32 pub fn vec_sink_for_decompression(
33     vec: &mut Vec<u8>,
34     offset: usize,
35     pos: usize,
36     required_capacity: usize,
37 ) -> SliceSink {
38     return {
39         vec.resize(offset + required_capacity, 0);
40         SliceSink::new(&mut vec[offset..], pos)
41     };
42 }
43 
44 pub trait Sink {
45     /// Returns a raw ptr to the first unfilled byte of the Sink. Analogous to `[pos..].as_ptr()`.
46     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
pos_mut_ptr(&mut self) -> *mut u847     unsafe fn pos_mut_ptr(&mut self) -> *mut u8;
48 
49     /// read byte at position
byte_at(&mut self, pos: usize) -> u850     fn byte_at(&mut self, pos: usize) -> u8;
51 
52     /// Pushes a byte to the end of the Sink.
53     #[cfg(feature = "safe-encode")]
push(&mut self, byte: u8)54     fn push(&mut self, byte: u8);
55 
56     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
base_mut_ptr(&mut self) -> *mut u857     unsafe fn base_mut_ptr(&mut self) -> *mut u8;
58 
pos(&self) -> usize59     fn pos(&self) -> usize;
60 
capacity(&self) -> usize61     fn capacity(&self) -> usize;
62 
63     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
set_pos(&mut self, new_pos: usize)64     unsafe fn set_pos(&mut self, new_pos: usize);
65 
66     #[cfg(feature = "safe-decode")]
extend_with_fill(&mut self, byte: u8, len: usize)67     fn extend_with_fill(&mut self, byte: u8, len: usize);
68 
69     /// Extends the Sink with `data`.
extend_from_slice(&mut self, data: &[u8])70     fn extend_from_slice(&mut self, data: &[u8]);
71 
extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize)72     fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize);
73 
74     /// Copies `len` bytes starting from `start` to the end of the Sink.
75     /// # Panics
76     /// Panics if `start` >= `pos`.
77     #[cfg(feature = "safe-decode")]
extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize)78     fn extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize);
79 
80     #[cfg(feature = "safe-decode")]
extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize)81     fn extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize);
82 }
83 
84 /// SliceSink is used as target to de/compress data into a preallocated and possibly uninitialized
85 /// `&[u8]`
86 /// space.
87 ///
88 /// # Handling of Capacity
89 /// Extend methods will panic if there's insufficient capacity left in the Sink.
90 ///
91 /// # Invariants
92 ///   - Bytes `[..pos()]` are always initialized.
93 pub struct SliceSink<'a> {
94     /// The working slice, which may contain uninitialized bytes
95     output: &'a mut [u8],
96     /// Number of bytes in start of `output` guaranteed to be initialized
97     pos: usize,
98 }
99 
100 impl<'a> SliceSink<'a> {
101     /// Creates a `Sink` backed by the given byte slice.
102     /// `pos` defines the initial output position in the Sink.
103     /// # Panics
104     /// Panics if `pos` is out of bounds.
105     #[inline]
new(output: &'a mut [u8], pos: usize) -> Self106     pub fn new(output: &'a mut [u8], pos: usize) -> Self {
107         // SAFETY: Caller guarantees that all elements of `output[..pos]` are initialized.
108         let _ = &mut output[..pos]; // bounds check pos
109         SliceSink { output, pos }
110     }
111 }
112 
113 impl<'a> Sink for SliceSink<'a> {
114     /// Returns a raw ptr to the first unfilled byte of the Sink. Analogous to `[pos..].as_ptr()`.
115     #[inline]
116     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
pos_mut_ptr(&mut self) -> *mut u8117     unsafe fn pos_mut_ptr(&mut self) -> *mut u8 {
118         self.base_mut_ptr().add(self.pos()) as *mut u8
119     }
120 
121     /// Pushes a byte to the end of the Sink.
122     #[inline]
byte_at(&mut self, pos: usize) -> u8123     fn byte_at(&mut self, pos: usize) -> u8 {
124         self.output[pos]
125     }
126 
127     /// Pushes a byte to the end of the Sink.
128     #[inline]
129     #[cfg(feature = "safe-encode")]
push(&mut self, byte: u8)130     fn push(&mut self, byte: u8) {
131         self.output[self.pos] = byte;
132         self.pos += 1;
133     }
134 
135     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
base_mut_ptr(&mut self) -> *mut u8136     unsafe fn base_mut_ptr(&mut self) -> *mut u8 {
137         self.output.as_mut_ptr()
138     }
139 
140     #[inline]
pos(&self) -> usize141     fn pos(&self) -> usize {
142         self.pos
143     }
144 
145     #[inline]
capacity(&self) -> usize146     fn capacity(&self) -> usize {
147         self.output.len()
148     }
149 
150     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
151     #[inline]
set_pos(&mut self, new_pos: usize)152     unsafe fn set_pos(&mut self, new_pos: usize) {
153         debug_assert!(new_pos <= self.capacity());
154         self.pos = new_pos;
155     }
156 
157     #[inline]
158     #[cfg(feature = "safe-decode")]
extend_with_fill(&mut self, byte: u8, len: usize)159     fn extend_with_fill(&mut self, byte: u8, len: usize) {
160         self.output[self.pos..self.pos + len].fill(byte);
161         self.pos += len;
162     }
163 
164     /// Extends the Sink with `data`.
165     #[inline]
extend_from_slice(&mut self, data: &[u8])166     fn extend_from_slice(&mut self, data: &[u8]) {
167         self.extend_from_slice_wild(data, data.len())
168     }
169 
170     #[inline]
extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize)171     fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize) {
172         assert!(copy_len <= data.len());
173         slice_copy(data, &mut self.output[self.pos..(self.pos) + data.len()]);
174         self.pos += copy_len;
175     }
176 
177     /// Copies `len` bytes starting from `start` to the end of the Sink.
178     /// # Panics
179     /// Panics if `start` >= `pos`.
180     #[inline]
181     #[cfg(feature = "safe-decode")]
extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize)182     fn extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize) {
183         self.output.copy_within(start..start + wild_len, self.pos);
184         self.pos += copy_len;
185     }
186 
187     #[inline]
188     #[cfg(feature = "safe-decode")]
189     #[cfg_attr(nightly, optimize(size))] // to avoid loop unrolling
extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize)190     fn extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize) {
191         let offset = self.pos - start;
192         for i in start + offset..start + offset + num_bytes {
193             self.output[i] = self.output[i - offset];
194         }
195         self.pos += num_bytes;
196     }
197 }
198 
199 /// PtrSink is used as target to de/compress data into a preallocated and possibly uninitialized
200 /// `&[u8]`
201 /// space.
202 ///
203 ///
204 #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
205 pub struct PtrSink {
206     /// The working slice, which may contain uninitialized bytes
207     output: *mut u8,
208     /// Number of bytes in start of `output` guaranteed to be initialized
209     pos: usize,
210     /// Number of bytes in output available
211     cap: usize,
212 }
213 
214 #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
215 impl PtrSink {
216     /// Creates a `Sink` backed by the given byte slice.
217     /// `pos` defines the initial output position in the Sink.
218     /// # Panics
219     /// Panics if `pos` is out of bounds.
220     #[inline]
from_vec(output: &mut Vec<u8>, pos: usize) -> Self221     pub fn from_vec(output: &mut Vec<u8>, pos: usize) -> Self {
222         // SAFETY: Bytes behind pointer may be uninitialized.
223         Self {
224             output: output.as_mut_ptr(),
225             pos,
226             cap: output.capacity(),
227         }
228     }
229 }
230 
231 #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
232 impl Sink for PtrSink {
233     /// Returns a raw ptr to the first unfilled byte of the Sink. Analogous to `[pos..].as_ptr()`.
234     #[inline]
235     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
pos_mut_ptr(&mut self) -> *mut u8236     unsafe fn pos_mut_ptr(&mut self) -> *mut u8 {
237         self.base_mut_ptr().add(self.pos()) as *mut u8
238     }
239 
240     /// Pushes a byte to the end of the Sink.
241     #[inline]
byte_at(&mut self, pos: usize) -> u8242     fn byte_at(&mut self, pos: usize) -> u8 {
243         unsafe { self.output.add(pos).read() }
244     }
245 
246     /// Pushes a byte to the end of the Sink.
247     #[inline]
248     #[cfg(feature = "safe-encode")]
push(&mut self, byte: u8)249     fn push(&mut self, byte: u8) {
250         unsafe {
251             self.pos_mut_ptr().write(byte);
252         }
253         self.pos += 1;
254     }
255 
256     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
base_mut_ptr(&mut self) -> *mut u8257     unsafe fn base_mut_ptr(&mut self) -> *mut u8 {
258         self.output
259     }
260 
261     #[inline]
pos(&self) -> usize262     fn pos(&self) -> usize {
263         self.pos
264     }
265 
266     #[inline]
capacity(&self) -> usize267     fn capacity(&self) -> usize {
268         self.cap
269     }
270 
271     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
272     #[inline]
set_pos(&mut self, new_pos: usize)273     unsafe fn set_pos(&mut self, new_pos: usize) {
274         debug_assert!(new_pos <= self.capacity());
275         self.pos = new_pos;
276     }
277 
278     #[inline]
279     #[cfg(feature = "safe-decode")]
extend_with_fill(&mut self, _byte: u8, _len: usize)280     fn extend_with_fill(&mut self, _byte: u8, _len: usize) {
281         unreachable!();
282     }
283 
284     /// Extends the Sink with `data`.
285     #[inline]
extend_from_slice(&mut self, data: &[u8])286     fn extend_from_slice(&mut self, data: &[u8]) {
287         self.extend_from_slice_wild(data, data.len())
288     }
289 
290     #[inline]
extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize)291     fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize) {
292         assert!(copy_len <= data.len());
293         unsafe {
294             core::ptr::copy_nonoverlapping(data.as_ptr(), self.pos_mut_ptr(), copy_len);
295         }
296         self.pos += copy_len;
297     }
298 
299     /// Copies `len` bytes starting from `start` to the end of the Sink.
300     /// # Panics
301     /// Panics if `start` >= `pos`.
302     #[inline]
303     #[cfg(feature = "safe-decode")]
extend_from_within(&mut self, _start: usize, _wild_len: usize, _copy_len: usize)304     fn extend_from_within(&mut self, _start: usize, _wild_len: usize, _copy_len: usize) {
305         unreachable!();
306     }
307 
308     #[inline]
309     #[cfg(feature = "safe-decode")]
extend_from_within_overlapping(&mut self, _start: usize, _num_bytes: usize)310     fn extend_from_within_overlapping(&mut self, _start: usize, _num_bytes: usize) {
311         unreachable!();
312     }
313 }
314 
315 #[cfg(test)]
316 mod tests {
317 
318     #[test]
319     #[cfg(any(feature = "safe-encode", feature = "safe-decode"))]
test_sink_slice()320     fn test_sink_slice() {
321         use crate::sink::Sink;
322         use crate::sink::SliceSink;
323         use alloc::vec::Vec;
324         let mut data = Vec::new();
325         data.resize(5, 0);
326         let sink = SliceSink::new(&mut data, 1);
327         assert_eq!(sink.pos(), 1);
328         assert_eq!(sink.capacity(), 5);
329     }
330 }
331