Skip to main content

prefix_arena/
prefix_arena.rs

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
20/// A bump-style arena over caller-provided byte storage.
21///
22/// `PrefixArena` hands out slices from the front of the remaining buffer and keeps
23/// the rest available for later use. It only manages buffer boundaries; it does
24/// not track which bytes are initialized.
25pub 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    /// Returns the number of bytes still available in the arena.
43    #[inline]
44    pub const fn len(&self) -> usize {
45        let remaining = unsafe { &*self.remaining.get() };
46        remaining.len()
47    }
48
49    /// Returns `true` when no bytes remain available.
50    #[inline(always)]
51    pub const fn is_empty(&self) -> bool {
52        self.len() == 0
53    }
54
55    /// Borrows the currently remaining arena space through a temporary view.
56    pub const fn view<'arena>(&'arena mut self) -> ArenaView<'arena, 'buf> {
57        // SAFETY: `self.remaining` points at the remaining part of the arena for `'buf`.
58        ArenaView::<'arena, 'buf>::new(self.remaining.get())
59    }
60
61    /// Removes the first `n` bytes from the remaining arena and returns them.
62    ///
63    /// The returned slice is uninitialized storage. The caller must initialize
64    /// it before reading from it.
65    ///
66    /// # Panics
67    /// Panics if `n > self.len()`.
68    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    /// Removes the first `n` bytes from the remaining arena and returns them as `u8`.
76    ///
77    /// # Safety
78    /// The caller must ensure both of the following:
79    /// - `n <= self.len()`.
80    /// - Every returned byte is initialized before it is read as `u8`.
81    #[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    /// Returns all bytes that still remain in the arena and consumes `self`.
90    ///
91    /// The returned slice is uninitialized storage. The caller must initialize
92    /// it before reading from it.
93    pub fn take_remaining(self) -> &'buf mut [MaybeUninit<u8>] {
94        self.remaining.into_inner()
95    }
96
97    /// Exposes the remaining arena as `&mut [u8]`, lets `f` initialize a prefix,
98    /// and then detaches that initialized prefix from the arena.
99    ///
100    /// If `f` returns `Err`, the arena remains unchanged.
101    ///
102    /// # Safety
103    /// `f` must return the length of a prefix that it actually initialized.
104    ///
105    /// # Panics
106    /// Panics if `f` returns a length greater than the currently remaining size.
107    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
123/// A temporary view over the remaining bytes of a [`PrefixArena`].
124///
125/// This is useful when code needs to fill an unknown-sized prefix of the
126/// remaining arena and then detach only the initialized portion.
127pub 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    /// Creates a temporary view over the remaining arena bytes.
137    const fn new(remaining: *mut &'buf mut [MaybeUninit<u8>]) -> Self {
138        Self {
139            remaining,
140            _marker: PhantomData,
141        }
142    }
143
144    /// Returns the number of bytes visible through this temporary view.
145    #[inline]
146    pub const fn len(&self) -> usize {
147        let remaining = unsafe { self.remaining.as_mut().unwrap_unchecked() };
148        remaining.len()
149    }
150
151    /// Returns `true` when no bytes are visible through this view.
152    #[inline(always)]
153    pub const fn is_empty(&self) -> bool {
154        self.len() == 0
155    }
156
157    /// Returns the remaining arena bytes as uninitialized storage.
158    #[inline]
159    pub const fn as_uninit_slice(&self) -> &[MaybeUninit<u8>] {
160        self.as_slice()
161    }
162
163    /// Returns the remaining arena bytes as uninitialized storage.
164    #[inline]
165    pub const fn as_slice(&self) -> &[MaybeUninit<u8>] {
166        unsafe { self.remaining.as_mut().unwrap_unchecked() }
167    }
168
169    /// Returns the remaining arena bytes as `u8`.
170    ///
171    /// # Safety
172    /// Every returned byte must be initialized before it is read as `u8`.
173    #[inline]
174    pub const unsafe fn as_slice_unchecked(&self) -> &[u8] {
175        unsafe { uninit_as_bytes(self.as_slice()) }
176    }
177
178    /// Returns the remaining arena bytes as mutable uninitialized storage.
179    #[inline]
180    pub const fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<u8>] {
181        self.as_slice_mut()
182    }
183
184    /// Returns the remaining arena bytes as mutable uninitialized storage.
185    #[inline]
186    pub const fn as_slice_mut(&mut self) -> &mut [MaybeUninit<u8>] {
187        unsafe { self.remaining.as_mut().unwrap_unchecked() }
188    }
189
190    /// Returns the remaining arena bytes as mutable `u8`.
191    ///
192    /// # Safety
193    /// Every returned byte must be initialized before it is read as `u8`.
194    #[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    /// Lets `f` initialize a prefix of the temporary view and returns that prefix.
200    ///
201    /// This method does not shrink the underlying arena.
202    ///
203    /// # Panics
204    /// Panics if `f` returns a length greater than `self.len()`.
205    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    /// Lets `f` initialize a prefix of the temporary view and then detaches that
218    /// prefix from the underlying arena.
219    ///
220    /// If `f` returns `Err`, the underlying arena remains unchanged.
221    ///
222    /// # Safety
223    /// `f` must return the length of a prefix that it actually initialized.
224    ///
225    /// # Panics
226    /// Panics if `f` returns a length greater than `self.len()`.
227    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    /// Removes the first `n` bytes from the underlying arena and returns them.
241    ///
242    /// The returned slice is uninitialized storage. The caller must initialize
243    /// it before reading from it.
244    ///
245    /// # Panics
246    /// Panics if `n > self.len()`.
247    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    /// Removes the first `n` bytes from the underlying arena and returns them as `u8`.
255    ///
256    /// # Safety
257    /// The caller must ensure both of the following:
258    /// - `n <= self.len()`.
259    /// - Every returned byte is initialized before it is read as `u8`.
260    #[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 take_remaining method
675    #[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); // Detach first 2 bytes
688        let remaining = unsafe { uninit_as_bytes_mut(head_arena.take_remaining()) };
689        assert_eq!(remaining, &[3, 4, 5]);
690    }
691}