|
1 | 1 | use std::mem::size_of;
|
2 | 2 | use std::os::raw::{c_int, c_long, c_longlong, c_short, c_uint, c_ulong, c_ulonglong, c_ushort};
|
3 | 3 | use std::ptr;
|
| 4 | +use ndarray::{Array, ArrayView, Dimension}; |
4 | 5 |
|
5 | 6 | #[cfg(feature = "half")]
|
6 | 7 | use half::{bf16, f16};
|
@@ -644,6 +645,55 @@ impl<'py> PyArrayDescrMethods<'py> for Bound<'py, PyArrayDescr> {
|
644 | 645 |
|
645 | 646 | impl Sealed for Bound<'_, PyArrayDescr> {}
|
646 | 647 |
|
| 648 | + |
| 649 | +/// Weaker form of `Clone` for types that can be cloned while the GIL is held. |
| 650 | +/// |
| 651 | +/// Any type that implements `Clone` can trivially implement `PyClone` by forwarding |
| 652 | +/// to the `Clone::clone` method. However, some types (notably `PyObject`) can only |
| 653 | +/// be safely cloned while the GIL is held, and therefore cannot implement `Clone`. |
| 654 | +/// This trait provides a mechanism for performing a clone while the GIL is held, as |
| 655 | +/// represented by the [`Python`] token provided as an argument to the [`py_clone`] |
| 656 | +/// method. All API's in the `numpy` crate require the GIL to be held, so this weaker |
| 657 | +/// alternative to `Clone` is a sufficient prerequisite for implementing the |
| 658 | +/// [`Element`] trait. |
| 659 | +/// |
| 660 | +/// # Implementing `PyClone` |
| 661 | +/// Implementing this trait is trivial for most types, and simply requires defining |
| 662 | +/// the `py_clone` method. The `vec_from_slice` and `array_from_view` methods have |
| 663 | +/// default implementations that simply map the `py_clone` method to each item in |
| 664 | +/// the collection, but types may want to override these implementations if there |
| 665 | +/// is a more efficient way to perform the conversion. In particular, `Clone` types |
| 666 | +/// may instead defer to the `ToOwned::to_owned` and `ArrayBase::to_owned` methods |
| 667 | +/// for increased performance. |
| 668 | +/// |
| 669 | +/// [`py_clone`]: Self::py_clone |
| 670 | +pub trait PyClone: Sized { |
| 671 | + /// Create a clone of the value while the GIL is guaranteed to be held. |
| 672 | + fn py_clone(&self, py: Python<'_>) -> Self; |
| 673 | + |
| 674 | + /// Create an owned copy of the slice while the GIL is guaranteed to be held. |
| 675 | + /// |
| 676 | + /// Some types may provide implementations of this method that are more efficient |
| 677 | + /// than simply mapping the `py_clone` method to each element in the slice. |
| 678 | + #[inline] |
| 679 | + fn vec_from_slice(py: Python<'_>, slc: &[Self]) -> Vec<Self> { |
| 680 | + slc.iter().map(|elem| elem.py_clone(py)).collect() |
| 681 | + } |
| 682 | + |
| 683 | + /// Create an owned copy of the array while the GIL is guaranteed to be held. |
| 684 | + /// |
| 685 | + /// Some types may provide implementations of this method that are more efficient |
| 686 | + /// than simply mapping the `py_clone` method to each element in the view. |
| 687 | + #[inline] |
| 688 | + fn array_from_view<D>(py: Python<'_>, view: ArrayView<'_, Self, D>) -> Array<Self, D> |
| 689 | + where |
| 690 | + D: Dimension |
| 691 | + { |
| 692 | + view.map(|elem| elem.py_clone(py)) |
| 693 | + } |
| 694 | +} |
| 695 | + |
| 696 | + |
647 | 697 | /// Represents that a type can be an element of `PyArray`.
|
648 | 698 | ///
|
649 | 699 | /// Currently, only integer/float/complex/object types are supported. The [NumPy documentation][enumerated-types]
|
|
0 commit comments