Use const generics for the base VecN structure
MODIFY
binding-generator/src/class.rs
binding-generator/src/class.rs
@@ -332,7 +332,12 @@ impl Element for Class<'_, '_> {
fn is_ignored(&self) -> bool {
DefaultElement::is_ignored(self)
|| self.is_template()
- || self.is_template_specialization() && !settings::IMPLEMENTED_GENERICS.contains(self.cpp_fullname().as_ref())
+ || self.is_template_specialization() &&
+ {
+ let cpp_fullname = self.cpp_fullname();
+ !settings::IMPLEMENTED_GENERICS.contains(cpp_fullname.as_ref())
+ && !settings::IMPLEMENTED_CONST_GENERICS.contains(cpp_fullname.as_ref())
+ }
|| !self.is_template_specialization() && !self.is_definition()
}

MODIFY
binding-generator/src/generator.rs
binding-generator/src/generator.rs
@@ -419,7 +419,9 @@ impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
underlying_type.as_function().is_some()
|| !underlying_type.is_excluded()
|| if let Some(templ) = underlying_type.as_template() {
- settings::IMPLEMENTED_GENERICS.contains(templ.cpp_fullname().as_ref())
+ let cpp_fullname = templ.cpp_fullname();
+ settings::IMPLEMENTED_GENERICS.contains(cpp_fullname.as_ref())
+ || settings::IMPLEMENTED_CONST_GENERICS.contains(cpp_fullname.as_ref())
} else {
false
}

MODIFY
binding-generator/src/settings.rs
binding-generator/src/settings.rs
@@ -874,6 +874,7 @@ pub static DATA_TYPES: Lazy<BTreeSet<&str>> = Lazy::new(|| btreeset! {
"cv::Rect", "cv::Rect2i", "cv::Rect2f", "cv::Rect2d",
});
+/// cpp_fullname
pub static IMPLEMENTED_GENERICS: Lazy<HashSet<&str>> = Lazy::new(|| hashset! {
"cv::Affine3",
"cv::Mat_",
@@ -883,6 +884,10 @@ pub static IMPLEMENTED_GENERICS: Lazy<HashSet<&str>> = Lazy::new(|| hashset! {
"cv::Rect_",
"cv::Scalar_",
"cv::Size_",
+});
+
+/// cpp_fullname
+pub static IMPLEMENTED_CONST_GENERICS: Lazy<HashSet<&str>> = Lazy::new(|| hashset! {
"cv::Vec",
});

MODIFY
binding-generator/src/type_ref/renderer.rs
binding-generator/src/type_ref/renderer.rs
@@ -3,7 +3,7 @@ use std::{
fmt::{self, Write},
};
-use crate::{Element, StringExt};
+use crate::{Element, settings, StringExt};
use super::{Kind, TemplateArg, TypeRef};
@@ -253,6 +253,8 @@ impl FishStyle {
fn render_rust_tpl_decl<'a>(renderer: impl TypeRefRenderer<'a>, type_ref: &TypeRef, fish_style: FishStyle) -> String {
let generic_types = type_ref.template_specialization_args();
if !generic_types.is_empty() {
+ let const_generics_implemented = type_ref.as_class()
+ .map_or(false, |cls| settings::IMPLEMENTED_CONST_GENERICS.contains(cls.cpp_fullname().as_ref()));
let mut constant_suffix = String::new();
let generic_types = generic_types.iter()
.filter_map(|t| {
@@ -262,8 +264,14 @@ fn render_rust_tpl_decl<'a>(renderer: impl TypeRefRenderer<'a>, type_ref: &TypeR
}
TemplateArg::Constant(literal) => {
if let Some(cnst) = type_ref.gen_env.resolve_class_constant(literal).and_then(|c| c.value()) {
+ if const_generics_implemented {
+ return Some(cnst.to_string().into())
+ }
constant_suffix += &cnst.to_string();
} else {
+ if const_generics_implemented {
+ return Some(literal.into())
+ }
constant_suffix += literal;
}
None

MODIFY
src/manual/core.rs
src/manual/core.rs
pub use affine3::*;
pub use CV_MAKETYPE as CV_MAKE_TYPE;
+pub use data_type::*;
pub use gpumat::*;
pub use input_output_array::*;
pub use mat::*;
@@ -31,6 +32,7 @@ macro_rules! valid_types {
}
mod affine3;
+mod data_type;
mod gpumat;
mod input_output_array;
mod mat;
@@ -44,15 +46,3 @@ mod size;
mod sized;
mod vec;
mod vector;
-
-#[inline]
-pub const fn CV_MAT_DEPTH(flags: i32) -> i32 {
- #![allow(non_snake_case)]
- flags & crate::core::Mat_DEPTH_MASK
-}
-
-#[inline]
-pub const fn CV_MAKETYPE(depth: i32, cn: i32) -> i32 {
- #![allow(non_snake_case)]
- CV_MAT_DEPTH(depth) + ((cn - 1) << crate::core::CV_CN_SHIFT)
-}

ADD
src/manual/core/data_type.rs
+use crate::core::{self, Point3_, Point_, Rect_, Size_, ValidPoint3Type, ValidPointType, ValidRectType, ValidSizeType, Vec};
+
+#[inline]
+pub const fn CV_MAT_DEPTH(flags: i32) -> i32 {
+ #![allow(non_snake_case)]
+ flags & crate::core::Mat_DEPTH_MASK
+}
+
+#[inline]
+pub const fn CV_MAKETYPE(depth: i32, cn: i32) -> i32 {
+ #![allow(non_snake_case)]
+ CV_MAT_DEPTH(depth) + ((cn - 1) << crate::core::CV_CN_SHIFT)
+}
+
+/// This sealed trait is implemented for types that are valid to use as Mat elements
+pub trait DataType: Copy + private::Sealed {
+ fn depth() -> i32;
+ fn channels() -> i32;
+
+ #[inline]
+ fn typ() -> i32 {
+ CV_MAKETYPE(Self::depth(), Self::channels())
+ }
+}
+
+macro_rules! data_type {
+ ($rust_type: ty, $mat_depth: expr, $channels: expr) => {
+ impl $crate::core::DataType for $rust_type {
+ #[inline]
+ fn depth() -> i32 { $mat_depth }
+
+ #[inline]
+ fn channels() -> i32 { $channels }
+ }
+
+ impl private::Sealed for $rust_type {}
+ };
+}
+
+// int
+data_type!(u8, core::CV_8U, 1);
+data_type!(i8, core::CV_8S, 1);
+data_type!(u16, core::CV_16U, 1);
+data_type!(i16, core::CV_16S, 1);
+data_type!(i32, core::CV_32S, 1);
+
+// float
+data_type!(f32, core::CV_32F, 1);
+data_type!(f64, core::CV_64F, 1);
+
+impl<T: DataType, const N: usize> DataType for Vec<T, N> {
+ #[inline]
+ fn depth() -> i32 { T::depth() }
+
+ #[inline]
+ fn channels() -> i32 { N as i32 }
+}
+
+impl<T: ValidPointType + DataType> DataType for Point_<T> {
+ #[inline]
+ fn depth() -> i32 { T::depth() }
+
+ #[inline]
+ fn channels() -> i32 { 2 }
+}
+
+impl<T: ValidPoint3Type + DataType> DataType for Point3_<T> {
+ #[inline]
+ fn depth() -> i32 { T::depth() }
+
+ #[inline]
+ fn channels() -> i32 { 3 }
+}
+
+impl<T: ValidSizeType + DataType> DataType for Size_<T> {
+ #[inline]
+ fn depth() -> i32 { T::depth() }
+
+ #[inline]
+ fn channels() -> i32 { 2 }
+}
+
+impl<T: ValidRectType + DataType> DataType for Rect_<T> {
+ #[inline]
+ fn depth() -> i32 { T::depth() }
+
+ #[inline]
+ fn channels() -> i32 { 4 }
+}
+
+mod private {
+ pub trait Sealed {}
+}
+
+impl<T: DataType, const N: usize> private::Sealed for Vec<T, N> {}
+
+impl<T: ValidPointType + DataType> private::Sealed for Point_<T> {}
+
+impl<T: ValidPoint3Type + DataType> private::Sealed for Point3_<T> {}
+
+impl<T: ValidSizeType + DataType> private::Sealed for Size_<T> {}
+
+impl<T: ValidRectType + DataType> private::Sealed for Rect_<T> {}

MODIFY
src/manual/core/mat.rs
src/manual/core/mat.rs
@@ -20,91 +20,6 @@ use crate::{
mod mat_;
-/// This sealed trait is implemented for types that are valid to use as Mat elements
-pub trait DataType: Copy + private::Sealed {
- fn depth() -> i32;
- fn channels() -> i32;
- fn typ() -> i32;
-}
-
-macro_rules! data_type {
- ($rust_type: ty, $mat_depth: expr, $channels: expr) => {
- impl $crate::core::DataType for $rust_type {
- #[inline]
- fn depth() -> i32 { $mat_depth }
-
- #[inline]
- fn channels() -> i32 { $channels }
-
- #[inline]
- fn typ() -> i32 { $crate::core::CV_MAKETYPE($mat_depth, $channels) }
- }
-
- impl private::Sealed for $rust_type {}
- };
-}
-
-// int
-data_type!(u8, core::CV_8U, 1);
-data_type!(i8, core::CV_8S, 1);
-data_type!(u16, core::CV_16U, 1);
-data_type!(i16, core::CV_16S, 1);
-data_type!(i32, core::CV_32S, 1);
-
-// float
-data_type!(f32, core::CV_32F, 1);
-data_type!(f64, core::CV_64F, 1);
-
-// vec int
-data_type!(core::Vec2b, core::CV_8U, 2);
-data_type!(core::Vec3b, core::CV_8U, 3);
-data_type!(core::Vec4b, core::CV_8U, 4);
-data_type!(core::Vec2<i8>, core::CV_8S, 2);
-data_type!(core::Vec3<i8>, core::CV_8S, 3);
-data_type!(core::Vec4<i8>, core::CV_8S, 4);
-data_type!(core::Vec2<u16>, core::CV_16U, 2);
-data_type!(core::Vec3<u16>, core::CV_16U, 3);
-data_type!(core::Vec4<u16>, core::CV_16U, 4);
-data_type!(core::Vec2s, core::CV_16S, 2);
-data_type!(core::Vec3s, core::CV_16S, 3);
-data_type!(core::Vec4s, core::CV_16S, 4);
-data_type!(core::Vec2i, core::CV_32S, 2);
-data_type!(core::Vec3i, core::CV_32S, 3);
-data_type!(core::Vec4i, core::CV_32S, 4);
-data_type!(core::Vec8i, core::CV_32S, 8);
-
-// vec float
-data_type!(core::Vec2f, core::CV_32F, 2);
-data_type!(core::Vec3f, core::CV_32F, 3);
-data_type!(core::Vec4f, core::CV_32F, 4);
-data_type!(core::Vec2d, core::CV_64F, 2);
-data_type!(core::Vec3d, core::CV_64F, 3);
-data_type!(core::Vec4d, core::CV_64F, 4);
-
-// scalar
-data_type!(core::Scalar, core::CV_64F, 4);
-
-// point
-data_type!(core::Point2i, core::CV_32S, 2);
-data_type!(core::Point2f, core::CV_32F, 2);
-data_type!(core::Point2d, core::CV_64F, 2);
-
-// point3
-data_type!(core::Point3i, core::CV_32S, 2);
-data_type!(core::Point3f, core::CV_32F, 2);
-data_type!(core::Point3d, core::CV_64F, 2);
-
-// size
-data_type!(core::Size2i, core::CV_32S, 2);
-data_type!(core::Size2f, core::CV_32F, 2);
-data_type!(core::Size2d, core::CV_64F, 2);
-
-// rect
-data_type!(core::Rect2i, core::CV_32S, 4);
-data_type!(core::Rect2f, core::CV_32F, 4);
-data_type!(core::Rect2d, core::CV_64F, 4);
-
-
#[inline(always)]
unsafe fn convert_ptr<T>(r: &u8) -> &T {
&*(r as *const u8 as *const T)
@@ -674,7 +589,3 @@ pub trait MatConstIteratorTraitManual: MatConstIteratorTrait {
impl<T: MatConstIteratorTrait> MatConstIteratorTraitManual for T {}
input_output_array! { MatExpr, from_matexpr }
-
-mod private {
- pub trait Sealed {}
-}

MODIFY
src/manual/core/point.rs
src/manual/core/point.rs
@@ -3,7 +3,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
use num_traits::{NumCast, ToPrimitive};
use crate::{
- core::{Rect_, Size_, ValidRectType, ValidSizeType, ValidVecType, Vec2},
+ core::{Rect_, Size_, ValidRectType, ValidSizeType, ValidVecType, Vec},
opencv_type_simple_generic,
};
@@ -24,7 +24,7 @@ impl<T: ValidPointType> Point_<T> {
}
#[inline]
- pub fn from_vec2(vec: Vec2<T>) -> Self where T: ValidVecType {
+ pub fn from_vec2(vec: Vec<T, 2>) -> Self where T: ValidVecType {
Self::new(vec[0], vec[1])
}
@@ -74,8 +74,8 @@ impl<T: ValidPointType> Point_<T> {
}
#[inline]
- pub fn to_vec2(&self) -> Vec2<T> where T: ValidVecType {
- Vec2::from([self.x, self.y])
+ pub fn to_vec2(&self) -> Vec<T, 2> where T: ValidVecType {
+ Vec::<_, 2>::from([self.x, self.y])
}
}

MODIFY
src/manual/core/point3.rs
src/manual/core/point3.rs
@@ -3,7 +3,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
use num_traits::{NumCast, ToPrimitive, Zero};
use crate::{
- core::{Point_, ValidPointType, ValidVecType, Vec3},
+ core::{Point_, ValidPointType, ValidVecType, Vec},
opencv_type_simple_generic,
};
@@ -25,7 +25,7 @@ impl<T: ValidPoint3Type> Point3_<T> {
}
#[inline]
- pub fn from_vec3(vec: Vec3<T>) -> Self where T: ValidVecType {
+ pub fn from_vec3(vec: Vec<T, 3>) -> Self where T: ValidVecType {
Self::new(vec[0], vec[1], vec[2])
}
@@ -73,8 +73,8 @@ impl<T: ValidPoint3Type> Point3_<T> {
}
#[inline]
- pub fn to_vec3(&self) -> Vec3<T> where T: ValidVecType {
- Vec3::from([self.x, self.y, self.z])
+ pub fn to_vec3(&self) -> Vec<T, 3> where T: ValidVecType {
+ Vec::<_, 3>::from([self.x, self.y, self.z])
}
}
opencv_type_simple_generic! { Point3_<ValidPoint3Type> }

MODIFY
src/manual/core/vec.rs
src/manual/core/vec.rs
-use std::ffi::c_void;
+use std::{
+ ffi::c_void,
+ ops::{Deref, DerefMut},
+};
use crate::{
core::{_InputArray, ToInputArray},
input_array_ref_forward,
- opencv_type_simple_generic,
Result,
sys,
- traits::Boxed,
+ traits::{Boxed, OpenCVType, OpenCVTypeArg, OpenCVTypeExternContainer},
};
pub use self::{scalar_inner::ValidScalarType, vec_inner::ValidVecType};
@@ -20,29 +22,37 @@ mod scalar_inner {
valid_types!(ValidScalarType: i32, f64);
}
-macro_rules! vec_impl {
- ($type: ident, $count: expr, $type_trait: ident) => {
/// [docs.opencv.org](https://docs.opencv.org/master/d6/dcf/classcv_1_1Vec.html)
#[repr(C)]
- #[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
- pub struct $type<T: $type_trait>(pub [T; $count]);
+#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
+pub struct Vec<T, const N: usize> (pub [T; N]);
- impl<T: $type_trait> $type<T> {
+impl<T, const N: usize> Default for Vec<T, N>
+ where
+ [T; N]: Default
+{
+ #[inline]
+ fn default() -> Self {
+ Self(Default::default())
+ }
+}
+
+impl<T: Copy, const N: usize> Vec<T, N> {
#[inline]
pub fn all(v0: T) -> Self {
- Self::from([v0; $count])
+ Self::from([v0; N])
}
}
- impl<T: $type_trait> From<[T; $count]> for $type<T> {
+impl<T, const N: usize> From<[T; N]> for Vec<T, N> {
#[inline]
- fn from(s: [T; $count]) -> Self {
+ fn from(s: [T; N]) -> Self {
Self(s)
}
}
- impl<T: $type_trait> std::ops::Deref for $type<T> {
- type Target = [T; $count];
+impl<T, const N: usize> Deref for Vec<T, N> {
+ type Target = [T; N];
#[inline]
fn deref(&self) -> &Self::Target {
@@ -50,24 +60,53 @@ macro_rules! vec_impl {
}
}
- impl<T: $type_trait> std::ops::DerefMut for $type<T> {
+impl<T, const N: usize> DerefMut for Vec<T, N> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
- opencv_type_simple_generic! { $type<$type_trait> }
- };
+impl<T: ValidVecType, const N: usize> OpenCVType<'_> for Vec<T, N> {
+ type Arg = Self;
+ type ExternReceive = Self;
+ type ExternContainer = Self;
+
+ #[inline]
+ fn opencv_into_extern_container(self) -> Result<Self> { Ok(self) }
+
+ #[inline]
+ fn opencv_into_extern_container_nofail(self) -> Self { self }
+
+ #[inline]
+ unsafe fn opencv_from_extern(s: Self) -> Self { s }
+}
+
+impl<T: ValidVecType, const N: usize> OpenCVTypeArg<'_> for Vec<T, N> {
+ type ExternContainer = Self;
+
+ #[inline]
+ fn opencv_into_extern_container(self) -> Result<Self> { Ok(self) }
+
+ #[inline]
+ fn opencv_into_extern_container_nofail(self) -> Self { self }
+}
+
+impl<T: ValidVecType, const N: usize> OpenCVTypeExternContainer for Vec<T, N> {
+ type ExternSend = *const Self;
+ type ExternSendMut = *mut Self;
+
+ #[inline]
+ fn opencv_as_extern(&self) -> Self::ExternSend { self }
+
+ #[inline]
+ fn opencv_as_extern_mut(&mut self) -> Self::ExternSendMut { self }
+
+ #[inline]
+ fn opencv_into_extern(self) -> Self::ExternSendMut { &mut *std::mem::ManuallyDrop::new(self) as _ }
}
-vec_impl!(Vec2, 2, ValidVecType);
-vec_impl!(Vec3, 3, ValidVecType);
-vec_impl!(Vec4, 4, ValidVecType);
-vec_impl!(Vec6, 6, ValidVecType);
-vec_impl!(Vec8, 8, ValidVecType);
-vec_impl!(Vec18, 18, ValidVecType);
-vec_impl!(Scalar_, 4, ValidScalarType);
+pub type Scalar_<T> = Vec<T, 4>;
impl<T: ValidScalarType> Scalar_<T> {
#[inline]

MODIFY
src/templ.rs
src/templ.rs
@@ -79,13 +79,13 @@ macro_rules! input_output_array_arg {
macro_rules! string_array_arg {
($name: ident) => {
- let $name = $name.iter().map(|x| x.as_ptr() as _).collect::<Vec<_>>();
+ let $name = $name.iter().map(|x| x.as_ptr() as _).collect::<::std::vec::Vec<_>>();
};
}
macro_rules! string_array_arg_mut {
($name: ident) => {
- let mut $name = $name.iter().map(|x| x.as_ptr() as _).collect::<Vec<_>>();
+ let mut $name = $name.iter().map(|x| x.as_ptr() as _).collect::<::std::vec::Vec<_>>();
};
}

Use const generics for the base VecN structure