Skip to content

Commit 46b2946

Browse files
committed
FEAT: New method .assume_init() for all array types
Add representation trait RawDataSubst that array storage types correctly (emulation of higher kinded types). Implement it as a transmute-like operation, using the representation guarantees that MaybeUninit documents. Make it a public method - avaialable on all array types - owned arrays, arcarray, array views and so on. The safety percussions of exposing this transformation are only explored to an extent, but it's a type change without value conversion so there should not be much that can go wrong. Interesting aspects include being able to have one ArcArray handle with the old type and one with the new type, or one owned array with old and a view with new.
1 parent abc1813 commit 46b2946

4 files changed

Lines changed: 96 additions & 33 deletions

File tree

src/data_traits.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,38 @@ unsafe impl<'a, A> Data for CowRepr<'a, A> {
528528
}
529529

530530
unsafe impl<'a, A> DataMut for CowRepr<'a, A> where A: Clone {}
531+
532+
/// Array representation trait.
533+
///
534+
/// The RawDataSubst trait maps the element type of array storage, while
535+
/// keeping the same kind of storage.
536+
///
537+
/// For example, `RawDataSubst<B>` can map the type `OwnedRepr<A>` to `OwnedRepr<B>`.
538+
pub trait RawDataSubst<A>: RawData {
539+
/// The resulting array storage of the same kind but substituted element type
540+
type Output: RawData<Elem = A>;
541+
}
542+
543+
impl<A, B> RawDataSubst<B> for OwnedRepr<A> {
544+
type Output = OwnedRepr<B>;
545+
}
546+
547+
impl<A, B> RawDataSubst<B> for OwnedArcRepr<A> {
548+
type Output = OwnedArcRepr<B>;
549+
}
550+
551+
impl<A, B> RawDataSubst<B> for RawViewRepr<*const A> {
552+
type Output = RawViewRepr<*const B>;
553+
}
554+
555+
impl<A, B> RawDataSubst<B> for RawViewRepr<*mut A> {
556+
type Output = RawViewRepr<*mut B>;
557+
}
558+
559+
impl<'a, A: 'a, B: 'a> RawDataSubst<B> for ViewRepr<&'a A> {
560+
type Output = ViewRepr<&'a B>;
561+
}
562+
563+
impl<'a, A: 'a, B: 'a> RawDataSubst<B> for ViewRepr<&'a mut A> {
564+
type Output = ViewRepr<&'a mut B>;
565+
}

src/impl_owned_array.rs

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
use std::mem::MaybeUninit;
2-
use std::mem::transmute;
31

42
use crate::imp_prelude::*;
5-
use crate::OwnedRepr;
63

74
/// Methods specific to `Array0`.
85
///
@@ -61,33 +58,3 @@ where
6158
self.data.into_vec()
6259
}
6360
}
64-
65-
/// Methods specific to `Array` of `MaybeUninit`.
66-
///
67-
/// ***See also all methods for [`ArrayBase`]***
68-
///
69-
/// [`ArrayBase`]: struct.ArrayBase.html
70-
impl<A, D> Array<MaybeUninit<A>, D>
71-
where
72-
D: Dimension,
73-
{
74-
/// Assert that the array's storage's elements are all fully initialized, and conver
75-
/// the array from element type `MaybeUninit<A>` to `A`.
76-
pub(crate) unsafe fn assume_init(self) -> Array<A, D> {
77-
// NOTE: Fully initialized includes elements not reachable in current slicing/view.
78-
//
79-
// Should this method be generalized to all array types?
80-
// (Will need a way to map the RawData<Elem=X> to RawData<Elem=Y> of same kind)
81-
82-
let Array { data, ptr, dim, strides } = self;
83-
let data = transmute::<OwnedRepr<MaybeUninit<A>>, OwnedRepr<A>>(data);
84-
let ptr = ptr.cast::<A>();
85-
86-
Array {
87-
data,
88-
ptr,
89-
dim,
90-
strides,
91-
}
92-
}
93-
}

src/impl_special_element_types.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2020 bluss and ndarray developers.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
use std::mem::size_of;
10+
use std::mem::ManuallyDrop;
11+
use std::mem::MaybeUninit;
12+
13+
use crate::imp_prelude::*;
14+
use crate::RawDataSubst;
15+
16+
17+
/// Methods specific to arrays with `MaybeUninit` elements.
18+
///
19+
/// ***See also all methods for [`ArrayBase`]***
20+
///
21+
/// [`ArrayBase`]: struct.ArrayBase.html
22+
impl<A, S, D> ArrayBase<S, D>
23+
where
24+
S: RawDataSubst<A, Elem=MaybeUninit<A>>,
25+
D: Dimension,
26+
{
27+
/// **Promise** that the array's elements are all fully initialized, and convert
28+
/// the array from element type `MaybeUninit<A>` to `A`.
29+
///
30+
/// For owned arrays, the promise must include all of the Array's storage
31+
pub unsafe fn assume_init(self) -> ArrayBase<<S as RawDataSubst<A>>::Output, D> {
32+
// NOTE: Fully initialized includes elements not reachable in current slicing/view.
33+
34+
let ArrayBase { data, ptr, dim, strides } = self;
35+
36+
// transmute from storage of MaybeUninit<A> to storage of A
37+
let data = unlimited_transmute::<S, S::Output>(data);
38+
let ptr = ptr.cast::<A>();
39+
40+
ArrayBase {
41+
data,
42+
ptr,
43+
dim,
44+
strides,
45+
}
46+
}
47+
}
48+
49+
/// Transmute from A to B.
50+
///
51+
/// Like transmute, but does not have the compile-time size check which blocks
52+
/// using regular transmute for "S to S::Output".
53+
///
54+
/// **Panics** if the size of A and B are different.
55+
unsafe fn unlimited_transmute<A, B>(data: A) -> B {
56+
assert_eq!(size_of::<A>(), size_of::<B>());
57+
let old_data = ManuallyDrop::new(data);
58+
(&*old_data as *const A as *const B).read()
59+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ pub use crate::aliases::*;
159159
#[allow(deprecated)]
160160
pub use crate::data_traits::{
161161
Data, DataClone, DataMut, DataOwned, DataShared, RawData, RawDataClone, RawDataMut,
162+
RawDataSubst,
162163
};
163164

164165
mod free_functions;
@@ -1483,6 +1484,7 @@ mod impl_constructors;
14831484

14841485
mod impl_methods;
14851486
mod impl_owned_array;
1487+
mod impl_special_element_types;
14861488

14871489
/// Private Methods
14881490
impl<A, S, D> ArrayBase<S, D>

0 commit comments

Comments
 (0)