opencv_binding_generator/writer/rust_native/
enumeration.rs1use std::borrow::Cow;
2use std::collections::HashMap;
3use std::sync::LazyLock;
4
5use semver::Version;
6
7use super::RustNativeGeneratedElement;
8use super::element::{DefaultRustNativeElement, RustElement};
9use crate::constant::{ConstDesc, Value};
10use crate::debug::NameDebug;
11use crate::enumeration::EnumBitfield;
12use crate::type_ref::{FishStyle, NameStyle};
13use crate::writer::rust_native::constant::ValueExt;
14use crate::{CompiledInterpolation, Const, EntityElement, Enum, StrExt, StringExt, SupportedModule};
15
16impl RustElement for Enum<'_, '_> {
17 fn rust_module(&self) -> SupportedModule {
18 DefaultRustNativeElement::rust_module(self.entity())
19 }
20
21 fn rust_name(&self, style: NameStyle) -> Cow<'_, str> {
22 DefaultRustNativeElement::rust_name(self, self.entity(), style).into()
23 }
24}
25
26impl RustNativeGeneratedElement for Enum<'_, '_> {
27 fn element_safe_id(&self) -> String {
28 format!("{}-{}", self.rust_module().opencv_name(), self.rust_name(NameStyle::decl()))
29 }
30
31 fn gen_rust(&self, opencv_version: &Version) -> String {
32 static ENUM_TPL: LazyLock<CompiledInterpolation> =
33 LazyLock::new(|| include_str!("tpl/enum/enum.tpl.rs").compile_interpolation());
34 static ENUM_BITFIELD_TPL: LazyLock<CompiledInterpolation> =
35 LazyLock::new(|| include_str!("tpl/enum/enum_bitfield.tpl.rs").compile_interpolation());
36
37 static CONST_TPL: LazyLock<CompiledInterpolation> =
38 LazyLock::new(|| include_str!("tpl/enum/const.tpl.rs").compile_interpolation());
39 static CONST_BITFIELD_TPL: LazyLock<CompiledInterpolation> =
40 LazyLock::new(|| include_str!("tpl/enum/const_bitfield.tpl.rs").compile_interpolation());
41
42 static CONST_IGNORED_TPL_SRC: &str = include_str!("tpl/enum/const_ignored.tpl.rs");
43 static CONST_IGNORED_TPL: LazyLock<CompiledInterpolation> = LazyLock::new(|| CONST_IGNORED_TPL_SRC.compile_interpolation());
44
45 let mut consts = self.consts();
46
47 let bitfield = self.bitfield();
48
49 let (const_tpl, const_ignored_tpl) = if bitfield.is_bitfield() {
50 (&CONST_BITFIELD_TPL, &CONST_BITFIELD_TPL)
52 } else {
53 (&CONST_TPL, &CONST_IGNORED_TPL)
54 };
55
56 let mut enum_consts = String::with_capacity(consts.len() * CONST_IGNORED_TPL_SRC.len());
57 let mut consts_list = String::with_capacity(consts.len() * 20);
58
59 let mut generated_values = HashMap::<String, Cow<str>>::with_capacity(consts.len());
60 match bitfield {
61 EnumBitfield::BitfieldWithoutZero => consts.insert(
62 0,
63 Const::new_desc(
64 ConstDesc::new("NONE", self.rust_module(), Value::integer(0))
65 .doc_comment("No flags are set, might not make sense for all enums"),
66 ),
67 ),
68 EnumBitfield::NotBitfield | EnumBitfield::BitfieldWithZero => {}
69 }
70 for c in &consts {
71 let name = c.rust_leafname(FishStyle::No);
72 let value = c.value().expect("Can't get value of enum variant");
73 let value = value.rust_render();
74 let duplicate_name = generated_values.get(value.as_ref()).map(|s| s.as_ref());
75 let enum_const_tpl = if duplicate_name.is_some() {
76 const_ignored_tpl
77 } else {
78 consts_list.extend_sep(", ", name.as_ref());
79 const_tpl
80 };
81 let comment_marker = if duplicate_name.is_some() && !bitfield.is_bitfield() {
82 "//"
83 } else {
84 "///"
85 };
86 let doc_comment = c.rust_doc_comment(comment_marker, opencv_version);
87 enum_const_tpl.interpolate_into(
88 &mut enum_consts,
89 &HashMap::from([
90 ("name", name.as_ref()),
91 ("value", value.as_ref()),
92 ("doc_comment", &doc_comment),
93 ("duplicate_name", duplicate_name.unwrap_or("")),
94 ]),
95 );
96
97 generated_values.insert(value.into_owned(), name);
98 }
99
100 let tpl = if bitfield.is_bitfield() {
101 &ENUM_BITFIELD_TPL
102 } else {
103 &ENUM_TPL
104 };
105 let rust_decl = self.rust_name(NameStyle::decl());
106 let rust_ref = &self.rust_name(NameStyle::ref_());
107 tpl.interpolate(&HashMap::from([
108 ("rust_decl", rust_decl.as_ref()),
109 ("rust_ref", rust_ref.as_ref()),
110 ("doc_comment", &self.rust_doc_comment("///", opencv_version)),
111 ("debug", &self.get_debug()),
112 ("enum_consts", &enum_consts),
113 ("consts_list", &consts_list),
114 ]))
115 }
116}