• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     {
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     {
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
50     #[allow(dead_code)]
byte_at(&mut self, pos: usize) -> u851     fn byte_at(&mut self, pos: usize) -> u8;
52 
53     /// Pushes a byte to the end of the Sink.
54     #[cfg(feature = "safe-encode")]
push(&mut self, byte: u8)55     fn push(&mut self, byte: u8);
56 
57     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
base_mut_ptr(&mut self) -> *mut u858     unsafe fn base_mut_ptr(&mut self) -> *mut u8;
59 
pos(&self) -> usize60     fn pos(&self) -> usize;
61 
capacity(&self) -> usize62     fn capacity(&self) -> usize;
63 
64     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
set_pos(&mut self, new_pos: usize)65     unsafe fn set_pos(&mut self, new_pos: usize);
66 
67     #[cfg(feature = "safe-decode")]
extend_with_fill(&mut self, byte: u8, len: usize)68     fn extend_with_fill(&mut self, byte: u8, len: usize);
69 
70     /// Extends the Sink with `data`.
extend_from_slice(&mut self, data: &[u8])71     fn extend_from_slice(&mut self, data: &[u8]);
72 
extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize)73     fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize);
74 
75     /// Copies `len` bytes starting from `start` to the end of the Sink.
76     /// # Panics
77     /// Panics if `start` >= `pos`.
78     #[cfg(feature = "safe-decode")]
extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize)79     fn extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize);
80 
81     #[cfg(feature = "safe-decode")]
extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize)82     fn extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize);
83 }
84 
85 /// SliceSink is used as target to de/compress data into a preallocated and possibly uninitialized
86 /// `&[u8]`
87 /// space.
88 ///
89 /// # Handling of Capacity
90 /// Extend methods will panic if there's insufficient capacity left in the Sink.
91 ///
92 /// # Invariants
93 ///   - Bytes `[..pos()]` are always initialized.
94 pub struct SliceSink<'a> {
95     /// The working slice, which may contain uninitialized bytes
96     output: &'a mut [u8],
97     /// Number of bytes in start of `output` guaranteed to be initialized
98     pos: usize,
99 }
100 
101 impl<'a> SliceSink<'a> {
102     /// Creates a `Sink` backed by the given byte slice.
103     /// `pos` defines the initial output position in the Sink.
104     /// # Panics
105     /// Panics if `pos` is out of bounds.
106     #[inline]
new(output: &'a mut [u8], pos: usize) -> Self107     pub fn new(output: &'a mut [u8], pos: usize) -> Self {
108         // SAFETY: Caller guarantees that all elements of `output[..pos]` are initialized.
109         let _ = &mut output[..pos]; // bounds check pos
110         SliceSink { output, pos }
111     }
112 }
113 
114 impl<'a> Sink for SliceSink<'a> {
115     /// Returns a raw ptr to the first unfilled byte of the Sink. Analogous to `[pos..].as_ptr()`.
116     #[inline]
117     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
pos_mut_ptr(&mut self) -> *mut u8118     unsafe fn pos_mut_ptr(&mut self) -> *mut u8 {
119         self.base_mut_ptr().add(self.pos()) as *mut u8
120     }
121 
122     /// Pushes a byte to the end of the Sink.
123     #[inline]
byte_at(&mut self, pos: usize) -> u8124     fn byte_at(&mut self, pos: usize) -> u8 {
125         self.output[pos]
126     }
127 
128     /// Pushes a byte to the end of the Sink.
129     #[inline]
130     #[cfg(feature = "safe-encode")]
push(&mut self, byte: u8)131     fn push(&mut self, byte: u8) {
132         self.output[self.pos] = byte;
133         self.pos += 1;
134     }
135 
136     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
base_mut_ptr(&mut self) -> *mut u8137     unsafe fn base_mut_ptr(&mut self) -> *mut u8 {
138         self.output.as_mut_ptr()
139     }
140 
141     #[inline]
pos(&self) -> usize142     fn pos(&self) -> usize {
143         self.pos
144     }
145 
146     #[inline]
capacity(&self) -> usize147     fn capacity(&self) -> usize {
148         self.output.len()
149     }
150 
151     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
152     #[inline]
set_pos(&mut self, new_pos: usize)153     unsafe fn set_pos(&mut self, new_pos: usize) {
154         debug_assert!(new_pos <= self.capacity());
155         self.pos = new_pos;
156     }
157 
158     #[inline]
159     #[cfg(feature = "safe-decode")]
extend_with_fill(&mut self, byte: u8, len: usize)160     fn extend_with_fill(&mut self, byte: u8, len: usize) {
161         self.output[self.pos..self.pos + len].fill(byte);
162         self.pos += len;
163     }
164 
165     /// Extends the Sink with `data`.
166     #[inline]
extend_from_slice(&mut self, data: &[u8])167     fn extend_from_slice(&mut self, data: &[u8]) {
168         self.extend_from_slice_wild(data, data.len())
169     }
170 
171     #[inline]
extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize)172     fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize) {
173         assert!(copy_len <= data.len());
174         slice_copy(data, &mut self.output[self.pos..(self.pos) + data.len()]);
175         self.pos += copy_len;
176     }
177 
178     /// Copies `len` bytes starting from `start` to the end of the Sink.
179     /// # Panics
180     /// Panics if `start` >= `pos`.
181     #[inline]
182     #[cfg(feature = "safe-decode")]
extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize)183     fn extend_from_within(&mut self, start: usize, wild_len: usize, copy_len: usize) {
184         self.output.copy_within(start..start + wild_len, self.pos);
185         self.pos += copy_len;
186     }
187 
188     #[inline]
189     #[cfg(feature = "safe-decode")]
190     #[cfg_attr(nightly, optimize(size))] // to avoid loop unrolling
extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize)191     fn extend_from_within_overlapping(&mut self, start: usize, num_bytes: usize) {
192         let offset = self.pos - start;
193         for i in start + offset..start + offset + num_bytes {
194             self.output[i] = self.output[i - offset];
195         }
196         self.pos += num_bytes;
197     }
198 }
199 
200 /// PtrSink is used as target to de/compress data into a preallocated and possibly uninitialized
201 /// `&[u8]`
202 /// space.
203 ///
204 ///
205 #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
206 pub struct PtrSink {
207     /// The working slice, which may contain uninitialized bytes
208     output: *mut u8,
209     /// Number of bytes in start of `output` guaranteed to be initialized
210     pos: usize,
211     /// Number of bytes in output available
212     cap: usize,
213 }
214 
215 #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
216 impl PtrSink {
217     /// Creates a `Sink` backed by the given byte slice.
218     /// `pos` defines the initial output position in the Sink.
219     /// # Panics
220     /// Panics if `pos` is out of bounds.
221     #[inline]
from_vec(output: &mut Vec<u8>, pos: usize) -> Self222     pub fn from_vec(output: &mut Vec<u8>, pos: usize) -> Self {
223         // SAFETY: Bytes behind pointer may be uninitialized.
224         Self {
225             output: output.as_mut_ptr(),
226             pos,
227             cap: output.capacity(),
228         }
229     }
230 }
231 
232 #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
233 impl Sink for PtrSink {
234     /// Returns a raw ptr to the first unfilled byte of the Sink. Analogous to `[pos..].as_ptr()`.
235     #[inline]
236     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
pos_mut_ptr(&mut self) -> *mut u8237     unsafe fn pos_mut_ptr(&mut self) -> *mut u8 {
238         self.base_mut_ptr().add(self.pos()) as *mut u8
239     }
240 
241     /// Pushes a byte to the end of the Sink.
242     #[inline]
byte_at(&mut self, pos: usize) -> u8243     fn byte_at(&mut self, pos: usize) -> u8 {
244         unsafe { self.output.add(pos).read() }
245     }
246 
247     /// Pushes a byte to the end of the Sink.
248     #[inline]
249     #[cfg(feature = "safe-encode")]
push(&mut self, byte: u8)250     fn push(&mut self, byte: u8) {
251         unsafe {
252             self.pos_mut_ptr().write(byte);
253         }
254         self.pos += 1;
255     }
256 
257     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
base_mut_ptr(&mut self) -> *mut u8258     unsafe fn base_mut_ptr(&mut self) -> *mut u8 {
259         self.output
260     }
261 
262     #[inline]
pos(&self) -> usize263     fn pos(&self) -> usize {
264         self.pos
265     }
266 
267     #[inline]
capacity(&self) -> usize268     fn capacity(&self) -> usize {
269         self.cap
270     }
271 
272     #[cfg(not(all(feature = "safe-encode", feature = "safe-decode")))]
273     #[inline]
set_pos(&mut self, new_pos: usize)274     unsafe fn set_pos(&mut self, new_pos: usize) {
275         debug_assert!(new_pos <= self.capacity());
276         self.pos = new_pos;
277     }
278 
279     #[inline]
280     #[cfg(feature = "safe-decode")]
extend_with_fill(&mut self, _byte: u8, _len: usize)281     fn extend_with_fill(&mut self, _byte: u8, _len: usize) {
282         unreachable!();
283     }
284 
285     /// Extends the Sink with `data`.
286     #[inline]
extend_from_slice(&mut self, data: &[u8])287     fn extend_from_slice(&mut self, data: &[u8]) {
288         self.extend_from_slice_wild(data, data.len())
289     }
290 
291     #[inline]
extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize)292     fn extend_from_slice_wild(&mut self, data: &[u8], copy_len: usize) {
293         assert!(copy_len <= data.len());
294         unsafe {
295             core::ptr::copy_nonoverlapping(data.as_ptr(), self.pos_mut_ptr(), copy_len);
296         }
297         self.pos += copy_len;
298     }
299 
300     /// Copies `len` bytes starting from `start` to the end of the Sink.
301     /// # Panics
302     /// Panics if `start` >= `pos`.
303     #[inline]
304     #[cfg(feature = "safe-decode")]
extend_from_within(&mut self, _start: usize, _wild_len: usize, _copy_len: usize)305     fn extend_from_within(&mut self, _start: usize, _wild_len: usize, _copy_len: usize) {
306         unreachable!();
307     }
308 
309     #[inline]
310     #[cfg(feature = "safe-decode")]
extend_from_within_overlapping(&mut self, _start: usize, _num_bytes: usize)311     fn extend_from_within_overlapping(&mut self, _start: usize, _num_bytes: usize) {
312         unreachable!();
313     }
314 }
315 
316 #[cfg(test)]
317 mod tests {
318 
319     #[test]
320     #[cfg(any(feature = "safe-encode", feature = "safe-decode"))]
test_sink_slice()321     fn test_sink_slice() {
322         use crate::sink::Sink;
323         use crate::sink::SliceSink;
324         use alloc::vec::Vec;
325         let mut data = Vec::new();
326         data.resize(5, 0);
327         let sink = SliceSink::new(&mut data, 1);
328         assert_eq!(sink.pos(), 1);
329         assert_eq!(sink.capacity(), 5);
330     }
331 }
332