uninit_tools/
buffer.rs

1//! Buffers for single-buffer and vectored I/O which tracking initializedness and how much has been
2//! filled. Container types pointing to possibly-uninitialized memory such as
3//! `Vec<MaybeUninit<Item>>`, `IoBox<Uninitialized>`, or `Box<[MaybeUninit<Item>]>` can be
4//! transformed into their initialized variants via the [`Initialize`] trait, within requiring
5//! unsafe code.
6//!
7//! This is an implementation of an API similar to what has been proposed in [this
8//! RFC](https://github.com/sfackler/rfcs/blob/read-buf/text/0000-read-buf.md).
9
10use core::fmt;
11use core::mem::MaybeUninit;
12
13use crate::initializer::BufferInitializer;
14use crate::traits::{Initialize, TrustedDeref};
15use crate::wrappers::AsUninit;
16
17pub struct Buffer<T> {
18    pub(crate) initializer: BufferInitializer<T>,
19    pub(crate) items_filled: usize,
20}
21
22/// A reference to a [`Buffer`], which is meant be a subset of the functionality offered by the
23/// fully owned buffer.
24///
25/// For example, it neither allows reading from the unfilled region, nor swapping out the buffer
26/// pointed to, with anything else.
27pub struct BufferRef<'buffer, T> {
28    // NOTE: The reference here is private, and never accessed using the API, _since we don't want
29    // an API user to be able to replace a `&mut Buffer` with a completely different one_.
30    inner: &'buffer mut Buffer<T>,
31}
32
33#[derive(Clone, Copy, Debug)]
34pub struct BufferParts<'a, I> {
35    pub filled_part: &'a [I],
36    pub unfilled_init_part: &'a [I],
37    pub unfilled_uninit_part: &'a [MaybeUninit<I>],
38}
39#[derive(Debug)]
40pub struct BufferPartsMut<'a, I> {
41    pub filled_part: &'a mut [I],
42    pub unfilled_init_part: &'a mut [I],
43    pub unfilled_uninit_part: &'a mut [MaybeUninit<I>],
44}
45
46impl<T> Buffer<T> {
47    /// Create a new buffer from an initializer.
48    #[inline]
49    pub const fn from_initializer(initializer: BufferInitializer<T>) -> Self {
50        Self {
51            initializer,
52            items_filled: 0,
53        }
54    }
55    /// Create a new buffer, defaulting to not being initialized, nor filled. Prefer
56    /// [`new`](Buffer::new) if the buffer is already initialized.
57    pub const fn uninit(inner: T) -> Self {
58        Self::from_initializer(BufferInitializer::uninit(inner))
59    }
60    /// Move out the buffer initializer, which contains the inner buffer and initialization cursor,
61    /// and get the filledness cursor.
62    #[inline]
63    pub fn into_raw_parts(self) -> (BufferInitializer<T>, usize) {
64        let Self {
65            initializer,
66            items_filled,
67        } = self;
68
69        (initializer, items_filled)
70    }
71    #[inline]
72    pub fn into_initializer(self) -> BufferInitializer<T> {
73        self.initializer
74    }
75    /// Move out the inner buffer, being uninitialized or initialized based on whatever it was when
76    /// this buffer was constructed.
77    ///
78    /// Use [`try_into_init`] if the buffer is initialized.
79    ///
80    /// [`try_into_init`]: #method.try_into_init
81    #[inline]
82    pub fn into_inner(self) -> T {
83        self.into_initializer().into_inner()
84    }
85
86    /// Get the number of items that are currently filled, within the buffer. Note that this is
87    /// different from the number of initialized items; use [`items_initialized`] for that.
88    ///
89    /// [`items_initialized`]: #method.items_initialized
90    #[inline]
91    pub const fn items_filled(&self) -> usize {
92        self.items_filled
93    }
94
95    #[inline]
96    pub fn by_ref(&mut self) -> BufferRef<'_, T> {
97        BufferRef { inner: self }
98    }
99
100    #[inline]
101    pub const fn initializer(&self) -> &BufferInitializer<T> {
102        &self.initializer
103    }
104
105    #[inline]
106    pub fn initializer_mut(&mut self) -> &mut BufferInitializer<T> {
107        &mut self.initializer
108    }
109}
110impl<T, Item> Buffer<AsUninit<T>>
111where
112    T: core::ops::Deref<Target = [Item]> + core::ops::DerefMut + TrustedDeref,
113{
114    pub fn new(init: T) -> Self {
115        Self::from_initializer(BufferInitializer::new(init))
116    }
117}
118
119impl<T> Buffer<T>
120where
121    T: Initialize,
122{
123    #[inline]
124    pub fn capacity(&self) -> usize {
125        self.initializer.capacity()
126    }
127
128    pub(crate) fn debug_assert_validity(&self) {
129        self.initializer.debug_assert_validity();
130        debug_assert!(self.items_filled() <= self.capacity());
131        debug_assert!(self.items_filled() <= self.initializer.items_initialized());
132    }
133    /// Get the number of items that may be filled before the buffer is full.
134    #[inline]
135    pub fn remaining(&self) -> usize {
136        debug_assert!(self.capacity() >= self.items_filled);
137        self.capacity().wrapping_sub(self.items_filled)
138    }
139    /// Check whether the buffer is completely filled, and thus also initialized.
140    #[inline]
141    pub fn is_full(&self) -> bool {
142        self.items_filled() == self.capacity()
143    }
144    /// Check whether the buffer is empty. It can be partially or fully initialized however.
145    #[inline]
146    pub fn is_empty(&self) -> bool {
147        self.items_filled() == 0
148    }
149    /// Retrieve a shared slice to the filled part of the buffer.
150    #[inline]
151    pub fn filled_part(&self) -> &[T::Item] {
152        unsafe {
153            self.debug_assert_validity();
154
155            let ptr = self.initializer.all_uninit().as_ptr();
156            let len = self.items_filled;
157
158            core::slice::from_raw_parts(ptr as *const T::Item, len)
159        }
160    }
161    /// Retrieve a mutable slice to the filled part of the buffer.
162    #[inline]
163    pub fn filled_part_mut(&mut self) -> &mut [T::Item] {
164        let orig_ptr = unsafe { self.initializer.all_uninit_mut().as_mut_ptr() };
165
166        unsafe {
167            self.debug_assert_validity();
168
169            let ptr = orig_ptr;
170            let len = self.items_filled;
171
172            core::slice::from_raw_parts_mut(ptr as *mut T::Item, len)
173        }
174    }
175    /// Get a shared slice to the unfilled part, which may be uninitialized.
176    #[inline]
177    pub fn unfilled_part(&self) -> &[MaybeUninit<T::Item>] {
178        let (orig_ptr, orig_len) = {
179            let orig = self.initializer.all_uninit();
180
181            (orig.as_ptr(), orig.len())
182        };
183
184        unsafe {
185            self.debug_assert_validity();
186
187            let ptr = orig_ptr.add(self.items_filled);
188            let len = orig_len.wrapping_sub(self.items_filled);
189
190            core::slice::from_raw_parts(ptr, len)
191        }
192    }
193    /// Get a mutable reference to the unfilled part of the buffer, which may overlap with the
194    /// initialized-but-nonfilled region.
195    ///
196    /// # Safety
197    ///
198    /// Due to the possibility of an overlap between the part that is initialized and the part that
199    /// is unfilled, the caller must ensure that the resulting slice is never used to deinitialize
200    /// the buffer.
201    ///
202    /// It is thus recommended to use [`append`](Self::append) or
203    /// [`fill_by_repeating`](Self::fill_by_repeating) instead, since those are the by far most
204    /// common operations to do when initializing. However, code that requires interfacing with
205    /// other APIs such as system calls, need to use this function.
206    ///
207    /// If mutable access really is needed for the unfilled region in safe code, consider using
208    /// [`all_parts_mut`](Self::all_parts_mut).
209    #[inline]
210    pub unsafe fn unfilled_part_mut(&mut self) -> &mut [MaybeUninit<T::Item>] {
211        let (orig_ptr, orig_len) = {
212            let orig = self.initializer.all_uninit_mut();
213            (orig.as_mut_ptr(), orig.len())
214        };
215
216        self.debug_assert_validity();
217
218        let ptr = orig_ptr.add(self.items_filled);
219        let len = orig_len.wrapping_sub(self.items_filled);
220
221        core::slice::from_raw_parts_mut(ptr, len)
222    }
223    /// Borrow both the filled and unfilled parts immutably.
224    #[inline]
225    pub fn filled_unfilled_parts(&self) -> (&[T::Item], &[MaybeUninit<T::Item>]) {
226        (self.filled_part(), self.unfilled_part())
227    }
228    /// Borrow the filled part, the unfilled but initialized part, and the unfilled and
229    /// uninitialized part.
230    #[inline]
231    pub fn all_parts(&self) -> BufferParts<'_, T::Item> {
232        BufferParts {
233            filled_part: self.filled_part(),
234            unfilled_init_part: self.unfilled_init_part(),
235            unfilled_uninit_part: self.unfilled_uninit_part(),
236        }
237    }
238
239    #[inline]
240    pub fn all_parts_mut(&mut self) -> BufferPartsMut<'_, T::Item> {
241        let (all_ptr, all_len) = unsafe {
242            let all = self.initializer.all_uninit_mut();
243
244            (all.as_mut_ptr(), all.len())
245        };
246
247        unsafe {
248            self.debug_assert_validity();
249
250            let filled_base_ptr = all_ptr as *mut T::Item;
251            let filled_len = self.items_filled;
252
253            let unfilled_init_base_ptr = all_ptr.add(self.items_filled) as *mut T::Item;
254            let unfilled_init_len = self
255                .initializer
256                .items_initialized()
257                .wrapping_sub(self.items_filled);
258
259            let unfilled_uninit_base_ptr = all_ptr.add(self.initializer.items_initialized());
260            let unfilled_uninit_len = all_len.wrapping_sub(self.initializer.items_initialized());
261
262            let filled_part = core::slice::from_raw_parts_mut(filled_base_ptr, filled_len);
263            let unfilled_init_part =
264                core::slice::from_raw_parts_mut(unfilled_init_base_ptr, unfilled_init_len);
265            let unfilled_uninit_part =
266                core::slice::from_raw_parts_mut(unfilled_uninit_base_ptr, unfilled_uninit_len);
267
268            BufferPartsMut {
269                filled_part,
270                unfilled_init_part,
271                unfilled_uninit_part,
272            }
273        }
274    }
275
276    /// Borrow both the filled and the unfilled parts, mutably.
277    ///
278    /// # Safety
279    ///
280    /// This is unsafe as the uninit part may have items in it that are tracked to be initialized.
281    /// It is hence the responsibility of the caller to ensure that the buffer is not deinitialized
282    /// by writing [`MaybeUninit::uninit()`] to it.
283    #[inline]
284    pub unsafe fn filled_unfilled_parts_mut(
285        &mut self,
286    ) -> (&mut [T::Item], &mut [MaybeUninit<T::Item>]) {
287        let (all_ptr, all_len) = {
288            let all = self.initializer.all_uninit_mut();
289
290            (all.as_mut_ptr(), all.len())
291        };
292
293        {
294            self.debug_assert_validity();
295
296            let filled_base_ptr = all_ptr as *mut T::Item;
297            let filled_len = self.items_filled;
298
299            let unfilled_base_ptr = all_ptr.add(self.items_filled);
300            let unfilled_len = all_len.wrapping_sub(self.items_filled);
301
302            let filled = core::slice::from_raw_parts_mut(filled_base_ptr, filled_len);
303            let unfilled = core::slice::from_raw_parts_mut(unfilled_base_ptr, unfilled_len);
304
305            (filled, unfilled)
306        }
307    }
308
309    #[inline]
310    pub fn unfilled_init_part(&self) -> &[T::Item] {
311        unsafe {
312            self.debug_assert_validity();
313
314            let all = self.initializer.all_uninit();
315            let all_ptr = all.as_ptr();
316
317            let unfilled_init_base_ptr = all_ptr.add(self.items_filled) as *const T::Item;
318            let unfilled_init_len = self
319                .initializer
320                .items_initialized()
321                .wrapping_sub(self.items_filled);
322
323            core::slice::from_raw_parts(unfilled_init_base_ptr, unfilled_init_len)
324        }
325    }
326
327    /// Get the initialized part of the unfilled part, if there is any.
328    #[inline]
329    pub fn unfilled_init_part_mut(&mut self) -> &mut [T::Item] {
330        let BufferPartsMut {
331            unfilled_init_part, ..
332        } = self.all_parts_mut();
333
334        unfilled_init_part
335    }
336    #[inline]
337    pub fn unfilled_uninit_part(&self) -> &[MaybeUninit<T::Item>] {
338        self.initializer.uninit_part()
339    }
340    /// Get the uninitialized part of the unfilled part, if there is any.
341    #[inline]
342    pub fn unfilled_uninit_part_mut(&mut self) -> &mut [MaybeUninit<T::Item>] {
343        self.initializer.uninit_part_mut()
344    }
345
346    #[inline]
347    pub fn unfilled_parts(&mut self) -> (&[T::Item], &[MaybeUninit<T::Item>]) {
348        let BufferParts {
349            unfilled_init_part,
350            unfilled_uninit_part,
351            ..
352        } = self.all_parts();
353
354        (unfilled_init_part, unfilled_uninit_part)
355    }
356    #[inline]
357    pub fn unfilled_parts_mut(&mut self) -> (&mut [T::Item], &mut [MaybeUninit<T::Item>]) {
358        let BufferPartsMut {
359            unfilled_init_part,
360            unfilled_uninit_part,
361            ..
362        } = self.all_parts_mut();
363
364        (unfilled_init_part, unfilled_uninit_part)
365    }
366
367    /// Revert the internal cursor to 0, forgetting about the initialized items.
368    #[inline]
369    pub fn revert_to_start(&mut self) {
370        self.by_ref().revert_to_start()
371    }
372    #[inline]
373    pub fn append(&mut self, slice: &[T::Item])
374    where
375        T::Item: Copy,
376    {
377        unsafe {
378            // TODO: If this would ever turn out to be worth it, this could be optimized as bounds
379            // checking gets redundant here.
380            let unfilled_part = self.unfilled_part_mut();
381            assert!(slice.len() <= unfilled_part.len());
382            unfilled_part[..slice.len()].copy_from_slice(crate::cast_init_to_uninit_slice(slice));
383
384            self.assume_init(slice.len())
385        }
386    }
387    #[inline]
388    pub fn advance(&mut self, count: usize) {
389        assert!(
390            self.initializer
391                .items_initialized()
392                .wrapping_sub(self.items_filled)
393                >= count,
394            "advancing filledness cursor beyond the initialized region ({} + {} = {} filled > {} init)",
395            self.items_filled,
396            count,
397            self.items_filled + count,
398            self.initializer.items_initialized,
399        );
400        self.items_filled = self.items_filled.wrapping_add(count);
401    }
402    #[inline]
403    pub fn advance_to_init_part(&mut self) {
404        self.items_filled = self.initializer.items_initialized;
405    }
406    // TODO: Method for increasing the items filled, but not the items initialized?
407    /// Increment the counter that marks the progress of filling, as well as the initialization
408    /// progress, `count` items.
409    ///
410    /// # Safety
411    ///
412    /// This does not initialize nor fill anything, and it is hence up to the user to ensure that
413    /// no uninitialized items are marked initialized.
414    pub unsafe fn assume_init(&mut self, count: usize) {
415        self.items_filled += count;
416        self.initializer.items_initialized =
417            core::cmp::max(self.items_filled, self.initializer.items_initialized);
418
419        self.debug_assert_validity();
420    }
421    /// Mark the buffer as fully filled and initialized, without actually filling the buffer.
422    ///
423    /// # Safety
424    ///
425    /// For this to be safe, the caller must ensure that every single item in the slice that the
426    /// buffer wraps, is initialized.
427    #[inline]
428    pub unsafe fn assume_init_all(&mut self) {
429        self.items_filled = self.capacity();
430        self.initializer.items_initialized = self.capacity();
431    }
432    #[inline]
433    pub fn fill_by_repeating(&mut self, item: T::Item)
434    where
435        T::Item: Copy,
436    {
437        unsafe {
438            crate::fill_uninit_slice(self.unfilled_part_mut(), item);
439            self.assume_init_all();
440        }
441    }
442}
443impl<T> Buffer<T>
444where
445    T: Initialize<Item = u8>,
446{
447    #[inline]
448    pub fn fill_by_zeroing(&mut self) {
449        self.fill_by_repeating(0_u8);
450    }
451}
452impl<'a> Buffer<AsUninit<&'a mut [u8]>> {
453    // TODO: Use a trait that makes the dynamic counter statically set to full.
454    #[inline]
455    pub fn from_slice_mut(slice: &'a mut [u8]) -> Self {
456        let mut initializer = BufferInitializer::new(slice);
457        unsafe {
458            initializer.advance_to_end();
459        }
460        Self::from_initializer(initializer)
461    }
462}
463impl<'a> Buffer<&'a mut [MaybeUninit<u8>]> {
464    #[inline]
465    pub fn from_uninit_slice_mut(slice: &'a mut [MaybeUninit<u8>]) -> Self {
466        Self::uninit(slice)
467    }
468}
469
470impl<'buffer, T> BufferRef<'buffer, T> {
471    #[inline]
472    pub fn items_filled(&self) -> usize {
473        self.inner.items_filled()
474    }
475
476    /// Reborrow the inner buffer, getting a buffer reference with a shorter lifetime.
477    #[inline]
478    pub fn by_ref(&mut self) -> BufferRef<'_, T> {
479        BufferRef { inner: self.inner }
480    }
481}
482
483impl<'buffer, T> BufferRef<'buffer, T>
484where
485    T: Initialize,
486{
487    #[inline]
488    pub fn remaining(&self) -> usize {
489        self.inner.remaining()
490    }
491    #[inline]
492    pub fn unfilled_parts(&mut self) -> (&mut [T::Item], &mut [MaybeUninit<T::Item>]) {
493        self.inner.unfilled_parts_mut()
494    }
495    /// Get a mutable and possibly-uninitialized reference to all of the buffer.
496    ///
497    /// # Safety
498    ///
499    /// The caller must not allow safe code to de-initialize the resulting slice.
500    #[inline]
501    pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit<T::Item>] {
502        self.inner.unfilled_part_mut()
503    }
504    /// Advance the counter of the number of items filled.
505    ///
506    /// The number of items that are initialized is also updated accordingly, so that the number of
507    /// items initialized is always greater than or equal to the number of items filled.
508    ///
509    /// # Safety
510    ///
511    /// The caller must uphold the initialization invariant.
512    #[inline]
513    pub unsafe fn advance(&mut self, count: usize) {
514        self.inner.assume_init(count)
515    }
516    /// Advance the counter of the number of items filled, and the number of items initialized, to
517    /// the end of the buffer.
518    ///
519    /// # Safety
520    ///
521    /// The caller must uphold the initialization invariant.
522    #[inline]
523    pub unsafe fn advance_all(&mut self) {
524        self.inner.assume_init_all();
525    }
526    #[inline]
527    pub fn revert_to_start(&mut self) {
528        self.inner.revert_to_start()
529    }
530    #[inline]
531    pub fn fill_by_repeating(&mut self, item: T::Item)
532    where
533        T::Item: Copy,
534    {
535        self.inner.fill_by_repeating(item)
536    }
537    #[inline]
538    pub fn append(&mut self, slice: &[T::Item])
539    where
540        T::Item: Copy,
541    {
542        self.inner.append(slice)
543    }
544}
545impl<T> BufferRef<'_, T>
546where
547    T: Initialize<Item = u8>,
548{
549    #[inline]
550    pub fn fill_by_zeroing(&mut self) {
551        self.inner.fill_by_zeroing()
552    }
553}
554
555impl<T> fmt::Debug for Buffer<T>
556where
557    T: Initialize,
558{
559    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
560        let ptr = self.initializer().all_uninit().as_ptr();
561        let items_init = self.initializer().items_initialized();
562        let items_filled = self.items_filled();
563        let total = self.capacity();
564
565        if f.alternate() {
566            let init_percentage = items_init as f64 / total as f64 * 100.0;
567            let filled_percentage = items_filled as f64 / total as f64 * 100.0;
568            write!(
569                f,
570                "[buffer at {:?}, {} B filled ({:.1}%), {} B init ({:.1}%), {} B total]",
571                ptr, items_filled, filled_percentage, items_init, init_percentage, total
572            )
573        } else {
574            write!(
575                f,
576                "[buffer at {:?}, {}/{}/{}]",
577                ptr, items_filled, items_init, total
578            )
579        }
580    }
581}
582
583#[cfg(test)]
584mod tests {
585    use super::*;
586
587    #[test]
588    fn basic_buffer_ops() {
589        let mut buffer = Buffer::uninit([MaybeUninit::<u8>::uninit(); 32]);
590        assert_eq!(buffer.capacity(), 32);
591        assert_eq!(buffer.remaining(), 32);
592        assert!(buffer.is_empty());
593        assert!(!buffer.is_full());
594        assert!(buffer.initializer().is_completely_uninit());
595        assert!(!buffer.initializer().is_completely_init());
596        assert_eq!(buffer.initializer().items_initialized(), 0);
597        assert_eq!(buffer.initializer().remaining(), 32);
598        assert_eq!(buffer.filled_part(), &[]);
599        assert_eq!(buffer.unfilled_part().len(), 32);
600        assert_eq!(buffer.filled_part_mut(), &mut []);
601        assert_eq!(unsafe { buffer.unfilled_part_mut().len() }, 32);
602        // TODO: more
603
604        let BufferParts {
605            filled_part,
606            unfilled_init_part,
607            unfilled_uninit_part,
608        } = buffer.all_parts();
609        assert_eq!(filled_part, &[]);
610        assert_eq!(unfilled_init_part, &[]);
611        assert_eq!(unfilled_uninit_part.len(), 32);
612
613        let BufferPartsMut {
614            filled_part,
615            unfilled_init_part,
616            unfilled_uninit_part,
617        } = buffer.all_parts_mut();
618        assert_eq!(filled_part, &mut []);
619        assert_eq!(unfilled_init_part, &mut []);
620        assert_eq!(unfilled_uninit_part.len(), 32);
621
622        let src = b"I am a really nice slice!";
623        let modified = b"I am a really wise slice!";
624
625        buffer.append(src);
626
627        assert!(!buffer.is_empty());
628        assert!(!buffer.is_full());
629        assert_eq!(buffer.filled_part(), src);
630        assert_eq!(buffer.filled_part_mut(), src);
631        assert!(!buffer.initializer().is_completely_init());
632        assert!(!buffer.initializer().is_completely_uninit());
633        assert_eq!(buffer.initializer().init_part(), src);
634        assert_eq!(buffer.initializer_mut().init_part_mut(), src);
635        assert_eq!(buffer.items_filled(), src.len());
636        assert_eq!(buffer.remaining(), 32 - src.len());
637
638        {
639            let slice_mut = buffer.filled_part_mut();
640            slice_mut[14] = b'w';
641            slice_mut[16] = b's';
642        }
643
644        assert!(!buffer.is_empty());
645        assert!(!buffer.is_full());
646        assert_eq!(buffer.filled_part(), modified);
647        assert_eq!(buffer.filled_part_mut(), modified);
648        assert_eq!(buffer.initializer().init_part(), modified);
649        assert_eq!(buffer.initializer_mut().init_part_mut(), modified);
650        assert_eq!(buffer.items_filled(), src.len());
651        assert_eq!(buffer.remaining(), 32 - src.len());
652        assert_eq!(buffer.unfilled_part().len(), 32 - src.len());
653        assert_eq!(unsafe { buffer.unfilled_part_mut().len() }, 32 - src.len());
654
655        let mut initializer = buffer.into_initializer();
656
657        assert_eq!(initializer.items_initialized(), modified.len());
658        assert_eq!(initializer.remaining(), 7);
659        initializer.partially_fill_uninit_part(3_usize, 0xFF_u8);
660        initializer.partially_zero_uninit_part(1_usize);
661        assert_eq!(initializer.remaining(), 3);
662
663        let modified_and_garbage_items = b"I am a really wise slice!\xFF\xFF\xFF\x00";
664        let (init, uninit) = initializer.init_uninit_parts();
665        assert_eq!(init, modified_and_garbage_items);
666        assert_eq!(uninit.len(), 3);
667
668        let (init, uninit) = initializer.init_uninit_parts_mut();
669        assert_eq!(init, modified_and_garbage_items);
670        init[2] = b'e';
671        assert_eq!(uninit.len(), 3);
672
673        let mut buffer = Buffer::from_initializer(initializer);
674        buffer.advance(modified.len());
675
676        let BufferParts {
677            filled_part,
678            unfilled_init_part,
679            unfilled_uninit_part,
680        } = buffer.all_parts();
681        let modified_again = b"I em a really wise slice!";
682        assert_eq!(filled_part, modified_again);
683        assert_eq!(unfilled_init_part, b"\xFF\xFF\xFF\x00");
684        assert_eq!(unfilled_uninit_part.len(), 3);
685
686        let BufferPartsMut {
687            filled_part,
688            unfilled_init_part,
689            unfilled_uninit_part,
690        } = buffer.all_parts_mut();
691        assert_eq!(filled_part, modified_again);
692        assert_eq!(unfilled_init_part, b"\xFF\xFF\xFF\x00");
693        unfilled_init_part[2] = b'\x13';
694        unfilled_init_part[3] = b'\x37';
695        assert_eq!(unfilled_init_part, b"\xFF\xFF\x13\x37");
696        assert_eq!(unfilled_uninit_part.len(), 3);
697
698        let rest = b" Right?";
699        buffer.append(rest);
700
701        assert_eq!(buffer.items_filled(), 32);
702        assert!(!buffer.is_empty());
703        assert!(buffer.is_full());
704        assert_eq!(buffer.remaining(), 0);
705
706        let total = b"I em a really wise slice! Right?";
707        assert_eq!(buffer.filled_part(), total);
708        assert_eq!(buffer.filled_part_mut(), total);
709        assert_eq!(buffer.initializer().remaining(), 0);
710        assert_eq!(buffer.initializer().items_initialized(), 32);
711        assert!(buffer.initializer().is_completely_init());
712        assert!(!buffer.initializer().is_completely_uninit());
713
714        buffer.advance_to_init_part();
715
716        // TODO: Shorthand?
717        let initialized: [u8; 32] = buffer.into_initializer().try_into_init().unwrap().into();
718        assert_eq!(&initialized, total);
719    }
720    #[test]
721    fn debug_impl() {
722        let array = [MaybeUninit::<u8>::uninit(); 32];
723        let mut buffer = Buffer::uninit(array);
724        buffer.append(b"Hello, world!");
725        buffer.initializer_mut().partially_zero_uninit_part(13);
726
727        assert_eq!(
728            format!("{:?}", buffer),
729            format!(
730                "[buffer at {:p}, 13/26/32]",
731                buffer.initializer().all_uninit().as_ptr()
732            )
733        );
734        assert_eq!(
735            format!("{:#?}", buffer),
736            format!(
737                "[buffer at {:p}, 13 B filled (40.6%), 26 B init (81.2%), 32 B total]",
738                buffer.initializer().all_uninit().as_ptr()
739            )
740        );
741    }
742}