66//!
77//! SPDX-License-Identifier: Apache-2.0
88//!
9- use core:: { cell:: Cell , mem, ptr:: NonNull , slice} ;
9+ use core:: { cell:: Cell , mem, mem :: MaybeUninit , ptr:: NonNull , slice} ;
1010
1111use crate :: { Error , Result , SliceKey } ;
1212
4949 }
5050 }
5151
52- /// Create a new storage container with a slice of memory.
53- pub fn with_capacity ( slice : & ' a mut [ u8 ] ) -> Storage < ' a , D > {
54- let storage = Storage {
55- // SAFETY: This is reinterpreting a byte slice as a Node<D> slice.
56- // 1. The alignment is checked implicitly by the slice bounds.
57- // 2. The correct number of Node<D> elements that fit in the byte slice is calculated.
58- // 3. The lifetime ensures the byte slice remains valid for the storage's lifetime
59- data : unsafe {
60- slice:: from_raw_parts_mut :: < ' a , Node < D > > (
61- slice as * mut [ u8 ] as * mut Node < D > ,
62- slice. len ( ) / mem:: size_of :: < Node < D > > ( ) ,
63- )
64- } ,
65- length : 0 ,
66- available : Cell :: default ( ) ,
67- } ;
68-
69- Self :: build_linked_list ( storage. data ) ;
70- storage. available . set ( storage. data [ 0 ] . as_mut_ptr ( ) ) ;
71- storage
72- }
73-
7452 fn build_linked_list ( buffer : & [ Node < D > ] ) {
7553 let mut node = & buffer[ 0 ] ;
7654 for next in buffer. iter ( ) . skip ( 1 ) {
@@ -176,8 +154,55 @@ where
176154
177155impl < ' a , D > Storage < ' a , D >
178156where
179- D : SliceKey + Copy ,
157+ D : SliceKey + Copy + Default ,
180158{
159+ /// Create a new storage container with a slice of memory.
160+ ///
161+ /// # Trait Requirements
162+ ///
163+ /// This method requires `D: Default` to initialize nodes. If your type
164+ /// doesn't implement Default, you cannot use with_capacity.
165+ pub fn with_capacity ( slice : & ' a mut [ u8 ] ) -> Storage < ' a , D > {
166+ // SAFETY: This is reinterpreting a byte slice as a MaybeUninit<Node<D>> slice.
167+ // Using MaybeUninit explicitly represents uninitialized memory and avoids undefined
168+ // behavior from creating references to uninitialized Node<D>.
169+ let uninit_buffer = unsafe {
170+ slice:: from_raw_parts_mut :: < ' a , MaybeUninit < Node < D > > > (
171+ slice as * mut [ u8 ] as * mut MaybeUninit < Node < D > > ,
172+ slice. len ( ) / mem:: size_of :: < Node < D > > ( ) ,
173+ )
174+ } ;
175+
176+ // Initialize all nodes with Default values
177+ for elem in uninit_buffer. iter_mut ( ) {
178+ // SAFETY: We're initializing uninitialized memory using MaybeUninit::write,
179+ // which is the safe way to initialize MaybeUninit without reading the old value.
180+ elem. write ( Node :: new ( D :: default ( ) ) ) ;
181+ }
182+
183+ // SAFETY: All elements have been initialized in the loop above.
184+ // We can now safely convert from MaybeUninit<Node<D>> to Node<D>.
185+ let buffer = unsafe {
186+ slice:: from_raw_parts_mut (
187+ uninit_buffer. as_mut_ptr ( ) as * mut Node < D > ,
188+ uninit_buffer. len ( )
189+ )
190+ } ;
191+
192+ let storage = Storage {
193+ data : buffer,
194+ length : 0 ,
195+ available : Cell :: default ( ) ,
196+ } ;
197+
198+ if !storage. data . is_empty ( ) {
199+ Self :: build_linked_list ( storage. data ) ;
200+ storage. available . set ( storage. data [ 0 ] . as_mut_ptr ( ) ) ;
201+ }
202+
203+ storage
204+ }
205+
181206 /// Resizes the storage container to a new slice of memory.
182207 ///
183208 /// # Panics
@@ -187,18 +212,50 @@ where
187212 /// # Time Complexity
188213 ///
189214 /// O(n)
215+ ///
216+ /// # Trait Requirements
217+ ///
218+ /// This method requires `D: Default` to initialize new nodes.
190219 pub fn resize ( & mut self , slice : & ' a mut [ u8 ] ) {
191- // SAFETY: This is reinterpreting a byte slice as a Node<D> slice.
192- // 1. The alignment is handled by slice casting rules
193- // 2. The correct number of Node<D> elements that fit in the byte slice is calculated
194- // 3. The lifetime 'a ensures the byte slice remains valid for the storage's lifetime
195- let buffer = unsafe {
196- slice:: from_raw_parts_mut :: < ' a , Node < D > > (
197- slice as * mut [ u8 ] as * mut Node < D > ,
220+ // SAFETY: This is reinterpreting a byte slice as a MaybeUninit<Node<D>> slice.
221+ // Using MaybeUninit explicitly represents uninitialized memory and avoids undefined
222+ // behavior from creating references to uninitialized Node<D>.
223+ let uninit_buffer = unsafe {
224+ slice:: from_raw_parts_mut :: < ' a , MaybeUninit < Node < D > > > (
225+ slice as * mut [ u8 ] as * mut MaybeUninit < Node < D > > ,
198226 slice. len ( ) / mem:: size_of :: < Node < D > > ( ) ,
199227 )
200228 } ;
201229
230+ assert ! ( uninit_buffer. len( ) >= self . len( ) ) ;
231+
232+ // When current capacity is 0, we need to initialize all nodes
233+ if self . capacity ( ) == 0 {
234+ // Initialize all nodes since we have no existing data
235+ for elem in uninit_buffer. iter_mut ( ) {
236+ elem. write ( Node :: new ( D :: default ( ) ) ) ;
237+ }
238+ } else {
239+ // Only initialize NEW nodes (beyond self.len())
240+ // The first self.len() nodes will have their data copied from old buffer
241+ for elem in uninit_buffer[ ..self . len ( ) ] . iter_mut ( ) {
242+ // Initialize with a temporary value that will be immediately overwritten
243+ elem. write ( Node :: new ( D :: default ( ) ) ) ;
244+ }
245+ // Initialize only the new nodes (beyond current length)
246+ for elem in uninit_buffer[ self . len ( ) ..] . iter_mut ( ) {
247+ elem. write ( Node :: new ( D :: default ( ) ) ) ;
248+ }
249+ }
250+
251+ // SAFETY: All elements have been initialized. Convert to Node<D> slice.
252+ let buffer = unsafe {
253+ slice:: from_raw_parts_mut (
254+ uninit_buffer. as_mut_ptr ( ) as * mut Node < D > ,
255+ uninit_buffer. len ( )
256+ )
257+ } ;
258+
202259 assert ! ( buffer. len( ) >= self . len( ) ) ;
203260
204261 // When current capacity is 0, we just need to copy the data and build the available list
0 commit comments