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 elaborate_name.starts_with("std::") {
451 if let Some(decl) = self.get_declaration().map(|decl| decl.get_definition().unwrap_or(decl)) {
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().map(|decl| decl.get_definition().unwrap_or(decl)) {
461 let cpp_refname = decl.cpp_name(CppNameStyle::Reference);
462 if cpp_refname.starts_with("std::") && cpp_refname.contains("::vector") {
463 TypeRefKind::StdVector(Vector::new(self, gen_env))
464 } else if cpp_refname.starts_with("std::") && cpp_refname.contains("::tuple") {
465 TypeRefKind::StdTuple(Tuple::new(self, gen_env))
466 } else if cpp_refname.starts_with("std::") && cpp_refname.contains("::pair") {
467 TypeRefKind::StdTuple(Tuple::pair(self, gen_env))
468 } else if cpp_refname.starts_with("cv::Ptr")
469 && matches!(decl.get_kind(), EntityKind::StructDecl | EntityKind::ClassDecl)
470 {
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 {
485 generic_type.replace_in_place("const ", "");
486 if let Some(&(rust, cpp)) = settings::PRIMITIVE_TYPEDEFS.get(generic_type.as_str()) {
487 TypeRefKind::Primitive(rust, cpp)
489 } else {
490 TypeRefKind::Generic(generic_type)
491 }
492 }
493 }
494 }
495
496 TypeKind::Typedef => {
497 let decl = self
498 .get_declaration()
499 .map(|decl| decl.get_definition().unwrap_or(decl))
500 .expect("Can't get typedef declaration");
501 let decl_name = decl.cpp_name(CppNameStyle::Reference);
502 if let Some(&(rust, cpp)) = settings::PRIMITIVE_TYPEDEFS.get(decl_name.as_ref()) {
503 TypeRefKind::Primitive(rust, cpp)
504 } else if decl.is_system() {
505 if decl_name.starts_with("std::") && decl_name.ends_with("::string") {
506 TypeRefKind::Class(Class::new(decl, gen_env))
507 } else {
508 TypeRefKind::Ignored
509 }
510 } else {
511 match Typedef::try_new(decl, gen_env) {
512 NewTypedefResult::Typedef(tdef) => TypeRefKind::Typedef(tdef),
513 NewTypedefResult::Class(cls) => TypeRefKind::Class(cls),
514 NewTypedefResult::Enum(enm) => TypeRefKind::Enum(enm),
515 }
516 }
517 }
518
519 TypeKind::Enum => {
520 let decl = self
521 .get_declaration()
522 .map(|decl| decl.get_definition().unwrap_or(decl))
523 .expect("Can't get typedef declaration");
524 TypeRefKind::Enum(Enum::new(decl, gen_env))
525 }
526
527 TypeKind::FunctionPrototype => {
528 if let Some(parent) = parent_entity {
529 TypeRefKind::Function(Function::new(self, parent, gen_env))
530 } else {
531 TypeRefKind::Ignored
532 }
533 }
534
535 TypeKind::ConstantArray | TypeKind::IncompleteArray => {
536 let mut size = self.get_size();
537 if size.is_none() {
538 if let TypeRefTypeHint::AddArrayLength(force_size) = type_hint {
539 size = Some(force_size);
540 }
541 }
542 TypeRefKind::Array(
543 TypeRef::new_ext(
544 self.get_element_type().expect("Can't get array element type"),
545 type_hint,
546 None,
547 gen_env,
548 ),
549 size,
550 )
551 }
552
553 TypeKind::MemberPointer | TypeKind::DependentSizedArray => TypeRefKind::Ignored,
554
555 _ => unreachable!("Can't decide kind: {:#?}", self),
556 }
557 })
558 }
559
560 fn template_specialization_args<'ge>(self, gen_env: &'ge GeneratorEnv<'tu>) -> Vec<TemplateArg<'tu, 'ge>> {
561 match self.get_kind() {
562 TypeKind::Typedef => {
563 vec![]
564 }
565 _ => {
566 let args = self.get_template_argument_types().unwrap_or_default();
567 static TYPE_EXTRACT: LazyLock<Regex> = LazyLock::new(|| {
570 Regex::new(r"^.+<\s*(.+?)\s*(?:,\s*(.+?)\s*)?(?:,\s*(.+?)\s*)?(?:,\s*(.+?)\s*)?>$")
571 .expect("Can't compile static regex")
572 });
573 let display_name = self
575 .get_declaration()
576 .and_then(|d| d.get_display_name())
577 .unwrap_or_else(|| self.get_display_name());
578 let generic_args: LazyCell<Option<Captures>, _> = LazyCell::new(|| TYPE_EXTRACT.captures(display_name.as_bytes()));
579 args
580 .into_iter()
581 .enumerate()
582 .map(|(i, type_ref)| {
583 if let Some(type_ref) = type_ref {
584 TemplateArg::Typename(TypeRef::new(type_ref, gen_env))
585 } else {
586 if let Some(generic_args) = &*generic_args {
587 generic_args
588 .get(i + 1)
589 .map(|m| TemplateArg::Constant(String::from_utf8_lossy(m.as_bytes()).into_owned()))
590 } else {
591 None
592 }
593 .unwrap_or(TemplateArg::Unknown)
594 }
595 })
596 .collect::<Vec<_>>()
597 }
598 }
599 }
600}