opencv_binding_generator/
typedef.rs1use std::borrow::Cow;
2use std::fmt;
3use std::ops::ControlFlow;
4use std::rc::Rc;
5
6use clang::{Entity, EntityKind};
7pub use desc::TypedefDesc;
8
9use crate::debug::{DefinitionLocation, LocationName};
10use crate::element::ExcludeKind;
11use crate::type_ref::{CppNameStyle, NameStyle, TypeRefDesc, TypeRefKind, TypeRefTypeHint};
12use crate::writer::rust_native::type_ref::TypeRefExt;
13use crate::{
14 settings, Class, Constness, DefaultElement, Element, EntityExt, Enum, GeneratedType, GeneratorEnv, NameDebug, StrExt, TypeRef,
15};
16
17mod desc;
18
19#[derive(Clone)]
20pub enum Typedef<'tu, 'ge> {
21 Clang {
22 entity: Entity<'tu>,
23 gen_env: &'ge GeneratorEnv<'tu>,
24 },
25 Desc(Rc<TypedefDesc<'tu, 'ge>>),
26}
27
28impl<'tu, 'ge> Typedef<'tu, 'ge> {
29 pub fn try_new(entity: Entity<'tu>, gen_env: &'ge GeneratorEnv<'tu>) -> NewTypedefResult<'tu, 'ge> {
40 let mut out = NewTypedefResult::Typedef(Self::Clang { entity, gen_env });
41 let _ = entity.walk_children_while(|child| {
42 let child_unnamed_or_same_name = child
43 .get_name()
44 .map_or(true, |child_name| Some(child_name) == entity.get_name());
45 if child_unnamed_or_same_name {
46 match child.get_kind() {
47 EntityKind::StructDecl => {
48 out = NewTypedefResult::Class(Class::new_ext(child, entity.cpp_name(CppNameStyle::Reference), gen_env));
49 }
50 EntityKind::EnumDecl => {
51 out = NewTypedefResult::Enum(Enum::new_ext(child, entity.cpp_name(CppNameStyle::Reference), gen_env));
52 }
53 _ => {}
54 }
55 }
56 ControlFlow::Break(())
57 });
58 out
59 }
60
61 pub fn new_desc(desc: TypedefDesc<'tu, 'ge>) -> Self {
62 Self::Desc(Rc::new(desc))
63 }
64
65 pub fn type_ref(&self) -> TypeRef<'tu, 'ge> {
66 match self {
67 Self::Clang { entity, gen_env } => TypeRef::new(entity.get_type().expect("Can't get typedef type"), gen_env),
68 Self::Desc(desc) => TypeRef::new_desc(TypeRefDesc::new(
69 TypeRefKind::Typedef(Self::Desc(Rc::clone(desc))),
70 Constness::Mut,
71 )),
72 }
73 }
74
75 pub fn underlying_type_ref(&self) -> TypeRef<'tu, 'ge> {
76 match self {
77 Self::Clang { entity, gen_env } => TypeRef::new_ext(
78 entity
79 .get_typedef_underlying_type()
80 .expect("Can't get typedef underlying type"),
81 TypeRefTypeHint::None,
82 Some(*entity),
83 gen_env,
84 ),
85 Self::Desc(desc) => desc.underlying_type.clone(),
86 }
87 }
88
89 pub fn generated_types(&self) -> Vec<GeneratedType<'tu, 'ge>> {
90 self.underlying_type_ref().generated_types()
91 }
92}
93
94impl Element for Typedef<'_, '_> {
95 fn exclude_kind(&self) -> ExcludeKind {
96 DefaultElement::exclude_kind(self)
97 .with_exclude_kind(|| self.underlying_type_ref().exclude_kind())
98 .with_is_excluded(|| {
99 settings::PRIMITIVE_TYPEDEFS.contains_key(self.cpp_name(CppNameStyle::Reference).as_ref()) || {
100 let underlying_type = self.underlying_type_ref();
101 self.type_ref().rust_name(NameStyle::ref_()) == underlying_type.rust_name(NameStyle::ref_())
104 }
105 })
106 }
107
108 fn is_system(&self) -> bool {
109 match self {
110 Self::Clang { entity, .. } => DefaultElement::is_system(*entity),
111 Self::Desc(_) => false,
112 }
113 }
114
115 fn is_public(&self) -> bool {
116 match self {
117 Self::Clang { entity, .. } => DefaultElement::is_public(*entity),
118 Self::Desc(_) => true,
119 }
120 }
121
122 fn doc_comment(&self) -> Cow<'_, str> {
123 match self {
124 Self::Clang { entity, .. } => entity.doc_comment(),
125 Self::Desc(_) => "".into(),
126 }
127 }
128
129 fn cpp_namespace(&self) -> Cow<'_, str> {
130 match self {
131 Self::Clang { entity, .. } => DefaultElement::cpp_namespace(*entity).into(),
132 Self::Desc(desc) => desc.cpp_fullname.namespace().into(),
133 }
134 }
135
136 fn cpp_name(&self, style: CppNameStyle) -> Cow<'_, str> {
137 match self {
138 Self::Clang { entity, .. } => DefaultElement::cpp_name(self, *entity, style),
139 Self::Desc(desc) => desc.cpp_fullname.cpp_name_from_fullname(style).into(),
140 }
141 }
142}
143
144pub enum NewTypedefResult<'tu, 'ge> {
145 Typedef(Typedef<'tu, 'ge>),
146 Class(Class<'tu, 'ge>),
147 Enum(Enum<'tu, 'ge>),
148}
149
150impl NewTypedefResult<'_, '_> {
151 pub fn exclude_kind(&self) -> ExcludeKind {
152 match self {
153 NewTypedefResult::Typedef(tdef) => tdef.exclude_kind(),
154 NewTypedefResult::Class(cls) => cls.exclude_kind(),
155 NewTypedefResult::Enum(enm) => enm.exclude_kind(),
156 }
157 }
158}
159
160impl<'me> NameDebug<'me> for &'me Typedef<'_, '_> {
161 fn file_line_name(self) -> LocationName<'me> {
162 match self {
163 Typedef::Clang { entity, .. } => entity.file_line_name(),
164 Typedef::Desc(desc) => LocationName::new(DefinitionLocation::Generated, desc.cpp_fullname.as_ref()),
165 }
166 }
167}
168
169impl PartialEq for Typedef<'_, '_> {
170 fn eq(&self, other: &Self) -> bool {
171 self.cpp_name(CppNameStyle::Reference) == other.cpp_name(CppNameStyle::Reference)
172 }
173}
174
175impl fmt::Debug for Typedef<'_, '_> {
176 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
177 let mut debug_struct = f.debug_struct(match self {
178 Self::Clang { .. } => "Typedef::Clang",
179 Self::Desc(_) => "Typedef::Desc",
180 });
181 self
182 .update_debug_struct(&mut debug_struct)
183 .field("underlying_type_ref", &self.underlying_type_ref())
184 .finish()
185 }
186}