Skip to content

Commit e19e40d

Browse files
committed
Documentation about rust-owned array
1 parent cf04b51 commit e19e40d

File tree

3 files changed

+44
-43
lines changed

3 files changed

+44
-43
lines changed

src/array.rs

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,21 @@ use types::{NpyDataType, TypeNum};
1818
/// [NumPy ndarray](https://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html).
1919
///
2020
/// # Memory location
21-
/// Numpy api allows to use a memory area allocated outside Pyhton.
2221
///
23-
/// However, we designed `PyArray` to always **owns a memory area allocated in Python's private
24-
/// heap**, where all memories are managed by GC.
22+
/// 1.`PyArray` constructed via `IntoPyArray::into_pyarray` or `PyArray::from_vec`
23+
/// or `PyArray::from_owned_array`
2524
///
26-
/// This means you always need to pay allocation cost when you create a `PyArray`, but don't need
27-
/// to fear memory leak.
25+
/// These methods don't allocate and use `Box<[T]>` as container.
26+
///
27+
/// Please take care that **you cannot use some destructive methods like `resize`,
28+
/// for this kind of array**.
29+
///
30+
/// 2.`PyArray` constructed via other methods, like `ToPyArray::to_pyarray` or `PyArray::from_slice`
31+
/// or `PyArray::from_array`.
32+
///
33+
/// These methods allocate a memory area in Python's private heap.
34+
///
35+
/// In this case, you have no restriction.
2836
///
2937
/// # Reference
3038
///
@@ -33,11 +41,6 @@ use types::{NpyDataType, TypeNum};
3341
/// See [pyo3's document](https://pyo3.rs/master/doc/pyo3/index.html#ownership-and-lifetimes)
3442
/// for the reason.
3543
///
36-
/// # Mutation
37-
/// You can do destructive changes to `PyArray` via &self methods like [`move_to`](#method.move_to).
38-
///
39-
/// About this design, see
40-
/// [pyo3's document](https://pyo3.rs/master/doc/pyo3/index.html#ownership-and-lifetimes), too.
4144
///
4245
/// # Dimension
4346
/// `PyArray` has 2 type parametes `T` and `D`. `T` represents its data type like `f32`, and `D`
@@ -582,6 +585,22 @@ impl<T: TypeNum> PyArray<T, Ix1> {
582585
array
583586
}
584587

588+
/// Construct one-dimension PyArray from `Vec`.
589+
///
590+
/// # Example
591+
/// ```
592+
/// # extern crate pyo3; extern crate numpy; fn main() {
593+
/// use numpy::PyArray;
594+
/// let gil = pyo3::Python::acquire_gil();
595+
/// let vec = vec![1, 2, 3, 4, 5];
596+
/// let pyarray = PyArray::from_vec(gil.python(), vec);
597+
/// assert_eq!(pyarray.as_slice().unwrap(), &[1, 2, 3, 4, 5]);
598+
/// # }
599+
/// ```
600+
pub fn from_vec<'py>(py: Python<'py>, vec: Vec<T>) -> &'py Self {
601+
IntoPyArray::into_pyarray(vec, py)
602+
}
603+
585604
/// Construct one-dimension PyArray from `impl ExactSizeIterator`.
586605
///
587606
/// # Example
@@ -621,8 +640,7 @@ impl<T: TypeNum> PyArray<T, Ix1> {
621640
/// # }
622641
/// ```
623642
pub fn from_iter(py: Python, iter: impl IntoIterator<Item = T>) -> &Self {
624-
// ↓ max cached size of ndarray
625-
let mut capacity = 1024 / mem::size_of::<T>();
643+
let mut capacity = 512 / mem::size_of::<T>();
626644
let array = Self::new(py, [capacity], false);
627645
let mut length = 0;
628646
unsafe {
@@ -919,35 +937,6 @@ impl<T: TypeNum, D> PyArray<T, D> {
919937
}
920938
}
921939

922-
impl<T: TypeNum> PyArray<T, IxDyn> {
923-
/// Move the data of self into `other`, performing a data-type conversion if necessary.
924-
///
925-
/// For type safety, you have to convert `PyArray` to `PyArrayDyn` before using this method.
926-
/// # Example
927-
/// ```
928-
/// # extern crate pyo3; extern crate numpy; fn main() {
929-
/// use numpy::PyArray;
930-
/// let gil = pyo3::Python::acquire_gil();
931-
/// let pyarray_f = PyArray::arange(gil.python(), 2.0, 5.0, 1.0).into_dyn();
932-
/// let pyarray_i = PyArray::<i64, _>::new(gil.python(), [3], false);
933-
/// assert!(pyarray_f.move_to(pyarray_i).is_ok());
934-
/// assert_eq!(pyarray_i.as_slice().unwrap(), &[2, 3, 4]);
935-
/// # }
936-
pub fn move_to<U: TypeNum, D2: Dimension>(
937-
&self,
938-
other: &PyArray<U, D2>,
939-
) -> Result<(), ErrorKind> {
940-
let self_ptr = self.as_array_ptr();
941-
let other_ptr = other.as_array_ptr();
942-
let result = unsafe { PY_ARRAY_API.PyArray_MoveInto(other_ptr, self_ptr) };
943-
if result == -1 {
944-
Err(ErrorKind::dtype_cast(self, U::npy_data_type()))
945-
} else {
946-
Ok(())
947-
}
948-
}
949-
}
950-
951940
impl<T: TypeNum + AsPrimitive<f64>> PyArray<T, Ix1> {
952941
/// Return evenly spaced values within a given interval.
953942
/// Same as [numpy.arange](https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html).

src/convert.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@ use npyffi::npy_intp;
1414
///
1515
/// This trait takes `self`, which means **it holds a pointer to Rust heap, until `resize` or other
1616
/// destructive method is called**.
17+
///
18+
/// In addition, if you construct `PyArray` via this method,
19+
/// **you cannot use some destructive methods like `resize`.**
1720
/// # Example
1821
/// ```
1922
/// # extern crate pyo3; extern crate numpy; fn main() {
20-
/// use numpy::{PyArray, ToPyArray};
23+
/// use numpy::{PyArray, IntoPyArray};
2124
/// let gil = pyo3::Python::acquire_gil();
22-
/// let py_array = vec![1, 2, 3].to_pyarray(gil.python());
25+
/// let py_array = vec![1, 2, 3].into_pyarray(gil.python());
2326
/// assert_eq!(py_array.as_slice().unwrap(), &[1, 2, 3]);
27+
/// assert!(py_array.resize(100).is_err()); // You can't resize owned-by-rust array.
2428
/// # }
2529
/// ```
2630
pub trait IntoPyArray {

tests/array.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,11 @@ fn into_pyarray_array() {
225225
assert_eq!(py_arr.shape(), shape.as_slice());
226226
assert_eq!(py_arr.strides(), strides.as_slice());
227227
}
228+
229+
#[test]
230+
fn into_pyarray_cant_resize() {
231+
let gil = pyo3::Python::acquire_gil();
232+
let a = vec![1, 2, 3];
233+
let arr = a.into_pyarray(gil.python());
234+
assert!(arr.resize(100).is_err())
235+
}

0 commit comments

Comments
 (0)