uninit_tools/
initializer.rs

1use core::mem::MaybeUninit;
2
3use crate::traits::{Initialize, InitializeExt as _, InitializeVectored, TrustedDeref};
4use crate::wrappers::{AsUninit, AssertInit, AssertInitVectors, SingleVector};
5
6/// An initialized tracking a container type that dereferences into a slice of
7/// possibly-uninitialized items, and how many items have been initialized, respectively. The inner
8/// data can always be moved out as uninitialized, but when the buffer _has_ been fully
9/// initialized, the buffer can be turned into the initialized equivalent.
10// TODO: Is #[derive(Debug)] sound here?
11#[derive(Debug)]
12pub struct BufferInitializer<T> {
13    // This is the Buffer type, that wraps a _single_ buffer that is not guaranteed to be fully
14    // initialized when wrapped, but where the number of initialized items is tracked, so that it
15    // can still call naïve APIs that expected initialized buffers without overhead.
16    //
17    // The inner data, which must implement `Initialize` to do anything useful with points to a
18    // slice of possibly uninitialized items, and must always return the same slice in the trait
19    // (which is an unsafe trait implementation contract).
20    pub(crate) inner: T,
21    // Then we also have the initialization cursor, which marks the start of the uninitialized
22    // region. This is unrelated to the number of items filled into the buffer, but it must always
23    // be greater than or equal that.
24    //
25    // If this buffer is constructed from an already initialized slice, then this will be set to
26    // the total capacity of the buffer. This cursor can never be decreased, and it must be less
27    // than or equal to the total capacity.
28    //
29    // This allows dividing the buffer into an initialized region, and an uninitialized region.
30    pub(crate) items_initialized: usize,
31    // NOTE: If any of these contracts are broken inside the struct, expect UB. The
32    // _`debug_assert_valid_len`_ method will check this everywhere when debug assertions are
33    // enabled.
34}
35
36impl<T> BufferInitializer<T> {
37    /// Wrap a possibly-uninitialized buffer into the initializer, with the current initialization
38    /// cursor set to zero.
39    #[inline]
40    pub const fn uninit(inner: T) -> Self {
41        Self {
42            inner,
43            items_initialized: 0,
44        }
45    }
46
47    #[inline]
48    pub fn into_inner(self) -> T {
49        self.inner
50    }
51
52    #[inline]
53    pub const fn items_initialized(&self) -> usize {
54        self.items_initialized
55    }
56}
57impl<T, Item> BufferInitializer<AsUninit<T>>
58where
59    T: core::ops::Deref<Target = [Item]> + core::ops::DerefMut + TrustedDeref,
60{
61    /// Construct an initializer to a container that is already initialized. This ensures that no
62    /// bytes will be filled with zeroes, as they do not have to.
63    pub fn new(init: T) -> Self {
64        let mut this = Self::uninit(AsUninit(init));
65        // SAFETY: AsUninit wrapper ensures the type was already initialized.
66        unsafe {
67            this.advance_to_end();
68        }
69        this
70    }
71}
72impl<T> BufferInitializer<T>
73where
74    T: Initialize,
75{
76    pub(crate) fn debug_assert_validity(&self) {
77        debug_assert!(self.items_initialized <= self.capacity());
78    }
79
80    /// Advance the initialization counter by `count` items.
81    ///
82    /// # Safety
83    ///
84    /// For this to be safe, the caller must be sure that another `count` items from the previous
85    /// initialization offset, are initialized.
86    ///
87    /// This method does not do any bounds checking. Ergo, `count` can never be larger than
88    /// the value returned by [`remaining`](Self::remaining).
89    #[inline]
90    pub unsafe fn advance(&mut self, count: usize) {
91        self.items_initialized += count;
92    }
93    /// Advance the initialization counter to the end.
94    ///
95    /// # Safety
96    ///
97    /// While this eliminates the need for the caller to bounds check manually, unlike with
98    /// [`advance`](Self::advance), the caller must uphold the initialization invariant.
99    #[inline]
100    pub unsafe fn advance_to_end(&mut self) {
101        self.items_initialized = self.all_uninit().len();
102    }
103
104    /// Assume that the inner value is fully initialized, finalizing the original type into its
105    /// initialized counterpart.
106    ///
107    /// # Safety
108    ///
109    /// The caller must uphold the initialization invariant.
110    #[inline]
111    pub unsafe fn assume_init(self) -> AssertInit<T> {
112        self.inner.assume_init()
113    }
114
115    #[inline]
116    pub fn into_raw_parts(self) -> (T, usize) {
117        let Self {
118            inner,
119            items_initialized,
120        } = self;
121        (inner, items_initialized)
122    }
123
124    /// Retrieve a slice of a possibly uninitialized items, over the entire buffer.
125    #[inline]
126    pub fn all_uninit(&self) -> &[MaybeUninit<T::Item>] {
127        self.inner.as_maybe_uninit_slice()
128    }
129    /// Retrieve a mutable slice of a possibly uninitialized items, over the entire buffer.
130    ///
131    /// # Safety
132    ///
133    /// This is unsafe, because the caller must not de-initialize the slice as the API also
134    /// promises the initialized region to always actually be initialized.
135    #[inline]
136    pub unsafe fn all_uninit_mut(&mut self) -> &mut [MaybeUninit<T::Item>] {
137        self.inner.as_maybe_uninit_slice_mut()
138    }
139    /// Get the total size of the buffer that is being initialized.
140    #[inline]
141    pub fn capacity(&self) -> usize {
142        self.all_uninit().len()
143    }
144    /// Get the number of items that must be filled before the buffer gets fully initialized, and
145    /// can be turned into an initialized type (e.g. `Box<[U]>`).
146    #[inline]
147    pub fn remaining(&self) -> usize {
148        debug_assert!(self.capacity() >= self.items_initialized);
149        self.capacity().wrapping_sub(self.items_initialized)
150    }
151    /// Check whether the buffer is completely initialized. Note that this is unrelated to it being
152    /// filled.
153    #[inline]
154    pub fn is_completely_init(&self) -> bool {
155        self.items_initialized() == self.capacity()
156    }
157    /// Check whether no single item of the buffer has been initialized.
158    #[inline]
159    pub fn is_completely_uninit(&self) -> bool {
160        self.items_initialized() == 0
161    }
162    /// Retrieve a shared reference to the uninitialized part of the buffer. This is only included
163    /// for completeness, since apart from some corner cases where one does not have exclusive
164    /// access to the buffer but still wants to initialize it, is rather useless.
165    #[inline]
166    pub fn uninit_part(&self) -> &[MaybeUninit<T::Item>] {
167        let all = self.all_uninit();
168
169        // Validate that items_filled is valid, when _debug assertions_ are enabled.
170        self.debug_assert_validity();
171
172        // NOTE: We use unsafe to eliminate unnecessary bounds checking. This may be negligible for
173        // many scenarios, but we want to keep this interface zero-cost.
174        unsafe {
175            // SAFETY: We uphold the safety invariants:
176            //
177            // 1) the pointer belongs to the same allocated object, since we are simply taking a
178            //    subslice of an existing slice;
179            // 2) the offset multiplied by the item size cannot overflow an isize. This is
180            //    impossible, since while the size of U may be larget 1, the wrapper can never be
181            //    constructed, if the total size would exceed isize::MAX;
182            // 3) the resulting pointer cannot overflow the pointer size. This is also impossible,
183            //    since for `all` to be a valid slice, it must not wrap around in address space,
184            //    between its start and end range.
185            let ptr = all.as_ptr().add(self.items_initialized);
186            let len = all.len().wrapping_sub(self.items_initialized);
187
188            // SAFETY: This is safe, because:
189            //
190            // 1) the data is valid for the entire memory range, since we are taking a subset of an
191            //    already well-defined slice. Everything is therefore contained within a single
192            //    allocation object, and the pointer is already non-null, since the pointer
193            //    addition must not overflow;
194            // 2) while no item whatsoever in [items_filled, len) is guaranteed to be initialized,
195            //    MaybeUninit is special and is always considered initialized (even though the
196            //    value it wraps has no such guarantee);
197            // 3) the value is not mutated for the lifetime of the slice, since the slice is owned
198            //    by this struct, and there cannot exist a mutable borrow within this borrow for
199            //    the anonymous lifetime `'_`;
200            // 4) the number of items filled is not larger than isize::MAX. This is checked every
201            //    time items_filled changes.
202            core::slice::from_raw_parts(ptr, len)
203        }
204    }
205    /// Retrieve a shared slice to the initialized part of the buffer. Note that this is different
206    /// from the _filled_ part, as a buffer can be fully initialized but not filled.
207    #[inline]
208    pub fn init_part(&self) -> &[T::Item] {
209        // Validate that items_filled is valid, when _debug assertions_ are enabled.
210        self.debug_assert_validity();
211
212        // NOTE: Use of unsafe is only to eliminate bounds checks and maintain zero-cost.
213        unsafe {
214            let ptr = self.all_uninit().as_ptr();
215            let len = self.items_initialized;
216
217            // SAFETY: This is safe, due to the same invariants as with `uninit_part`, except for
218            // the initialization invariant. We uphold this, by guaranteeing that the entire slice
219            // we construct, is initialized, since this is a contract merely from using this
220            // wrapper. We also uphold the validity variant, which is somewhat different in this
221            // case, since we know that items_filled must be smaller than or equal to the size of
222            // the slice.
223            core::slice::from_raw_parts(ptr as *const T::Item, len)
224        }
225    }
226
227    /// Get a mutable slice to the uninitialized part of the buffer. Note that this is different
228    /// from the unfilled part of it.
229    #[inline]
230    pub fn uninit_part_mut(&mut self) -> &mut [MaybeUninit<T::Item>] {
231        // NOTE: We extract pointers to avoid multiple mutable aliases when invoking
232        // core::slice::from_raw_parts_mut.
233        let (orig_ptr, orig_len) = unsafe {
234            let orig = self.all_uninit_mut();
235            (orig.as_mut_ptr(), orig.len())
236        };
237        unsafe {
238            // Validate that items_filled is correct when debug assertions are enabled.
239            self.debug_assert_validity();
240
241            // SAFETY: This pointer arithmetic operation, is safe for the same reasons as with
242            // `uninit_part`.
243            let ptr = orig_ptr.add(self.items_initialized);
244            let len = orig_len.wrapping_sub(self.items_initialized);
245
246            // SAFETY: This is safe for the exact same reasons as with `uninit_part`, but that
247            // there must not be any reference _at all_ to the inner slice. This is upheld by
248            // knowing that we have already borrowed the owner of the slice mutably.
249            core::slice::from_raw_parts_mut(ptr, len)
250        }
251    }
252
253    /// Retrieve a mutable slice to the initialized part of the buffer. Note that this is not the
254    /// same as the filled part.
255    #[inline]
256    pub fn init_part_mut(&mut self) -> &mut [T::Item] {
257        let orig_ptr = unsafe { self.all_uninit_mut().as_mut_ptr() };
258
259        unsafe {
260            let ptr = orig_ptr;
261            let len = self.items_initialized;
262
263            // SAFETY: This is safe for the exact same reasons as with `init_part`, except that we
264            // also ensure that there is no access whatsoever to the inner data, since we are
265            // borrowing `self` mutably.
266            core::slice::from_raw_parts_mut(ptr as *mut T::Item, len)
267        }
268    }
269    /// Try to transform the initializing type, into its initialized counterpart, provided that the
270    /// it has been fully initialized.
271    #[inline]
272    pub fn try_into_init(self) -> Result<AssertInit<T>, Self> {
273        if self.is_completely_init() {
274            Ok(unsafe { self.assume_init() })
275        } else {
276            Err(self)
277        }
278    }
279    /// Finish the initialization by writing `item` to the uninitialized region, and then get the
280    /// final initialized type.
281    pub fn finish_init_by_filling(mut self, item: T::Item) -> AssertInit<T>
282    where
283        T::Item: Copy,
284    {
285        self.fill_uninit_part(item);
286        unsafe { self.assume_init() }
287    }
288    /// Fill the uninitialized part with copies of `item` (memset).
289    ///
290    /// After this method has been called, it is safe to [`assume_init`]. [`try_into_init`] will
291    /// then also succeed.
292    ///
293    /// [`assume_init`]: #method.assume_init
294    /// [`try_into_init`]: #method.try_into_init
295    #[inline]
296    pub fn fill_uninit_part(&mut self, item: T::Item)
297    where
298        T::Item: Copy,
299    {
300        crate::fill_uninit_slice(self.uninit_part_mut(), item);
301        unsafe {
302            self.advance_to_end();
303        }
304    }
305    #[inline]
306    pub fn partially_fill_uninit_part(&mut self, count: usize, item: T::Item)
307    where
308        T::Item: Copy,
309    {
310        crate::fill_uninit_slice(&mut self.uninit_part_mut()[..count], item);
311        // SAFETY: The slice indexing will already bounds check.
312        unsafe { self.advance(count) }
313    }
314    /// Get both the initialized and uninitialized parts simultaneously. This method is nothing but
315    /// a shorthand for the individual methods, but included for completeness.
316    ///
317    /// This is because the mutable counterpart [`init_uninit_parts_mut`] cannot be done separately
318    /// by calling the [`init_part_mut`] and [`uninit_part_mut`] methods.
319    ///
320    /// [`init_part_mut`]: #method.init_part_mut
321    /// [`uninit_part_mut`]: #method.uninit_part_mut
322    /// [`init_uninit_parts_mut`]: #method.init_uninit_parts_mut
323    #[inline]
324    pub fn init_uninit_parts(&self) -> (&[T::Item], &[MaybeUninit<T::Item>]) {
325        (self.init_part(), self.uninit_part())
326    }
327    /// Borrow both the initialized as well as the uninitialized parts, mutably.
328    #[inline]
329    pub fn init_uninit_parts_mut(&mut self) -> (&mut [T::Item], &mut [MaybeUninit<T::Item>]) {
330        let (all_ptr, all_len) = unsafe {
331            let all = self.all_uninit_mut();
332
333            (all.as_mut_ptr(), all.len())
334        };
335
336        unsafe {
337            self.debug_assert_validity();
338
339            let init_base_ptr = all_ptr as *mut T::Item;
340            let init_len = self.items_initialized;
341
342            let uninit_base_ptr = all_ptr.add(self.items_initialized);
343            let uninit_len = all_len.wrapping_sub(self.items_initialized);
344
345            let init = core::slice::from_raw_parts_mut(init_base_ptr, init_len);
346            let uninit = core::slice::from_raw_parts_mut(uninit_base_ptr, uninit_len);
347
348            (init, uninit)
349        }
350    }
351}
352impl<T> BufferInitializer<T>
353where
354    // TODO: Other zeroable types than u8. Perhaps num-traits, or just a macro for all the
355    // primitive integers?
356    T: Initialize<Item = u8>,
357{
358    /// Finish the initialization by zeroing uninitialized region, and then get the final
359    /// initialized type.
360    pub fn finish_init_by_zeroing(self) -> AssertInit<T> {
361        self.finish_init_by_filling(0_u8)
362    }
363    #[inline]
364    pub fn partially_zero_uninit_part(&mut self, count: usize) {
365        crate::fill_uninit_slice(&mut self.uninit_part_mut()[..count], 0_u8);
366        // SAFETY: The slice indexing will already bounds check.
367        unsafe { self.advance(count) }
368    }
369    /// Zero the uninitialized part.
370    ///
371    /// After this method has been called, it is safe to [`assume_init`]. [`try_into_init`] will
372    /// then also succeed.
373    ///
374    /// [`assume_init`]: #method.assume_init
375    /// [`try_into_init`]: #method.try_into_init
376    #[inline]
377    pub fn zero_uninit_part(&mut self) {
378        self.fill_uninit_part(0_u8);
379        unsafe { self.advance_to_end() }
380    }
381}
382
383pub struct BuffersInitializer<T> {
384    // The inner buffer. At the moment there is no type-level restriction that it has to implement
385    // InitializeVectored for BuffersInitializer to be able to wrap it (to allow for const fn), but
386    // that may change in a future release.
387    pub(crate) inner: T,
388
389    // A cursor marking the number of _vectors_ that have been fully initialized. Once
390    // `items_initialized_for_vector` approaches the length of the vector indexed by this field,
391    // this index will increment, and `items_initialized_for_vector` will reset to zero. Vectors
392    // with length zero are skipped entirely.
393    pub(crate) vectors_initialized: usize,
394    pub(crate) items_initialized_for_vector: usize,
395}
396
397impl<T> BuffersInitializer<T> {
398    #[inline]
399    pub const fn uninit(inner: T) -> Self {
400        Self {
401            inner,
402            vectors_initialized: 0,
403            items_initialized_for_vector: 0,
404        }
405    }
406    #[inline]
407    pub fn into_raw_parts(self) -> (T, usize, usize) {
408        let Self {
409            inner,
410            vectors_initialized,
411            items_initialized_for_vector,
412        } = self;
413
414        (inner, vectors_initialized, items_initialized_for_vector)
415    }
416    #[inline]
417    pub fn into_inner(self) -> T {
418        let (inner, _, _) = self.into_raw_parts();
419
420        inner
421    }
422}
423impl<T> BuffersInitializer<SingleVector<T>> {
424    pub fn from_single_buffer_initializer(single: BufferInitializer<T>) -> Self {
425        let BufferInitializer {
426            items_initialized,
427            inner,
428        } = single;
429
430        Self {
431            items_initialized_for_vector: items_initialized,
432            vectors_initialized: 0,
433            inner: SingleVector(inner),
434        }
435    }
436}
437
438impl<T, Item> BuffersInitializer<T>
439where
440    T: InitializeVectored,
441    T::UninitVector: Initialize<Item = Item>,
442{
443    #[inline]
444    fn all_vectors_uninit(&self) -> &[T::UninitVector] {
445        self.inner.as_maybe_uninit_vectors()
446    }
447
448    /// Retrieve the current buffer immutably, provided that there is one.
449    #[inline]
450    pub fn current_vector_all(&self) -> Option<&[MaybeUninit<Item>]> {
451        self.debug_assert_validity();
452
453        let vectors_initialized = self.vectors_initialized;
454
455        if vectors_initialized != self.total_vector_count() {
456            Some(unsafe {
457                self.all_vectors_uninit()
458                    .get_unchecked(vectors_initialized)
459                    .as_maybe_uninit_slice()
460            })
461        } else {
462            None
463        }
464    }
465    /// Retrieve the current buffer mutably, provided that there is one.
466    ///
467    /// # Safety
468    ///
469    /// This is unsafe because the caller must not de-initialize the buffer.
470    #[inline]
471    pub unsafe fn current_vector_all_mut(&mut self) -> Option<&mut [MaybeUninit<Item>]> {
472        self.debug_assert_validity();
473
474        let vectors_initialized = self.vectors_initialized;
475
476        if vectors_initialized != self.total_vector_count() {
477            let all_vectors_uninit_mut = self.all_uninit_vectors_mut();
478            let current_vector_uninit_mut =
479                all_vectors_uninit_mut.get_unchecked_mut(vectors_initialized);
480            Some(current_vector_uninit_mut.as_maybe_uninit_slice_mut())
481        } else {
482            None
483        }
484    }
485
486    #[inline]
487    pub fn current_vector_init_part(&self) -> Option<&[Item]> {
488        let (init_part, _) = self.current_vector_init_uninit_parts()?;
489
490        Some(init_part)
491    }
492
493    #[inline]
494    pub fn current_vector_uninit_part(&self) -> Option<&[MaybeUninit<Item>]> {
495        let (_, uninit_part) = self.current_vector_init_uninit_parts()?;
496
497        Some(uninit_part)
498    }
499    #[inline]
500    pub fn current_vector_init_uninit_parts(&self) -> Option<(&[Item], &[MaybeUninit<Item>])> {
501        let vector = self.current_vector_all()?;
502
503        Some(unsafe {
504            let init_vector_base_ptr = vector.as_ptr() as *const Item;
505            let init_vector_len = self.items_initialized_for_vector;
506
507            let init_vector = core::slice::from_raw_parts(init_vector_base_ptr, init_vector_len);
508
509            let uninit_vector_base_ptr = vector.as_ptr().add(self.items_initialized_for_vector);
510            let uninit_vector_len = vector.len().wrapping_sub(self.items_initialized_for_vector);
511
512            let uninit_vector =
513                core::slice::from_raw_parts(uninit_vector_base_ptr, uninit_vector_len);
514
515            (init_vector, uninit_vector)
516        })
517    }
518
519    #[inline]
520    pub fn current_vector_init_part_mut(&mut self) -> Option<&mut [Item]> {
521        let (init_part_mut, _) = self.current_vector_init_uninit_parts_mut()?;
522
523        Some(init_part_mut)
524    }
525
526    #[inline]
527    pub fn current_vector_uninit_part_mut(&mut self) -> Option<&mut [MaybeUninit<Item>]> {
528        let (_, uninit_part_mut) = self.current_vector_init_uninit_parts_mut()?;
529
530        Some(uninit_part_mut)
531    }
532    #[inline]
533    pub fn current_vector_init_uninit_parts_mut(
534        &mut self,
535    ) -> Option<(&mut [Item], &mut [MaybeUninit<Item>])> {
536        let (orig_base_ptr, orig_len) = unsafe {
537            let vector = self.current_vector_all_mut()?;
538
539            (vector.as_mut_ptr(), vector.len())
540        };
541        Some(unsafe {
542            let init_vector_base_ptr = orig_base_ptr as *mut Item;
543            let init_vector_len = self.items_initialized_for_vector;
544
545            let init_vector =
546                core::slice::from_raw_parts_mut(init_vector_base_ptr, init_vector_len);
547
548            let uninit_vector_base_ptr = orig_base_ptr.add(self.items_initialized_for_vector);
549            let uninit_vector_len = orig_len.wrapping_sub(self.items_initialized_for_vector);
550
551            let uninit_vector =
552                core::slice::from_raw_parts_mut(uninit_vector_base_ptr, uninit_vector_len);
553
554            (init_vector, uninit_vector)
555        })
556    }
557
558    fn debug_assert_validity(&self) {
559        debug_assert!(self
560            .inner
561            .as_maybe_uninit_vectors()
562            .get(self.vectors_initialized)
563            .map_or(true, |current_vector| current_vector
564                .as_maybe_uninit_slice()
565                .len()
566                >= self.items_initialized_for_vector));
567        debug_assert!(self.items_initialized_for_vector <= isize::MAX as usize);
568        debug_assert!(self.inner.as_maybe_uninit_vectors().len() >= self.vectors_initialized);
569    }
570
571    /// Get the total number of vectors, since the wrapper was constructed.
572    #[inline]
573    pub fn total_vector_count(&self) -> usize {
574        self.inner.as_maybe_uninit_vectors().len()
575    }
576
577    /// Get the number of vectors that are currently filled and completely initialized.
578    #[inline]
579    pub fn vectors_initialized(&self) -> usize {
580        self.vectors_initialized
581    }
582
583    /// Get the number of vectors remaining, possibly including the vector that is currently
584    /// initializing.
585    #[inline]
586    pub fn vectors_remaining(&self) -> usize {
587        self.total_vector_count()
588            .wrapping_sub(self.vectors_initialized())
589    }
590
591    /// Counts the items that must be filled before the whole buffer is initialized.
592    ///
593    /// Note that this can be expensive if there are many buffers; it is O(n), where `n` is the
594    /// number of vectors that have not yet been initialized. If all vectors are already filled,
595    /// then this completes in constant time.
596    pub fn count_items_to_initialize(&self) -> usize {
597        let items_to_initialize_for_remaining = self
598            .all_uninit_vectors()
599            .iter()
600            .skip(self.vectors_initialized + 1_usize)
601            .map(|buffer| buffer.as_maybe_uninit_slice().len())
602            .sum::<usize>();
603
604        self.items_initialized_for_vector + items_to_initialize_for_remaining
605    }
606    pub fn count_total_items_in_all_vectors(&self) -> usize {
607        self.all_uninit_vectors()
608            .iter()
609            .map(|buffer| buffer.as_maybe_uninit_slice().len())
610            .sum()
611    }
612
613    /// Get the number of items that have been initialized for the vector at the given index.
614    ///
615    /// For vectors that has not yet been advanced to, this will zero, while vectors that are
616    /// already initialized will return the full length of that vector. The currently initializing
617    /// vector will return the partial length of the items within that vector that have been
618    /// initialized.
619    ///
620    /// # Safety
621    ///
622    /// The caller must ensure that vector_index is within the bounds of the slice of vectors given
623    /// by the inner wrapped value.
624    #[inline]
625    pub unsafe fn items_initialized_for_vector_unchecked(&self, vector_index: usize) -> usize {
626        let ordering = vector_index.cmp(&self.vectors_initialized);
627
628        match ordering {
629            core::cmp::Ordering::Equal => self.items_initialized_for_vector,
630            core::cmp::Ordering::Greater => 0,
631            core::cmp::Ordering::Less => self
632                .all_uninit_vectors()
633                .get_unchecked(vector_index)
634                .as_maybe_uninit_slice()
635                .len(),
636        }
637    }
638    #[inline]
639    pub fn items_initialized_for_vector(&self, vector_index: usize) -> usize {
640        assert!(vector_index < self.total_vector_count());
641
642        unsafe { self.items_initialized_for_vector_unchecked(vector_index) }
643    }
644    #[inline]
645    pub fn items_initialized_for_current_vector(&self) -> usize {
646        if self.vectors_initialized() != self.total_vector_count() {
647            self.items_initialized_for_vector
648        } else {
649            0
650        }
651    }
652
653    /// Get the uninitialized version of all vectors wrapped by this initializer.
654    #[inline]
655    pub fn all_uninit_vectors(&self) -> &[T::UninitVector] {
656        self.inner.as_maybe_uninit_vectors()
657    }
658    /// Get the uninitialized version of all vectors wrapped by this initializer, mutably.
659    ///
660    /// # Safety
661    ///
662    /// The caller must not de-initialize any values.
663    #[inline]
664    pub unsafe fn all_uninit_vectors_mut(&mut self) -> &mut [T::UninitVector] {
665        self.inner.as_maybe_uninit_vectors_mut()
666    }
667    /// Advance the initialization cursor by `count` items, counting the number of items that were
668    /// advanced. The `count` input may be higher than the total number of items in the buffer,
669    /// without panics or UB.
670    ///
671    /// # Safety
672    ///
673    /// For this to be safe, then `count` items in the vectors ranging from the current vector, to
674    /// subsequent vectors, must be initialized.
675    ///
676    /// Additionally, `count` must never overflow `isize::MAX`, but it may be larger than the total
677    /// number of items in the vectors (to avoid having to count them in the beginning, for
678    /// performance purposes).
679    #[inline]
680    pub unsafe fn advance(&mut self, mut count: usize) -> usize {
681        let mut items_advanced = 0;
682
683        while let Some(current_uninit_part) = self.current_vector_uninit_part() {
684            let current_uninit_part_len = current_uninit_part.len();
685
686            if count >= current_uninit_part_len {
687                self.vectors_initialized = self
688                    .vectors_initialized
689                    .checked_add(1)
690                    .expect("reached usize::MAX when incrementing the buffer index");
691                self.items_initialized_for_vector = 0;
692
693                count -= current_uninit_part_len;
694
695                items_advanced -= current_uninit_part_len;
696                continue;
697            } else {
698                self.items_initialized_for_vector += current_uninit_part_len;
699            }
700        }
701
702        items_advanced
703    }
704    /// Advance the initialization progress to the end of the current vector, thus wrapping and
705    /// continuing to the next
706    ///
707    /// # Safety
708    ///
709    /// This is unsafe not only because of the initialization invariant, but also because it does
710    /// not check whether the _initialized vectors_ counter is at the end (meaning that all vectors
711    /// are initialized). The caller must hence ensure that the value of [`vectors_remaining`] is
712    /// larger than zero.
713    ///
714    /// [`vectors_remaining`]: #method.vectors_remaining
715    pub unsafe fn advance_current_vector_to_end(&mut self) {
716        self.debug_assert_validity();
717
718        self.vectors_initialized += 1;
719        self.items_initialized_for_vector = 0;
720    }
721    pub unsafe fn advance_current_vector(&mut self, count: usize) {
722        self.debug_assert_validity();
723
724        if let Some(current_vector) = self.current_vector_all() {
725            let current_vector_len = current_vector.len();
726            let end = self.items_initialized_for_vector + count;
727
728            assert!(end <= current_vector_len);
729
730            if end == current_vector_len {
731                self.vectors_initialized += 1;
732                self.items_initialized_for_vector = 0;
733            } else {
734                self.items_initialized_for_vector = end;
735            }
736        } else if count > 0 {
737            panic!("cannot advance beyond the end of the current vector")
738        }
739    }
740    pub fn partially_fill_current_vector_uninit_part(&mut self, count: usize, item: Item)
741    where
742        Item: Copy,
743    {
744        if let Some(current_vector_uninit_part_mut) = self.current_vector_uninit_part_mut() {
745            crate::fill_uninit_slice(&mut current_vector_uninit_part_mut[..count], item);
746            unsafe { self.advance_current_vector(count) }
747        } else if count > 0 {
748            panic!("cannot partially fill a vector when none are left");
749        }
750    }
751    pub fn fill_current_vector_uninit_part(&mut self, item: Item)
752    where
753        Item: Copy,
754    {
755        if let Some(current_vector_uninit_part_mut) = self.current_vector_uninit_part_mut() {
756            crate::fill_uninit_slice(current_vector_uninit_part_mut, item);
757            unsafe { self.advance_current_vector_to_end() }
758        }
759    }
760    pub fn try_into_init(self) -> Result<AssertInitVectors<T>, Self> {
761        if self.vectors_remaining() == 0 {
762            Ok(unsafe { AssertInitVectors::new_unchecked(self.into_inner()) })
763        } else {
764            Err(self)
765        }
766    }
767}
768impl<T> BuffersInitializer<T>
769where
770    T: InitializeVectored,
771    // TODO: Again, additional zeroable types.
772    T::UninitVector: Initialize<Item = u8>,
773{
774    pub fn partially_zero_current_vector_uninit_part(&mut self, count: usize) {
775        self.partially_fill_current_vector_uninit_part(count, 0_u8)
776    }
777    pub fn zero_current_vector_uninit_part(&mut self) {
778        self.fill_current_vector_uninit_part(0_u8)
779    }
780}
781
782#[cfg(test)]
783mod tests {
784    use super::*;
785
786    mod single {
787        use super::*;
788
789        #[test]
790        fn new_fills_completely() {
791            let slice = *b"Calling BufferInitializer::new() will ensure that the initialization marker is put at the end of the slice, making it fully zero-cost when already using initialized memory.";
792            let mut copy = slice;
793
794            let mut initializer = BufferInitializer::new(&mut copy[..]);
795
796            assert_eq!(initializer.remaining(), 0);
797            assert_eq!(initializer.capacity(), slice.len());
798            assert!(initializer.is_completely_init());
799            assert!(!initializer.is_completely_uninit());
800            assert!(initializer.uninit_part().is_empty());
801            assert!(initializer.uninit_part_mut().is_empty());
802            assert_eq!(initializer.init_part(), slice);
803            assert_eq!(initializer.init_part_mut(), slice);
804            assert!(initializer.try_into_init().is_ok());
805        }
806
807        #[test]
808        fn basic_initialization() {
809            let mut slice = [MaybeUninit::uninit(); 32];
810            let buffer = BufferInitializer::uninit(&mut slice[..]);
811            let initialized = buffer.finish_init_by_filling(42_u8);
812            assert!(initialized.iter().all(|&byte| byte == 42_u8));
813        }
814        #[test]
815        fn buffer_parts() {
816            let mut slice = [MaybeUninit::<u8>::uninit(); 32];
817            let mut buffer = BufferInitializer::uninit(&mut slice[..]);
818
819            assert_eq!(buffer.uninit_part().len(), 32);
820            assert_eq!(buffer.uninit_part_mut().len(), 32);
821            assert_eq!(buffer.init_part(), &[]);
822            assert_eq!(buffer.init_part_mut(), &mut []);
823            assert!(!buffer.is_completely_init());
824
825            // TODO: Fill partially, and then check further.
826        }
827    }
828    mod vectored {
829        use super::*;
830
831        #[test]
832        fn fill_uninit_part() {
833            let mut first = [MaybeUninit::uninit(); 32];
834            let mut second = [MaybeUninit::uninit(); 128];
835            let mut third = [MaybeUninit::uninit(); 64];
836
837            let mut vectors = [&mut first[..], &mut second[..], &mut third[..]];
838            let mut initializer = BuffersInitializer::uninit(&mut vectors[..]);
839
840            initializer.zero_current_vector_uninit_part();
841            assert_eq!(initializer.vectors_initialized(), 1);
842            assert_eq!(initializer.items_initialized_for_current_vector(), 0);
843
844            initializer.partially_zero_current_vector_uninit_part(96);
845            assert_eq!(initializer.vectors_initialized(), 1);
846            assert_eq!(initializer.items_initialized_for_current_vector(), 96);
847
848            initializer.partially_fill_current_vector_uninit_part(32, 0x13_u8);
849            assert_eq!(initializer.vectors_initialized(), 2);
850            assert_eq!(initializer.items_initialized_for_current_vector(), 0);
851
852            initializer.partially_fill_current_vector_uninit_part(16, 0x37_u8);
853            assert_eq!(initializer.vectors_initialized(), 2);
854            assert_eq!(initializer.items_initialized_for_current_vector(), 16);
855            initializer.fill_current_vector_uninit_part(0x42);
856            assert_eq!(initializer.vectors_initialized(), 3);
857            assert!(initializer.current_vector_all().is_none());
858        }
859    }
860}