1use core::mem::MaybeUninit;
2
3pub const fn _assert_send<T: Send>() {}
4pub const fn _assert_sync<T: Sync>() {}
5
6#[derive(Debug, Default)]
7pub struct PartialBuffer<B> {
8 buffer: B,
9 index: usize,
10}
11
12impl<B: AsRef<[u8]>> PartialBuffer<B> {
13 pub fn new(buffer: B) -> Self {
14 Self { buffer, index: 0 }
15 }
16
17 pub fn written(&self) -> &[u8] {
18 &self.buffer.as_ref()[..self.index]
19 }
20
21 pub fn written_len(&self) -> usize {
23 self.index
24 }
25
26 pub fn unwritten(&self) -> &[u8] {
27 &self.buffer.as_ref()[self.index..]
28 }
29
30 pub fn advance(&mut self, amount: usize) {
31 self.index += amount;
32 debug_assert!(self.index <= self.buffer.as_ref().len());
33 }
34
35 pub fn get_mut(&mut self) -> &mut B {
36 &mut self.buffer
37 }
38
39 pub fn into_inner(self) -> B {
40 self.buffer
41 }
42
43 pub fn reset(&mut self) {
44 self.index = 0;
45 }
46}
47
48impl<B: AsRef<[u8]> + AsMut<[u8]>> PartialBuffer<B> {
49 pub fn unwritten_mut(&mut self) -> &mut [u8] {
50 &mut self.buffer.as_mut()[self.index..]
51 }
52
53 pub fn copy_unwritten_from<C: AsRef<[u8]>>(&mut self, other: &mut PartialBuffer<C>) -> usize {
54 let len = self.unwritten().len().min(other.unwritten().len());
55
56 self.unwritten_mut()[..len].copy_from_slice(&other.unwritten()[..len]);
57
58 self.advance(len);
59 other.advance(len);
60 len
61 }
62}
63
64impl<B: AsRef<[u8]> + Default> PartialBuffer<B> {
65 pub fn take(&mut self) -> Self {
66 std::mem::take(self)
67 }
68}
69
70impl<B: AsRef<[u8]> + AsMut<[u8]>> From<B> for PartialBuffer<B> {
71 fn from(buffer: B) -> Self {
72 Self::new(buffer)
73 }
74}
75
76#[derive(Debug)]
88pub struct WriteBuffer<'a> {
89 buffer: &'a mut [MaybeUninit<u8>],
90 index: usize,
91 initialized: usize,
92}
93
94impl<'a> WriteBuffer<'a> {
95 pub fn new_initialized(buffer: &'a mut [u8]) -> Self {
96 Self {
97 initialized: buffer.len(),
98 buffer: unsafe { &mut *(buffer as *mut [u8] as *mut _) },
101 index: 0,
102 }
103 }
104
105 pub fn new_uninitialized(buffer: &'a mut [MaybeUninit<u8>]) -> Self {
106 Self {
107 buffer,
108 index: 0,
109 initialized: 0,
110 }
111 }
112
113 pub fn capacity(&self) -> usize {
114 self.buffer.len()
115 }
116
117 pub fn as_mut_ptr(&mut self) -> *mut u8 {
118 self.buffer.as_mut_ptr() as *mut _
119 }
120
121 pub fn initialized_len(&self) -> usize {
122 self.initialized
123 }
124
125 pub fn written(&self) -> &[u8] {
126 assert!(self.index <= self.initialized);
127
128 unsafe { &*(&self.buffer[..self.index] as *const _ as *const [u8]) }
130 }
131
132 pub fn written_len(&self) -> usize {
134 self.index
135 }
136
137 pub fn has_no_spare_space(&self) -> bool {
139 self.index == self.buffer.len()
140 }
141
142 pub fn initialize_unwritten(&mut self) -> &mut [u8] {
145 self.buffer[self.initialized..]
146 .iter_mut()
147 .for_each(|maybe_uninit| {
148 maybe_uninit.write(0);
149 });
150 self.initialized = self.buffer.len();
151
152 unsafe { &mut *(&mut self.buffer[self.index..] as *mut _ as *mut [u8]) }
153 }
154
155 pub fn advance(&mut self, amount: usize) {
161 assert!(amount <= self.buffer.len() - self.index);
163 assert!(amount <= self.initialized - self.index);
164
165 self.index += amount;
166 }
167
168 pub fn reset(&mut self) {
169 self.index = 0;
170 }
171
172 pub unsafe fn unwritten_mut(&mut self) -> &mut [MaybeUninit<u8>] {
182 &mut self.buffer[self.index..]
183 }
184
185 pub unsafe fn assume_init(&mut self, n: usize) {
199 assert!(n <= self.buffer.len() - self.index);
201
202 self.initialized = self.initialized.max(self.index + n);
203 }
204
205 pub unsafe fn assume_init_and_advance(&mut self, n: usize) {
215 assert!(n <= self.buffer.len() - self.index);
216
217 self.index += n;
218 self.initialized = self.initialized.max(self.index);
219 }
220
221 pub unsafe fn set_written_and_initialized_len(&mut self, n: usize) {
232 assert!(n <= self.buffer.len());
233
234 self.index = n;
235 self.initialized = self.initialized.max(n);
236 }
237
238 pub fn copy_unwritten_from<C: AsRef<[u8]>>(&mut self, other: &mut PartialBuffer<C>) -> usize {
239 fn inner(this: &mut WriteBuffer<'_>, input: &[u8]) -> usize {
240 let out = unsafe { this.unwritten_mut() };
242
243 let len = out.len().min(input.len());
244
245 out[..len]
246 .iter_mut()
247 .zip(&input[..len])
248 .for_each(|(maybe_uninit, byte)| {
249 maybe_uninit.write(*byte);
250 });
251
252 unsafe { this.assume_init_and_advance(len) };
254 len
255 }
256
257 let len = inner(self, other.unwritten());
258 other.advance(len);
259
260 len
261 }
262}
263
264#[cfg(test)]
265mod tests {
266 use super::{PartialBuffer, WriteBuffer};
267 use std::{
268 mem::MaybeUninit,
269 panic::{catch_unwind, AssertUnwindSafe},
270 };
271
272 #[test]
273 fn advance_within_initialized_buffer() {
274 let mut storage = [1, 2, 3, 4];
275 let mut output = WriteBuffer::new_initialized(&mut storage);
276
277 output.advance(0);
278 assert!(output.written().is_empty());
279 output.advance(2);
280 assert_eq!(output.written(), &[1, 2]);
281 output.advance(2);
282 assert_eq!(output.written(), &[1, 2, 3, 4]);
283 output.advance(0);
284 assert_eq!(output.written(), &[1, 2, 3, 4]);
285 }
286
287 #[test]
288 #[should_panic]
289 fn advance_into_uninitialized_buffer_panics() {
290 let mut allocation = Vec::<u8>::with_capacity(8);
291 let mut output = WriteBuffer::new_uninitialized(&mut allocation.spare_capacity_mut()[..8]);
292
293 output.advance(1);
294 }
295
296 #[test]
297 fn advance_past_initialized_preserves_written_data() {
298 let mut storage = [MaybeUninit::uninit(); 4];
299 let mut output = WriteBuffer::new_uninitialized(&mut storage);
300 output.copy_unwritten_from(&mut PartialBuffer::new(&[1, 2][..]));
301 output.reset();
302 output.advance(1);
303
304 let result = catch_unwind(AssertUnwindSafe(|| output.advance(2)));
305
306 assert!(result.is_err());
307 assert_eq!(output.written(), &[1]);
308 output.advance(1);
309 assert_eq!(output.written(), &[1, 2]);
310 }
311
312 #[test]
313 #[should_panic]
314 fn advance_past_capacity_panics() {
315 let mut storage = [0; 4];
316 let mut output = WriteBuffer::new_initialized(&mut storage);
317 output.advance(4);
318
319 output.advance(1);
320 }
321
322 #[test]
323 #[should_panic]
324 fn advance_overflow_panics() {
325 let mut storage = [0; 4];
326 let mut output = WriteBuffer::new_initialized(&mut storage);
327 output.advance(1);
328
329 output.advance(usize::MAX);
330 }
331
332 #[test]
333 fn assume_init_is_not_additive() {
334 let mut storage = [MaybeUninit::new(1); 6];
335 let mut output = WriteBuffer::new_uninitialized(&mut storage);
336
337 for n in [4, 2, 4, 0] {
338 unsafe { output.assume_init(n) };
340 assert_eq!(output.initialized_len(), 4);
341 assert_eq!(output.written_len(), 0);
342 }
343 }
344
345 #[test]
346 fn assume_init_starts_at_written_len() {
347 let mut storage = [MaybeUninit::new(1); 6];
348 let mut output = WriteBuffer::new_uninitialized(&mut storage);
349
350 unsafe { output.assume_init(4) };
352 output.advance(2);
353 unsafe { output.assume_init(3) };
355 assert_eq!(output.initialized_len(), 5);
356 assert_eq!(output.written_len(), 2);
357 }
358
359 #[test]
360 #[should_panic]
361 fn assume_init_overflow_panics() {
362 let mut storage = [1; 4];
363 let mut output = WriteBuffer::new_initialized(&mut storage);
364 output.advance(1);
365
366 unsafe { output.assume_init(usize::MAX) };
368 }
369
370 #[test]
371 #[should_panic]
372 fn assume_init_and_advance_overflow_panics() {
373 let mut storage = [1; 4];
374 let mut output = WriteBuffer::new_initialized(&mut storage);
375 output.advance(1);
376
377 unsafe { output.assume_init_and_advance(usize::MAX) };
379 }
380
381 #[test]
382 #[should_panic]
383 fn set_written_and_initialized_len_past_capacity_panics() {
384 let mut storage = [1; 4];
385 let mut output = WriteBuffer::new_initialized(&mut storage);
386
387 unsafe { output.set_written_and_initialized_len(5) };
389 }
390}