Automatically implement Clone for Mat, SparseMat, UMat, GpuMat and HostMem
MODIFY
binding-generator/src/class.rs
binding-generator/src/class.rs
@@ -121,6 +121,10 @@ impl<'tu> Class<'tu> {
}
}
+ pub fn has_clone(&self) -> bool {
+ self.methods().into_iter().any(|m| m.is_clone())
+ }
+
pub fn rust_trait_name(&self, full: bool) -> Cow<str> {
let mut out = self.rust_name(full);
if self.is_trait() && !self.is_abstract() {

MODIFY
binding-generator/src/func.rs
binding-generator/src/func.rs
@@ -278,6 +278,18 @@ impl<'tu> Func<'tu> {
|| self.gen_env.get_export_config(self.entity).map_or(false, |e| e.no_except)
}
+ pub fn is_clone(&self) -> bool {
+ if self.rust_leafname() == "clone" {
+ if let Some(c) = self.as_instance_method() {
+ self.arguments().is_empty() && self.return_type().as_class().map_or(false, |r| r == c)
+ } else {
+ false
+ }
+ } else {
+ false
+ }
+ }
+
pub fn as_specialized(&self) -> Option<&'static HashMap<&'static str, &'static str>> {
if let FunctionTypeHint::Specialized(spec) = self.type_hint {
Some(spec)

MODIFY
binding-generator/src/writer/rust_native/class.rs
binding-generator/src/writer/rust_native/class.rs
@@ -27,6 +27,10 @@ fn gen_rust_class(c: &Class, opencv_version: &str) -> String {
|| include_str!("tpl/class/impl.tpl.rs").compile_interpolation()
);
+ static IMPL_CLONE_TPL: Lazy<CompiledInterpolation> = Lazy::new(
+ || include_str!("tpl/class/impl_clone.tpl.rs").compile_interpolation()
+ );
+
static SIMPLE_TPL: Lazy<CompiledInterpolation> = Lazy::new(
|| include_str!("tpl/class/simple.tpl.rs").compile_interpolation()
);
@@ -65,7 +69,8 @@ fn gen_rust_class(c: &Class, opencv_version: &str) -> String {
} else {
c.field_methods(fields.iter())
};
- methods.extend_from_slice(c.methods().as_slice());
+ let class_methods = c.methods();
+ methods.extend_from_slice(class_methods.as_slice());
if is_trait {
let mut bases = c.bases().into_iter()
.filter(|b| !b.is_excluded() && !b.is_simple()) // todo, allow extension of simple classes for e.g. Elliptic_KeyPoint
@@ -196,20 +201,30 @@ fn gen_rust_class(c: &Class, opencv_version: &str) -> String {
.map(|c| c.gen_rust(opencv_version))
.join("");
+ let rust_local = c.rust_localname();
+ let impls = if c.has_clone() {
+ IMPL_CLONE_TPL.interpolate(&hashmap! {
+ "rust_local" => rust_local.clone(),
+ })
+ } else {
+ "".to_string()
+ };
+
out += &tpl.interpolate(&hashmap! {
"doc_comment" => Cow::Owned(c.rendered_doc_comment(opencv_version)),
"debug" => get_debug(c).into(),
- "rust_local" => type_ref.rust_local(),
- "rust_full" => type_ref.rust_full(),
+ "rust_local" => rust_local.clone(),
+ "rust_full" => c.rust_fullname(),
"rust_extern_const" => type_ref.rust_extern_with_const(Constness::Const),
"rust_extern_mut" => type_ref.rust_extern_with_const(Constness::Mut),
"fields" => fields.join("").into(),
"bases" => bases.join("").into(),
"impl" => IMPL_TPL.interpolate(&hashmap! {
- "rust_local" => c.rust_localname(),
+ "rust_local" => rust_local,
"consts" => consts.into(),
"methods" => inherent_methods.into(),
- }).into()
+ }).into(),
+ "impls" => impls.into(),
});
}
out

MODIFY
binding-generator/src/writer/rust_native/func.rs
binding-generator/src/writer/rust_native/func.rs
@@ -280,7 +280,9 @@ impl RustNativeGeneratedElement for Func<'_> {
}
fn gen_rust(&self, opencv_version: &str) -> String {
- let name = if let Some(name_hint) = self.name_hint() {
+ let name = if self.is_clone() {
+ "try_clone".into()
+ } else if let Some(name_hint) = self.name_hint() {
name_hint.into()
} else {
self.rust_leafname()

MODIFY
binding-generator/src/writer/rust_native/tpl/class/boxed.tpl.rs
binding-generator/src/writer/rust_native/tpl/class/boxed.tpl.rs
@@ -22,5 +22,5 @@ unsafe impl Send for {{rust_local}} {}
{{bases}}
{{impl}}
-
+{{impls}}

MODIFY
binding-generator/src/writer/rust_native/tpl/class/impl.tpl.rs
binding-generator/src/writer/rust_native/tpl/class/impl.tpl.rs
@@ -2,3 +2,5 @@ impl {{rust_local}} {
{{consts}}
{{methods}}
}
+
+

ADD
binding-generator/src/writer/rust_native/tpl/class/impl_clone.tpl.rs
+impl Clone for {{rust_local}} {
+ #[inline(always)]
+ /// Calls try_clone() and panics if that fails
+ fn clone(&self) -> Self {
+ self.try_clone().expect("Cannot clone {{rust_local}}")
+ }
+}
+
+

MODIFY
binding-generator/src/writer/rust_native/tpl/class/simple.tpl.rs
binding-generator/src/writer/rust_native/tpl/class/simple.tpl.rs
@@ -9,5 +9,5 @@ pub struct {{rust_local}} {
opencv_type_simple! { {{rust_full}} }
{{impl}}
-
+{{impls}}

MODIFY
examples/warp_perspective_demo.rs
examples/warp_perspective_demo.rs
@@ -106,7 +106,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let roi_corners_len = roi_corners.lock().unwrap().len();
if validation_needed.load(Ordering::Relaxed) && roi_corners_len < 4 {
validation_needed.store(false, Ordering::Relaxed);
- image = original_image.clone()?;
+ image = original_image.clone();
{
let roi_corners = roi_corners.lock().unwrap();
for i in 0..roi_corners_len {
@@ -121,7 +121,7 @@ fn main() -> Result<(), Box<dyn Error>> {
highgui::imshow(WINDOW_TITLE, &image)?;
}
if validation_needed.load(Ordering::Relaxed) && roi_corners_len == 4 {
- image = original_image.clone()?;
+ image = original_image.clone();
{
let roi_corners = roi_corners.lock().unwrap();
for i in 0..4 {

MODIFY
tests/mat.rs
tests/mat.rs
@@ -327,7 +327,7 @@ fn mat_continuous() -> Result<()> {
assert_eq!(8., vec[1][0]);
assert_eq!(9., vec[1][1]);
- let mat_clone = sub_mat_non_cont.clone()?;
+ let mat_clone = sub_mat_non_cont.try_clone()?;
assert_eq!(mat.typ()?, mat_clone.typ()?);
assert_eq!(2, mat_clone.rows());
assert_eq!(2, mat_clone.cols());
@@ -475,7 +475,7 @@ fn mat_locate_roi() -> Result<()> {
#[test]
fn mat_convert() -> Result<()> {
let mat = Mat::from_slice(&[1, 2, 3, 4])?;
- let mut mat_ = mat.clone()?.try_into_typed::<i32>()?;
+ let mut mat_ = mat.try_clone()?.try_into_typed::<i32>()?;
assert_eq!(3, *mat_.at(2)?);
*mat_.at_mut(3)? = 8;
assert_eq!(8, *mat_.at(3)?);

MODIFY
tests/tracking.rs
tests/tracking.rs
@@ -12,7 +12,7 @@ fn typed_mat() -> Result<()> {
let mut params = TrackerSamplerPF_Params::default()?;
assert_eq!(&[15., 15., 15., 15.], params.std().data_typed()?);
let mat = Mat::new_rows_cols_with_default(1, 4, f64::typ(), Scalar::all(8.))?.try_into_typed::<f64>()?;
- let mat_src = mat.clone()?.try_into_typed::<f64>()?;
+ let mat_src = mat.try_clone()?.try_into_typed::<f64>()?;
params.set_std(mat);
let mat = params.std();
assert_eq!(mat.size()?, mat_src.size()?);

MODIFY
tests/umat.rs
tests/umat.rs
@@ -104,7 +104,7 @@ fn umat_continuous() -> Result<()> {
assert!(sub_umat_non_cont.is_submatrix()?);
assert!(!sub_umat_non_cont.is_continuous()?);
- let umat_clone = sub_umat_non_cont.clone()?;
+ let umat_clone = sub_umat_non_cont.try_clone()?;
assert_eq!(umat.typ()?, umat_clone.typ()?);
assert_eq!(2, umat_clone.rows());
assert_eq!(2, umat_clone.cols());

Automatically implement Clone for Mat, SparseMat, UMat, GpuMat and HostMem