@@ -114,26 +114,16 @@ impl<T: ?Sized> AlignedBox<T> {
114114}
115115
116116impl < T > AlignedBox < T > {
117- /// Store `value` of type `T` on the heap, making sure that it is aligned to a multiple of
118- /// `alignment`. It is also checked if `alignment` is a valid alignment for type `T` or
119- /// increased to a valid alignment otherwise.
120- ///
121- /// # Example
122- /// Place value 17 of type `i32` on the heap, aligned to 64 bytes:
123- /// ```
124- /// use aligned_box::AlignedBox;
125- ///
126- /// let b = AlignedBox::<i32>::new(64, 17);
127- /// ```
128- pub fn new (
117+ fn allocate (
129118 mut alignment : usize ,
130- value : T ,
131- ) -> std:: result:: Result < AlignedBox < T > , std:: boxed:: Box < dyn std:: error:: Error > > {
119+ nelems : usize ,
120+ ) -> std:: result:: Result < ( * mut T , std:: alloc:: Layout ) , std:: boxed:: Box < dyn std:: error:: Error > >
121+ {
132122 if alignment < std:: mem:: align_of :: < T > ( ) {
133123 alignment = std:: mem:: align_of :: < T > ( ) ;
134124 }
135125
136- let memsize: usize = std:: mem:: size_of :: < T > ( ) ;
126+ let memsize: usize = std:: mem:: size_of :: < T > ( ) * nelems ;
137127 if memsize == 0 {
138128 return Err ( AlignedBoxError :: ZeroAlloc . into ( ) ) ;
139129 }
@@ -146,48 +136,25 @@ impl<T> AlignedBox<T> {
146136 return Err ( AlignedBoxError :: OutOfMemory . into ( ) ) ;
147137 }
148138
149- // SAFETY: The pointer is non-null, refers to properly sized and aligned memory and it is
150- // consumed such that it cannot be used from anywhere outside the Box.
151- let mut b = unsafe { AlignedBox :: < T > :: from_raw_parts ( ptr, layout) } ;
152-
153- // *b is not a valid instance of T but uninitialized memory. We have to write to it without
154- // dropping the old (invalid) value. Also the original value must not be dropped.
155- // SAFETY: Both value and *b point to valid and properly aligned memory.
156- unsafe { std:: ptr:: write ( & mut * b, value) } ;
157-
158- Ok ( b)
139+ Ok ( ( ptr, layout) )
159140 }
160141
161142 fn new_uninitialized_sliced (
162- mut alignment : usize ,
143+ alignment : usize ,
163144 nelems : usize ,
164145 ) -> std:: result:: Result < AlignedBox < [ T ] > , std:: boxed:: Box < dyn std:: error:: Error > > {
165- if alignment < std:: mem:: align_of :: < T > ( ) {
166- alignment = std:: mem:: align_of :: < T > ( ) ;
167- }
168-
169146 // Make sure the requested amount of Ts will fit into a slice.
170147 let maxelems = ( isize:: MAX as usize ) / std:: mem:: size_of :: < T > ( ) ;
171148 if nelems > maxelems {
172149 return Err ( AlignedBoxError :: TooManyElements . into ( ) ) ;
173150 }
174151
175- let memsize: usize = std:: mem:: size_of :: < T > ( ) * nelems;
176- if memsize == 0 {
177- return Err ( AlignedBoxError :: ZeroAlloc . into ( ) ) ;
178- }
179-
180- let layout = std:: alloc:: Layout :: from_size_align ( memsize, alignment) ?;
152+ let ( ptr, layout) = AlignedBox :: < T > :: allocate ( alignment, nelems) ?;
181153
182- // SAFETY: Requirements on layout are enforced by using from_size_align().
183- let ptr = unsafe { std:: alloc:: alloc ( layout) as * mut T } ;
184- if ptr. is_null ( ) {
185- return Err ( AlignedBoxError :: OutOfMemory . into ( ) ) ;
186- }
187-
188- // SAFETY: Requirements on ptr and nelems have been verified: ptr is non-null, nelems does
189- // not exceed the maximum size. The referenced memory is not accessed as long as slice
190- // exists.
154+ // SAFETY: Requirements on ptr and nelems have been verified here and by
155+ // AlignedBox::alocate():
156+ // ptr is non-null, nelems does not exceed the maximum size.
157+ // The referenced memory is not accessed as long as slice exists.
191158 let slice = unsafe { std:: slice:: from_raw_parts_mut ( ptr, nelems) } ;
192159
193160 // SAFETY: We only create a single Box from the given slice. The slice itself is consumed
@@ -196,6 +163,35 @@ impl<T> AlignedBox<T> {
196163
197164 Ok ( b)
198165 }
166+
167+ /// Store `value` of type `T` on the heap, making sure that it is aligned to a multiple of
168+ /// `alignment`. It is also checked if `alignment` is a valid alignment for type `T` or
169+ /// increased to a valid alignment otherwise.
170+ ///
171+ /// # Example
172+ /// Place value 17 of type `i32` on the heap, aligned to 64 bytes:
173+ /// ```
174+ /// use aligned_box::AlignedBox;
175+ ///
176+ /// let b = AlignedBox::<i32>::new(64, 17);
177+ /// ```
178+ pub fn new (
179+ alignment : usize ,
180+ value : T ,
181+ ) -> std:: result:: Result < AlignedBox < T > , std:: boxed:: Box < dyn std:: error:: Error > > {
182+ let ( ptr, layout) = AlignedBox :: < T > :: allocate ( alignment, 1 ) ?;
183+
184+ // SAFETY: The pointer is non-null, refers to properly sized and aligned memory and it is
185+ // consumed such that it cannot be used from anywhere outside the Box.
186+ let mut b = unsafe { AlignedBox :: < T > :: from_raw_parts ( ptr, layout) } ;
187+
188+ // *b is not a valid instance of T but uninitialized memory. We have to write to it without
189+ // dropping the old (invalid) value. Also the original value must not be dropped.
190+ // SAFETY: Both value and *b point to valid and properly aligned memory.
191+ unsafe { std:: ptr:: write ( & mut * b, value) } ;
192+
193+ Ok ( b)
194+ }
199195}
200196
201197impl < T : Default > AlignedBox < [ T ] > {
0 commit comments