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