Skip to content

Commit 44a37f3

Browse files
committed
Refactor slice constructors to reduce code duplication
1 parent edde578 commit 44a37f3

File tree

1 file changed

+28
-49
lines changed

1 file changed

+28
-49
lines changed

src/lib.rs

Lines changed: 28 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -157,23 +157,8 @@ impl<T> AlignedBox<T> {
157157

158158
Ok(b)
159159
}
160-
}
161160

162-
impl<T: Default> AlignedBox<[T]> {
163-
/// Allocate memory for `nelems` values of type `T` on the heap, making sure that it is aligned
164-
/// to a multiple of `alignment`. All values are initialized by the default value of type `T`.
165-
/// It is also checked if `alignment` is a valid alignment for type `T` or increased to a
166-
/// valid alignment otherwise.
167-
///
168-
/// # Example
169-
/// Allocate memory for 1024 values of type `f32` on the heap, aligned to 128 bytes. Values
170-
/// are initialized by their default value:
171-
/// ```
172-
/// use aligned_box::AlignedBox;
173-
///
174-
/// let b = AlignedBox::<[f32]>::slice_from_default(128, 1024);
175-
/// ```
176-
pub fn slice_from_default(
161+
fn new_uninitialized_sliced(
177162
mut alignment: usize,
178163
nelems: usize,
179164
) -> std::result::Result<AlignedBox<[T]>, std::boxed::Box<dyn std::error::Error>> {
@@ -207,7 +192,31 @@ impl<T: Default> AlignedBox<[T]> {
207192

208193
// SAFETY: We only create a single Box from the given slice. The slice itself is consumed
209194
// so that the referenced memory can be modified from now on.
210-
let mut b = unsafe { AlignedBox::<[T]>::from_raw_parts(slice, layout) };
195+
let b = unsafe { AlignedBox::<[T]>::from_raw_parts(slice, layout) };
196+
197+
Ok(b)
198+
}
199+
}
200+
201+
impl<T: Default> AlignedBox<[T]> {
202+
/// Allocate memory for `nelems` values of type `T` on the heap, making sure that it is aligned
203+
/// to a multiple of `alignment`. All values are initialized by the default value of type `T`.
204+
/// It is also checked if `alignment` is a valid alignment for type `T` or increased to a
205+
/// valid alignment otherwise.
206+
///
207+
/// # Example
208+
/// Allocate memory for 1024 values of type `f32` on the heap, aligned to 128 bytes. Values
209+
/// are initialized by their default value:
210+
/// ```
211+
/// use aligned_box::AlignedBox;
212+
///
213+
/// let b = AlignedBox::<[f32]>::slice_from_default(128, 1024);
214+
/// ```
215+
pub fn slice_from_default(
216+
alignment: usize,
217+
nelems: usize,
218+
) -> std::result::Result<AlignedBox<[T]>, std::boxed::Box<dyn std::error::Error>> {
219+
let mut b = AlignedBox::<T>::new_uninitialized_sliced(alignment, nelems)?;
211220

212221
for i in (*b).iter_mut() {
213222
let d = T::default(); // create new default value
@@ -236,41 +245,11 @@ impl<T: Copy> AlignedBox<[T]> {
236245
///
237246
/// let b = AlignedBox::<[f32]>::slice_from_value(128, 1024, std::f32::consts::PI);
238247
pub fn slice_from_value(
239-
mut alignment: usize,
248+
alignment: usize,
240249
nelems: usize,
241250
value: T,
242251
) -> std::result::Result<AlignedBox<[T]>, std::boxed::Box<dyn std::error::Error>> {
243-
if alignment < std::mem::align_of::<T>() {
244-
alignment = std::mem::align_of::<T>();
245-
}
246-
247-
// Make sure the requested amount of Ts will fit into a slice.
248-
let maxelems = (isize::MAX as usize) / std::mem::size_of::<T>();
249-
if nelems > maxelems {
250-
return Err(AlignedBoxError::TooManyElements.into());
251-
}
252-
253-
let memsize: usize = std::mem::size_of::<T>() * nelems;
254-
if memsize == 0 {
255-
return Err(AlignedBoxError::ZeroAlloc.into());
256-
}
257-
258-
let layout = std::alloc::Layout::from_size_align(memsize, alignment)?;
259-
260-
// SAFETY: Requirements on layout are enforced by using from_size_align().
261-
let ptr = unsafe { std::alloc::alloc(layout) as *mut T };
262-
if ptr.is_null() {
263-
return Err(AlignedBoxError::OutOfMemory.into());
264-
}
265-
266-
// SAFETY: Requirements on ptr and nelems have been verified: ptr is non-null, nelems does
267-
// not exceed the maximum size. The referenced memory is not accessed as long as slice
268-
// exists.
269-
let slice = unsafe { std::slice::from_raw_parts_mut(ptr, nelems) };
270-
271-
// SAFETY: We only create a single Box from the given slice. The slice itself is consumed
272-
// so that the referenced memory can be modified from now on.
273-
let mut b = unsafe { AlignedBox::<[T]>::from_raw_parts(slice, layout) };
252+
let mut b = AlignedBox::<T>::new_uninitialized_sliced(alignment, nelems)?;
274253

275254
for i in (*b).iter_mut() {
276255
// T is Copy and therefore also !Drop. We can simply copy from value to *i without

0 commit comments

Comments
 (0)