opencv_binding_generator/
enumeration.rs1use std::borrow::Cow;
2use std::fmt;
3use std::ops::ControlFlow;
4use std::rc::Rc;
5
6use clang::{Entity, EntityKind, EntityVisitResult};
7
8use crate::comment::strip_doxygen_comment_markers;
9use crate::debug::LocationName;
10use crate::element::ExcludeKind;
11use crate::type_ref::CppNameStyle;
12use crate::{Const, DefaultElement, Element, EntityElement, EntityExt, NameDebug, StrExt};
13
14#[derive(Clone, PartialEq)]
15pub struct Enum<'tu> {
16 entity: Entity<'tu>,
17 custom_fullname: Option<Rc<str>>,
18}
19
20impl<'tu> Enum<'tu> {
21 pub fn new(entity: Entity<'tu>) -> Self {
22 Self {
23 entity,
24 custom_fullname: None,
25 }
26 }
27
28 pub fn new_ext(entity: Entity<'tu>, custom_fullname: impl Into<Rc<str>>) -> Self {
29 Self {
30 entity,
31 custom_fullname: Some(custom_fullname.into()),
32 }
33 }
34
35 pub fn is_anonymous(&self) -> bool {
36 self.entity.is_anonymous() || self.cpp_name(CppNameStyle::Declaration).starts_with("(anonymous enum")
37 }
38
39 pub fn as_typedefed(&self) -> Option<Entity<'tu>> {
40 if matches!(self.entity.get_kind(), EntityKind::TypedefDecl | EntityKind::TypeAliasDecl) {
41 let mut child = None;
42 let _ = self.entity.walk_children_while(|c| {
43 child = Some(c);
44 ControlFlow::Break(())
45 });
46 Some(child.expect("Invalid anonymous typedefed enum"))
47 } else {
48 None
49 }
50 }
51
52 pub fn consts(&self) -> Vec<Const<'tu>> {
53 let mut out = vec![];
54 self.as_typedefed().unwrap_or(self.entity).visit_children(|const_decl, _| {
55 if const_decl.get_kind() == EntityKind::EnumConstantDecl {
56 out.push(Const::new(const_decl));
57 }
58 EntityVisitResult::Continue
59 });
60 out
61 }
62}
63
64impl<'tu> EntityElement<'tu> for Enum<'tu> {
65 fn entity(&self) -> Entity<'tu> {
66 self.entity
67 }
68}
69
70impl Element for Enum<'_> {
71 fn exclude_kind(&self) -> ExcludeKind {
72 DefaultElement::exclude_kind(self).with_is_excluded(|| self.as_typedefed().is_some())
73 }
74
75 fn is_system(&self) -> bool {
76 DefaultElement::is_system(self.entity)
77 }
78
79 fn is_public(&self) -> bool {
80 DefaultElement::is_public(self.entity)
81 }
82
83 fn doc_comment(&self) -> Cow<str> {
84 strip_doxygen_comment_markers(&self.entity.get_comment().unwrap_or_default()).into()
85 }
86
87 fn cpp_namespace(&self) -> Cow<str> {
88 if let Some(custom_fullname) = &self.custom_fullname {
89 custom_fullname.namespace().into()
90 } else {
91 DefaultElement::cpp_namespace(self.entity).into()
92 }
93 }
94
95 fn cpp_name(&self, style: CppNameStyle) -> Cow<str> {
96 if let Some(custom_fullname) = self.custom_fullname.as_deref() {
97 custom_fullname.cpp_name_from_fullname(style).into()
98 } else {
99 DefaultElement::cpp_name(self, self.entity(), style)
100 }
101 }
102}
103
104impl<'me> NameDebug<'me> for &'me Enum<'_> {
105 fn file_line_name(self) -> LocationName<'me> {
106 self.entity.file_line_name()
107 }
108}
109
110impl fmt::Debug for Enum<'_> {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112 let mut debug_struct = f.debug_struct("Enum");
113 self
114 .update_debug_struct(&mut debug_struct)
115 .field("consts", &self.consts())
116 .finish()
117 }
118}