From 777829953c4a4bfd7e813a61ba0194b543c924b2 Mon Sep 17 00:00:00 2001 From: andrei-papou Date: Mon, 6 May 2019 17:03:36 +0300 Subject: [PATCH 1/8] COW implementation + tests --- src/data_traits.rs | 98 ++++++++++++++++++++++++++++++++++++++++++ src/impl_cow.rs | 55 ++++++++++++++++++++++++ src/lib.rs | 36 ++++++++++++++++ src/prelude.rs | 1 + tests/array.rs | 103 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 293 insertions(+) create mode 100644 src/impl_cow.rs diff --git a/src/data_traits.rs b/src/data_traits.rs index bd4522968..f4df024c6 100644 --- a/src/data_traits.rs +++ b/src/data_traits.rs @@ -16,6 +16,7 @@ use crate::{ Dimension, RawViewRepr, ViewRepr, + CowRepr, OwnedRepr, OwnedRcRepr, OwnedArcRepr, @@ -412,3 +413,100 @@ unsafe impl DataOwned for OwnedArcRepr { self } } + +unsafe impl<'a, A> RawData for CowRepr<'a, A> { + type Elem = A; + fn _data_slice(&self) -> Option<&[A]> { + match self { + CowRepr::View(view) => view._data_slice(), + CowRepr::Owned(data) => data._data_slice(), + } + } + private_impl!{} +} + +unsafe impl<'a, A> RawDataMut for CowRepr<'a, A> + where A: Clone +{ + #[inline] + fn try_ensure_unique(array: &mut ArrayBase) + where Self: Sized, + D: Dimension + { + match array.data { + CowRepr::View(_) => { + let owned = array.to_owned(); + array.data = CowRepr::Owned(owned.data); + array.ptr = owned.ptr; + array.dim = owned.dim; + array.strides = owned.strides; + } + CowRepr::Owned(_) => {} + } + } + + #[inline] + fn try_is_unique(&mut self) -> Option { + Some(self.is_owned()) + } +} + +unsafe impl<'a, A> RawDataClone for CowRepr<'a, A> + where A: Clone +{ + unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) { + match self { + CowRepr::View(view) => { + let (new_view, ptr) = view.clone_with_ptr(ptr); + (CowRepr::View(new_view), ptr) + }, + CowRepr::Owned(data) => { + let (new_data, ptr) = data.clone_with_ptr(ptr); + (CowRepr::Owned(new_data), ptr) + }, + } + } + + #[doc(hidden)] + unsafe fn clone_from_with_ptr(&mut self, other: &Self, ptr: *mut Self::Elem) -> *mut Self::Elem { + match (&mut *self, other) { + (CowRepr::View(self_), CowRepr::View(other)) => { + self_.clone_from_with_ptr(other, ptr) + }, + (CowRepr::Owned(self_), CowRepr::Owned(other)) => { + self_.clone_from_with_ptr(other, ptr) + }, + (_, CowRepr::Owned(other)) => { + let (cloned, ptr) = other.clone_with_ptr(ptr); + *self = CowRepr::Owned(cloned); + ptr + }, + (_, CowRepr::View(other)) => { + let (cloned, ptr) = other.clone_with_ptr(ptr); + *self = CowRepr::View(cloned); + ptr + } + } + } +} + +unsafe impl<'a, A> Data for CowRepr<'a, A> { + #[inline] + fn into_owned(self_: ArrayBase, D>) -> ArrayBase, D> + where + A: Clone, + D: Dimension, + { + match self_.data { + CowRepr::View(_) => self_.to_owned(), + CowRepr::Owned(data) => ArrayBase { + data, + ptr: self_.ptr, + dim: self_.dim, + strides: self_.strides, + }, + } + } +} + +unsafe impl<'a, A> DataMut for CowRepr<'a, A> where A: Clone {} diff --git a/src/impl_cow.rs b/src/impl_cow.rs new file mode 100644 index 000000000..560412f61 --- /dev/null +++ b/src/impl_cow.rs @@ -0,0 +1,55 @@ +// Copyright 2019 ndarray developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::imp_prelude::*; + +/// Methods specific to `ArrayCow`. +/// +/// ***See also all methods for [`ArrayBase`]*** +/// +/// [`ArrayBase`]: struct.ArrayBase.html +impl<'a, A, D> ArrayCow<'a, A, D> + where + D: Dimension, +{ + pub fn is_view(&self) -> bool { + self.data.is_view() + } + + pub fn is_owned(&self) -> bool { + self.data.is_owned() + } +} + +impl<'a, A, D> From> for ArrayCow<'a, A, D> + where + D: Dimension, +{ + fn from(view: ArrayView<'a, A, D>) -> ArrayCow<'a, A, D> { + ArrayBase { + data: CowRepr::View(view.data), + ptr: view.ptr, + dim: view.dim, + strides: view.strides, + } + } +} + +impl<'a, A, D> From> for ArrayCow<'a, A, D> + where + D: Dimension, +{ + fn from(array: Array) -> ArrayCow<'a, A, D> { + ArrayBase { + data: CowRepr::Owned(array.data), + ptr: array.ptr, + dim: array.dim, + strides: array.strides, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 8b44c21d2..a96c3d63b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,6 +205,7 @@ mod imp_prelude { DataShared, RawViewRepr, ViewRepr, + CowRepr, Ix, Ixs, }; pub use crate::dimension::DimensionExt; @@ -1230,6 +1231,20 @@ pub type ArcArray = ArrayBase, D>; /// and so on. pub type Array = ArrayBase, D>; +/// An array with copy-on-write behavior. +/// +/// An `ArrayCow` represents either a uniquely owned array or a view of an +/// array. The `'a` corresponds to the lifetime of the view variant. +/// +/// Array views have all the methods of an array (see [`ArrayBase`][ab]). +/// +/// See also [`ArcArray`](type.ArcArray.html), which also provides +/// copy-on-write behavior but has a reference-counted pointer to the data +/// instead of either a view or a uniquely owned copy. +/// +/// [ab]: struct.ArrayBase.html +pub type ArrayCow<'a, A, D> = ArrayBase, D>; + /// A read-only array view. /// /// An array view represents an array or a part of it, created from @@ -1374,6 +1389,24 @@ impl ViewRepr { } } +pub enum CowRepr<'a, A> { + View(ViewRepr<&'a A>), + Owned(OwnedRepr), +} + +impl<'a, A> CowRepr<'a, A> { + pub fn is_view(&self) -> bool { + match self { + CowRepr::View(_) => true, + CowRepr::Owned(_) => false, + } + } + + pub fn is_owned(&self) -> bool { + !self.is_view() + } +} + mod impl_clone; mod impl_constructors; @@ -1494,6 +1527,9 @@ mod impl_views; // Array raw view methods mod impl_raw_views; +// Copy-on-write array methods +mod impl_cow; + /// A contiguous array shape of n dimensions. /// /// Either c- or f- memory ordered (*c* a.k.a *row major* is the default). diff --git a/src/prelude.rs b/src/prelude.rs index 80c98e34c..25ab3ae65 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -25,6 +25,7 @@ pub use crate::{ Array, ArcArray, RcArray, + ArrayCow, ArrayView, ArrayViewMut, RawArrayView, diff --git a/tests/array.rs b/tests/array.rs index bbe05bbda..0b5bb5111 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -1891,3 +1891,106 @@ fn array_macros() { let empty2: Array = array![[]]; assert_eq!(empty2, array![[]]); } + +#[cfg(test)] +mod array_cow_tests { + use super::*; + use ndarray::Data; + + fn is_content_identical(arr1: &ArrayBase, arr2: &ArrayBase) -> bool + where A: Clone + PartialEq, + S1: Data, + S2: Data, + D: Dimension + { + arr1.iter().zip(arr2.iter()).all(|(x1, x2)| x1 == x2) + } + + #[test] + fn test_is_view() { + let arr: Array = array![[1, 2], [3, 4]]; + let arr_cow = ArrayCow::::from(arr.view()); + assert!(arr_cow.is_view()); + let arr_cow = ArrayCow::::from(arr.clone()); + assert!(!arr_cow.is_view()); + } + + #[test] + fn test_is_owned() { + let arr: Array = array![[1, 2], [3, 4]]; + let arr_cow = ArrayCow::::from(arr.clone()); + assert!(arr_cow.is_owned()); + let arr_cow = ArrayCow::::from(arr.view()); + assert!(!arr_cow.is_owned()); + } + + #[test] + fn test_element_mutation() { + let arr: Array2 = array![[1, 2], [3, 4]]; + let mut arr_cow = ArrayCow::::from(arr.view()); + arr_cow[(1, 1)] = 2; + let expected_arr: Array2 = array![[1, 2], [3, 2]]; + assert!(arr_cow.is_owned()); + assert!(is_content_identical(&arr_cow, &expected_arr)); + + let mut arr_cow = ArrayCow::::from(arr.clone()); + let prev_ptr = arr_cow.as_ptr(); + arr_cow[(1, 1)] = 2; + assert_eq!(arr_cow.as_ptr(), prev_ptr); + assert!(is_content_identical(&arr_cow, &expected_arr)); + } + + #[test] + fn test_clone() { + let arr: Array2 = array![[1, 2], [3, 4]]; + let arr_cow = ArrayCow::::from(arr.view()); + let arr_cow_clone = arr_cow.clone(); + assert!(arr_cow_clone.is_view()); + assert!(is_content_identical(&arr_cow, &arr_cow_clone)); + assert_eq!(arr_cow.dim(), arr_cow_clone.dim()); + assert_eq!(arr_cow.strides(), arr_cow_clone.strides()); + + let arr_cow = ArrayCow::::from(arr.clone()); + let arr_cow_clone = arr_cow.clone(); + assert!(arr_cow_clone.is_owned()); + assert!(is_content_identical(&arr_cow, &arr_cow_clone)); + assert_eq!(arr_cow.dim(), arr_cow_clone.dim()); + assert_eq!(arr_cow.strides(), arr_cow_clone.strides()); + } + + #[test] + fn test_clone_from() { + let arr: Array2 = array![[1, 2], [3, 4]]; + let other_arr: Array2 = array![[11, 12], [13, 14]]; + + fn perform_checks(arr1: &ArrayCow, arr2: &ArrayCow) { + assert!(is_content_identical(arr1, arr2)); + assert_eq!(arr1.dim(), arr2.dim()); + assert_eq!(arr1.strides(), arr2.strides()); + } + + let arr_cow_src = ArrayCow::::from(arr.view()); + let mut arr_cow_dst = ArrayCow::::from(other_arr.clone()); + arr_cow_dst.clone_from(&arr_cow_src); + assert!(arr_cow_dst.is_view()); + perform_checks(&arr_cow_src, &arr_cow_dst); + + let arr_cow_src = ArrayCow::::from(arr.view()); + let mut arr_cow_dst = ArrayCow::::from(other_arr.view()); + arr_cow_dst.clone_from(&arr_cow_src); + assert!(arr_cow_dst.is_view()); + perform_checks(&arr_cow_src, &arr_cow_dst); + + let arr_cow_src = ArrayCow::::from(arr.clone()); + let mut arr_cow_dst = ArrayCow::::from(other_arr.view()); + arr_cow_dst.clone_from(&arr_cow_src); + assert!(arr_cow_dst.is_owned()); + perform_checks(&arr_cow_src, &arr_cow_dst); + + let arr_cow_src = ArrayCow::::from(arr.clone()); + let mut arr_cow_dst = ArrayCow::::from(other_arr.clone()); + arr_cow_dst.clone_from(&arr_cow_src); + assert!(arr_cow_dst.is_owned()); + perform_checks(&arr_cow_src, &arr_cow_dst); + } +} From 20cc81e39316173a644ba4e5f0b7ab36dd0d9d22 Mon Sep 17 00:00:00 2001 From: andrei-papou Date: Wed, 8 May 2019 16:45:32 +0300 Subject: [PATCH 2/8] Finished the tests --- tests/array.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/array.rs b/tests/array.rs index 0b5bb5111..319538bb4 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -1993,4 +1993,17 @@ mod array_cow_tests { assert!(arr_cow_dst.is_owned()); perform_checks(&arr_cow_src, &arr_cow_dst); } + + #[test] + fn test_into_owned() { + let arr: Array2 = array![[1, 2], [3, 4]]; + let cont_arr = ArrayCow::::from(arr.view()).into_owned(); + assert!(is_content_identical(&arr, &cont_arr)); + + let cont_arr = ArrayCow::::from(arr.clone()); + let prev_ptr = cont_arr.as_ptr(); + let cont_arr = cont_arr.into_owned(); + assert_eq!(cont_arr.as_ptr(), prev_ptr); + assert!(is_content_identical(&arr, &cont_arr)); + } } From 885527ad82dbdcce9c41589a43a3a550474c8a34 Mon Sep 17 00:00:00 2001 From: andrei-papou Date: Wed, 15 May 2019 12:39:08 +0300 Subject: [PATCH 3/8] Fixed some tests --- tests/array.rs | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/tests/array.rs b/tests/array.rs index dbb2c5102..62fa44676 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -1963,33 +1963,16 @@ fn array_macros() { #[cfg(test)] mod array_cow_tests { use super::*; - use ndarray::Data; - - fn is_content_identical(arr1: &ArrayBase, arr2: &ArrayBase) -> bool - where A: Clone + PartialEq, - S1: Data, - S2: Data, - D: Dimension - { - arr1.iter().zip(arr2.iter()).all(|(x1, x2)| x1 == x2) - } #[test] - fn test_is_view() { + fn test_is_variant() { let arr: Array = array![[1, 2], [3, 4]]; let arr_cow = ArrayCow::::from(arr.view()); assert!(arr_cow.is_view()); - let arr_cow = ArrayCow::::from(arr.clone()); - assert!(!arr_cow.is_view()); - } - - #[test] - fn test_is_owned() { - let arr: Array = array![[1, 2], [3, 4]]; + assert!(!arr_cow.is_owned()); let arr_cow = ArrayCow::::from(arr.clone()); assert!(arr_cow.is_owned()); - let arr_cow = ArrayCow::::from(arr.view()); - assert!(!arr_cow.is_owned()); + assert!(!arr_cow.is_view()); } #[test] @@ -1999,13 +1982,13 @@ mod array_cow_tests { arr_cow[(1, 1)] = 2; let expected_arr: Array2 = array![[1, 2], [3, 2]]; assert!(arr_cow.is_owned()); - assert!(is_content_identical(&arr_cow, &expected_arr)); + assert_eq!(arr_cow, expected_arr); let mut arr_cow = ArrayCow::::from(arr.clone()); let prev_ptr = arr_cow.as_ptr(); arr_cow[(1, 1)] = 2; assert_eq!(arr_cow.as_ptr(), prev_ptr); - assert!(is_content_identical(&arr_cow, &expected_arr)); + assert_eq!(arr_cow, expected_arr); } #[test] @@ -2014,14 +1997,14 @@ mod array_cow_tests { let arr_cow = ArrayCow::::from(arr.view()); let arr_cow_clone = arr_cow.clone(); assert!(arr_cow_clone.is_view()); - assert!(is_content_identical(&arr_cow, &arr_cow_clone)); + assert_eq!(arr_cow, arr_cow_clone); assert_eq!(arr_cow.dim(), arr_cow_clone.dim()); assert_eq!(arr_cow.strides(), arr_cow_clone.strides()); let arr_cow = ArrayCow::::from(arr.clone()); let arr_cow_clone = arr_cow.clone(); assert!(arr_cow_clone.is_owned()); - assert!(is_content_identical(&arr_cow, &arr_cow_clone)); + assert_eq!(arr_cow, arr_cow_clone); assert_eq!(arr_cow.dim(), arr_cow_clone.dim()); assert_eq!(arr_cow.strides(), arr_cow_clone.strides()); } @@ -2032,7 +2015,7 @@ mod array_cow_tests { let other_arr: Array2 = array![[11, 12], [13, 14]]; fn perform_checks(arr1: &ArrayCow, arr2: &ArrayCow) { - assert!(is_content_identical(arr1, arr2)); + assert_eq!(arr1, arr2); assert_eq!(arr1.dim(), arr2.dim()); assert_eq!(arr1.strides(), arr2.strides()); } @@ -2066,12 +2049,12 @@ mod array_cow_tests { fn test_into_owned() { let arr: Array2 = array![[1, 2], [3, 4]]; let cont_arr = ArrayCow::::from(arr.view()).into_owned(); - assert!(is_content_identical(&arr, &cont_arr)); + assert_eq!(arr, cont_arr); let cont_arr = ArrayCow::::from(arr.clone()); let prev_ptr = cont_arr.as_ptr(); let cont_arr = cont_arr.into_owned(); assert_eq!(cont_arr.as_ptr(), prev_ptr); - assert!(is_content_identical(&arr, &cont_arr)); + assert_eq!(arr, cont_arr); } } From d34a675bf289b2668454e3d686c4fb4fad8f7e23 Mon Sep 17 00:00:00 2001 From: andrei-papou Date: Wed, 15 May 2019 14:27:00 +0300 Subject: [PATCH 4/8] Fixed rustfmt errors --- src/data_traits.rs | 41 ++++++++++++++++++++++------------------- src/impl_cow.rs | 12 ++++++------ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/data_traits.rs b/src/data_traits.rs index 62cc2abad..b8fe84234 100644 --- a/src/data_traits.rs +++ b/src/data_traits.rs @@ -12,7 +12,7 @@ use std::mem::{self, size_of}; use std::sync::Arc; use crate::{ - ArrayBase, CowRepr, Dimension, OwnedArcRepr, OwnedRcRepr, OwnedRepr, RawViewRepr, ViewRepr + ArrayBase, CowRepr, Dimension, OwnedArcRepr, OwnedRcRepr, OwnedRepr, RawViewRepr, ViewRepr, }; /// Array representation trait. @@ -434,16 +434,18 @@ unsafe impl<'a, A> RawData for CowRepr<'a, A> { CowRepr::Owned(data) => data._data_slice(), } } - private_impl!{} + private_impl! {} } unsafe impl<'a, A> RawDataMut for CowRepr<'a, A> - where A: Clone +where + A: Clone, { #[inline] fn try_ensure_unique(array: &mut ArrayBase) - where Self: Sized, - D: Dimension + where + Self: Sized, + D: Dimension, { match array.data { CowRepr::View(_) => { @@ -464,35 +466,36 @@ unsafe impl<'a, A> RawDataMut for CowRepr<'a, A> } unsafe impl<'a, A> RawDataClone for CowRepr<'a, A> - where A: Clone +where + A: Clone, { unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) { match self { CowRepr::View(view) => { let (new_view, ptr) = view.clone_with_ptr(ptr); (CowRepr::View(new_view), ptr) - }, + } CowRepr::Owned(data) => { let (new_data, ptr) = data.clone_with_ptr(ptr); (CowRepr::Owned(new_data), ptr) - }, + } } } #[doc(hidden)] - unsafe fn clone_from_with_ptr(&mut self, other: &Self, ptr: *mut Self::Elem) -> *mut Self::Elem { + unsafe fn clone_from_with_ptr( + &mut self, + other: &Self, + ptr: *mut Self::Elem, + ) -> *mut Self::Elem { match (&mut *self, other) { - (CowRepr::View(self_), CowRepr::View(other)) => { - self_.clone_from_with_ptr(other, ptr) - }, - (CowRepr::Owned(self_), CowRepr::Owned(other)) => { - self_.clone_from_with_ptr(other, ptr) - }, + (CowRepr::View(self_), CowRepr::View(other)) => self_.clone_from_with_ptr(other, ptr), + (CowRepr::Owned(self_), CowRepr::Owned(other)) => self_.clone_from_with_ptr(other, ptr), (_, CowRepr::Owned(other)) => { let (cloned, ptr) = other.clone_with_ptr(ptr); *self = CowRepr::Owned(cloned); ptr - }, + } (_, CowRepr::View(other)) => { let (cloned, ptr) = other.clone_with_ptr(ptr); *self = CowRepr::View(cloned); @@ -505,9 +508,9 @@ unsafe impl<'a, A> RawDataClone for CowRepr<'a, A> unsafe impl<'a, A> Data for CowRepr<'a, A> { #[inline] fn into_owned(self_: ArrayBase, D>) -> ArrayBase, D> - where - A: Clone, - D: Dimension, + where + A: Clone, + D: Dimension, { match self_.data { CowRepr::View(_) => self_.to_owned(), diff --git a/src/impl_cow.rs b/src/impl_cow.rs index 560412f61..47b2af574 100644 --- a/src/impl_cow.rs +++ b/src/impl_cow.rs @@ -14,8 +14,8 @@ use crate::imp_prelude::*; /// /// [`ArrayBase`]: struct.ArrayBase.html impl<'a, A, D> ArrayCow<'a, A, D> - where - D: Dimension, +where + D: Dimension, { pub fn is_view(&self) -> bool { self.data.is_view() @@ -27,8 +27,8 @@ impl<'a, A, D> ArrayCow<'a, A, D> } impl<'a, A, D> From> for ArrayCow<'a, A, D> - where - D: Dimension, +where + D: Dimension, { fn from(view: ArrayView<'a, A, D>) -> ArrayCow<'a, A, D> { ArrayBase { @@ -41,8 +41,8 @@ impl<'a, A, D> From> for ArrayCow<'a, A, D> } impl<'a, A, D> From> for ArrayCow<'a, A, D> - where - D: Dimension, +where + D: Dimension, { fn from(array: Array) -> ArrayCow<'a, A, D> { ArrayBase { From 502144ee95b8ce7db7fadbb5a1d58eadbe4f0ad6 Mon Sep 17 00:00:00 2001 From: Jim Turner Date: Wed, 29 May 2019 20:07:52 -0400 Subject: [PATCH 5/8] Apply ArrayCow tests to non-standard layouts --- tests/array.rs | 151 ++++++++++++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 63 deletions(-) diff --git a/tests/array.rs b/tests/array.rs index 62fa44676..b8c528a99 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -1970,91 +1970,116 @@ mod array_cow_tests { let arr_cow = ArrayCow::::from(arr.view()); assert!(arr_cow.is_view()); assert!(!arr_cow.is_owned()); - let arr_cow = ArrayCow::::from(arr.clone()); + let arr_cow = ArrayCow::::from(arr); assert!(arr_cow.is_owned()); assert!(!arr_cow.is_view()); } + fn run_with_various_layouts(mut f: impl FnMut(Array2)) { + for all in vec![ + Array2::from_shape_vec((7, 8), (0..7 * 8).collect()).unwrap(), + Array2::from_shape_vec((7, 8).f(), (0..7 * 8).collect()).unwrap(), + ] { + f(all.clone()); + f(all.clone().slice_move(s![.., 2..5])); + f(all.clone().slice_move(s![3..5, 2..5])); + f(all.clone().slice_move(s![.., ..;2])); + f(all.clone().slice_move(s![..;3, ..])); + f(all.clone().slice_move(s![.., ..;-1])); + f(all.clone().slice_move(s![..;-2, ..;-1])); + f(all.clone().slice_move(s![2..5;-2, 3..6])); + f(all.clone().slice_move(s![2..5;-2, 3..6;-1])); + } + } + #[test] fn test_element_mutation() { - let arr: Array2 = array![[1, 2], [3, 4]]; - let mut arr_cow = ArrayCow::::from(arr.view()); - arr_cow[(1, 1)] = 2; - let expected_arr: Array2 = array![[1, 2], [3, 2]]; - assert!(arr_cow.is_owned()); - assert_eq!(arr_cow, expected_arr); - - let mut arr_cow = ArrayCow::::from(arr.clone()); - let prev_ptr = arr_cow.as_ptr(); - arr_cow[(1, 1)] = 2; - assert_eq!(arr_cow.as_ptr(), prev_ptr); - assert_eq!(arr_cow, expected_arr); + run_with_various_layouts(|arr: Array2| { + let mut expected = arr.clone(); + expected[(1, 1)] = 2; + + let mut arr_cow = ArrayCow::::from(arr.view()); + arr_cow[(1, 1)] = 2; + assert!(arr_cow.is_owned()); + assert_eq!(arr_cow, expected); + + let ptr = arr.as_ptr(); + let mut arr_cow = ArrayCow::::from(arr); + assert_eq!(arr_cow.as_ptr(), ptr); + arr_cow[(1, 1)] = 2; + assert_eq!(arr_cow.as_ptr(), ptr); + assert_eq!(arr_cow, expected); + }); } #[test] fn test_clone() { - let arr: Array2 = array![[1, 2], [3, 4]]; - let arr_cow = ArrayCow::::from(arr.view()); - let arr_cow_clone = arr_cow.clone(); - assert!(arr_cow_clone.is_view()); - assert_eq!(arr_cow, arr_cow_clone); - assert_eq!(arr_cow.dim(), arr_cow_clone.dim()); - assert_eq!(arr_cow.strides(), arr_cow_clone.strides()); - - let arr_cow = ArrayCow::::from(arr.clone()); - let arr_cow_clone = arr_cow.clone(); - assert!(arr_cow_clone.is_owned()); - assert_eq!(arr_cow, arr_cow_clone); - assert_eq!(arr_cow.dim(), arr_cow_clone.dim()); - assert_eq!(arr_cow.strides(), arr_cow_clone.strides()); + run_with_various_layouts(|arr: Array2| { + let arr_cow = ArrayCow::::from(arr.view()); + let arr_cow_clone = arr_cow.clone(); + assert!(arr_cow_clone.is_view()); + assert_eq!(arr_cow, arr_cow_clone); + assert_eq!(arr_cow.dim(), arr_cow_clone.dim()); + assert_eq!(arr_cow.strides(), arr_cow_clone.strides()); + + let arr_cow = ArrayCow::::from(arr); + let arr_cow_clone = arr_cow.clone(); + assert!(arr_cow_clone.is_owned()); + assert_eq!(arr_cow, arr_cow_clone); + assert_eq!(arr_cow.dim(), arr_cow_clone.dim()); + assert_eq!(arr_cow.strides(), arr_cow_clone.strides()); + }); } #[test] fn test_clone_from() { - let arr: Array2 = array![[1, 2], [3, 4]]; - let other_arr: Array2 = array![[11, 12], [13, 14]]; - - fn perform_checks(arr1: &ArrayCow, arr2: &ArrayCow) { + fn assert_eq_contents_and_layout(arr1: &ArrayCow, arr2: &ArrayCow) { assert_eq!(arr1, arr2); assert_eq!(arr1.dim(), arr2.dim()); assert_eq!(arr1.strides(), arr2.strides()); } - let arr_cow_src = ArrayCow::::from(arr.view()); - let mut arr_cow_dst = ArrayCow::::from(other_arr.clone()); - arr_cow_dst.clone_from(&arr_cow_src); - assert!(arr_cow_dst.is_view()); - perform_checks(&arr_cow_src, &arr_cow_dst); - - let arr_cow_src = ArrayCow::::from(arr.view()); - let mut arr_cow_dst = ArrayCow::::from(other_arr.view()); - arr_cow_dst.clone_from(&arr_cow_src); - assert!(arr_cow_dst.is_view()); - perform_checks(&arr_cow_src, &arr_cow_dst); - - let arr_cow_src = ArrayCow::::from(arr.clone()); - let mut arr_cow_dst = ArrayCow::::from(other_arr.view()); - arr_cow_dst.clone_from(&arr_cow_src); - assert!(arr_cow_dst.is_owned()); - perform_checks(&arr_cow_src, &arr_cow_dst); - - let arr_cow_src = ArrayCow::::from(arr.clone()); - let mut arr_cow_dst = ArrayCow::::from(other_arr.clone()); - arr_cow_dst.clone_from(&arr_cow_src); - assert!(arr_cow_dst.is_owned()); - perform_checks(&arr_cow_src, &arr_cow_dst); + run_with_various_layouts(|arr: Array2| { + run_with_various_layouts(|other_arr: Array2| { + let arr_cow_src = ArrayCow::::from(arr.view()); + let mut arr_cow_dst = ArrayCow::::from(other_arr.clone()); + arr_cow_dst.clone_from(&arr_cow_src); + assert!(arr_cow_dst.is_view()); + assert_eq_contents_and_layout(&arr_cow_src, &arr_cow_dst); + + let arr_cow_src = ArrayCow::::from(arr.view()); + let mut arr_cow_dst = ArrayCow::::from(other_arr.view()); + arr_cow_dst.clone_from(&arr_cow_src); + assert!(arr_cow_dst.is_view()); + assert_eq_contents_and_layout(&arr_cow_src, &arr_cow_dst); + + let arr_cow_src = ArrayCow::::from(arr.clone()); + let mut arr_cow_dst = ArrayCow::::from(other_arr.view()); + arr_cow_dst.clone_from(&arr_cow_src); + assert!(arr_cow_dst.is_owned()); + assert_eq_contents_and_layout(&arr_cow_src, &arr_cow_dst); + + let arr_cow_src = ArrayCow::::from(arr.clone()); + let mut arr_cow_dst = ArrayCow::::from(other_arr.clone()); + arr_cow_dst.clone_from(&arr_cow_src); + assert!(arr_cow_dst.is_owned()); + assert_eq_contents_and_layout(&arr_cow_src, &arr_cow_dst); + }); + }); } #[test] fn test_into_owned() { - let arr: Array2 = array![[1, 2], [3, 4]]; - let cont_arr = ArrayCow::::from(arr.view()).into_owned(); - assert_eq!(arr, cont_arr); - - let cont_arr = ArrayCow::::from(arr.clone()); - let prev_ptr = cont_arr.as_ptr(); - let cont_arr = cont_arr.into_owned(); - assert_eq!(cont_arr.as_ptr(), prev_ptr); - assert_eq!(arr, cont_arr); + run_with_various_layouts(|arr: Array2| { + let before = ArrayCow::::from(arr.view()); + let after = before.into_owned(); + assert_eq!(arr, after); + + let before = ArrayCow::::from(arr.clone()); + let ptr = before.as_ptr(); + let after = before.into_owned(); + assert_eq!(after.as_ptr(), ptr); + assert_eq!(arr, after); + }); } } From aefaacf2646b3d650a58b0d8d7f0debeb57f0051 Mon Sep 17 00:00:00 2001 From: Jim Turner Date: Wed, 29 May 2019 21:01:21 -0400 Subject: [PATCH 6/8] Improve documentation for ArrayCow --- src/doc/ndarray_for_numpy_users/mod.rs | 9 ++- src/impl_cow.rs | 2 + src/lib.rs | 99 ++++++++++++++++++++++++-- 3 files changed, 101 insertions(+), 9 deletions(-) diff --git a/src/doc/ndarray_for_numpy_users/mod.rs b/src/doc/ndarray_for_numpy_users/mod.rs index 037752fa0..87f5111e1 100644 --- a/src/doc/ndarray_for_numpy_users/mod.rs +++ b/src/doc/ndarray_for_numpy_users/mod.rs @@ -72,9 +72,11 @@ //! In `ndarray`, all arrays are instances of [`ArrayBase`][ArrayBase], but //! `ArrayBase` is generic over the ownership of the data. [`Array`][Array] //! owns its data; [`ArrayView`][ArrayView] is a view; -//! [`ArrayViewMut`][ArrayViewMut] is a mutable view; and -//! [`ArcArray`][ArcArray] has a reference-counted pointer to its data (with -//! copy-on-write mutation). Arrays and views follow Rust's aliasing rules. +//! [`ArrayViewMut`][ArrayViewMut] is a mutable view; [`ArrayCow`][ArrayCow] +//! either owns its data or is a view (with copy-on-write mutation of the view +//! variant); and [`ArcArray`][ArcArray] has a reference-counted pointer to its +//! data (with copy-on-write mutation). Arrays and views follow Rust's aliasing +//! rules. //! //! //! @@ -564,6 +566,7 @@ //! [Array]: ../../type.Array.html //! [Array2]: ../../type.Array2.html //! [ArrayBase]: ../../struct.ArrayBase.html +//! [ArrayCow]: ../../type.ArrayCow.html //! [ArrayView]: ../../type.ArrayView.html //! [ArrayViewMut]: ../../type.ArrayViewMut.html //! [.assign()]: ../../struct.ArrayBase.html#method.assign diff --git a/src/impl_cow.rs b/src/impl_cow.rs index 47b2af574..34f6386a0 100644 --- a/src/impl_cow.rs +++ b/src/impl_cow.rs @@ -17,10 +17,12 @@ impl<'a, A, D> ArrayCow<'a, A, D> where D: Dimension, { + /// Returns `true` iff the array is the view (borrowed) variant. pub fn is_view(&self) -> bool { self.data.is_view() } + /// Returns `true` iff the array is the owned variant. pub fn is_owned(&self) -> bool { self.data.is_owned() } diff --git a/src/lib.rs b/src/lib.rs index ac66d936a..7f44d2e10 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -218,8 +218,9 @@ pub type Ixs = isize; /// The `ArrayBase` is parameterized by `S` for the data container and /// `D` for the dimensionality. /// -/// Type aliases [`Array`], [`ArcArray`], [`ArrayView`], and [`ArrayViewMut`] refer -/// to `ArrayBase` with different types for the data container. +/// Type aliases [`Array`], [`ArcArray`], [`ArrayView`], [`ArrayViewMut`], and +/// [`ArrayCow`] refer to `ArrayBase` with different types for the data +/// container. /// /// [`Array`]: type.Array.html /// [`ArcArray`]: type.ArcArray.html @@ -230,6 +231,7 @@ pub type Ixs = isize; /// /// + [Array](#array) /// + [ArcArray](#arcarray) +/// + [ArrayCow](#arraycow) /// + [Array Views](#array-views) /// + [Indexing and Dimension](#indexing-and-dimension) /// + [Loops, Producers and Iterators](#loops-producers-and-iterators) @@ -273,6 +275,16 @@ pub type Ixs = isize; /// [`view_mut()`](#method.view_mut) or [`get_mut()`](#method.get_mut), /// will break sharing and require a clone of the data (if it is not uniquely held). /// +/// ## `ArrayCow` +/// +/// [`ArrayCow`](type.ArrayCow.html) is analogous to +/// [`std::borrow::Cow`](https://doc.rust-lang.org/std/borrow/enum.Cow.html). +/// It can represent either an immutable view or a uniquely owned array. If an +/// `ArrayCow` instance is the immutable view variant, then calling a method +/// for mutating elements in the array will cause it to be converted into the +/// owned variant (by cloning all the elements) before the modification is +/// performed. +/// /// ## Array Views /// /// [`ArrayView`] and [`ArrayViewMut`] are read-only and read-write array views @@ -705,7 +717,7 @@ pub type Ixs = isize; /// /// /// -/// +/// /// /// /// @@ -721,6 +733,11 @@ pub type Ixs = isize; /// /// +/// @@ -751,6 +768,11 @@ pub type Ixs = isize; /// /// +/// @@ -781,6 +803,11 @@ pub type Ixs = isize; /// /// +/// @@ -791,6 +818,41 @@ pub type Ixs = isize; /// /// /// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// /// /// /// @@ -811,6 +873,11 @@ pub type Ixs = isize; /// /// +/// @@ -841,6 +908,11 @@ pub type Ixs = isize; /// /// +/// @@ -859,7 +931,7 @@ pub type Ixs = isize; /// equivalent with dim `D2` (e.g. converting from dynamic dim to const dim) /// /// -/// -/// -/// /// /// /// /// -/// +/// /// /// /// /// /// /// /// /// /// @@ -1293,12 +1294,12 @@ pub type Array = ArrayBase, D>; /// An array with copy-on-write behavior. /// -/// An `ArrayCow` represents either a uniquely owned array or a view of an +/// An `CowArray` represents either a uniquely owned array or a view of an /// array. The `'a` corresponds to the lifetime of the view variant. /// /// This type is analogous to /// [`std::borrow::Cow`](https://doc.rust-lang.org/std/borrow/enum.Cow.html). -/// If an `ArrayCow` instance is the immutable view variant, then calling a +/// If a `CowArray` instance is the immutable view variant, then calling a /// method for mutating elements in the array will cause it to be converted /// into the owned variant (by cloning all the elements) before the /// modification is performed. @@ -1310,7 +1311,7 @@ pub type Array = ArrayBase, D>; /// instead of either a view or a uniquely owned copy. /// /// [ab]: struct.ArrayBase.html -pub type ArrayCow<'a, A, D> = ArrayBase, D>; +pub type CowArray<'a, A, D> = ArrayBase, D>; /// A read-only array view. /// @@ -1456,10 +1457,10 @@ impl ViewRepr { } } -/// ArrayCow's representation. +/// CowArray's representation. /// /// *Don't use this type directly—use the type alias -/// [`ArrayCow`](type.ArrayCow.html) for the array type!* +/// [`CowArray`](type.CowArray.html) for the array type!* pub enum CowRepr<'a, A> { /// Borrowed data. View(ViewRepr<&'a A>), diff --git a/src/prelude.rs b/src/prelude.rs index 4d08b6731..4d3887971 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -21,7 +21,7 @@ #[doc(no_inline)] #[allow(deprecated)] pub use crate::{ - ArcArray, Array, ArrayBase, ArrayCow, ArrayView, ArrayViewMut, RawArrayView, RawArrayViewMut, + ArcArray, Array, ArrayBase, ArrayView, ArrayViewMut, CowArray, RawArrayView, RawArrayViewMut, RcArray, }; diff --git a/tests/array.rs b/tests/array.rs index b8c528a99..1187133bc 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -1967,10 +1967,10 @@ mod array_cow_tests { #[test] fn test_is_variant() { let arr: Array = array![[1, 2], [3, 4]]; - let arr_cow = ArrayCow::::from(arr.view()); + let arr_cow = CowArray::::from(arr.view()); assert!(arr_cow.is_view()); assert!(!arr_cow.is_owned()); - let arr_cow = ArrayCow::::from(arr); + let arr_cow = CowArray::::from(arr); assert!(arr_cow.is_owned()); assert!(!arr_cow.is_view()); } @@ -1998,13 +1998,13 @@ mod array_cow_tests { let mut expected = arr.clone(); expected[(1, 1)] = 2; - let mut arr_cow = ArrayCow::::from(arr.view()); + let mut arr_cow = CowArray::::from(arr.view()); arr_cow[(1, 1)] = 2; assert!(arr_cow.is_owned()); assert_eq!(arr_cow, expected); let ptr = arr.as_ptr(); - let mut arr_cow = ArrayCow::::from(arr); + let mut arr_cow = CowArray::::from(arr); assert_eq!(arr_cow.as_ptr(), ptr); arr_cow[(1, 1)] = 2; assert_eq!(arr_cow.as_ptr(), ptr); @@ -2015,14 +2015,14 @@ mod array_cow_tests { #[test] fn test_clone() { run_with_various_layouts(|arr: Array2| { - let arr_cow = ArrayCow::::from(arr.view()); + let arr_cow = CowArray::::from(arr.view()); let arr_cow_clone = arr_cow.clone(); assert!(arr_cow_clone.is_view()); assert_eq!(arr_cow, arr_cow_clone); assert_eq!(arr_cow.dim(), arr_cow_clone.dim()); assert_eq!(arr_cow.strides(), arr_cow_clone.strides()); - let arr_cow = ArrayCow::::from(arr); + let arr_cow = CowArray::::from(arr); let arr_cow_clone = arr_cow.clone(); assert!(arr_cow_clone.is_owned()); assert_eq!(arr_cow, arr_cow_clone); @@ -2033,7 +2033,7 @@ mod array_cow_tests { #[test] fn test_clone_from() { - fn assert_eq_contents_and_layout(arr1: &ArrayCow, arr2: &ArrayCow) { + fn assert_eq_contents_and_layout(arr1: &CowArray, arr2: &CowArray) { assert_eq!(arr1, arr2); assert_eq!(arr1.dim(), arr2.dim()); assert_eq!(arr1.strides(), arr2.strides()); @@ -2041,26 +2041,26 @@ mod array_cow_tests { run_with_various_layouts(|arr: Array2| { run_with_various_layouts(|other_arr: Array2| { - let arr_cow_src = ArrayCow::::from(arr.view()); - let mut arr_cow_dst = ArrayCow::::from(other_arr.clone()); + let arr_cow_src = CowArray::::from(arr.view()); + let mut arr_cow_dst = CowArray::::from(other_arr.clone()); arr_cow_dst.clone_from(&arr_cow_src); assert!(arr_cow_dst.is_view()); assert_eq_contents_and_layout(&arr_cow_src, &arr_cow_dst); - let arr_cow_src = ArrayCow::::from(arr.view()); - let mut arr_cow_dst = ArrayCow::::from(other_arr.view()); + let arr_cow_src = CowArray::::from(arr.view()); + let mut arr_cow_dst = CowArray::::from(other_arr.view()); arr_cow_dst.clone_from(&arr_cow_src); assert!(arr_cow_dst.is_view()); assert_eq_contents_and_layout(&arr_cow_src, &arr_cow_dst); - let arr_cow_src = ArrayCow::::from(arr.clone()); - let mut arr_cow_dst = ArrayCow::::from(other_arr.view()); + let arr_cow_src = CowArray::::from(arr.clone()); + let mut arr_cow_dst = CowArray::::from(other_arr.view()); arr_cow_dst.clone_from(&arr_cow_src); assert!(arr_cow_dst.is_owned()); assert_eq_contents_and_layout(&arr_cow_src, &arr_cow_dst); - let arr_cow_src = ArrayCow::::from(arr.clone()); - let mut arr_cow_dst = ArrayCow::::from(other_arr.clone()); + let arr_cow_src = CowArray::::from(arr.clone()); + let mut arr_cow_dst = CowArray::::from(other_arr.clone()); arr_cow_dst.clone_from(&arr_cow_src); assert!(arr_cow_dst.is_owned()); assert_eq_contents_and_layout(&arr_cow_src, &arr_cow_dst); @@ -2071,11 +2071,11 @@ mod array_cow_tests { #[test] fn test_into_owned() { run_with_various_layouts(|arr: Array2| { - let before = ArrayCow::::from(arr.view()); + let before = CowArray::::from(arr.view()); let after = before.into_owned(); assert_eq!(arr, after); - let before = ArrayCow::::from(arr.clone()); + let before = CowArray::::from(arr.clone()); let ptr = before.as_ptr(); let after = before.into_owned(); assert_eq!(after.as_ptr(), ptr);
OutputInputInput
/// +/// `ArrayCow<'a, A, D>` +/// +/// +/// /// `ArrayView<'a, A, D>` /// /// /// +/// [`a.into_owned()`][.into_owned()] +/// +/// +/// /// [`a.to_owned()`][.to_owned()] /// /// /// +/// [`a.into_owned().into_shared()`][.into_shared()] +/// +/// +/// /// [`a.to_owned().into_shared()`][.into_shared()] /// ///
+/// +/// `ArrayCow<'a, A, D>` +/// +/// +/// +/// [`ArrayCow::from(a)`](type.ArrayCow.html#impl-From%2C%20D>>) +/// +/// +/// +/// [`ArrayCow::from(a.into_owned())`](type.ArrayCow.html#impl-From%2C%20D>>) +/// +/// +/// +/// no-op +/// +/// +/// +/// [`ArrayCow::from(a)`](type.ArrayCow.html#impl-From%2C%20D>>) +/// +/// +/// +/// [`ArrayCow::from(a.view())`](type.ArrayCow.html#impl-From%2C%20D>>) +/// +///
/// +/// [`a.view()`][.view()] +/// +/// +/// /// [`a.view()`][.view()] or [`a.reborrow()`][ArrayView::reborrow()] /// /// /// +/// [`a.view_mut()`][.view_mut()] +/// +/// +/// /// illegal /// /// +/// /// /// [`a.into_dimensionality::()`][.into_dimensionality()] /// @@ -874,7 +946,7 @@ pub type Ixs = isize; /// equivalent with dim `IxDyn` /// /// +/// /// /// [`a.into_dyn()`][.into_dyn()] /// @@ -889,7 +961,7 @@ pub type Ixs = isize; /// `Array` (new element type) /// /// +/// /// /// [`a.map(|x| x.do_your_conversion())`][.map()] /// @@ -1224,6 +1296,13 @@ pub type Array = ArrayBase, D>; /// An `ArrayCow` represents either a uniquely owned array or a view of an /// array. The `'a` corresponds to the lifetime of the view variant. /// +/// This type is analogous to +/// [`std::borrow::Cow`](https://doc.rust-lang.org/std/borrow/enum.Cow.html). +/// If an `ArrayCow` instance is the immutable view variant, then calling a +/// method for mutating elements in the array will cause it to be converted +/// into the owned variant (by cloning all the elements) before the +/// modification is performed. +/// /// Array views have all the methods of an array (see [`ArrayBase`][ab]). /// /// See also [`ArcArray`](type.ArcArray.html), which also provides @@ -1377,12 +1456,19 @@ impl ViewRepr { } } +/// ArrayCow's representation. +/// +/// *Don't use this type directly—use the type alias +/// [`ArrayCow`](type.ArrayCow.html) for the array type!* pub enum CowRepr<'a, A> { + /// Borrowed data. View(ViewRepr<&'a A>), + /// Owned data. Owned(OwnedRepr), } impl<'a, A> CowRepr<'a, A> { + /// Returns `true` iff the data is the `View` variant. pub fn is_view(&self) -> bool { match self { CowRepr::View(_) => true, @@ -1390,6 +1476,7 @@ impl<'a, A> CowRepr<'a, A> { } } + /// Returns `true` iff the data is the `Owned` variant. pub fn is_owned(&self) -> bool { !self.is_view() } From fde676d61644b54b31e6458aade8f1c3e530a1bf Mon Sep 17 00:00:00 2001 From: Jim Turner Date: Wed, 29 May 2019 21:01:54 -0400 Subject: [PATCH 7/8] Use match This is just a personal preference. --- src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 7f44d2e10..bfa9fdc8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1478,7 +1478,10 @@ impl<'a, A> CowRepr<'a, A> { /// Returns `true` iff the data is the `Owned` variant. pub fn is_owned(&self) -> bool { - !self.is_view() + match self { + CowRepr::View(_) => false, + CowRepr::Owned(_) => true, + } } } From a1d07d6bf3a9635d3d1c6cbfa5b2f92729e22693 Mon Sep 17 00:00:00 2001 From: Jim Turner Date: Wed, 29 May 2019 21:14:29 -0400 Subject: [PATCH 8/8] Rename ArrayCow to CowArray --- src/doc/ndarray_for_numpy_users/mod.rs | 4 +-- src/impl_cow.rs | 12 ++++---- src/lib.rs | 39 +++++++++++++------------- src/prelude.rs | 2 +- tests/array.rs | 34 +++++++++++----------- 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/doc/ndarray_for_numpy_users/mod.rs b/src/doc/ndarray_for_numpy_users/mod.rs index 87f5111e1..c2ec9e2d2 100644 --- a/src/doc/ndarray_for_numpy_users/mod.rs +++ b/src/doc/ndarray_for_numpy_users/mod.rs @@ -72,7 +72,7 @@ //! In `ndarray`, all arrays are instances of [`ArrayBase`][ArrayBase], but //! `ArrayBase` is generic over the ownership of the data. [`Array`][Array] //! owns its data; [`ArrayView`][ArrayView] is a view; -//! [`ArrayViewMut`][ArrayViewMut] is a mutable view; [`ArrayCow`][ArrayCow] +//! [`ArrayViewMut`][ArrayViewMut] is a mutable view; [`CowArray`][CowArray] //! either owns its data or is a view (with copy-on-write mutation of the view //! variant); and [`ArcArray`][ArcArray] has a reference-counted pointer to its //! data (with copy-on-write mutation). Arrays and views follow Rust's aliasing @@ -566,7 +566,6 @@ //! [Array]: ../../type.Array.html //! [Array2]: ../../type.Array2.html //! [ArrayBase]: ../../struct.ArrayBase.html -//! [ArrayCow]: ../../type.ArrayCow.html //! [ArrayView]: ../../type.ArrayView.html //! [ArrayViewMut]: ../../type.ArrayViewMut.html //! [.assign()]: ../../struct.ArrayBase.html#method.assign @@ -575,6 +574,7 @@ //! [.cols()]: ../../struct.ArrayBase.html#method.cols //! [.column()]: ../../struct.ArrayBase.html#method.column //! [.column_mut()]: ../../struct.ArrayBase.html#method.column_mut +//! [CowArray]: ../../type.CowArray.html //! [::default()]: ../../struct.ArrayBase.html#method.default //! [.diag()]: ../../struct.ArrayBase.html#method.diag //! [.dim()]: ../../struct.ArrayBase.html#method.dim diff --git a/src/impl_cow.rs b/src/impl_cow.rs index 34f6386a0..52a06bfa2 100644 --- a/src/impl_cow.rs +++ b/src/impl_cow.rs @@ -8,12 +8,12 @@ use crate::imp_prelude::*; -/// Methods specific to `ArrayCow`. +/// Methods specific to `CowArray`. /// /// ***See also all methods for [`ArrayBase`]*** /// /// [`ArrayBase`]: struct.ArrayBase.html -impl<'a, A, D> ArrayCow<'a, A, D> +impl<'a, A, D> CowArray<'a, A, D> where D: Dimension, { @@ -28,11 +28,11 @@ where } } -impl<'a, A, D> From> for ArrayCow<'a, A, D> +impl<'a, A, D> From> for CowArray<'a, A, D> where D: Dimension, { - fn from(view: ArrayView<'a, A, D>) -> ArrayCow<'a, A, D> { + fn from(view: ArrayView<'a, A, D>) -> CowArray<'a, A, D> { ArrayBase { data: CowRepr::View(view.data), ptr: view.ptr, @@ -42,11 +42,11 @@ where } } -impl<'a, A, D> From> for ArrayCow<'a, A, D> +impl<'a, A, D> From> for CowArray<'a, A, D> where D: Dimension, { - fn from(array: Array) -> ArrayCow<'a, A, D> { + fn from(array: Array) -> CowArray<'a, A, D> { ArrayBase { data: CowRepr::Owned(array.data), ptr: array.ptr, diff --git a/src/lib.rs b/src/lib.rs index bfa9fdc8c..9741989d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -218,20 +218,21 @@ pub type Ixs = isize; /// The `ArrayBase` is parameterized by `S` for the data container and /// `D` for the dimensionality. /// -/// Type aliases [`Array`], [`ArcArray`], [`ArrayView`], [`ArrayViewMut`], and -/// [`ArrayCow`] refer to `ArrayBase` with different types for the data +/// Type aliases [`Array`], [`ArcArray`], [`CowArray`], [`ArrayView`], and +/// [`ArrayViewMut`] refer to `ArrayBase` with different types for the data /// container. /// /// [`Array`]: type.Array.html /// [`ArcArray`]: type.ArcArray.html /// [`ArrayView`]: type.ArrayView.html /// [`ArrayViewMut`]: type.ArrayViewMut.html +/// [`CowArray`]: type.CowArray.html /// /// ## Contents /// /// + [Array](#array) /// + [ArcArray](#arcarray) -/// + [ArrayCow](#arraycow) +/// + [CowArray](#cowarray) /// + [Array Views](#array-views) /// + [Indexing and Dimension](#indexing-and-dimension) /// + [Loops, Producers and Iterators](#loops-producers-and-iterators) @@ -275,12 +276,12 @@ pub type Ixs = isize; /// [`view_mut()`](#method.view_mut) or [`get_mut()`](#method.get_mut), /// will break sharing and require a clone of the data (if it is not uniquely held). /// -/// ## `ArrayCow` +/// ## `CowArray` /// -/// [`ArrayCow`](type.ArrayCow.html) is analogous to +/// [`CowArray`](type.CowArray.html) is analogous to /// [`std::borrow::Cow`](https://doc.rust-lang.org/std/borrow/enum.Cow.html). -/// It can represent either an immutable view or a uniquely owned array. If an -/// `ArrayCow` instance is the immutable view variant, then calling a method +/// It can represent either an immutable view or a uniquely owned array. If a +/// `CowArray` instance is the immutable view variant, then calling a method /// for mutating elements in the array will cause it to be converted into the /// owned variant (by cloning all the elements) before the modification is /// performed. @@ -733,7 +734,7 @@ pub type Ixs = isize; /// /// -/// `ArrayCow<'a, A, D>` +/// `CowArray<'a, A, D>` /// /// @@ -818,22 +819,22 @@ pub type Ixs = isize; ///
/// -/// `ArrayCow<'a, A, D>` +/// `CowArray<'a, A, D>` /// /// /// -/// [`ArrayCow::from(a)`](type.ArrayCow.html#impl-From%2C%20D>>) +/// [`CowArray::from(a)`](type.CowArray.html#impl-From%2C%20D>>) /// /// /// -/// [`ArrayCow::from(a.into_owned())`](type.ArrayCow.html#impl-From%2C%20D>>) +/// [`CowArray::from(a.into_owned())`](type.CowArray.html#impl-From%2C%20D>>) /// /// @@ -843,12 +844,12 @@ pub type Ixs = isize; /// /// -/// [`ArrayCow::from(a)`](type.ArrayCow.html#impl-From%2C%20D>>) +/// [`CowArray::from(a)`](type.CowArray.html#impl-From%2C%20D>>) /// /// /// -/// [`ArrayCow::from(a.view())`](type.ArrayCow.html#impl-From%2C%20D>>) +/// [`CowArray::from(a.view())`](type.CowArray.html#impl-From%2C%20D>>) /// ///