opencv_binding_generator/writer/rust_native/
element.rs1use std::borrow::Cow;
2use std::fmt::Debug;
3
4use clang::{Entity, EntityKind};
5
6use super::comment::RenderComment;
7use crate::type_ref::FishStyle;
8use crate::{
9 opencv_module_from_path, reserved_rename, settings, CppNameStyle, Element, GeneratedType, IteratorExt, NameStyle, StringExt,
10};
11
12pub struct DefaultRustNativeElement;
13
14impl DefaultRustNativeElement {
15 pub fn rust_module(entity: Entity) -> Cow<'static, str> {
16 entity
17 .get_location()
18 .expect("Can't get location")
19 .get_spelling_location()
20 .file
21 .and_then(|file| opencv_module_from_path(&file.get_path()).map(|m| m.to_string()))
22 .map_or_else(|| Cow::Borrowed("core"), Cow::Owned)
23 }
24
25 pub fn rust_module_reference(this: &(impl RustElement + ?Sized)) -> Cow<str> {
26 let module = this.rust_module();
27 if settings::STATIC_MODULES.contains(module.as_ref()) {
28 module
29 } else {
30 format!("crate::{}", module_safe_name(module)).into()
31 }
32 }
33
34 pub fn rust_leafname(this: &(impl Element + ?Sized)) -> Cow<str> {
35 reserved_rename(this.cpp_name(CppNameStyle::Declaration))
36 }
37
38 pub fn rust_name(this: &(impl RustElement + ?Sized), entity: Entity, name_style: NameStyle) -> String {
39 let mut parts = Vec::with_capacity(4);
40 parts.push(this.rust_leafname(name_style.turbo_fish_style()));
41 let mut entity = entity;
42 let module = Self::rust_module(entity);
43 while let Some(parent) = entity.get_semantic_parent() {
44 match parent.get_kind() {
45 EntityKind::ClassDecl | EntityKind::StructDecl | EntityKind::ClassTemplate => {
46 let parent_name = parent.get_name().expect("Can't get parent name");
47 if parts.last().map_or(true, |last| last != &parent_name) {
48 parts.push(parent_name.into());
49 }
50 }
51 EntityKind::EnumDecl => {
52 if parent.is_scoped() {
53 parts.push(parent.get_name().expect("Can't get parent name").into());
54 }
55 }
56 EntityKind::TranslationUnit | EntityKind::UnexposedDecl | EntityKind::FunctionTemplate => {
57 break;
58 }
59 EntityKind::Namespace => {
60 let parent_namespace = parent.get_name().expect("Can't get parent name");
61 let no_skip_prefix = settings::NO_SKIP_NAMESPACE_IN_LOCALNAME
62 .get(module.as_ref())
63 .and_then(|module_specific| module_specific.get(parent_namespace.as_str()))
64 .or_else(|| {
65 settings::NO_SKIP_NAMESPACE_IN_LOCALNAME
66 .get("*")
67 .and_then(|generic| generic.get(parent_namespace.as_str()))
68 });
69 if let Some(&prefix) = no_skip_prefix {
70 parts.push(prefix.into());
71 } else {
72 break;
73 }
74 }
75 EntityKind::Constructor | EntityKind::FunctionDecl | EntityKind::Method | EntityKind::NotImplemented => {}
76 _ => {
77 unreachable!("Can't get kind of parent: {parent:#?} for element: {entity:#?}")
78 }
79 }
80 entity = parent;
81 }
82 let decl_name = parts.into_iter().rev().join("_");
83 match name_style {
84 NameStyle::Declaration => decl_name,
85 NameStyle::Reference(_) => {
86 let mut out = this.rust_module_reference().into_owned();
87 out.extend_sep("::", &decl_name);
88 out
89 }
90 }
91 }
92
93 pub fn rendered_doc_comment(entity: Entity, comment_marker: &str, opencv_version: &str) -> String {
94 RenderComment::new(&entity.doc_comment(), opencv_version)
95 .render_with_comment_marker(comment_marker)
96 .into_owned()
97 }
98}
99
100pub trait RustNativeGeneratedElement {
101 fn element_order(&self) -> u8 {
103 50
104 }
105
106 fn element_safe_id(&self) -> String;
107
108 fn gen_rust(&self, _opencv_version: &str) -> String {
109 "".to_string()
110 }
111
112 fn gen_rust_externs(&self) -> String {
113 "".to_string()
114 }
115
116 fn gen_cpp(&self) -> String {
117 "".to_string()
118 }
119}
120
121pub trait RustElement: Element {
122 fn rust_module(&self) -> Cow<str>;
123
124 fn rust_module_reference(&self) -> Cow<str> {
125 DefaultRustNativeElement::rust_module_reference(self)
126 }
127
128 fn rust_name(&self, style: NameStyle) -> Cow<str>;
129
130 fn rust_leafname(&self, _fish_style: FishStyle) -> Cow<str> {
135 DefaultRustNativeElement::rust_leafname(self)
136 }
137
138 fn rendered_doc_comment(&self, comment_marker: &str, opencv_version: &str) -> String;
139}
140
141pub trait DebugRust {
142 type DebugType: Debug;
143
144 fn dbg_rust(self) -> Self::DebugType;
145}
146
147impl<'ne, 'tu: 'ne, 'ge: 'ne> AsRef<dyn RustNativeGeneratedElement + 'ne> for GeneratedType<'tu, 'ge> {
148 fn as_ref(&self) -> &(dyn RustNativeGeneratedElement + 'ne) {
149 match self {
150 GeneratedType::Vector(vec) => vec,
151 GeneratedType::SmartPtr(ptr) => ptr,
152 GeneratedType::Tuple(tuple) => tuple,
153 GeneratedType::AbstractRefWrapper(aref) => aref,
154 }
155 }
156}
157
158fn module_safe_name(module: Cow<str>) -> Cow<str> {
160 match module.as_ref() {
161 "3d" => Cow::Borrowed("mod_3d"),
162 _ => module,
163 }
164}