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 SupportedModule,
11};
12
13pub struct DefaultRustNativeElement;
14
15impl DefaultRustNativeElement {
16 pub fn rust_module(entity: Entity) -> SupportedModule {
17 entity
18 .get_location()
19 .expect("Can't get location")
20 .get_spelling_location()
21 .file
22 .and_then(|file| opencv_module_from_path(&file.get_path()))
23 .unwrap_or(SupportedModule::Core)
24 }
25
26 pub fn rust_module_reference(this: &(impl RustElement + ?Sized)) -> Cow<'_, str> {
27 let module = this.rust_module();
28 let module_rust_safe_name = module.rust_safe_name();
29 if settings::STATIC_RUST_MODULES.contains(module_rust_safe_name) {
30 module_rust_safe_name.into()
31 } else {
32 format!("crate::{module_rust_safe_name}").into()
33 }
34 }
35
36 pub fn rust_leafname(this: &(impl Element + ?Sized)) -> Cow<'_, str> {
37 reserved_rename(this.cpp_name(CppNameStyle::Declaration))
38 }
39
40 pub fn rust_name(this: &(impl RustElement + ?Sized), entity: Entity, name_style: NameStyle) -> String {
41 let mut parts = Vec::with_capacity(4);
42 parts.push(this.rust_leafname(name_style.turbo_fish_style()));
43 let mut entity = entity;
44 let module = Self::rust_module(entity);
45 while let Some(parent) = entity.get_semantic_parent() {
46 match parent.get_kind() {
47 EntityKind::ClassDecl | EntityKind::StructDecl | EntityKind::ClassTemplate => {
48 let parent_name = parent.get_name().expect("Can't get parent name");
49 if parts.last().is_none_or(|last| last != &parent_name) {
50 parts.push(parent_name.into());
51 }
52 }
53 EntityKind::EnumDecl => {
54 if parent.is_scoped() {
55 parts.push(parent.get_name().expect("Can't get parent name").into());
56 }
57 }
58 EntityKind::TranslationUnit | EntityKind::UnexposedDecl | EntityKind::FunctionTemplate => {
59 break;
60 }
61 EntityKind::Namespace => {
62 let parent_namespace = parent.get_name().expect("Can't get parent name");
63 let no_skip_prefix = settings::NO_SKIP_NAMESPACE_IN_LOCALNAME
64 .get(&Some(module))
65 .and_then(|module_specific| module_specific.get(parent_namespace.as_str()))
66 .or_else(|| {
67 settings::NO_SKIP_NAMESPACE_IN_LOCALNAME
68 .get(&None)
69 .and_then(|generic| generic.get(parent_namespace.as_str()))
70 });
71 if let Some(&prefix) = no_skip_prefix {
72 parts.push(prefix.into());
73 } else {
74 break;
75 }
76 }
77 EntityKind::Constructor | EntityKind::FunctionDecl | EntityKind::Method | EntityKind::NotImplemented => {}
78 _ => {
79 unreachable!("Can't get kind of parent: {parent:#?} for element: {entity:#?}")
80 }
81 }
82 entity = parent;
83 }
84 let decl_name = parts.into_iter().rev().join("_");
85 match name_style {
86 NameStyle::Declaration => decl_name,
87 NameStyle::Reference(_) => {
88 let mut out = this.rust_module_reference().into_owned();
89 out.extend_sep("::", &decl_name);
90 out
91 }
92 }
93 }
94}
95
96pub trait RustNativeGeneratedElement {
97 fn element_order(&self) -> u8 {
99 50
100 }
101
102 fn element_safe_id(&self) -> String;
103
104 fn gen_rust(&self, _opencv_version: &str) -> String {
105 "".to_string()
106 }
107
108 fn gen_rust_externs(&self) -> String {
109 "".to_string()
110 }
111
112 fn gen_cpp(&self) -> String {
113 "".to_string()
114 }
115}
116
117pub trait RustElement: Element {
118 fn rust_module(&self) -> SupportedModule;
119
120 fn rust_module_reference(&self) -> Cow<'_, str> {
121 DefaultRustNativeElement::rust_module_reference(self)
122 }
123
124 fn rust_name(&self, style: NameStyle) -> Cow<'_, str>;
125
126 fn rust_leafname(&self, _fish_style: FishStyle) -> Cow<'_, str> {
131 DefaultRustNativeElement::rust_leafname(self)
132 }
133
134 fn rust_doc_comment(&self, comment_marker: &str, opencv_version: &str) -> String {
135 RenderComment::new(self.doc_comment().into_owned(), opencv_version)
136 .render_with_comment_marker(comment_marker)
137 .into_owned()
138 }
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}