Skip to content

Commit

Permalink
Implement TryFrom for enumerations
Browse files Browse the repository at this point in the history
  • Loading branch information
twistedfall committed Apr 21, 2024
1 parent 9611d66 commit f86e068
Show file tree
Hide file tree
Showing 38 changed files with 4,289 additions and 49 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
* 0.91.1
* Add `TryFrom<i32>` impls for enums to allow easy fallible conversions from `i32`.

* 0.91.0
* Multiple improvements for `InputArray`/`OutputArray`/`InputOutputArray` handling:
* It's now possible to use the following types as `InputArray`: `&[u8]`/`[u8; N]`, `Vector<bool>` `Vector<GpuMat>` and the
Expand Down
77 changes: 45 additions & 32 deletions binding-generator/src/writer/rust_native/enumeration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,40 +41,53 @@ impl RustNativeGeneratedElement for Enum<'_> {
static CONST_IGNORED_TPL: Lazy<CompiledInterpolation> =
Lazy::new(|| include_str!("tpl/enum/const_ignored.tpl.rs").compile_interpolation());

static FROM_CONST_TPL: Lazy<CompiledInterpolation> =
Lazy::new(|| include_str!("tpl/enum/from_const.tpl.rs").compile_interpolation());

static FROM_CONST_IGNORED_TPL: Lazy<CompiledInterpolation> =
Lazy::new(|| include_str!("tpl/enum/from_const_ignored.tpl.rs").compile_interpolation());

let consts = self.consts();
let mut generated_values = HashMap::with_capacity(consts.len());
let consts = consts
.into_iter()
.map(|c| {
let name = c.rust_leafname(FishStyle::No).into_owned();
let value = c.value().expect("Can't get value of enum variant").to_string();
let duplicate_name = generated_values.get(&value).cloned();
let tpl = if duplicate_name.is_some() {
&CONST_IGNORED_TPL
} else {
&CONST_TPL
};
let comment_marker = if duplicate_name.is_some() {
"//"
} else {
"///"
};
let doc_comment = c.rendered_doc_comment(comment_marker, opencv_version);
generated_values.insert(value.clone(), name.clone());
tpl.interpolate(&HashMap::from([
("doc_comment", doc_comment),
("duplicate_name", duplicate_name.unwrap_or_default()),
("name", name),
("value", value),
]))
})
.collect::<Vec<_>>();

let mut enum_consts = Vec::with_capacity(consts.len());
let mut from_consts = Vec::with_capacity(consts.len());

let mut generated_values = HashMap::<String, String>::with_capacity(consts.len());
for c in consts {
let name = c.rust_leafname(FishStyle::No).into_owned();
let value = c.value().expect("Can't get value of enum variant").to_string();
let duplicate_name = generated_values.get(&value).map(|s| s.as_str());
let (enum_const_tpl, from_const_tpl) = if duplicate_name.is_some() {
(&CONST_IGNORED_TPL, &FROM_CONST_IGNORED_TPL)
} else {
(&CONST_TPL, &FROM_CONST_TPL)
};
let comment_marker = if duplicate_name.is_some() {
"//"
} else {
"///"
};
let doc_comment = c.rendered_doc_comment(comment_marker, opencv_version);

let inter_vars = HashMap::from([
("name", name.as_str()),
("value", value.as_str()),
("doc_comment", &doc_comment),
("duplicate_name", duplicate_name.unwrap_or("")),
]);
enum_consts.push(enum_const_tpl.interpolate(&inter_vars));
from_consts.push(from_const_tpl.interpolate(&inter_vars));

generated_values.insert(value, name);
}

ENUM_TPL.interpolate(&HashMap::from([
("doc_comment", self.rendered_doc_comment("///", opencv_version).into()),
("debug", self.get_debug().into()),
("rust_local", self.rust_name(NameStyle::decl())),
("rust_full", self.rust_name(NameStyle::ref_())),
("consts", consts.join("").into()),
("rust_local", self.rust_name(NameStyle::decl()).as_ref()),
("rust_full", self.rust_name(NameStyle::ref_()).as_ref()),
("doc_comment", &self.rendered_doc_comment("///", opencv_version)),
("debug", &self.get_debug()),
("enum_consts", &enum_consts.join("")),
("from_consts", &from_consts.join("")),
]))
}
}
13 changes: 12 additions & 1 deletion binding-generator/src/writer/rust_native/tpl/enum/enum.tpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum {{rust_local}} {
{{consts}}
{{enum_consts}}
}

impl TryFrom<i32> for {{rust_local}} {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
{{from_consts}}
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: {{rust_full}}"))),
}
}
}

opencv_type_enum! { {{rust_full}} }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{{value}} => Ok(Self::{{name}}),

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Duplicate of {{duplicate_name}}
// {{value}} => Ok(Self::{{name}}),

12 changes: 12 additions & 0 deletions docs/aruco.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ pub mod aruco {
ARUCO_CW_TOP_LEFT_CORNER = 1,
}

impl TryFrom<i32> for PatternPositionType {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::ARUCO_CCW_CENTER),
1 => Ok(Self::ARUCO_CW_TOP_LEFT_CORNER),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::aruco::PatternPositionType"))),
}
}
}

opencv_type_enum! { crate::aruco::PatternPositionType }

/// @overload
Expand Down
12 changes: 12 additions & 0 deletions docs/bgsegm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ pub mod bgsegm {
LSBP_CAMERA_MOTION_COMPENSATION_LK = 1,
}

impl TryFrom<i32> for LSBPCameraMotionCompensation {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::LSBP_CAMERA_MOTION_COMPENSATION_NONE),
1 => Ok(Self::LSBP_CAMERA_MOTION_COMPENSATION_LK),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::bgsegm::LSBPCameraMotionCompensation"))),
}
}
}

opencv_type_enum! { crate::bgsegm::LSBPCameraMotionCompensation }

/// Creates a CNT Background Subtractor
Expand Down
141 changes: 141 additions & 0 deletions docs/calib3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,18 @@ pub mod calib3d {
ASYMMETRIC_GRID = 1,
}

impl TryFrom<i32> for CirclesGridFinderParameters_GridType {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::SYMMETRIC_GRID),
1 => Ok(Self::ASYMMETRIC_GRID),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::CirclesGridFinderParameters_GridType"))),
}
}
}

opencv_type_enum! { crate::calib3d::CirclesGridFinderParameters_GridType }

#[repr(C)]
Expand All @@ -435,6 +447,21 @@ pub mod calib3d {
CALIB_HAND_EYE_DANIILIDIS = 4,
}

impl TryFrom<i32> for HandEyeCalibrationMethod {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::CALIB_HAND_EYE_TSAI),
1 => Ok(Self::CALIB_HAND_EYE_PARK),
2 => Ok(Self::CALIB_HAND_EYE_HORAUD),
3 => Ok(Self::CALIB_HAND_EYE_ANDREFF),
4 => Ok(Self::CALIB_HAND_EYE_DANIILIDIS),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::HandEyeCalibrationMethod"))),
}
}
}

opencv_type_enum! { crate::calib3d::HandEyeCalibrationMethod }

#[repr(C)]
Expand All @@ -447,6 +474,21 @@ pub mod calib3d {
LOCAL_OPTIM_SIGMA = 4,
}

impl TryFrom<i32> for LocalOptimMethod {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::LOCAL_OPTIM_NULL),
1 => Ok(Self::LOCAL_OPTIM_INNER_LO),
2 => Ok(Self::LOCAL_OPTIM_INNER_AND_ITER_LO),
3 => Ok(Self::LOCAL_OPTIM_GC),
4 => Ok(Self::LOCAL_OPTIM_SIGMA),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::LocalOptimMethod"))),
}
}
}

opencv_type_enum! { crate::calib3d::LocalOptimMethod }

#[repr(C)]
Expand All @@ -457,6 +499,19 @@ pub mod calib3d {
NEIGH_FLANN_RADIUS = 2,
}

impl TryFrom<i32> for NeighborSearchMethod {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::NEIGH_FLANN_KNN),
1 => Ok(Self::NEIGH_GRID),
2 => Ok(Self::NEIGH_FLANN_RADIUS),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::NeighborSearchMethod"))),
}
}
}

opencv_type_enum! { crate::calib3d::NeighborSearchMethod }

#[repr(C)]
Expand All @@ -468,6 +523,20 @@ pub mod calib3d {
COV_POLISHER = 3,
}

impl TryFrom<i32> for PolishingMethod {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::NONE_POLISHER),
1 => Ok(Self::LSQ_POLISHER),
2 => Ok(Self::MAGSAC),
3 => Ok(Self::COV_POLISHER),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::PolishingMethod"))),
}
}
}

opencv_type_enum! { crate::calib3d::PolishingMethod }

#[repr(C)]
Expand All @@ -479,6 +548,18 @@ pub mod calib3d {
CALIB_ROBOT_WORLD_HAND_EYE_LI = 1,
}

impl TryFrom<i32> for RobotWorldHandEyeCalibrationMethod {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::CALIB_ROBOT_WORLD_HAND_EYE_SHAH),
1 => Ok(Self::CALIB_ROBOT_WORLD_HAND_EYE_LI),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::RobotWorldHandEyeCalibrationMethod"))),
}
}
}

opencv_type_enum! { crate::calib3d::RobotWorldHandEyeCalibrationMethod }

#[repr(C)]
Expand All @@ -490,6 +571,20 @@ pub mod calib3d {
SAMPLING_PROSAC = 3,
}

impl TryFrom<i32> for SamplingMethod {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::SAMPLING_UNIFORM),
1 => Ok(Self::SAMPLING_PROGRESSIVE_NAPSAC),
2 => Ok(Self::SAMPLING_NAPSAC),
3 => Ok(Self::SAMPLING_PROSAC),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::SamplingMethod"))),
}
}
}

opencv_type_enum! { crate::calib3d::SamplingMethod }

#[repr(C)]
Expand All @@ -501,6 +596,20 @@ pub mod calib3d {
SCORE_METHOD_LMEDS = 3,
}

impl TryFrom<i32> for ScoreMethod {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::SCORE_METHOD_RANSAC),
1 => Ok(Self::SCORE_METHOD_MSAC),
2 => Ok(Self::SCORE_METHOD_MAGSAC),
3 => Ok(Self::SCORE_METHOD_LMEDS),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::ScoreMethod"))),
}
}
}

opencv_type_enum! { crate::calib3d::ScoreMethod }

#[repr(C)]
Expand Down Expand Up @@ -546,6 +655,26 @@ pub mod calib3d {
SOLVEPNP_MAX_COUNT = 9,
}

impl TryFrom<i32> for SolvePnPMethod {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::SOLVEPNP_ITERATIVE),
1 => Ok(Self::SOLVEPNP_EPNP),
2 => Ok(Self::SOLVEPNP_P3P),
3 => Ok(Self::SOLVEPNP_DLS),
4 => Ok(Self::SOLVEPNP_UPNP),
5 => Ok(Self::SOLVEPNP_AP3P),
6 => Ok(Self::SOLVEPNP_IPPE),
7 => Ok(Self::SOLVEPNP_IPPE_SQUARE),
8 => Ok(Self::SOLVEPNP_SQPNP),
9 => Ok(Self::SOLVEPNP_MAX_COUNT),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::SolvePnPMethod"))),
}
}
}

opencv_type_enum! { crate::calib3d::SolvePnPMethod }

/// cv::undistort mode
Expand All @@ -556,6 +685,18 @@ pub mod calib3d {
PROJ_SPHERICAL_EQRECT = 1,
}

impl TryFrom<i32> for UndistortTypes {
type Error = crate::Error;

fn try_from(value: i32) -> Result<Self, Self::Error> {
match value {
0 => Ok(Self::PROJ_SPHERICAL_ORTHO),
1 => Ok(Self::PROJ_SPHERICAL_EQRECT),
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::UndistortTypes"))),
}
}
}

opencv_type_enum! { crate::calib3d::UndistortTypes }

pub type CirclesGridFinderParameters2 = crate::calib3d::CirclesGridFinderParameters;
Expand Down

0 comments on commit f86e068

Please sign in to comment.