@@ -114,26 +114,16 @@ impl<T: ?Sized> AlignedBox<T> {
114
114
}
115
115
116
116
impl < 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 (
129
118
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
+ {
132
122
if alignment < std:: mem:: align_of :: < T > ( ) {
133
123
alignment = std:: mem:: align_of :: < T > ( ) ;
134
124
}
135
125
136
- let memsize: usize = std:: mem:: size_of :: < T > ( ) ;
126
+ let memsize: usize = std:: mem:: size_of :: < T > ( ) * nelems ;
137
127
if memsize == 0 {
138
128
return Err ( AlignedBoxError :: ZeroAlloc . into ( ) ) ;
139
129
}
@@ -146,48 +136,25 @@ impl<T> AlignedBox<T> {
146
136
return Err ( AlignedBoxError :: OutOfMemory . into ( ) ) ;
147
137
}
148
138
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) )
159
140
}
160
141
161
142
fn new_uninitialized_sliced (
162
- mut alignment : usize ,
143
+ alignment : usize ,
163
144
nelems : usize ,
164
145
) -> 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
-
169
146
// Make sure the requested amount of Ts will fit into a slice.
170
147
let maxelems = ( isize:: MAX as usize ) / std:: mem:: size_of :: < T > ( ) ;
171
148
if nelems > maxelems {
172
149
return Err ( AlignedBoxError :: TooManyElements . into ( ) ) ;
173
150
}
174
151
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) ?;
181
153
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.
191
158
let slice = unsafe { std:: slice:: from_raw_parts_mut ( ptr, nelems) } ;
192
159
193
160
// SAFETY: We only create a single Box from the given slice. The slice itself is consumed
@@ -196,6 +163,35 @@ impl<T> AlignedBox<T> {
196
163
197
164
Ok ( b)
198
165
}
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
+ }
199
195
}
200
196
201
197
impl < T : Default > AlignedBox < [ T ] > {
0 commit comments