1use core::cell::UnsafeCell;
2use core::marker::PhantomData;
3use core::mem::MaybeUninit;
4
5#[inline(always)]
6const unsafe fn bytes_as_uninit_mut(slice: &mut [u8]) -> &mut [MaybeUninit<u8>] {
7 unsafe { core::mem::transmute::<&mut [u8], &mut [MaybeUninit<u8>]>(slice) }
8}
9
10#[inline(always)]
11const unsafe fn uninit_as_bytes(slice: &[MaybeUninit<u8>]) -> &[u8] {
12 unsafe { core::mem::transmute::<&[MaybeUninit<u8>], &[u8]>(slice) }
13}
14
15#[inline(always)]
16const unsafe fn uninit_as_bytes_mut(slice: &mut [MaybeUninit<u8>]) -> &mut [u8] {
17 unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(slice) }
18}
19
20pub struct PrefixArena<'buf> {
26 remaining: UnsafeCell<&'buf mut [MaybeUninit<u8>]>,
27}
28
29impl<'buf> PrefixArena<'buf> {
30 #[inline(always)]
31 pub const fn new(arena: &'buf mut [u8]) -> Self {
32 Self::from_uninit(unsafe { bytes_as_uninit_mut(arena) })
33 }
34
35 #[inline]
36 pub const fn from_uninit(arena: &'buf mut [MaybeUninit<u8>]) -> Self {
37 Self {
38 remaining: UnsafeCell::new(arena),
39 }
40 }
41
42 #[inline]
44 pub const fn len(&self) -> usize {
45 let remaining = unsafe { &*self.remaining.get() };
46 remaining.len()
47 }
48
49 #[inline(always)]
51 pub const fn is_empty(&self) -> bool {
52 self.len() == 0
53 }
54
55 pub const fn view<'arena>(&'arena mut self) -> ArenaView<'arena, 'buf> {
57 ArenaView::<'arena, 'buf>::new(self.remaining.get())
59 }
60
61 pub fn take_prefix(&self, n: usize) -> &'buf mut [MaybeUninit<u8>] {
69 let buffer = unsafe { &mut *self.remaining.get() };
70 let (used, remaining) = buffer.split_at_mut(n);
71 unsafe { *self.remaining.get() = remaining };
72 used
73 }
74
75 #[inline(always)]
82 pub unsafe fn take_prefix_unchecked(&self, n: usize) -> &'buf mut [u8] {
83 let buffer = unsafe { &mut *self.remaining.get() };
84 let (used, remaining) = unsafe { buffer.split_at_mut_unchecked(n) };
85 unsafe { *self.remaining.get() = remaining };
86 unsafe { uninit_as_bytes_mut(used) }
87 }
88
89 pub fn take_remaining(self) -> &'buf mut [MaybeUninit<u8>] {
94 self.remaining.into_inner()
95 }
96
97 pub fn init_prefix_with<F, E>(self, f: F) -> Result<&'buf mut [u8], E>
108 where
109 F: FnOnce(&mut [u8]) -> Result<usize, E>,
110 {
111 let buffer: &mut [MaybeUninit<u8>] =
112 unsafe { self.remaining.get().as_mut().unwrap_unchecked() };
113 let slice: &mut [u8] = unsafe { uninit_as_bytes_mut(buffer) };
114 let initialized_len = f(slice)?;
115 if initialized_len > slice.len() {
116 panic!("Initializer function returned a length greater than the current buffer size");
117 }
118
119 Ok(unsafe { self.take_prefix_unchecked(initialized_len) })
120 }
121}
122
123pub struct ArenaView<'arena, 'buf>
128where
129 'buf: 'arena,
130{
131 remaining: *mut &'buf mut [MaybeUninit<u8>],
132 _marker: PhantomData<&'arena ()>,
133}
134
135impl<'arena, 'buf> ArenaView<'arena, 'buf> {
136 const fn new(remaining: *mut &'buf mut [MaybeUninit<u8>]) -> Self {
138 Self {
139 remaining,
140 _marker: PhantomData,
141 }
142 }
143
144 #[inline]
146 pub const fn len(&self) -> usize {
147 let remaining = unsafe { self.remaining.as_mut().unwrap_unchecked() };
148 remaining.len()
149 }
150
151 #[inline(always)]
153 pub const fn is_empty(&self) -> bool {
154 self.len() == 0
155 }
156
157 #[inline]
159 pub const fn as_uninit_slice(&self) -> &[MaybeUninit<u8>] {
160 self.as_slice()
161 }
162
163 #[inline]
165 pub const fn as_slice(&self) -> &[MaybeUninit<u8>] {
166 unsafe { self.remaining.as_mut().unwrap_unchecked() }
167 }
168
169 #[inline]
174 pub const unsafe fn as_slice_unchecked(&self) -> &[u8] {
175 unsafe { uninit_as_bytes(self.as_slice()) }
176 }
177
178 #[inline]
180 pub const fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<u8>] {
181 self.as_slice_mut()
182 }
183
184 #[inline]
186 pub const fn as_slice_mut(&mut self) -> &mut [MaybeUninit<u8>] {
187 unsafe { self.remaining.as_mut().unwrap_unchecked() }
188 }
189
190 #[inline]
195 pub const unsafe fn as_slice_mut_unchecked(&mut self) -> &mut [u8] {
196 unsafe { uninit_as_bytes_mut(self.as_slice_mut()) }
197 }
198
199 pub fn init_with<F, E>(&mut self, f: F) -> Result<&mut [u8], E>
206 where
207 F: FnOnce(&mut [u8]) -> Result<usize, E>,
208 {
209 let slice: &mut [u8] = unsafe { self.as_slice_mut_unchecked() };
210 let initialized_len = f(slice)?;
211 if initialized_len > slice.len() {
212 panic!("Initializer function returned a length greater than the current buffer size");
213 }
214 Ok(&mut slice[..initialized_len])
215 }
216
217 pub fn init_prefix_with<F, E>(mut self, f: F) -> Result<&'buf mut [u8], E>
228 where
229 F: FnOnce(&mut [u8]) -> Result<usize, E>,
230 {
231 let slice: &mut [u8] = unsafe { self.as_slice_mut_unchecked() };
232 let initialized_len = f(slice)?;
233 if initialized_len > slice.len() {
234 panic!("Initializer function returned a length greater than the current buffer size");
235 }
236
237 Ok(unsafe { self.take_prefix_unchecked(initialized_len) })
238 }
239
240 pub fn take_prefix(self, n: usize) -> &'buf mut [MaybeUninit<u8>] {
248 let buffer = unsafe { &mut *self.remaining.as_mut().unwrap_unchecked() };
249 let (used, remaining) = buffer.split_at_mut(n);
250 unsafe { *self.remaining.as_mut().unwrap_unchecked() = remaining };
251 used
252 }
253
254 #[inline(always)]
261 pub unsafe fn take_prefix_unchecked(self, n: usize) -> &'buf mut [u8]
262 where
263 'buf: 'arena,
264 {
265 let buffer = unsafe { &mut *self.remaining.as_mut().unwrap_unchecked() };
266 let (used, remaining) = unsafe { buffer.split_at_mut_unchecked(n) };
267 unsafe { *self.remaining.as_mut().unwrap_unchecked() = remaining };
268 unsafe { uninit_as_bytes_mut(used) }
269 }
270}
271
272impl<'buf> From<&'buf mut [u8]> for PrefixArena<'buf> {
273 fn from(buffer: &'buf mut [u8]) -> Self {
274 Self::new(buffer)
275 }
276}
277
278impl<'buf> From<&'buf mut [MaybeUninit<u8>]> for PrefixArena<'buf> {
279 fn from(buffer: &'buf mut [MaybeUninit<u8>]) -> Self {
280 Self::from_uninit(buffer)
281 }
282}
283
284impl<'buf, const N: usize> From<&'buf mut [u8; N]> for PrefixArena<'buf> {
285 fn from(buffer: &'buf mut [u8; N]) -> Self {
286 Self::new(&mut buffer[..])
287 }
288}
289
290impl<'buf, const N: usize> From<&'buf mut [MaybeUninit<u8>; N]> for PrefixArena<'buf> {
291 fn from(buffer: &'buf mut [MaybeUninit<u8>; N]) -> Self {
292 Self::from_uninit(&mut buffer[..])
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use super::*;
299 use std::vec::Vec;
300
301 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
302 enum TestError {
303 Expected,
304 }
305
306 #[test]
307 fn test_init_from_initialized() {
308 let mut data = [1, 2, 3, 4, 5];
309 let head_arena = PrefixArena::new(&mut data);
310 assert_eq!(head_arena.len(), 5);
311 assert!(!head_arena.is_empty());
312 }
313
314 #[test]
315 fn test_init_from_uninitialized() {
316 let mut data = [1, 2, 3, 4, 5].map(MaybeUninit::new);
317 let head_arena = PrefixArena::from_uninit(&mut data);
318 assert_eq!(head_arena.len(), 5);
319 assert!(!head_arena.is_empty());
320 }
321
322 #[test]
323 fn test_from_slice() {
324 let mut data = [1, 2, 3, 4, 5];
325 let head_arena = PrefixArena::new(&mut data[..]);
326 assert_eq!(head_arena.len(), 5);
327 assert_eq!(
328 unsafe { uninit_as_bytes(head_arena.take_remaining()) },
329 &[1, 2, 3, 4, 5]
330 );
331 }
332
333 #[test]
334 fn test_from_uninitialized_slice() {
335 let data: [u8; 5] = [1, 2, 3, 4, 5];
336 let mut uninit_data = data.map(MaybeUninit::new);
337
338 let head_arena = PrefixArena::from_uninit(&mut uninit_data);
339 assert_eq!(head_arena.len(), 5);
340 assert!(!head_arena.is_empty());
341 }
342
343 #[test]
344 fn test_from_array() {
345 let mut data = [1, 2, 3, 4, 5];
346 let head_arena = PrefixArena::from(&mut data);
347 assert_eq!(head_arena.len(), 5);
348 }
349
350 #[test]
351 fn test_from_array_for_temporary_buffer() {
352 let mut data = [1, 2, 3, 4, 5];
353 let mut head_arena = PrefixArena::from(&mut data);
354 assert_eq!(head_arena.len(), 5);
355 assert_eq!(head_arena.view().len(), 5);
356 }
357
358 #[test]
359 fn test_empty_buffer() {
360 let mut data = [];
361 let head_arena = PrefixArena::new(&mut data);
362 assert_eq!(head_arena.len(), 0);
363 assert!(head_arena.is_empty());
364 }
365
366 #[test]
367 fn test_empty_buffer_for_temporary_buffer() {
368 let mut data = [];
369 let mut head_arena = PrefixArena::new(&mut data);
370 assert_eq!(head_arena.len(), 0);
371 assert!(head_arena.is_empty());
372 let temp_buffer = head_arena.view();
373 assert_eq!(temp_buffer.len(), 0);
374 assert!(temp_buffer.is_empty());
375 }
376
377 #[test]
378 fn test_temp_buffer_as_slice() {
379 let mut data = [1, 2, 3, 4, 5];
380 let mut head_arena = PrefixArena::new(&mut data);
381 let mut temp_buffer = head_arena.view();
382 assert_eq!(
383 unsafe { uninit_as_bytes(temp_buffer.as_slice_mut()) },
384 &[1, 2, 3, 4, 5]
385 );
386 }
387 #[test]
388 fn test_temp_buffer_as_slice_unchecked() {
389 let mut data = [1, 2, 3, 4, 5];
390 let mut head_arena = PrefixArena::new(&mut data);
391 let temp_buffer = head_arena.view();
392 assert_eq!(
393 unsafe { temp_buffer.as_slice_unchecked() },
394 &[1, 2, 3, 4, 5]
395 );
396 }
397
398 #[test]
399 fn test_temp_buffer_as_mut_slice() {
400 let mut data = [1, 2, 3, 4, 5];
401 let mut head_arena = PrefixArena::new(&mut data);
402 let mut temp_buffer = head_arena.view();
403 let slice = temp_buffer.as_slice_mut();
404 slice[0].write(10);
405 assert_eq!(
406 unsafe { temp_buffer.as_slice_unchecked() },
407 &[10, 2, 3, 4, 5]
408 );
409 }
410
411 #[test]
412 fn test_temp_buffer_as_mut_slice_unchecked() {
413 let mut data = [1, 2, 3, 4, 5];
414 let mut head_arena = PrefixArena::new(&mut data);
415 let mut temp_buffer = head_arena.view();
416 let slice = unsafe { temp_buffer.as_slice_mut_unchecked() };
417 slice[0] = 10;
418 assert_eq!(
419 unsafe { temp_buffer.as_slice_unchecked() },
420 &[10, 2, 3, 4, 5]
421 );
422 }
423
424 #[test]
425 fn test_head_arena_init_then_acquire_with() {
426 let mut data = [0u8; 5];
427 let head_arena = PrefixArena::new(&mut data);
428
429 let detached = head_arena
430 .init_prefix_with(|buffer| {
431 buffer[..3].copy_from_slice(&[7, 8, 9]);
432 Ok::<usize, TestError>(3)
433 })
434 .unwrap();
435
436 assert_eq!(detached, &[7, 8, 9]);
437 }
438
439 #[test]
440 #[should_panic(
441 expected = "Initializer function returned a length greater than the current buffer size"
442 )]
443 fn test_head_arena_init_then_acquire_with_panics_on_invalid_len() {
444 let mut data = [0u8; 3];
445 let head_arena = PrefixArena::new(&mut data);
446
447 let _ = head_arena.init_prefix_with(|_| Ok::<usize, TestError>(4));
448 }
449
450 #[test]
451 fn test_temp_buffer_as_mut_with_init() {
452 let mut data = [0u8; 5];
453 let mut head_arena = PrefixArena::new(&mut data);
454 let mut temp_buffer = head_arena.view();
455
456 let initialized = temp_buffer
457 .init_with(|buffer| {
458 buffer[..2].copy_from_slice(&[11, 12]);
459 Ok::<usize, TestError>(2)
460 })
461 .unwrap();
462
463 assert_eq!(initialized, &[11, 12]);
464 assert_eq!(temp_buffer.len(), 5);
465 assert_eq!(head_arena.len(), 5);
466 }
467
468 #[test]
469 fn test_temp_buffer_init_then_acquire_with() {
470 let mut data = [0u8; 5];
471 let mut head_arena = PrefixArena::new(&mut data);
472 let temp_buffer = head_arena.view();
473
474 let detached = temp_buffer
475 .init_prefix_with(|buffer| {
476 buffer[..2].copy_from_slice(&[21, 22]);
477 Ok::<usize, TestError>(2)
478 })
479 .unwrap();
480
481 assert_eq!(detached, &[21, 22]);
482 assert_eq!(head_arena.len(), 3);
483 assert_eq!(
484 unsafe { uninit_as_bytes(head_arena.take_remaining()) },
485 &[0, 0, 0]
486 );
487 }
488
489 #[test]
490 fn test_temp_buffer_init_then_acquire_with_error_preserves_arena() {
491 let mut data = [1u8, 2, 3, 4, 5];
492 let mut head_arena = PrefixArena::new(&mut data);
493 let temp_buffer = head_arena.view();
494
495 let error = temp_buffer
496 .init_prefix_with(|buffer| {
497 buffer[0] = 99;
498 Err::<usize, TestError>(TestError::Expected)
499 })
500 .unwrap_err();
501
502 assert_eq!(error, TestError::Expected);
503 assert_eq!(head_arena.len(), 5);
504 assert_eq!(
505 unsafe { uninit_as_bytes(head_arena.take_remaining()) },
506 &[99, 2, 3, 4, 5]
507 );
508 }
509
510 #[test]
511 #[should_panic(
512 expected = "Initializer function returned a length greater than the current buffer size"
513 )]
514 fn test_temp_buffer_as_mut_with_init_panics_on_invalid_len() {
515 let mut data = [0u8; 3];
516 let mut head_arena = PrefixArena::new(&mut data);
517 let mut temp_buffer = head_arena.view();
518
519 let _ = temp_buffer.init_with(|_| Ok::<usize, TestError>(4));
520 }
521
522 #[test]
523 #[should_panic(
524 expected = "Initializer function returned a length greater than the current buffer size"
525 )]
526 fn test_temp_buffer_init_then_acquire_with_panics_on_invalid_len() {
527 let mut data = [0u8; 3];
528 let mut head_arena = PrefixArena::new(&mut data);
529 let temp_buffer = head_arena.view();
530
531 let _ = temp_buffer.init_prefix_with(|_| Ok::<usize, TestError>(4));
532 }
533
534 #[test]
535 fn test_take_front_partial() {
536 let mut data = [1, 2, 3, 4, 5];
537 let head_arena = PrefixArena::new(&mut data);
538
539 let detached = unsafe { head_arena.take_prefix_unchecked(2) };
540 assert_eq!(detached, &[1, 2]);
541 assert_eq!(head_arena.len(), 3);
542 assert_eq!(
543 unsafe { uninit_as_bytes(head_arena.take_remaining()) },
544 &[3, 4, 5]
545 );
546 }
547
548 #[test]
549 fn test_take_front_all() {
550 let mut data = [1, 2, 3];
551 let head_arena = PrefixArena::new(&mut data);
552
553 let detached = unsafe { head_arena.take_prefix_unchecked(3) };
554 assert_eq!(detached, &[1, 2, 3]);
555 assert_eq!(head_arena.len(), 0);
556 assert!(head_arena.is_empty());
557 }
558
559 #[test]
560 fn test_multiple_take_fronts() {
561 let mut data = [1, 2, 3, 4, 5, 6];
562 let head_arena = PrefixArena::new(&mut data);
563 let first = unsafe { head_arena.take_prefix_unchecked(2) };
564 assert_eq!(first, &[1, 2]);
565 assert_eq!(head_arena.len(), 4);
566
567 let second = unsafe { head_arena.take_prefix_unchecked(2) };
568 assert_eq!(second, &[3, 4]);
569 assert_eq!(head_arena.len(), 2);
570 assert_eq!(
571 unsafe { uninit_as_bytes(head_arena.take_remaining()) },
572 &[5, 6]
573 );
574 }
575
576 #[test]
577 #[should_panic]
578 fn test_take_front_too_large() {
579 let mut data = [1, 2, 3];
580 let head_arena = PrefixArena::new(&mut data);
581 head_arena.take_prefix(4);
582 }
583
584 #[test]
585 fn test_take_front_zero() {
586 let mut data = [1, 2, 3];
587 let head_arena = PrefixArena::new(&mut data);
588
589 let detached = head_arena.take_prefix(0);
590 assert_eq!(detached.len(), 0);
591 assert_eq!(head_arena.len(), 3);
592 assert_eq!(
593 unsafe { uninit_as_bytes(head_arena.take_remaining()) },
594 &[1, 2, 3]
595 );
596 }
597
598 #[test]
599 fn test_usage_in_a_loop() {
600 const PART_SIZE: usize = 3;
601 const BUFFER_SIZE: usize = 10;
602 const EXPECTED_PARTS: [u8; BUFFER_SIZE] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
603 let mut data: [u8; BUFFER_SIZE] = EXPECTED_PARTS;
604
605 let head_arena = PrefixArena::new(&mut data);
606
607 let mut detached_parts = Vec::new();
608
609 while !head_arena.is_empty() {
610 let to_detach = core::cmp::min(head_arena.len(), PART_SIZE);
611 let detached = unsafe { head_arena.take_prefix_unchecked(to_detach) };
612 detached_parts.push(detached);
613 }
614
615 let mut expected_it = EXPECTED_PARTS.iter();
616 for detached in detached_parts {
617 detached.iter().for_each(|&byte| {
618 assert_eq!(byte, *expected_it.next().unwrap());
619 });
620 }
621 }
622
623 #[test]
624 fn test_no_borrowing_glue() {
625 const PART_SIZE: usize = 3;
626 const BUFFER_SIZE: usize = 10;
627 const EXPECTED_PARTS: [u8; BUFFER_SIZE] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
628
629 let mut data = EXPECTED_PARTS;
630 let head_arena = PrefixArena::new(&mut data);
631
632 let mut detached_parts = Vec::new();
633
634 while !head_arena.is_empty() {
635 let to_detach = core::cmp::min(head_arena.len(), PART_SIZE);
636 let detached = unsafe { head_arena.take_prefix_unchecked(to_detach) };
637 detached_parts.push(detached);
638 }
639
640 let mut expected_it = EXPECTED_PARTS.iter();
641 for detached in detached_parts {
642 detached.iter().for_each(|&byte| {
643 assert_eq!(byte, *expected_it.next().unwrap());
644 });
645 }
646 }
647
648 #[test]
649 fn test_no_borrowing_glue_with_temp_buffer_detach() {
650 const PART_SIZE: usize = 3;
651 const BUFFER_SIZE: usize = 10;
652 const EXPECTED_PARTS: [u8; BUFFER_SIZE] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
653
654 let mut data = EXPECTED_PARTS;
655 let mut head_arena = PrefixArena::new(&mut data);
656
657 let mut detached_parts = Vec::new();
658
659 while !head_arena.is_empty() {
660 let temp_buffer = head_arena.view();
661 let to_detach = core::cmp::min(temp_buffer.len(), PART_SIZE);
662 let detached = unsafe { temp_buffer.take_prefix_unchecked(to_detach) };
663 detached_parts.push(detached);
664 }
665
666 let mut expected_it = EXPECTED_PARTS.iter();
667 for detached in detached_parts {
668 detached.iter().for_each(|&byte| {
669 assert_eq!(byte, *expected_it.next().unwrap());
670 });
671 }
672 }
673
674 #[test]
676 fn test_take_remaining() {
677 let mut data = [1, 2, 3, 4, 5];
678 let head_arena = PrefixArena::new(&mut data);
679 let remaining = unsafe { uninit_as_bytes_mut(head_arena.take_remaining()) };
680 assert_eq!(remaining, &[1, 2, 3, 4, 5]);
681 }
682
683 #[test]
684 fn subsequent_take_remaining() {
685 let mut data = [1, 2, 3, 4, 5];
686 let head_arena = PrefixArena::new(&mut data);
687 let _ = head_arena.take_prefix(2); let remaining = unsafe { uninit_as_bytes_mut(head_arena.take_remaining()) };
689 assert_eq!(remaining, &[3, 4, 5]);
690 }
691}