opencv_binding_generator/writer/rust_native/
enumeration.rs

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