Skip to content

Commit f86e068

Browse files
committed
Implement TryFrom for enumerations
1 parent 9611d66 commit f86e068

38 files changed

+4289
-49
lines changed

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
* 0.91.1
2+
* Add `TryFrom<i32>` impls for enums to allow easy fallible conversions from `i32`.
3+
14
* 0.91.0
25
* Multiple improvements for `InputArray`/`OutputArray`/`InputOutputArray` handling:
36
* It's now possible to use the following types as `InputArray`: `&[u8]`/`[u8; N]`, `Vector<bool>` `Vector<GpuMat>` and the

binding-generator/src/writer/rust_native/enumeration.rs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,40 +41,53 @@ impl RustNativeGeneratedElement for Enum<'_> {
4141
static CONST_IGNORED_TPL: Lazy<CompiledInterpolation> =
4242
Lazy::new(|| include_str!("tpl/enum/const_ignored.tpl.rs").compile_interpolation());
4343

44+
static FROM_CONST_TPL: Lazy<CompiledInterpolation> =
45+
Lazy::new(|| include_str!("tpl/enum/from_const.tpl.rs").compile_interpolation());
46+
47+
static FROM_CONST_IGNORED_TPL: Lazy<CompiledInterpolation> =
48+
Lazy::new(|| include_str!("tpl/enum/from_const_ignored.tpl.rs").compile_interpolation());
49+
4450
let consts = self.consts();
45-
let mut generated_values = HashMap::with_capacity(consts.len());
46-
let consts = consts
47-
.into_iter()
48-
.map(|c| {
49-
let name = c.rust_leafname(FishStyle::No).into_owned();
50-
let value = c.value().expect("Can't get value of enum variant").to_string();
51-
let duplicate_name = generated_values.get(&value).cloned();
52-
let tpl = if duplicate_name.is_some() {
53-
&CONST_IGNORED_TPL
54-
} else {
55-
&CONST_TPL
56-
};
57-
let comment_marker = if duplicate_name.is_some() {
58-
"//"
59-
} else {
60-
"///"
61-
};
62-
let doc_comment = c.rendered_doc_comment(comment_marker, opencv_version);
63-
generated_values.insert(value.clone(), name.clone());
64-
tpl.interpolate(&HashMap::from([
65-
("doc_comment", doc_comment),
66-
("duplicate_name", duplicate_name.unwrap_or_default()),
67-
("name", name),
68-
("value", value),
69-
]))
70-
})
71-
.collect::<Vec<_>>();
51+
52+
let mut enum_consts = Vec::with_capacity(consts.len());
53+
let mut from_consts = Vec::with_capacity(consts.len());
54+
55+
let mut generated_values = HashMap::<String, String>::with_capacity(consts.len());
56+
for c in consts {
57+
let name = c.rust_leafname(FishStyle::No).into_owned();
58+
let value = c.value().expect("Can't get value of enum variant").to_string();
59+
let duplicate_name = generated_values.get(&value).map(|s| s.as_str());
60+
let (enum_const_tpl, from_const_tpl) = if duplicate_name.is_some() {
61+
(&CONST_IGNORED_TPL, &FROM_CONST_IGNORED_TPL)
62+
} else {
63+
(&CONST_TPL, &FROM_CONST_TPL)
64+
};
65+
let comment_marker = if duplicate_name.is_some() {
66+
"//"
67+
} else {
68+
"///"
69+
};
70+
let doc_comment = c.rendered_doc_comment(comment_marker, opencv_version);
71+
72+
let inter_vars = HashMap::from([
73+
("name", name.as_str()),
74+
("value", value.as_str()),
75+
("doc_comment", &doc_comment),
76+
("duplicate_name", duplicate_name.unwrap_or("")),
77+
]);
78+
enum_consts.push(enum_const_tpl.interpolate(&inter_vars));
79+
from_consts.push(from_const_tpl.interpolate(&inter_vars));
80+
81+
generated_values.insert(value, name);
82+
}
83+
7284
ENUM_TPL.interpolate(&HashMap::from([
73-
("doc_comment", self.rendered_doc_comment("///", opencv_version).into()),
74-
("debug", self.get_debug().into()),
75-
("rust_local", self.rust_name(NameStyle::decl())),
76-
("rust_full", self.rust_name(NameStyle::ref_())),
77-
("consts", consts.join("").into()),
85+
("rust_local", self.rust_name(NameStyle::decl()).as_ref()),
86+
("rust_full", self.rust_name(NameStyle::ref_()).as_ref()),
87+
("doc_comment", &self.rendered_doc_comment("///", opencv_version)),
88+
("debug", &self.get_debug()),
89+
("enum_consts", &enum_consts.join("")),
90+
("from_consts", &from_consts.join("")),
7891
]))
7992
}
8093
}

binding-generator/src/writer/rust_native/tpl/enum/enum.tpl.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,18 @@
33
#[repr(C)]
44
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
55
pub enum {{rust_local}} {
6-
{{consts}}
6+
{{enum_consts}}
7+
}
8+
9+
impl TryFrom<i32> for {{rust_local}} {
10+
type Error = crate::Error;
11+
12+
fn try_from(value: i32) -> Result<Self, Self::Error> {
13+
match value {
14+
{{from_consts}}
15+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: {{rust_full}}"))),
16+
}
17+
}
718
}
819

920
opencv_type_enum! { {{rust_full}} }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{{value}} => Ok(Self::{{name}}),
2+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Duplicate of {{duplicate_name}}
2+
// {{value}} => Ok(Self::{{name}}),
3+

docs/aruco.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ pub mod aruco {
6060
ARUCO_CW_TOP_LEFT_CORNER = 1,
6161
}
6262

63+
impl TryFrom<i32> for PatternPositionType {
64+
type Error = crate::Error;
65+
66+
fn try_from(value: i32) -> Result<Self, Self::Error> {
67+
match value {
68+
0 => Ok(Self::ARUCO_CCW_CENTER),
69+
1 => Ok(Self::ARUCO_CW_TOP_LEFT_CORNER),
70+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::aruco::PatternPositionType"))),
71+
}
72+
}
73+
}
74+
6375
opencv_type_enum! { crate::aruco::PatternPositionType }
6476

6577
/// @overload

docs/bgsegm.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ pub mod bgsegm {
1414
LSBP_CAMERA_MOTION_COMPENSATION_LK = 1,
1515
}
1616

17+
impl TryFrom<i32> for LSBPCameraMotionCompensation {
18+
type Error = crate::Error;
19+
20+
fn try_from(value: i32) -> Result<Self, Self::Error> {
21+
match value {
22+
0 => Ok(Self::LSBP_CAMERA_MOTION_COMPENSATION_NONE),
23+
1 => Ok(Self::LSBP_CAMERA_MOTION_COMPENSATION_LK),
24+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::bgsegm::LSBPCameraMotionCompensation"))),
25+
}
26+
}
27+
}
28+
1729
opencv_type_enum! { crate::bgsegm::LSBPCameraMotionCompensation }
1830

1931
/// Creates a CNT Background Subtractor

docs/calib3d.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,18 @@ pub mod calib3d {
418418
ASYMMETRIC_GRID = 1,
419419
}
420420

421+
impl TryFrom<i32> for CirclesGridFinderParameters_GridType {
422+
type Error = crate::Error;
423+
424+
fn try_from(value: i32) -> Result<Self, Self::Error> {
425+
match value {
426+
0 => Ok(Self::SYMMETRIC_GRID),
427+
1 => Ok(Self::ASYMMETRIC_GRID),
428+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::CirclesGridFinderParameters_GridType"))),
429+
}
430+
}
431+
}
432+
421433
opencv_type_enum! { crate::calib3d::CirclesGridFinderParameters_GridType }
422434

423435
#[repr(C)]
@@ -435,6 +447,21 @@ pub mod calib3d {
435447
CALIB_HAND_EYE_DANIILIDIS = 4,
436448
}
437449

450+
impl TryFrom<i32> for HandEyeCalibrationMethod {
451+
type Error = crate::Error;
452+
453+
fn try_from(value: i32) -> Result<Self, Self::Error> {
454+
match value {
455+
0 => Ok(Self::CALIB_HAND_EYE_TSAI),
456+
1 => Ok(Self::CALIB_HAND_EYE_PARK),
457+
2 => Ok(Self::CALIB_HAND_EYE_HORAUD),
458+
3 => Ok(Self::CALIB_HAND_EYE_ANDREFF),
459+
4 => Ok(Self::CALIB_HAND_EYE_DANIILIDIS),
460+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::HandEyeCalibrationMethod"))),
461+
}
462+
}
463+
}
464+
438465
opencv_type_enum! { crate::calib3d::HandEyeCalibrationMethod }
439466

440467
#[repr(C)]
@@ -447,6 +474,21 @@ pub mod calib3d {
447474
LOCAL_OPTIM_SIGMA = 4,
448475
}
449476

477+
impl TryFrom<i32> for LocalOptimMethod {
478+
type Error = crate::Error;
479+
480+
fn try_from(value: i32) -> Result<Self, Self::Error> {
481+
match value {
482+
0 => Ok(Self::LOCAL_OPTIM_NULL),
483+
1 => Ok(Self::LOCAL_OPTIM_INNER_LO),
484+
2 => Ok(Self::LOCAL_OPTIM_INNER_AND_ITER_LO),
485+
3 => Ok(Self::LOCAL_OPTIM_GC),
486+
4 => Ok(Self::LOCAL_OPTIM_SIGMA),
487+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::LocalOptimMethod"))),
488+
}
489+
}
490+
}
491+
450492
opencv_type_enum! { crate::calib3d::LocalOptimMethod }
451493

452494
#[repr(C)]
@@ -457,6 +499,19 @@ pub mod calib3d {
457499
NEIGH_FLANN_RADIUS = 2,
458500
}
459501

502+
impl TryFrom<i32> for NeighborSearchMethod {
503+
type Error = crate::Error;
504+
505+
fn try_from(value: i32) -> Result<Self, Self::Error> {
506+
match value {
507+
0 => Ok(Self::NEIGH_FLANN_KNN),
508+
1 => Ok(Self::NEIGH_GRID),
509+
2 => Ok(Self::NEIGH_FLANN_RADIUS),
510+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::NeighborSearchMethod"))),
511+
}
512+
}
513+
}
514+
460515
opencv_type_enum! { crate::calib3d::NeighborSearchMethod }
461516

462517
#[repr(C)]
@@ -468,6 +523,20 @@ pub mod calib3d {
468523
COV_POLISHER = 3,
469524
}
470525

526+
impl TryFrom<i32> for PolishingMethod {
527+
type Error = crate::Error;
528+
529+
fn try_from(value: i32) -> Result<Self, Self::Error> {
530+
match value {
531+
0 => Ok(Self::NONE_POLISHER),
532+
1 => Ok(Self::LSQ_POLISHER),
533+
2 => Ok(Self::MAGSAC),
534+
3 => Ok(Self::COV_POLISHER),
535+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::PolishingMethod"))),
536+
}
537+
}
538+
}
539+
471540
opencv_type_enum! { crate::calib3d::PolishingMethod }
472541

473542
#[repr(C)]
@@ -479,6 +548,18 @@ pub mod calib3d {
479548
CALIB_ROBOT_WORLD_HAND_EYE_LI = 1,
480549
}
481550

551+
impl TryFrom<i32> for RobotWorldHandEyeCalibrationMethod {
552+
type Error = crate::Error;
553+
554+
fn try_from(value: i32) -> Result<Self, Self::Error> {
555+
match value {
556+
0 => Ok(Self::CALIB_ROBOT_WORLD_HAND_EYE_SHAH),
557+
1 => Ok(Self::CALIB_ROBOT_WORLD_HAND_EYE_LI),
558+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::RobotWorldHandEyeCalibrationMethod"))),
559+
}
560+
}
561+
}
562+
482563
opencv_type_enum! { crate::calib3d::RobotWorldHandEyeCalibrationMethod }
483564

484565
#[repr(C)]
@@ -490,6 +571,20 @@ pub mod calib3d {
490571
SAMPLING_PROSAC = 3,
491572
}
492573

574+
impl TryFrom<i32> for SamplingMethod {
575+
type Error = crate::Error;
576+
577+
fn try_from(value: i32) -> Result<Self, Self::Error> {
578+
match value {
579+
0 => Ok(Self::SAMPLING_UNIFORM),
580+
1 => Ok(Self::SAMPLING_PROGRESSIVE_NAPSAC),
581+
2 => Ok(Self::SAMPLING_NAPSAC),
582+
3 => Ok(Self::SAMPLING_PROSAC),
583+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::SamplingMethod"))),
584+
}
585+
}
586+
}
587+
493588
opencv_type_enum! { crate::calib3d::SamplingMethod }
494589

495590
#[repr(C)]
@@ -501,6 +596,20 @@ pub mod calib3d {
501596
SCORE_METHOD_LMEDS = 3,
502597
}
503598

599+
impl TryFrom<i32> for ScoreMethod {
600+
type Error = crate::Error;
601+
602+
fn try_from(value: i32) -> Result<Self, Self::Error> {
603+
match value {
604+
0 => Ok(Self::SCORE_METHOD_RANSAC),
605+
1 => Ok(Self::SCORE_METHOD_MSAC),
606+
2 => Ok(Self::SCORE_METHOD_MAGSAC),
607+
3 => Ok(Self::SCORE_METHOD_LMEDS),
608+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::ScoreMethod"))),
609+
}
610+
}
611+
}
612+
504613
opencv_type_enum! { crate::calib3d::ScoreMethod }
505614

506615
#[repr(C)]
@@ -546,6 +655,26 @@ pub mod calib3d {
546655
SOLVEPNP_MAX_COUNT = 9,
547656
}
548657

658+
impl TryFrom<i32> for SolvePnPMethod {
659+
type Error = crate::Error;
660+
661+
fn try_from(value: i32) -> Result<Self, Self::Error> {
662+
match value {
663+
0 => Ok(Self::SOLVEPNP_ITERATIVE),
664+
1 => Ok(Self::SOLVEPNP_EPNP),
665+
2 => Ok(Self::SOLVEPNP_P3P),
666+
3 => Ok(Self::SOLVEPNP_DLS),
667+
4 => Ok(Self::SOLVEPNP_UPNP),
668+
5 => Ok(Self::SOLVEPNP_AP3P),
669+
6 => Ok(Self::SOLVEPNP_IPPE),
670+
7 => Ok(Self::SOLVEPNP_IPPE_SQUARE),
671+
8 => Ok(Self::SOLVEPNP_SQPNP),
672+
9 => Ok(Self::SOLVEPNP_MAX_COUNT),
673+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::SolvePnPMethod"))),
674+
}
675+
}
676+
}
677+
549678
opencv_type_enum! { crate::calib3d::SolvePnPMethod }
550679

551680
/// cv::undistort mode
@@ -556,6 +685,18 @@ pub mod calib3d {
556685
PROJ_SPHERICAL_EQRECT = 1,
557686
}
558687

688+
impl TryFrom<i32> for UndistortTypes {
689+
type Error = crate::Error;
690+
691+
fn try_from(value: i32) -> Result<Self, Self::Error> {
692+
match value {
693+
0 => Ok(Self::PROJ_SPHERICAL_ORTHO),
694+
1 => Ok(Self::PROJ_SPHERICAL_EQRECT),
695+
_ => Err(crate::Error::new(crate::core::StsBadArg, format!("Value: {value} is not valid for enum: crate::calib3d::UndistortTypes"))),
696+
}
697+
}
698+
}
699+
559700
opencv_type_enum! { crate::calib3d::UndistortTypes }
560701

561702
pub type CirclesGridFinderParameters2 = crate::calib3d::CirclesGridFinderParameters;

0 commit comments

Comments
 (0)