Skip to content

Commit 00a8d48

Browse files
committed
FEAT: Add constructor method build_uninit
This method allows creating any owned array and initializing it - the method helps by giving mutable access even to normally copy-on-write arrays, because when first created, the array is unshared.
1 parent b9c12b0 commit 00a8d48

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

src/data_traits.rs

+7
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,13 @@ unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> {}
402402
/// A representation that is a unique or shared owner of its data.
403403
///
404404
/// ***Internal trait, see `Data`.***
405+
// The owned storage represents the ownership and allocation of the array's elements.
406+
// The storage may be unique or shared ownership style; it must be an aliasable owner
407+
// (permit aliasing pointers, such as our separate array head pointer).
408+
//
409+
// The array storage must be initially mutable - copy on write arrays may require copying for
410+
// unsharing storage before mutating it. The initially allocated storage must be mutable so
411+
// that it can be mutated directly - through .raw_view_mut_unchecked() - for initialization.
405412
pub unsafe trait DataOwned: Data {
406413
/// Corresponding owned data with MaybeUninit elements
407414
type MaybeUninit: DataOwned<Elem = MaybeUninit<Self::Elem>>

src/impl_constructors.rs

+33
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,39 @@ where
586586
ArrayBase::from_shape_vec_unchecked(shape, v)
587587
}
588588
}
589+
590+
/// Create an array with uninitalized elements, shape `shape`.
591+
///
592+
/// The uninitialized elements of type `A` are represented by the type `MaybeUninit<A>`,
593+
/// an easier way to handle uninit values correctly.
594+
///
595+
/// The `builder` closure gets unshared access to the array through a raw view
596+
/// and can use it to modify the array before it is returned. This allows initializing
597+
/// the array for any owned array type (avoiding clone requirements for copy-on-write,
598+
/// because the array is unshared when initially created).
599+
///
600+
/// Only *when* the array is completely initialized with valid elements, can it be
601+
/// converted to an array of `A` elements using [`.assume_init()`].
602+
///
603+
/// **Panics** if the number of elements in `shape` would overflow isize.
604+
///
605+
/// ### Safety
606+
///
607+
/// The whole of the array must be initialized before it is converted
608+
/// using [`.assume_init()`] or otherwise traversed.
609+
///
610+
pub(crate) fn build_uninit<Sh, F>(shape: Sh, builder: F) -> ArrayBase<S::MaybeUninit, D>
611+
where
612+
Sh: ShapeBuilder<Dim = D>,
613+
F: FnOnce(RawArrayViewMut<MaybeUninit<A>, D>),
614+
{
615+
let mut array = Self::uninit(shape);
616+
// Safe because: the array is unshared here
617+
unsafe {
618+
builder(array.raw_view_mut_unchecked());
619+
}
620+
array
621+
}
589622
}
590623

591624
impl<S, A, D> ArrayBase<S, D>

src/impl_methods.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,17 @@ where
13831383
unsafe { RawArrayViewMut::new(self.ptr, self.dim.clone(), self.strides.clone()) }
13841384
}
13851385

1386+
/// Return a raw mutable view of the array.
1387+
///
1388+
/// Safety: The caller must ensure that the owned array is unshared when this is called
1389+
#[inline]
1390+
pub(crate) unsafe fn raw_view_mut_unchecked(&mut self) -> RawArrayViewMut<A, D>
1391+
where
1392+
S: DataOwned,
1393+
{
1394+
RawArrayViewMut::new(self.ptr, self.dim.clone(), self.strides.clone())
1395+
}
1396+
13861397
/// Return the array’s data as a slice, if it is contiguous and in standard order.
13871398
/// Return `None` otherwise.
13881399
///

0 commit comments

Comments
 (0)