1use std::borrow::Cow;
2use std::borrow::Cow::{Borrowed, Owned};
3use std::fmt;
4use std::ops::ControlFlow;
5use std::rc::Rc;
6
7use clang::{Availability, Entity, EntityKind, ExceptionSpecification};
8pub use desc::{FuncCppBody, FuncDesc, FuncRustBody, FuncRustExtern};
9pub use func_matcher::{FuncMatchProperties, FuncMatcher, Pred, UsageTracker};
10pub use kind::{FuncKind, OperatorKind, ReturnKind};
11use once_cell::sync::Lazy;
12use regex::bytes::Regex;
13use slice_arg_finder::SliceArgFinder;
14
15use crate::comment::strip_doxygen_comment_markers;
16use crate::debug::{DefinitionLocation, LocationName};
17use crate::element::ExcludeKind;
18use crate::entity::ToEntity;
19use crate::field::FieldDesc;
20use crate::settings::{FuncSpec, ARG_OVERRIDE_SELF};
21use crate::type_ref::{Constness, CppNameStyle, FishStyle, TypeRefDesc, TypeRefTypeHint};
22use crate::writer::rust_native::element::RustElement;
23use crate::writer::rust_native::type_ref::TypeRefExt;
24use crate::{
25 debug, Class, CowMapBorrowedExt, DefaultElement, Element, EntityExt, Field, GeneratedType, GeneratorEnv, IteratorExt,
26 NameDebug, NameStyle, StrExt, StringExt, TypeRef,
27};
28
29mod desc;
30mod func_matcher;
31mod kind;
32mod slice_arg_finder;
33
34#[derive(Clone)]
35pub enum Func<'tu, 'ge> {
36 Clang {
37 entity: Entity<'tu>,
38 rust_custom_leafname: Option<Rc<str>>,
39 gen_env: &'ge GeneratorEnv<'tu>,
40 },
41 Desc(Rc<FuncDesc<'tu, 'ge>>),
42}
43
44impl<'tu, 'ge> Func<'tu, 'ge> {
45 pub fn new(entity: Entity<'tu>, gen_env: &'ge GeneratorEnv<'tu>) -> Self {
46 Self::Clang {
47 entity,
48 rust_custom_leafname: None,
49 gen_env,
50 }
51 }
52
53 pub fn new_ext(entity: Entity<'tu>, rust_custom_leafname: Option<Rc<str>>, gen_env: &'ge GeneratorEnv<'tu>) -> Self {
54 Self::Clang {
55 entity,
56 rust_custom_leafname,
57 gen_env,
58 }
59 }
60
61 pub fn new_desc(desc: FuncDesc<'tu, 'ge>) -> Self {
62 Self::Desc(Rc::new(desc))
63 }
64
65 pub fn set_rust_custom_leafname(&mut self, rust_custom_leafname: Option<Rc<str>>) {
67 match self {
68 Self::Clang {
69 rust_custom_leafname: old_rust_custom_leafname,
70 ..
71 } => *old_rust_custom_leafname = rust_custom_leafname,
72 Self::Desc(desc) => {
73 if desc.rust_custom_leafname != rust_custom_leafname {
74 Rc::make_mut(desc).rust_custom_leafname = rust_custom_leafname;
75 }
76 }
77 }
78 }
79
80 pub fn rust_custom_leafname(&self) -> Option<&str> {
81 match self {
82 Self::Clang {
83 rust_custom_leafname, ..
84 } => rust_custom_leafname.as_deref(),
85 Self::Desc(desc) => desc.rust_custom_leafname.as_ref().map(|n| n.as_ref()),
86 }
87 }
88
89 pub fn specialize(self, spec: &FuncSpec) -> Self {
90 let specialized = |type_ref: &TypeRef| -> Option<TypeRef<'static, 'static>> {
91 if type_ref.kind().is_generic() {
92 spec
93 .1
94 .get(type_ref.source().cpp_name(CppNameStyle::Declaration).as_ref())
95 .map(|spec_type| type_ref.map(|_| spec_type().with_inherent_constness(type_ref.constness())))
96 } else {
97 None
98 }
99 };
100
101 let arguments = self
102 .arguments()
103 .iter()
104 .map(|arg| {
105 let arg_type_ref = arg.type_ref();
106 specialized(&arg_type_ref).map_or_else(
107 || arg.clone(),
108 |type_ref| {
109 Field::new_desc(FieldDesc {
110 cpp_fullname: arg.cpp_name(CppNameStyle::Reference).into(),
111 type_ref,
112 default_value: arg.default_value().map(|v| v.into()),
113 })
114 },
115 )
116 })
117 .collect();
118 let return_type_ref = self.return_type_ref();
119 let kind = match self.kind().into_owned() {
120 FuncKind::GenericFunction => FuncKind::Function,
121 FuncKind::GenericInstanceMethod(cls) => FuncKind::InstanceMethod(cls),
122 kind => kind,
123 };
124 let spec_values = spec.1.values();
125 let mut generic = String::with_capacity(spec_values.len() * 16);
126 for spec in spec_values {
127 generic.extend_sep(", ", &spec().cpp_name(CppNameStyle::Reference));
128 }
129 let mut desc = self.to_desc_with_skip_config(InheritConfig::empty().kind().arguments().return_type_ref());
130 let rust_custom_leafname = Some(if spec.0.contains('+') {
131 spec.0.replacen('+', &self.rust_leafname(FishStyle::No), 1).into()
132 } else {
133 spec.0.into()
134 });
135 let desc_mut = Rc::make_mut(&mut desc);
136 desc_mut.kind = kind;
137 desc_mut.type_hint = FuncTypeHint::Specialized;
138 desc_mut.rust_custom_leafname = rust_custom_leafname;
139 desc_mut.arguments = arguments;
140 desc_mut.return_type_ref = specialized(&return_type_ref).unwrap_or_else(|| return_type_ref.into_owned());
141 desc_mut.cpp_body = FuncCppBody::ManualCall(format!("{{{{name}}}}<{generic}>({{{{args}}}})").into());
142 Self::Desc(desc)
143 }
144
145 pub(crate) fn to_desc_with_skip_config(&self, skip_config: InheritConfig) -> Rc<FuncDesc<'tu, 'ge>> {
146 match self {
147 Func::Clang { .. } => {
148 let kind = if skip_config.kind {
149 FuncKind::Function
150 } else {
151 self.kind().into_owned()
152 };
153 let cpp_name = if skip_config.name {
154 Rc::from("")
155 } else {
156 self.cpp_name(CppNameStyle::Reference).into()
157 };
158 let doc_comment = if skip_config.doc_comment {
159 Rc::from("")
160 } else {
161 self.doc_comment().into()
162 };
163 let arguments: Rc<[Field]> = if skip_config.arguments {
164 Rc::new([])
165 } else {
166 self.arguments().into_owned().into()
167 };
168 let return_type_ref = if skip_config.return_type_ref {
169 TypeRefDesc::void()
170 } else {
171 self.return_type_ref().into_owned()
172 };
173 let def_loc = if skip_config.definition_location {
174 DefinitionLocation::Generated
175 } else {
176 self.file_line_name().location
177 };
178 Rc::new(FuncDesc {
179 kind,
180 type_hint: FuncTypeHint::None,
181 constness: self.constness(),
182 return_kind: self.return_kind(),
183 cpp_name,
184 rust_custom_leafname: self.rust_custom_leafname().map(Rc::from),
185 rust_module: self.rust_module(),
186 doc_comment,
187 def_loc,
188 rust_generic_decls: Rc::new([]),
189 arguments,
190 return_type_ref,
191 cpp_body: FuncCppBody::Auto,
192 rust_body: FuncRustBody::Auto,
193 rust_extern_definition: FuncRustExtern::Auto,
194 cfg_attr: Rc::new(None),
195 })
196 }
197 Func::Desc(desc) => {
198 let kind = if skip_config.kind {
199 FuncKind::Function
200 } else {
201 desc.kind.clone()
202 };
203 let return_type_ref = if skip_config.return_type_ref {
204 TypeRefDesc::void()
205 } else {
206 desc.return_type_ref.clone()
207 };
208 let def_loc = if skip_config.definition_location {
209 DefinitionLocation::Generated
210 } else {
211 desc.def_loc.clone()
212 };
213 let mut desc = Rc::clone(desc);
214 let desc_mut = Rc::make_mut(&mut desc);
215 desc_mut.kind = kind;
216 desc_mut.return_type_ref = return_type_ref;
217 desc_mut.def_loc = def_loc;
218 desc
219 }
220 }
221 }
222
223 pub fn inherit(&mut self, ancestor: &Func<'tu, 'ge>, inherit_config: InheritConfig) {
224 #[inline]
225 fn transfer<'tu, 'ge>(desc: &mut FuncDesc<'tu, 'ge>, ancestor: &Func<'tu, 'ge>, config: InheritConfig) {
226 if config.kind {
227 desc.kind = ancestor.kind().into_owned();
228 }
229 if config.name {
230 desc.cpp_name = ancestor.cpp_name(CppNameStyle::Reference).into();
231 }
232 if config.doc_comment {
233 desc.doc_comment = ancestor.doc_comment_overloaded().into();
234 }
235 if config.arguments {
236 desc.arguments = ancestor.arguments().into();
237 }
238 if config.return_type_ref {
239 desc.return_type_ref = ancestor.return_type_ref().into_owned();
240 }
241 if config.definition_location {
242 desc.def_loc = ancestor.file_line_name().location;
243 }
244 }
245
246 match self {
247 Func::Clang { .. } => {
248 if inherit_config.any_enabled() {
249 let mut desc = self.to_desc_with_skip_config(inherit_config);
250 transfer(Rc::make_mut(&mut desc), ancestor, inherit_config);
251 *self = Func::Desc(desc);
252 }
253 }
254 Func::Desc(desc) => transfer(Rc::make_mut(desc), ancestor, inherit_config),
255 }
256 }
257
258 pub fn inheriting(mut self, ancestor: &Func<'tu, 'ge>, inherit_config: InheritConfig) -> Self {
259 self.inherit(ancestor, inherit_config);
260 self
261 }
262
263 pub fn is_specialized(&self) -> bool {
268 match self {
269 &Self::Clang { .. } => false,
270 Self::Desc(desc) => matches!(desc.type_hint, FuncTypeHint::Specialized),
271 }
272 }
273
274 pub fn kind(&self) -> Cow<FuncKind<'tu, 'ge>> {
275 match self {
276 &Self::Clang { entity, gen_env, .. } => {
277 const OPERATOR: &str = "operator";
278 Owned(match entity.get_kind() {
279 EntityKind::FunctionDecl => {
280 if let Some(operator) = entity.cpp_name(CppNameStyle::Declaration).strip_prefix(OPERATOR) {
281 let arg_count = entity.get_arguments().map_or(0, |v| v.len());
282 FuncKind::FunctionOperator(OperatorKind::new(operator.trim(), arg_count))
283 } else {
284 FuncKind::Function
285 }
286 }
287 EntityKind::Constructor => FuncKind::Constructor(Class::new(
288 entity.get_semantic_parent().expect("Can't get parent of constructor"),
289 gen_env,
290 )),
291 EntityKind::Method => {
292 let class = Class::new(entity.get_semantic_parent().expect("Can't get parent of method"), gen_env);
293 if entity.is_static_method() {
294 FuncKind::StaticMethod(class)
295 } else if let Some(operator) = entity.cpp_name(CppNameStyle::Declaration).strip_prefix(OPERATOR) {
296 let arg_count = entity.get_arguments().map_or(0, |v| v.len());
297 FuncKind::InstanceOperator(class, OperatorKind::new(operator.trim(), arg_count))
298 } else {
299 FuncKind::InstanceMethod(class)
300 }
301 }
302 EntityKind::ConversionFunction => FuncKind::ConversionMethod(Class::new(
303 entity.get_semantic_parent().expect("Can't get parent of method"),
304 gen_env,
305 )),
306 EntityKind::FunctionTemplate => match entity.get_template_kind() {
307 Some(EntityKind::Method) => FuncKind::GenericInstanceMethod(Class::new(
308 entity.get_semantic_parent().expect("Can't get parent of generic method"),
309 gen_env,
310 )),
311 _ => FuncKind::GenericFunction,
312 },
313 _ => unreachable!("Unknown function entity: {:#?}", entity),
314 })
315 }
316 Self::Desc(desc) => Borrowed(&desc.kind),
317 }
318 }
319
320 pub fn constness(&self) -> Constness {
321 match self {
322 &Self::Clang { entity, .. } => Constness::from_is_const(entity.is_const_method()),
323 Self::Desc(desc) => desc.constness,
324 }
325 }
326
327 pub fn is_abstract(&self) -> bool {
328 match self {
329 Self::Clang { entity, .. } => entity.is_pure_virtual_method(),
330 Self::Desc(_) => false,
331 }
332 }
333
334 pub fn is_generic(&self) -> bool {
335 match self {
336 Func::Clang { entity, .. } => {
337 matches!(entity.get_kind(), EntityKind::FunctionTemplate)
338 }
339 Func::Desc(desc) => match desc.kind {
340 FuncKind::GenericFunction | FuncKind::GenericInstanceMethod(..) => true,
341 FuncKind::Function
342 | FuncKind::Constructor(..)
343 | FuncKind::InstanceMethod(..)
344 | FuncKind::StaticMethod(..)
345 | FuncKind::FieldAccessor(..)
346 | FuncKind::ConversionMethod(..)
347 | FuncKind::FunctionOperator(..)
348 | FuncKind::InstanceOperator(..) => false,
349 },
350 }
351 }
352
353 pub fn doc_comment_overloaded(&self) -> Cow<str> {
356 let mut out = self.doc_comment();
357 match self {
358 Func::Clang { gen_env, .. } => {
359 let line = self.file_line_name().location.as_file().map_or(0, |(_, line)| line);
360 const OVERLOAD: &str = "@overload";
361 if let Some(idx) = out.find(OVERLOAD) {
362 let rep = if let Some(copy) = gen_env.get_func_comment(line, self.cpp_name(CppNameStyle::Reference).as_ref()) {
363 Owned(format!("{copy}\n\n## Overloaded parameters\n"))
364 } else {
365 "This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.".into()
366 };
367 out.to_mut().replace_range(idx..idx + OVERLOAD.len(), &rep);
368 }
369 static COPY_BRIEF: Lazy<Regex> = Lazy::new(|| Regex::new(r"@copybrief\s+(\w+)").unwrap());
370 out.to_mut().replace_in_place_regex_cb(©_BRIEF, |comment, caps| {
371 let copy_name = caps.get(1).map(|(s, e)| &comment[s..e]).expect("Impossible");
372 let mut copy_full_name = self.cpp_namespace().into_owned();
373 copy_full_name.extend_sep("::", copy_name);
374 if let Some(copy) = gen_env.get_func_comment(line, ©_full_name) {
375 Some(copy.into())
376 } else {
377 Some("".into())
378 }
379 });
380 }
381 Func::Desc(_) => {}
382 }
383 out
384 }
385
386 pub fn return_kind(&self) -> ReturnKind {
387 match self {
388 Self::Clang { entity, gen_env, .. } => {
389 let is_infallible = matches!(
390 entity.get_exception_specification(),
391 Some(ExceptionSpecification::BasicNoexcept) | Some(ExceptionSpecification::Unevaluated)
392 ) || gen_env.settings.force_infallible.get(&mut self.matcher()).is_some();
393 if is_infallible {
394 let return_type_ref = self.return_type_ref();
395 if return_type_ref.kind().return_as_naked(return_type_ref.type_hint()) {
396 ReturnKind::InfallibleNaked
397 } else {
398 ReturnKind::InfallibleViaArg
399 }
400 } else {
401 ReturnKind::Fallible
402 }
403 }
404 Self::Desc(desc) => desc.return_kind,
405 }
406 }
407
408 pub fn safety(&self) -> Safety {
409 let out = match self {
410 Func::Clang { gen_env, .. } => Safety::from_is_unsafe(gen_env.settings.func_unsafe.get(&mut self.matcher()).is_some()),
411 Func::Desc(_) => Safety::Safe,
412 };
413 out.or_is_unsafe(|| {
414 self.arguments().iter().any(|a| {
415 let type_ref = a.type_ref();
416 type_ref.kind().is_rust_by_ptr(type_ref.type_hint()) && !a.is_user_data()
417 })
418 })
419 }
420
421 pub fn is_default_constructor(&self) -> bool {
422 match self {
423 &Self::Clang { entity, .. } => entity.is_default_constructor() && !self.has_arguments(),
424 Self::Desc(_) => false,
425 }
426 }
427
428 pub fn is_clone(&self) -> bool {
429 if self.cpp_name(CppNameStyle::Declaration) == "clone" {
430 self
431 .kind()
432 .as_instance_method()
433 .is_some_and(|c| !self.has_arguments() && self.return_type_ref().kind().as_class().is_some_and(|r| r.as_ref() == c))
434 } else {
435 false
436 }
437 }
438
439 pub fn is_no_discard(&self) -> bool {
440 match self {
441 &Self::Clang { entity, gen_env, .. } => gen_env.get_export_config(entity).is_some_and(|c| c.no_discard),
442 Self::Desc(_) => false,
443 }
444 }
445
446 pub fn return_type_ref(&self) -> Cow<TypeRef<'tu, 'ge>> {
447 match self {
448 &Self::Clang { entity, gen_env, .. } => {
449 let mut out = match self.kind().as_ref() {
450 FuncKind::Constructor(cls) => cls.type_ref(),
451 FuncKind::InstanceOperator(_, OperatorKind::Set) => TypeRefDesc::void(),
453 FuncKind::Function
454 | FuncKind::InstanceMethod(..)
455 | FuncKind::StaticMethod(..)
456 | FuncKind::FieldAccessor(..)
457 | FuncKind::ConversionMethod(..)
458 | FuncKind::GenericInstanceMethod(..)
459 | FuncKind::GenericFunction
460 | FuncKind::FunctionOperator(..)
461 | FuncKind::InstanceOperator(..) => {
462 let out = TypeRef::new(entity.get_result_type().expect("Can't get return type"), gen_env);
463 out.kind().as_reference().map(|cow| cow.into_owned()).unwrap_or(out)
464 }
465 };
466 if let Some(return_hint) = gen_env.settings.return_override.get(&mut self.matcher()) {
467 out.set_type_hint(return_hint.clone());
468 if let Some((_, borrow_arg_names, _)) = return_hint.as_boxed_as_ref() {
470 let borrow_arg_constness = if borrow_arg_names.contains(&ARG_OVERRIDE_SELF) {
471 self.constness()
472 } else {
473 self
474 .arguments()
475 .iter()
476 .find(|arg| borrow_arg_names.contains(&arg.cpp_name(CppNameStyle::Declaration).as_ref()))
477 .map(|arg| arg.type_ref().constness())
478 .unwrap_or_else(|| panic!("BoxedAsRef refers to the non-existent argument names: {borrow_arg_names:?}"))
479 };
480 out.set_inherent_constness(borrow_arg_constness);
481 }
482 } else if !out.kind().is_char_ptr_string(out.type_hint()) {
483 out.set_type_hint(TypeRefTypeHint::PrimitivePtrAsRaw);
484 }
485 Owned(out)
486 }
487 Self::Desc(desc) => Borrowed(&desc.return_type_ref),
488 }
489 }
490
491 pub fn has_arguments(&self) -> bool {
492 self.num_arguments() > 0
493 }
494
495 pub fn num_arguments(&self) -> usize {
496 match self {
497 &Func::Clang { entity, .. } => self.clang_arguments(entity).len(),
498 Func::Desc(desc) => desc.arguments.len(),
499 }
500 }
501
502 fn clang_arguments(&self, entity: Entity<'tu>) -> Vec<Entity<'tu>> {
503 match self.kind().as_ref() {
504 FuncKind::GenericFunction | FuncKind::GenericInstanceMethod(..) => {
505 let mut out = Vec::with_capacity(8);
506 let _ = entity.walk_children_while(|child| {
507 if child.get_kind() == EntityKind::ParmDecl {
508 out.push(child);
509 }
510 ControlFlow::Continue(())
511 });
512 out
513 }
514 _ => entity.get_arguments().expect("Can't get arguments"),
515 }
516 }
517
518 pub fn arguments(&self) -> Cow<[Field<'tu, 'ge>]> {
519 match self {
520 &Self::Clang { entity, gen_env, .. } => {
521 let arg_overrides = gen_env.settings.arg_override.get(&mut self.matcher());
522 let arguments = self.clang_arguments(entity);
523 let mut slice_arg_finder = SliceArgFinder::with_capacity(arguments.len());
524 let mut out = arguments
525 .into_iter()
526 .enumerate()
527 .map(|(idx, a)| {
528 if let Some(func_arg_override) = arg_overrides {
529 if let Some(type_hint) = a.get_name().and_then(|arg_name| func_arg_override.get(arg_name.as_str())) {
530 return Field::new_ext(a, type_hint.clone(), gen_env);
531 }
532 }
533 let out = Field::new(a, gen_env);
534 slice_arg_finder.feed(idx, &out);
535 out
536 })
537 .collect::<Vec<_>>();
538 for (slice_arg_indices, slice_len_arg_idx) in slice_arg_finder.finish() {
539 let mut slice_arg_names = Vec::with_capacity(slice_arg_indices.len());
540 for &slice_arg_idx in &slice_arg_indices {
541 let slice_arg = &mut out[slice_arg_idx];
542 slice_arg_names.push(slice_arg.rust_name(NameStyle::ref_()).into_owned());
543 slice_arg.set_type_ref_type_hint(TypeRefTypeHint::Slice);
544 }
545 let slice_len_arg = &mut out[slice_len_arg_idx];
546 let divisor = if slice_len_arg.cpp_name(CppNameStyle::Declaration).contains("pair") {
547 2
548 } else {
549 1
550 };
551 slice_len_arg.set_type_ref_type_hint(TypeRefTypeHint::LenForSlice(slice_arg_names.into(), divisor));
552 }
553 Owned(out)
554 }
555 Self::Desc(desc) => Borrowed(desc.arguments.as_ref()),
556 }
557 }
558
559 pub fn generated_types(&self) -> Vec<GeneratedType<'tu, 'ge>> {
560 self
561 .arguments()
562 .iter()
563 .map(|a| a.type_ref())
564 .filter(|t| !t.exclude_kind().is_ignored())
565 .flat_map(|t| t.generated_types())
566 .chain(self.return_type_ref().generated_types())
567 .collect()
568 }
569
570 pub fn identifier(&self) -> String {
571 let mut out = if let Some((_, fld)) = self.kind().as_field_accessor() {
572 let mut name = self.cpp_namespace().into_owned();
573 if !name.is_empty() {
574 name.push('_');
575 }
576 let decl_name = fld.cpp_name(CppNameStyle::Declaration);
577 name.reserve(decl_name.len() + 4);
578 name.push_str("prop");
579 let (first_letter, rest) = decl_name.capitalize_first_ascii_letter().expect("Empty decl_name");
580 name.push(first_letter);
581 name.push_str(rest);
582 name
583 } else {
584 self.cpp_name(CppNameStyle::Reference).into_owned()
585 };
586 if self.is_specialized() {
590 out.push('_');
591 out.push_str(&self.return_type_ref().cpp_name(CppNameStyle::Reference));
592 }
593 if self.constness().is_const() {
594 out.push_str("_const");
595 }
596 let args = self.arguments();
597 out.reserve(args.len() * 24);
598 for arg in args.as_ref() {
599 out.push('_');
600 out.push_str(&arg.type_ref().cpp_name_ext(CppNameStyle::Declaration, "", false));
601 }
602 out.cleanup_name();
603 out
604 }
605
606 pub fn matcher(&self) -> FuncMatchProperties {
607 FuncMatchProperties::new(self, self.cpp_name(CppNameStyle::Reference))
608 }
609
610 pub fn rust_body(&self) -> &FuncRustBody {
611 match self {
612 Self::Clang { .. } => &FuncRustBody::Auto,
613 Self::Desc(desc) => &desc.rust_body,
614 }
615 }
616
617 pub fn rust_extern_definition(&self) -> FuncRustExtern {
618 match self {
619 Self::Clang { .. } => FuncRustExtern::Auto,
620 Self::Desc(desc) => desc.rust_extern_definition,
621 }
622 }
623
624 pub fn cpp_body(&self) -> &FuncCppBody {
625 match self {
626 Self::Clang { .. } => &FuncCppBody::Auto,
627 Self::Desc(desc) => &desc.cpp_body,
628 }
629 }
630
631 pub fn cfg_attrs(&self) -> Option<(&str, &str)> {
632 match self {
633 Self::Clang { gen_env, .. } => gen_env.settings.func_cfg_attr.get(&mut self.matcher()).copied(),
634 Self::Desc(desc) => desc
635 .cfg_attr
636 .as_ref()
637 .as_ref()
638 .map(|(rust, cpp)| (rust.as_str(), cpp.as_str())),
639 }
640 }
641}
642
643impl<'tu> ToEntity<'tu> for &Func<'tu, '_> {
644 fn to_entity(self) -> Option<Entity<'tu>> {
645 match self {
646 Func::Clang { entity, .. } => Some(*entity),
647 Func::Desc(_) => None,
648 }
649 }
650}
651
652impl Element for Func<'_, '_> {
653 fn exclude_kind(&self) -> ExcludeKind {
654 DefaultElement::exclude_kind(self)
655 .with_reference_exclude_kind(|| self.return_type_ref().exclude_kind())
656 .with_is_excluded(|| {
657 let kind = self.kind();
658 let identifier = self.identifier();
659 let is_excluded = match self {
660 Func::Clang { entity, gen_env, .. } => {
661 entity.get_availability() == Availability::Unavailable
662 || gen_env.settings.func_exclude.contains(identifier.as_str())
663 }
664 Func::Desc(_) => false,
665 };
666 is_excluded
667 || self.is_generic()
668 || self.arguments().iter().any(|a| a.type_ref().exclude_kind().is_ignored())
669 || kind.as_operator().is_some_and(|(_, kind)| match kind {
670 OperatorKind::Unsupported => true,
671 OperatorKind::Incr | OperatorKind::Decr if self.num_arguments() == 1 => true,
673 _ => false,
674 }) || kind.as_constructor().is_some_and(|cls| cls.is_abstract()) })
676 }
677
678 fn is_system(&self) -> bool {
679 match self {
680 &Self::Clang { entity, .. } => DefaultElement::is_system(entity),
681 Self::Desc(_) => false,
682 }
683 }
684
685 fn is_public(&self) -> bool {
686 match self {
687 &Self::Clang { entity, .. } => DefaultElement::is_public(entity),
688 Self::Desc(_) => true,
689 }
690 }
691
692 fn doc_comment(&self) -> Cow<str> {
693 match self {
694 &Self::Clang { entity, .. } => strip_doxygen_comment_markers(&entity.get_comment().unwrap_or_default()).into(),
695 Self::Desc(desc) => desc.doc_comment.as_ref().into(),
696 }
697 }
698
699 fn cpp_namespace(&self) -> Cow<str> {
700 match self {
701 &Self::Clang { entity, .. } => DefaultElement::cpp_namespace(entity).into(),
702 Self::Desc(desc) => self.kind().map_borrowed(|kind| match kind {
703 FuncKind::Function | FuncKind::FunctionOperator(_) | FuncKind::GenericFunction => desc.cpp_name.namespace().into(),
704 FuncKind::Constructor(cls)
705 | FuncKind::InstanceMethod(cls)
706 | FuncKind::StaticMethod(cls)
707 | FuncKind::FieldAccessor(cls, _)
708 | FuncKind::ConversionMethod(cls)
709 | FuncKind::InstanceOperator(cls, _)
710 | FuncKind::GenericInstanceMethod(cls) => cls.cpp_name(CppNameStyle::Reference),
711 }),
712 }
713 }
714
715 fn cpp_name(&self, style: CppNameStyle) -> Cow<str> {
716 let decl_name = match self {
717 &Self::Clang { entity, gen_env, .. } => {
718 if matches!(entity.get_kind(), EntityKind::ConversionFunction) {
719 let ret_type = TypeRef::new(entity.get_result_type().expect("Can't get result type"), gen_env);
722 let ret_type = ret_type
723 .kind()
724 .as_reference()
725 .map(|tref| tref.into_owned())
726 .unwrap_or(ret_type);
727 format!("operator {}", ret_type.cpp_name(CppNameStyle::Reference)).into()
728 } else {
729 DefaultElement::cpp_name(self, entity, CppNameStyle::Declaration)
730 }
731 }
732 Self::Desc(desc) => desc.cpp_name.cpp_name_from_fullname(CppNameStyle::Declaration).into(),
733 };
734 match style {
735 CppNameStyle::Declaration => decl_name,
736 CppNameStyle::Reference => DefaultElement::cpp_decl_name_with_namespace(self, &decl_name),
737 }
738 }
739}
740
741impl<'me> NameDebug<'me> for &'me Func<'_, '_> {
742 fn file_line_name(self) -> LocationName<'me> {
743 match self {
744 Func::Clang { entity, .. } => entity.file_line_name(),
745 Func::Desc(desc) => LocationName::new(desc.def_loc.clone(), self.cpp_name(CppNameStyle::Reference)),
746 }
747 }
748
749 fn get_debug(self) -> String
750 where
751 Self: Sized,
752 {
753 if *debug::EMIT_DEBUG {
754 let LocationName { location, name } = self.file_line_name();
755 let render_lanes = self
756 .arguments()
757 .iter()
758 .map(|a| format!("{:?}", a.type_ref().render_lane()))
759 .join(", ");
760 format!(
761 "// {name}({render_lanes}) {location}\n\
762 // {func_match}",
763 func_match = self.matcher().dump()
764 )
765 } else {
766 "".to_string()
767 }
768 }
769}
770
771impl fmt::Debug for Func<'_, '_> {
772 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
773 let mut debug_struct = f.debug_struct(match self {
774 Self::Clang { .. } => "Func::Clang",
775 Self::Desc(_) => "Func::Desc",
776 });
777 self
778 .update_debug_struct(&mut debug_struct)
779 .field("constness", &self.constness())
780 .field("is_specialized", &self.is_specialized())
781 .field("return_kind", &self.return_kind())
782 .field("kind", &self.kind())
783 .field("return_type", &self.return_type_ref())
784 .field("arguments", &self.arguments())
785 .finish()
786 }
787}
788
789#[derive(Clone, Copy, Debug, PartialEq, Eq)]
790pub enum Safety {
791 Safe,
792 Unsafe,
793}
794
795impl Safety {
796 pub fn from_is_unsafe(is_unsafe: bool) -> Safety {
797 if is_unsafe {
798 Self::Unsafe
799 } else {
800 Self::Safe
801 }
802 }
803
804 pub fn is_safe(self) -> bool {
805 match self {
806 Self::Safe => true,
807 Self::Unsafe => false,
808 }
809 }
810
811 pub fn or_is_unsafe(self, other_is_unsafe: impl FnOnce() -> bool) -> Safety {
813 match self {
814 Safety::Safe => Self::from_is_unsafe(other_is_unsafe()),
815 Safety::Unsafe => Self::Unsafe,
816 }
817 }
818
819 pub fn rust_func_safety_qual(self) -> &'static str {
821 match self {
822 Safety::Safe => "",
823 Safety::Unsafe => "unsafe ",
824 }
825 }
826}
827
828#[derive(Copy, Clone, Debug, PartialEq, Eq)]
829pub enum FuncTypeHint {
830 None,
831 Specialized,
832}
833
834#[derive(Debug, Clone, Copy)]
835pub struct InheritConfig {
836 pub kind: bool,
837 pub name: bool,
838 pub doc_comment: bool,
839 pub arguments: bool,
840 pub return_type_ref: bool,
841 pub definition_location: bool,
842}
843
844impl InheritConfig {
845 pub const fn empty() -> Self {
846 Self {
847 kind: false,
848 name: false,
849 doc_comment: false,
850 arguments: false,
851 return_type_ref: false,
852 definition_location: false,
853 }
854 }
855
856 pub fn kind(mut self) -> Self {
857 self.kind = true;
858 self
859 }
860
861 pub fn with_name(mut self) -> Self {
862 self.name = true;
863 self
864 }
865
866 pub fn doc_comment(mut self) -> Self {
867 self.doc_comment = true;
868 self
869 }
870
871 pub fn arguments(mut self) -> Self {
872 self.arguments = true;
873 self
874 }
875
876 pub fn return_type_ref(mut self) -> Self {
877 self.return_type_ref = true;
878 self
879 }
880
881 pub fn definition_location(mut self) -> Self {
882 self.definition_location = true;
883 self
884 }
885
886 pub fn any_enabled(self) -> bool {
887 self.kind || self.name || self.arguments || self.doc_comment || self.return_type_ref || self.definition_location
888 }
889}