Fix implementation of Vector::clone for non-copy types
MODIFY
binding-generator/src/type_ref.rs
binding-generator/src/type_ref.rs
@@ -734,6 +734,20 @@ impl<'tu> TypeRef<'tu> {
|| self.canonical().as_simple_class().is_some()
}
+ pub fn is_clone(&self) -> bool {
+ self.is_copy() || match self.kind() {
+ Kind::StdVector(vec) => {
+ vec.element_type().is_clone()
+ },
+ Kind::Class(cls) => {
+ cls.has_clone()
+ },
+ _ => {
+ false
+ }
+ }
+ }
+
pub fn as_class(&self) -> Option<Class<'tu>> {
if let Kind::Class(out) = self.canonical().kind() {
Some(out)

MODIFY
binding-generator/src/writer/rust_native/tpl/vector/cpp.tpl.cpp
binding-generator/src/writer/rust_native/tpl/vector/cpp.tpl.cpp
@@ -7,10 +7,6 @@ extern "C" {
return new {{cpp_full}}();
}
- {{cpp_extern_return}} cv_{{rust_localalias}}_clone(const {{cpp_full}}* instance) {
- return new {{cpp_full}}(*instance);
- }
-
size_t cv_{{rust_localalias}}_len(const {{cpp_full}}* instance) {
return instance->size();
}

MODIFY
binding-generator/src/writer/rust_native/tpl/vector/cpp_methods_copy_non_bool.tpl.cpp
binding-generator/src/writer/rust_native/tpl/vector/cpp_methods_copy_non_bool.tpl.cpp
@@ -6,4 +6,8 @@ const {{inner_cpp_extern_return}}* cv_{{rust_localalias}}_data(const {{cpp_full}
return instance->data();
}
+ {{cpp_extern_return}} cv_{{rust_localalias}}_clone(const {{cpp_full}}* instance) {
+ return new {{cpp_full}}(*instance);
+ }
+

MODIFY
binding-generator/src/writer/rust_native/tpl/vector/rust.tpl.rs
binding-generator/src/writer/rust_native/tpl/vector/rust.tpl.rs
{{alias}}
vector_extern! { {{inner_rust_full}}, {{rust_extern_const}}, {{rust_extern_mut}},
- cv_{{rust_localalias}}_new, cv_{{rust_localalias}}_clone, cv_{{rust_localalias}}_delete,
+ cv_{{rust_localalias}}_new, cv_{{rust_localalias}}_delete,
cv_{{rust_localalias}}_len, cv_{{rust_localalias}}_is_empty,
cv_{{rust_localalias}}_capacity, cv_{{rust_localalias}}_shrink_to_fit,
cv_{{rust_localalias}}_reserve, cv_{{rust_localalias}}_remove,

MODIFY
binding-generator/src/writer/rust_native/tpl/vector/rust_copy_non_bool.tpl.rs
binding-generator/src/writer/rust_native/tpl/vector/rust_copy_non_bool.tpl.rs
vector_copy_non_bool! { {{inner_rust_full}}, {{rust_extern_const}}, {{rust_extern_mut}},
cv_{{rust_localalias}}_data, cv_{{rust_localalias}}_data_mut,
+ cv_{{rust_localalias}}_clone,
}

MODIFY
binding-generator/src/writer/rust_native/tpl/vector/rust_non_copy_or_bool.tpl.rs
binding-generator/src/writer/rust_native/tpl/vector/rust_non_copy_or_bool.tpl.rs
-vector_non_copy_or_bool! { {{inner_rust_full}} }
+vector_non_copy_or_bool! { {{clone}}{{inner_rust_full}} }

MODIFY
binding-generator/src/writer/rust_native/vector.rs
binding-generator/src/writer/rust_native/vector.rs
@@ -63,6 +63,11 @@ impl RustNativeGeneratedElement for Vector<'_> {
if element_type.is_copy() && !element_type.is_bool() {
additional_methods += &ADD_COPY_NON_BOOL_TPL.interpolate(&inter_vars);
} else {
+ inter_vars.insert("clone", if vec_type.is_clone() {
+ "clone "
+ } else {
+ ""
+ }.into());
additional_methods += &ADD_NON_COPY_OR_BOOL_TPL.interpolate(&inter_vars);
}
if self.is_data_type(&element_type) {

MODIFY
src/manual/core/vector.rs
src/manual/core/vector.rs
@@ -32,10 +32,6 @@ impl<T: VectorElement> Vector<T> where Self: VectorExtern<T> {
unsafe { Self::from_raw(Self::extern_new()) }
}
- fn clone(&self) -> Vector<T> {
- unsafe { Self::from_raw(self.extern_clone()) }
- }
-
/// Create a Vector with pre-defined capacity
pub fn with_capacity(capacity: size_t) -> Self {
let mut out = Self::new();
@@ -102,6 +98,11 @@ impl<T: VectorElement> Vector<T> where Self: VectorExtern<T> {
unsafe { self.extern_push(val.opencv_as_extern()) }
}
+ pub(crate) fn push_owned(&mut self, val: T) {
+ let val = val.opencv_into_extern_container_nofail();
+ unsafe { self.extern_push_owned(val.opencv_as_extern()) }
+ }
+
/// Insert a new element at the specified `index`
pub fn insert(&mut self, index: size_t, val: <T as OpenCVType>::Arg) -> Result<()> {
vector_index_check(index, self.len() + 1)?;
@@ -168,13 +169,6 @@ impl<T: VectorElement> Default for Vector<T> where Self: VectorExtern<T> {
}
}
-impl<T: VectorElement> Clone for Vector<T> where Vector<T>: VectorExtern<T> {
- #[inline]
- fn clone(&self) -> Vector<T> {
- self.clone()
- }
-}
-
impl<T: VectorElement> From<Vector<T>> for Vec<T> where Vector<T>: VectorExtern<T> {
#[inline]
fn from(from: Vector<T>) -> Self {

MODIFY
src/manual/core/vector/vector_extern.rs
src/manual/core/vector/vector_extern.rs
@@ -15,7 +15,6 @@ pub trait VectorElement: for<'a> OpenCVType<'a> where Vector<Self>: VectorExtern
#[doc(hidden)]
pub trait VectorExtern<T: for<'a> OpenCVType<'a>> {
#[doc(hidden)] unsafe fn extern_new() -> *mut c_void;
- #[doc(hidden)] unsafe fn extern_clone(&self) -> *mut c_void;
#[doc(hidden)] unsafe fn extern_delete(&mut self);
#[doc(hidden)] unsafe fn extern_len(&self) -> size_t;
#[doc(hidden)] unsafe fn extern_is_empty(&self) -> bool;
@@ -27,6 +26,7 @@ pub trait VectorExtern<T: for<'a> OpenCVType<'a>> {
#[doc(hidden)] unsafe fn extern_clear(&mut self);
#[doc(hidden)] unsafe fn extern_get(&self, index: size_t) -> Result<<T as OpenCVType<'_>>::ExternReceive>;
#[doc(hidden)] unsafe fn extern_push<'a>(&mut self, val: <<<T as OpenCVType<'a>>::Arg as OpenCVTypeArg<'a>>::ExternContainer as OpenCVTypeExternContainer>::ExternSend);
+ #[doc(hidden)] unsafe fn extern_push_owned(&mut self, val: <<T as OpenCVType>::ExternContainer as OpenCVTypeExternContainer>::ExternSend);
#[doc(hidden)] unsafe fn extern_insert<'a>(&mut self, index: size_t, val: <<<T as OpenCVType<'a>>::Arg as OpenCVTypeArg<'a>>::ExternContainer as OpenCVTypeExternContainer>::ExternSend);
#[doc(hidden)] unsafe fn extern_set<'a>(&mut self, index: size_t, val: <<<T as OpenCVType<'a>>::Arg as OpenCVTypeArg<'a>>::ExternContainer as OpenCVTypeExternContainer>::ExternSend);
}
@@ -38,7 +38,6 @@ macro_rules! vector_extern {
$vector_extern_const: ty,
$vector_extern_mut: ty,
$extern_new: ident,
- $extern_clone: ident,
$extern_delete: ident,
$extern_len: ident,
$extern_is_empty: ident,
@@ -51,7 +50,7 @@ macro_rules! vector_extern {
$extern_get: ident,
$extern_set: ident,
$extern_push: ident,
- $extern_insert: ident,
+ $extern_insert: ident $(,)?
) => {
impl $crate::manual::core::VectorExtern<$type> for $crate::manual::core::Vector<$type> {
#[inline(always)]
@@ -60,12 +59,6 @@ macro_rules! vector_extern {
$extern_new()
}
- #[inline(always)]
- unsafe fn extern_clone(&self) -> $vector_extern_mut {
- extern "C" { fn $extern_clone(instance: $vector_extern_const) -> $vector_extern_mut; }
- $extern_clone(self.as_raw())
- }
-
#[inline(always)]
unsafe fn extern_delete(&mut self) {
extern "C" { fn $extern_delete(instance: $vector_extern_mut); }
@@ -132,6 +125,12 @@ macro_rules! vector_extern {
$extern_push(self.as_raw_mut(), val)
}
+ #[inline(always)]
+ unsafe fn extern_push_owned(&mut self, val: <<$type as $crate::traits::OpenCVType>::ExternContainer as $crate::traits::OpenCVTypeExternContainer>::ExternSend) {
+ extern "C" { fn $extern_push<'a>(instance: $vector_extern_mut, val: <<<$type as $crate::traits::OpenCVType<'a>>::Arg as $crate::traits::OpenCVTypeArg<'a>>::ExternContainer as $crate::traits::OpenCVTypeExternContainer>::ExternSend); }
+ $extern_push(self.as_raw_mut(), val)
+ }
+
#[inline(always)]
unsafe fn extern_insert<'a>(&mut self, index: $crate::platform_types::size_t, val: <<<$type as $crate::traits::OpenCVType<'a>>::Arg as $crate::traits::OpenCVTypeArg<'a>>::ExternContainer as $crate::traits::OpenCVTypeExternContainer>::ExternSend) {
extern "C" { fn $extern_insert<'a>(instance: $vector_extern_mut, index: $crate::platform_types::size_t, val: <<<$type as $crate::traits::OpenCVType<'a>>::Arg as $crate::traits::OpenCVTypeArg<'a>>::ExternContainer as $crate::traits::OpenCVTypeExternContainer>::ExternSend); }
@@ -160,8 +159,17 @@ macro_rules! vector_copy_non_bool {
$vector_extern_const: ty,
$vector_extern_mut: ty,
$extern_data_const: ident,
- $extern_data_mut: ident $(,)?
+ $extern_data_mut: ident,
+ $extern_clone: ident $(,)?
) => {
+ impl $crate::manual::core::Vector<$type> where $crate::manual::core::Vector<$type>: $crate::manual::core::VectorExtern<$type> {
+ #[inline(always)]
+ unsafe fn extern_clone(&self) -> $vector_extern_mut {
+ extern "C" { fn $extern_clone(instance: $vector_extern_const) -> $vector_extern_mut; }
+ $extern_clone(self.as_raw())
+ }
+ }
+
impl $crate::manual::core::VectorElement for $type where $crate::manual::core::Vector<$type>: $crate::manual::core::VectorExtern<$type> {
#[inline(always)]
fn convert_to_vec(v: &$crate::manual::core::Vector<$type>) -> std::vec::Vec<$type> {
@@ -169,6 +177,12 @@ macro_rules! vector_copy_non_bool {
}
}
+ impl std::clone::Clone for $crate::manual::core::Vector<$type> where Self: $crate::manual::core::VectorExtern<$type> {
+ fn clone(&self) -> Self {
+ unsafe { Self::from_raw(self.extern_clone()) }
+ }
+ }
+
impl $crate::manual::core::VectorExternCopyNonBool<$type> for $crate::manual::core::Vector<$type> {
#[inline(always)]
unsafe fn extern_data(&self) -> *const $type {
@@ -187,14 +201,23 @@ macro_rules! vector_copy_non_bool {
#[macro_export]
macro_rules! vector_non_copy_or_bool {
- (
- $type: ty
- ) => {
+ (clone $type: ty) => {
+ impl std::clone::Clone for $crate::manual::core::Vector<$type> where Self: $crate::manual::core::VectorExtern<$type> {
+ fn clone(&self) -> Self {
+ let mut out = Self::with_capacity(self.capacity());
+ self.iter()
+ .for_each(|elem| out.push_owned(elem.clone()));
+ out
+ }
+ }
+ vector_non_copy_or_bool! { $type }
+ };
+ ($type: ty) => {
impl $crate::manual::core::VectorElement for $type where $crate::manual::core::Vector<$type>: $crate::manual::core::VectorExtern<$type> {
#[inline(always)]
fn convert_to_vec(v: &$crate::manual::core::Vector<$type>) -> std::vec::Vec<$type> {
(0..v.len()).map(|x| unsafe { v.get_unchecked(x) }).collect()
}
}
- };
+ }
}

MODIFY
tests/vector.rs
tests/vector.rs
@@ -5,6 +5,7 @@ use opencv::{
self,
DMatch,
Point2d,
+ Point2f,
Point3i,
Scalar,
SparseMat_Hdr,
@@ -21,10 +22,12 @@ use opencv::{
VectorOfi8,
VectorOfMat,
VectorOfPoint2d,
+ VectorOfPoint2f,
VectorOfPoint3i,
VectorOfString,
VectorOfu8,
VectorOfVec4i,
+ VectorOfVectorOfPoint2f,
VectorOfVectorOfPoint3i,
}
};
@@ -519,3 +522,77 @@ fn property() -> Result<()> {
assert_eq!(pool_out.len(), pool.len());
Ok(())
}
+
+#[test]
+fn clone() -> Result<()> {
+ {
+ let src = vec![1, 2, 3, 4, 5, 6];
+ let mut primitive = VectorOfi32::from_iter(src.clone());
+ let primitive_clone = primitive.clone();
+ primitive.remove(2)?;
+ assert_eq!(primitive.len() + 1, primitive_clone.len());
+ primitive.set(1, 10)?;
+ assert_eq!(10, primitive.get(1)?);
+ primitive.as_mut_slice()[2] = 80;
+ assert_eq!(80, primitive.get(2)?);
+ drop(primitive);
+ assert_eq!(primitive_clone.as_slice(), src.as_slice())
+ }
+ {
+ let src = vec![Point2d::new(1., 2.), Point2d::new(3., 4.), Point2d::new(5., 6.)];
+ let mut simple = VectorOfPoint2d::from_iter(src.clone());
+ let simple_clone = simple.clone();
+ simple.remove(2)?;
+ assert_eq!(simple.len() + 1, simple_clone.len());
+ simple.set(0, Point2d::new(10., 11.))?;
+ assert_eq!(10., simple.get(0)?.x);
+ assert_eq!(11., simple.get(0)?.y);
+ simple.as_mut_slice()[1] = Point2d::new(20., 21.);
+ assert_eq!(20., simple.get(1)?.x);
+ assert_eq!(21., simple.get(1)?.y);
+ drop(simple);
+ assert_eq!(simple_clone.as_slice(), src.as_slice())
+ }
+ {
+ let mut src = vec![
+ Mat::new_rows_cols_with_default(10, 20, f64::typ(), Scalar::from(10.))?,
+ Mat::new_rows_cols_with_default(5, 8, i32::typ(), Scalar::from(20.))?,
+ ];
+ let src_clone = src.clone();
+ assert_eq!(20, *src[1].at_2d::<i32>(2, 2)?);
+ assert_eq!(20, *src_clone[1].at_2d::<i32>(2, 2)?);
+ *src[1].at_2d_mut::<i32>(2, 2)? = 30;
+ assert_eq!(30, *src[1].at_2d::<i32>(2, 2)?);
+ assert_eq!(20, *src_clone[1].at_2d::<i32>(2, 2)?);
+ let mut boxed = VectorOfMat::from_iter(src_clone);
+ let boxed_clone = boxed.clone();
+ assert_eq!(20, *boxed.get(1)?.at_2d::<i32>(2, 2)?);
+ assert_eq!(20, *boxed_clone.get(1)?.at_2d::<i32>(2, 2)?);
+ *boxed.get(1)?.at_2d_mut::<i32>(2, 2)? = 30;
+ assert_eq!(30, *boxed.get(1)?.at_2d::<i32>(2, 2)?);
+ assert_eq!(20, *boxed_clone.get(1)?.at_2d::<i32>(2, 2)?);
+ boxed.remove(1)?;
+ assert_eq!(boxed.len() + 1, boxed_clone.len());
+ boxed.set(0, Mat::new_rows_cols_with_default(40, 50, f64::typ(), Scalar::from(40.))?)?;
+ assert_eq!(40., *boxed.get(0)?.at_2d::<f64>(2, 2)?);
+ assert_eq!(10., *boxed_clone.get(0)?.at_2d::<f64>(2, 2)?);
+ drop(boxed);
+ assert_eq!(10., *boxed_clone.get(0)?.at_2d::<f64>(2, 2)?);
+ }
+ {
+ let src = vec![
+ VectorOfPoint2f::from_iter(vec![Point2f::new(10., 11.), Point2f::new(12., 13.)]),
+ VectorOfPoint2f::from_iter(vec![Point2f::new(20., 21.), Point2f::new(22., 23.)]),
+ VectorOfPoint2f::from_iter(vec![Point2f::new(30., 31.), Point2f::new(32., 33.)]),
+ ];
+ let mut vec_of_vec = VectorOfVectorOfPoint2f::from_iter(src.clone());
+ let vec_of_vec_clone = vec_of_vec.clone();
+ assert_eq!(21., vec_of_vec.get(1)?.get(0)?.y);
+ assert_eq!(21., vec_of_vec_clone.get(1)?.get(0)?.y);
+ vec_of_vec.set(1, VectorOfPoint2f::from_iter(vec![Point2f::new(40., 41.), Point2f::new(42., 43.)]));
+ assert_eq!(41., vec_of_vec.get(1)?.get(0)?.y);
+ assert_eq!(21., vec_of_vec_clone.get(1)?.get(0)?.y);
+ }
+
+ Ok(())
+}

Fix implementation of Vector::clone for non-copy types