1- use core:: mem:: MaybeUninit ;
1+ use core:: mem:: { self , MaybeUninit } ;
22use core:: ptr;
33
4- /// Helper struct to build up an array element by element .
4+ /// An array of at most `N` elements .
55struct ArrayBuilder < T , const N : usize > {
6- arr : [ MaybeUninit < T > ; N ] , // Invariant: arr[..len] is initialized .
6+ arr : [ MaybeUninit < T > ; N ] , // Invariant: arr[..len] is valid .
77 len : usize , // Invariant: len <= N.
88}
99
1010impl < T , const N : usize > ArrayBuilder < T , N > {
11+ /// Initializes a new, empty `ArrayBuilder`.
1112 pub fn new ( ) -> Self {
13+ // SAFETY: the validity invariant trivially hold for a zero-length array.
1214 Self {
1315 arr : [ ( ) ; N ] . map ( |_| MaybeUninit :: uninit ( ) ) ,
1416 len : 0 ,
1517 }
1618 }
1719
20+ /// Pushes `value` onto the end of the array.
21+ ///
22+ /// # Panics
23+ ///
24+ /// This panics if `self.len() >= N`.
1825 pub fn push ( & mut self , value : T ) {
19- // We maintain the invariant here that arr[..len] is initialized .
26+ // SAFETY: we maintain the invariant here that arr[..len] is valid .
2027 // Indexing with self.len also ensures self.len < N, and thus <= N after
2128 // the increment.
2229 self . arr [ self . len ] = MaybeUninit :: new ( value) ;
2330 self . len += 1 ;
2431 }
2532
33+ /// Consumes the elements in the `ArrayBuilder` and returns them as an array `[T; N]`.
34+ ///
35+ /// If `self.len() < N`, this returns `None`.
2636 pub fn take ( & mut self ) -> Option < [ T ; N ] > {
2737 if self . len == N {
28- // Take the array, resetting the length back to zero.
29- let arr = core:: mem:: replace ( & mut self . arr , [ ( ) ; N ] . map ( |_| MaybeUninit :: uninit ( ) ) ) ;
38+ // Take the array, resetting our length back to zero.
3039 self . len = 0 ;
40+ let arr = mem:: replace ( & mut self . arr , [ ( ) ; N ] . map ( |_| MaybeUninit :: uninit ( ) ) ) ;
3141
32- // SAFETY: we had len == N, so all elements in arr are initialized .
42+ // SAFETY: we had len == N, so all elements in arr are valid .
3343 Some ( unsafe { arr. map ( |v| v. assume_init ( ) ) } )
3444 } else {
3545 None
@@ -40,10 +50,10 @@ impl<T, const N: usize> ArrayBuilder<T, N> {
4050impl < T , const N : usize > Drop for ArrayBuilder < T , N > {
4151 fn drop ( & mut self ) {
4252 unsafe {
43- // SAFETY: arr[..len] is initialized , so must be dropped.
44- // First we create a pointer to this initialized slice, then drop
45- // that slice in-place. The cast from *mut MaybeUninit<T> to *mut T
46- // is always sound by the layout guarantees of MaybeUninit.
53+ // SAFETY: arr[..len] is valid , so must be dropped. First we create
54+ // a pointer to this valid slice, then drop that slice in-place.
55+ // The cast from *mut MaybeUninit<T> to *mut T is always sound by
56+ // the layout guarantees of MaybeUninit.
4757 let ptr_to_first: * mut MaybeUninit < T > = self . arr . as_mut_ptr ( ) ;
4858 let ptr_to_slice = ptr:: slice_from_raw_parts_mut ( ptr_to_first. cast :: < T > ( ) , self . len ) ;
4959 ptr:: drop_in_place ( ptr_to_slice) ;
0 commit comments