1use std::cell::LazyCell;
2use std::rc::Rc;
3use std::sync::LazyLock;
4
5use clang::{Entity, EntityKind, Type, TypeKind};
6use regex::bytes::{Captures, Regex};
7
8use crate::class::ClassDesc;
9use crate::function::Function;
10use crate::smart_ptr::{SmartPtr, SmartPtrDesc};
11use crate::tuple::Tuple;
12use crate::type_ref::{Constness, TemplateArg, TypeRef, TypeRefKind, TypeRefTypeHint};
13use crate::typedef::{NewTypedefResult, TypedefDesc};
14use crate::vector::{Vector, VectorDesc};
15use crate::{settings, Class, CppNameStyle, Element, Enum, GeneratorEnv, StringExt, Typedef};
16
17#[derive(Clone, Debug)]
18pub struct TypeRefDesc<'tu, 'ge> {
19 pub kind: TypeRefKind<'tu, 'ge>,
20 pub inherent_constness: Constness,
21 pub type_hint: TypeRefTypeHint,
22 pub template_specialization_args: Rc<[TemplateArg<'tu, 'ge>]>,
23}
24
25impl<'tu, 'ge> TypeRefDesc<'tu, 'ge> {
26 pub fn new(kind: TypeRefKind<'tu, 'ge>, inherent_constness: Constness) -> Self {
27 Self {
28 kind,
29 inherent_constness,
30 type_hint: TypeRefTypeHint::None,
31 template_specialization_args: Rc::new([]),
32 }
33 }
34
35 pub fn try_primitive(cpp_name: &str) -> Option<TypeRef<'tu, 'ge>> {
36 let names = match cpp_name {
37 "void" => Some(TypeKind::Void),
38 "bool" => Some(TypeKind::Bool),
39 "char" => Some(TypeKind::CharS),
40 "signed char" => Some(TypeKind::SChar),
41 "unsigned char" => Some(TypeKind::UChar),
42 "wchar_t" => Some(TypeKind::WChar),
43 "char16_t" => Some(TypeKind::Char16),
44 "char32_t" => Some(TypeKind::Char32),
45 "short" => Some(TypeKind::Short),
46 "unsigned short" => Some(TypeKind::UShort),
47 "int" => Some(TypeKind::Int),
48 "unsigned int" => Some(TypeKind::UInt),
49 "long" => Some(TypeKind::Long),
50 "unsigned long" => Some(TypeKind::ULong),
51 "long long" => Some(TypeKind::LongLong),
52 "unsigned long long" => Some(TypeKind::ULongLong),
53 "__int128_t" => Some(TypeKind::Int128),
54 "__uint128_t" => Some(TypeKind::UInt128),
55 "float" => Some(TypeKind::Float),
56 "double" => Some(TypeKind::Double),
57 _ => None,
58 };
59 names
60 .and_then(TypeRefKind::try_from_clang_primitive)
61 .or_else(|| {
62 settings::PRIMITIVE_TYPEDEFS
63 .get(cpp_name)
64 .map(|(rust, cpp)| TypeRefKind::Primitive(rust, cpp))
65 })
66 .map(|type_ref_kind| TypeRef::new_desc(TypeRefDesc::new(type_ref_kind, Constness::Mut)))
67 }
68
69 pub fn void() -> TypeRef<'tu, 'ge> {
70 Self::try_primitive("void").expect("Static primitive type")
71 }
72
73 pub fn bool() -> TypeRef<'tu, 'ge> {
74 Self::try_primitive("bool").expect("Static primitive type")
75 }
76
77 pub fn schar() -> TypeRef<'tu, 'ge> {
78 Self::try_primitive("signed char").expect("Static primitive type")
79 }
80
81 pub fn char() -> TypeRef<'tu, 'ge> {
82 Self::try_primitive("char").expect("Static primitive type")
83 }
84
85 pub fn char_ptr() -> TypeRef<'tu, 'ge> {
86 TypeRef::new_pointer(Self::char())
87 }
88
89 pub fn char_const_ptr() -> TypeRef<'tu, 'ge> {
90 TypeRef::new_pointer(Self::char().with_inherent_constness(Constness::Const))
91 }
92
93 pub fn uchar() -> TypeRef<'tu, 'ge> {
94 Self::try_primitive("unsigned char").expect("Static primitive type")
95 }
96
97 pub fn float() -> TypeRef<'tu, 'ge> {
98 Self::try_primitive("float").expect("Static primitive type")
99 }
100
101 pub fn double() -> TypeRef<'tu, 'ge> {
102 Self::try_primitive("double").expect("Static primitive type")
103 }
104
105 pub fn int() -> TypeRef<'tu, 'ge> {
106 Self::try_primitive("int").expect("Static primitive type")
107 }
108
109 pub fn int64_t() -> TypeRef<'tu, 'ge> {
110 Self::try_primitive("int64_t").expect("Static primitive type")
111 }
112
113 pub fn uint64_t() -> TypeRef<'tu, 'ge> {
114 Self::try_primitive("uint64_t").expect("Static primitive type")
115 }
116
117 pub fn size_t() -> TypeRef<'tu, 'ge> {
118 Self::try_primitive("size_t").expect("Static primitive type")
119 }
120
121 pub fn array_int(size: Option<usize>) -> TypeRef<'tu, 'ge> {
122 TypeRef::new_array(Self::int(), size)
123 }
124
125 pub fn array_uchar(size: Option<usize>) -> TypeRef<'tu, 'ge> {
126 TypeRef::new_array(Self::uchar(), size)
127 }
128
129 pub fn cv_size_() -> TypeRef<'tu, 'ge> {
131 TypeRef::new_class(ClassDesc::cv_size_())
132 }
133
134 pub fn cv_size() -> TypeRef<'tu, 'ge> {
136 TypeRef::new_typedef(TypedefDesc::cv_size())
137 }
138
139 pub fn cv_point_() -> TypeRef<'tu, 'ge> {
141 TypeRef::new_class(ClassDesc::cv_point_())
142 }
143
144 pub fn cv_point() -> TypeRef<'tu, 'ge> {
146 TypeRef::new_typedef(TypedefDesc::cv_point())
147 }
148
149 pub fn cv_point2f() -> TypeRef<'tu, 'ge> {
151 TypeRef::new_typedef(TypedefDesc::cv_point2f())
152 }
153
154 pub fn cv_point2d() -> TypeRef<'tu, 'ge> {
156 TypeRef::new_typedef(TypedefDesc::cv_point2d())
157 }
158
159 pub fn cv_point3i() -> TypeRef<'tu, 'ge> {
161 TypeRef::new_typedef(TypedefDesc::cv_point3i())
162 }
163
164 pub fn cv_point3f() -> TypeRef<'tu, 'ge> {
166 TypeRef::new_typedef(TypedefDesc::cv_point3f())
167 }
168
169 pub fn cv_point3d() -> TypeRef<'tu, 'ge> {
171 TypeRef::new_typedef(TypedefDesc::cv_point3d())
172 }
173
174 pub fn cv_vec() -> TypeRef<'tu, 'ge> {
176 TypeRef::new_class(ClassDesc::cv_vec())
177 }
178
179 pub fn cv_vec2f() -> TypeRef<'tu, 'ge> {
181 TypeRef::new_typedef(TypedefDesc::cv_vec2f())
182 }
183
184 pub fn cv_vec2d() -> TypeRef<'tu, 'ge> {
186 TypeRef::new_typedef(TypedefDesc::cv_vec2d())
187 }
188
189 pub fn cv_vec3f() -> TypeRef<'tu, 'ge> {
191 TypeRef::new_typedef(TypedefDesc::cv_vec3f())
192 }
193
194 pub fn cv_vec3d() -> TypeRef<'tu, 'ge> {
196 TypeRef::new_typedef(TypedefDesc::cv_vec3d())
197 }
198
199 pub fn cv_vec4i() -> TypeRef<'tu, 'ge> {
201 TypeRef::new_typedef(TypedefDesc::cv_vec4i())
202 }
203
204 pub fn cv_scalar_() -> TypeRef<'tu, 'ge> {
206 TypeRef::new_class(ClassDesc::cv_scalar_())
207 }
208
209 pub fn cv_scalar() -> TypeRef<'tu, 'ge> {
211 TypeRef::new_typedef(TypedefDesc::cv_scalar())
212 }
213
214 pub fn cv_input_array() -> TypeRef<'tu, 'ge> {
216 TypeRef::new_class(ClassDesc::cv_input_array())
217 }
218
219 pub fn cv_output_array() -> TypeRef<'tu, 'ge> {
221 TypeRef::new_class(ClassDesc::cv_output_array())
222 }
223
224 pub fn cv_input_output_array() -> TypeRef<'tu, 'ge> {
226 TypeRef::new_class(ClassDesc::cv_input_output_array())
227 }
228
229 pub fn cv_string() -> TypeRef<'tu, 'ge> {
231 TypeRef::new_class(ClassDesc::cv_string())
232 }
233
234 pub fn std_string() -> TypeRef<'tu, 'ge> {
236 TypeRef::new_class(ClassDesc::std_string())
237 }
238
239 pub fn vector_of_vector_of_double() -> TypeRef<'tu, 'ge> {
241 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRef::new_vector(Vector::new_desc(
242 VectorDesc::new(TypeRefDesc::double()),
243 )))))
244 }
245
246 pub fn vector_of_int() -> TypeRef<'tu, 'ge> {
248 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::int())))
249 }
250
251 pub fn vector_of_vector_of_int() -> TypeRef<'tu, 'ge> {
253 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(Self::vector_of_int())))
254 }
255
256 pub fn vector_of_cv_string() -> TypeRef<'tu, 'ge> {
258 TypeRef::new_vector(VectorDesc::vector_of_cv_string())
259 }
260
261 pub fn vector_of_cv_vec2f() -> TypeRef<'tu, 'ge> {
263 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_vec2f())))
264 }
265
266 pub fn vector_of_cv_vec2d() -> TypeRef<'tu, 'ge> {
268 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_vec2d())))
269 }
270
271 pub fn vector_of_cv_vec3f() -> TypeRef<'tu, 'ge> {
273 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_vec3f())))
274 }
275
276 pub fn vector_of_vector_of_cv_vec2f() -> TypeRef<'tu, 'ge> {
278 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::vector_of_cv_vec2f())))
279 }
280
281 pub fn vector_of_vector_of_cv_vec2d() -> TypeRef<'tu, 'ge> {
283 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::vector_of_cv_vec2d())))
284 }
285
286 pub fn vector_of_vector_of_cv_vec3f() -> TypeRef<'tu, 'ge> {
288 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::vector_of_cv_vec3f())))
289 }
290
291 pub fn vector_of_vector_of_cv_vec3d() -> TypeRef<'tu, 'ge> {
293 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::vector_of_cv_vec3d())))
294 }
295
296 pub fn vector_of_cv_vec3d() -> TypeRef<'tu, 'ge> {
298 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_vec3d())))
299 }
300
301 pub fn vector_of_cv_vec4i() -> TypeRef<'tu, 'ge> {
303 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_vec4i())))
304 }
305
306 pub fn vector_of_vector_of_cv_point() -> TypeRef<'tu, 'ge> {
308 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRef::new_vector(Vector::new_desc(
309 VectorDesc::new(TypeRefDesc::cv_point()),
310 )))))
311 }
312
313 pub fn vector_of_cv_point2f() -> TypeRef<'tu, 'ge> {
315 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_point2f())))
316 }
317
318 pub fn vector_of_cv_point2d() -> TypeRef<'tu, 'ge> {
320 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_point2d())))
321 }
322
323 pub fn vector_of_cv_point3i() -> TypeRef<'tu, 'ge> {
325 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_point3i())))
326 }
327
328 pub fn vector_of_vector_of_cv_point3i() -> TypeRef<'tu, 'ge> {
330 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(Self::vector_of_cv_point3i())))
331 }
332
333 pub fn vector_of_cv_point3f() -> TypeRef<'tu, 'ge> {
335 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_point3f())))
336 }
337
338 pub fn vector_of_vector_of_cv_point3f() -> TypeRef<'tu, 'ge> {
340 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(Self::vector_of_cv_point3f())))
341 }
342
343 pub fn vector_of_cv_point3d() -> TypeRef<'tu, 'ge> {
345 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(TypeRefDesc::cv_point3d())))
346 }
347
348 pub fn vector_of_vector_of_cv_point2f() -> TypeRef<'tu, 'ge> {
350 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(Self::vector_of_cv_point2f())))
351 }
352
353 pub fn vector_of_vector_of_cv_point2d() -> TypeRef<'tu, 'ge> {
355 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(Self::vector_of_cv_point2d())))
356 }
357
358 pub fn vector_of_vector_of_cv_point3d() -> TypeRef<'tu, 'ge> {
360 TypeRef::new_vector(Vector::new_desc(VectorDesc::new(Self::vector_of_cv_point3d())))
361 }
362
363 pub fn ptr_of_float() -> TypeRef<'tu, 'ge> {
365 TypeRef::new_smartptr(SmartPtr::new_desc(SmartPtrDesc::new(TypeRefDesc::float())))
366 }
367
368 pub fn ptr_of_cv_feature2d() -> TypeRef<'tu, 'ge> {
370 TypeRef::new_smartptr(SmartPtr::new_desc(SmartPtrDesc::new(TypeRefDesc::cv_feature2d())))
371 }
372
373 pub fn cv_feature2d() -> TypeRef<'tu, 'ge> {
375 TypeRef::new_class(ClassDesc::cv_feature2d())
376 }
377
378 pub fn cv_dnn_dict_value() -> TypeRef<'tu, 'ge> {
380 TypeRef::new_class(ClassDesc::cv_dnn_dict_value())
381 }
382
383 pub fn ptr_of_cv_keypoint() -> TypeRef<'tu, 'ge> {
385 TypeRef::new_smartptr(SmartPtr::new_desc(SmartPtrDesc::new(TypeRefDesc::cv_keypoint())))
386 }
387
388 pub fn cv_keypoint() -> TypeRef<'tu, 'ge> {
390 TypeRef::new_class(ClassDesc::cv_keypoint())
391 }
392}
393
394pub trait ClangTypeExt<'tu> {
395 fn kind<'ge>(
396 self,
397 type_hint: TypeRefTypeHint,
398 parent_entity: Option<Entity<'tu>>,
399 gen_env: &'ge GeneratorEnv<'tu>,
400 ) -> TypeRefKind<'tu, 'ge>;
401
402 fn template_specialization_args<'ge>(self, gen_env: &'ge GeneratorEnv<'tu>) -> Vec<TemplateArg<'tu, 'ge>>;
403}
404
405impl<'tu> ClangTypeExt<'tu> for Type<'tu> {
406 fn kind<'ge>(
407 self,
408 type_hint: TypeRefTypeHint,
409 parent_entity: Option<Entity<'tu>>,
410 gen_env: &'ge GeneratorEnv<'tu>,
411 ) -> TypeRefKind<'tu, 'ge> {
412 let kind = self.get_kind();
413 TypeRefKind::try_from_clang_primitive(kind).unwrap_or_else(|| {
414 match kind {
415 TypeKind::Pointer => {
416 let pointee = self.get_pointee_type().expect("No pointee type for pointer");
417 let pointee_typeref = TypeRef::new_ext(pointee, type_hint.recurse_inner(), parent_entity, gen_env);
418 let pointee_kind = pointee_typeref.kind();
419 if pointee_kind.is_function() {
420 pointee_kind.into_owned()
421 } else if matches!(pointee_typeref.type_hint(), TypeRefTypeHint::Slice) {
422 TypeRefKind::Array(pointee_typeref, None)
423 } else {
424 TypeRefKind::Pointer(pointee_typeref)
425 }
426 }
427
428 TypeKind::LValueReference => TypeRefKind::Reference(TypeRef::new_ext(
429 self.get_pointee_type().expect("No pointee type for reference"),
430 type_hint.recurse_inner(),
431 parent_entity,
432 gen_env,
433 )),
434
435 TypeKind::RValueReference => TypeRefKind::RValueReference(TypeRef::new_ext(
436 self.get_pointee_type().expect("No pointee type for reference"),
437 type_hint,
438 parent_entity,
439 gen_env,
440 )),
441
442 TypeKind::Elaborated => {
443 let out = self
444 .get_elaborated_type()
445 .expect("Can't get elaborated type")
446 .kind(type_hint, parent_entity, gen_env);
447 if matches!(out, TypeRefKind::Class(..)) {
448 let mut elaborate_name = self.get_display_name();
449 elaborate_name.replace_in_place("const ", "");
450 if let Some(decl) = self.get_declaration() {
451 if elaborate_name.starts_with("std::") {
452 return TypeRefKind::Class(Class::new_ext(decl, elaborate_name, gen_env));
453 }
454 }
455 }
456 out
457 }
458
459 TypeKind::Record | TypeKind::Unexposed => {
460 if let Some(decl) = self.get_declaration() {
461 let cpp_refname = decl.cpp_name(CppNameStyle::Reference);
462 let kind = decl.get_kind();
463 let is_decl = kind == EntityKind::StructDecl || kind == EntityKind::ClassDecl;
464 if cpp_refname.starts_with("std::") && cpp_refname.contains("::vector") {
465 TypeRefKind::StdVector(Vector::new(self, gen_env))
466 } else if cpp_refname.starts_with("std::") && cpp_refname.contains("::tuple") {
467 TypeRefKind::StdTuple(Tuple::new(self, gen_env))
468 } else if cpp_refname.starts_with("std::") && cpp_refname.contains("::pair") {
469 TypeRefKind::StdTuple(Tuple::pair(self, gen_env))
470 } else if is_decl && cpp_refname.starts_with("cv::Ptr") {
471 TypeRefKind::SmartPtr(SmartPtr::new(decl, gen_env))
472 } else {
473 TypeRefKind::Class(Class::new(decl, gen_env))
474 }
475 } else {
476 let mut generic_type = self.get_display_name();
477 if generic_type.contains('(') && generic_type.contains(')') {
479 if let Some(parent_entity) = parent_entity {
480 TypeRefKind::Function(Function::new(self, parent_entity, gen_env))
481 } else {
482 TypeRefKind::Ignored
483 }
484 } else if let Some(&(rust, cpp)) = settings::PRIMITIVE_TYPEDEFS.get(generic_type.as_str()) {
485 TypeRefKind::Primitive(rust, cpp)
487 } else {
488 generic_type.replace_in_place("const ", "");
489 TypeRefKind::Generic(generic_type)
490 }
491 }
492 }
493
494 TypeKind::Typedef => {
495 let decl = self.get_declaration().expect("Can't get typedef declaration");
496 let decl_name = decl.cpp_name(CppNameStyle::Reference);
497 if let Some(&(rust, cpp)) = settings::PRIMITIVE_TYPEDEFS.get(decl_name.as_ref()) {
498 TypeRefKind::Primitive(rust, cpp)
499 } else if decl.is_system() {
500 if decl_name.starts_with("std::") && decl_name.ends_with("::string") {
501 TypeRefKind::Class(Class::new(decl, gen_env))
502 } else {
503 TypeRefKind::Ignored
504 }
505 } else {
506 match Typedef::try_new(decl, gen_env) {
507 NewTypedefResult::Typedef(tdef) => TypeRefKind::Typedef(tdef),
508 NewTypedefResult::Class(cls) => TypeRefKind::Class(cls),
509 NewTypedefResult::Enum(enm) => TypeRefKind::Enum(enm),
510 }
511 }
512 }
513
514 TypeKind::Enum => TypeRefKind::Enum(Enum::new(
515 self.get_declaration().expect("Can't get enum declaration"),
516 gen_env,
517 )),
518
519 TypeKind::FunctionPrototype => {
520 if let Some(parent) = parent_entity {
521 TypeRefKind::Function(Function::new(self, parent, gen_env))
522 } else {
523 TypeRefKind::Ignored
524 }
525 }
526
527 TypeKind::ConstantArray | TypeKind::IncompleteArray => {
528 let mut size = self.get_size();
529 if size.is_none() {
530 if let TypeRefTypeHint::AddArrayLength(force_size) = type_hint {
531 size = Some(force_size);
532 }
533 }
534 TypeRefKind::Array(
535 TypeRef::new_ext(
536 self.get_element_type().expect("Can't get array element type"),
537 type_hint,
538 None,
539 gen_env,
540 ),
541 size,
542 )
543 }
544
545 TypeKind::MemberPointer | TypeKind::DependentSizedArray => TypeRefKind::Ignored,
546
547 _ => unreachable!("Can't decide kind: {:#?}", self),
548 }
549 })
550 }
551
552 fn template_specialization_args<'ge>(self, gen_env: &'ge GeneratorEnv<'tu>) -> Vec<TemplateArg<'tu, 'ge>> {
553 match self.get_kind() {
554 TypeKind::Typedef => {
555 vec![]
556 }
557 _ => {
558 let args = self.get_template_argument_types().unwrap_or_default();
559 static TYPE_EXTRACT: LazyLock<Regex> = LazyLock::new(|| {
562 Regex::new(r"^.+<\s*(.+?)\s*(?:,\s*(.+?)\s*)?(?:,\s*(.+?)\s*)?(?:,\s*(.+?)\s*)?>$")
563 .expect("Can't compile static regex")
564 });
565 let display_name = self
567 .get_declaration()
568 .and_then(|d| d.get_display_name())
569 .unwrap_or_else(|| self.get_display_name());
570 let generic_args: LazyCell<Option<Captures>, _> = LazyCell::new(|| TYPE_EXTRACT.captures(display_name.as_bytes()));
571 args
572 .into_iter()
573 .enumerate()
574 .map(|(i, type_ref)| {
575 if let Some(type_ref) = type_ref {
576 TemplateArg::Typename(TypeRef::new(type_ref, gen_env))
577 } else {
578 if let Some(generic_args) = &*generic_args {
579 generic_args
580 .get(i + 1)
581 .map(|m| TemplateArg::Constant(String::from_utf8_lossy(m.as_bytes()).into_owned()))
582 } else {
583 None
584 }
585 .unwrap_or(TemplateArg::Unknown)
586 }
587 })
588 .collect::<Vec<_>>()
589 }
590 }
591 }
592}