ifc_lite_core/generated/
schema_registry.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub enum SchemaVersion {
16 Ifc2x3,
17 Ifc4,
18 Ifc4x1,
19 Ifc4x2,
20 Ifc4x3,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub struct SchemaEntityInfo {
29 pub name: &'static str,
30 pub parent: Option<&'static str>,
31 pub is_abstract: bool,
32}
33
34impl SchemaVersion {
35 pub fn from_file_schema(label: &str) -> Option<Self> {
42 let upper = label.trim().to_ascii_uppercase();
43 if is_schema_family(&upper, "IFC4X3") {
44 Some(Self::Ifc4x3)
45 } else if is_schema_family(&upper, "IFC4X2") {
46 Some(Self::Ifc4x2)
47 } else if is_schema_family(&upper, "IFC4X1") {
48 Some(Self::Ifc4x1)
49 } else if is_schema_family(&upper, "IFC4") {
50 Some(Self::Ifc4)
51 } else if is_schema_family(&upper, "IFC2X3") {
52 Some(Self::Ifc2x3)
53 } else {
54 None
55 }
56 }
57
58 pub fn attribute_names(self, entity_name: &str) -> Option<&'static [&'static str]> {
62 match self {
63 Self::Ifc2x3 => attribute_names_ifc2x3(entity_name),
64 Self::Ifc4 => attribute_names_ifc4(entity_name),
65 Self::Ifc4x1 => attribute_names_ifc4x1(entity_name),
66 Self::Ifc4x2 => attribute_names_ifc4x2(entity_name),
67 Self::Ifc4x3 => attribute_names_ifc4x3(entity_name),
68 }
69 }
70
71 pub fn entity_info(self, entity_name: &str) -> Option<SchemaEntityInfo> {
74 match self {
75 Self::Ifc2x3 => entity_info_ifc2x3(entity_name),
76 Self::Ifc4 => entity_info_ifc4(entity_name),
77 Self::Ifc4x1 => entity_info_ifc4x1(entity_name),
78 Self::Ifc4x2 => entity_info_ifc4x2(entity_name),
79 Self::Ifc4x3 => entity_info_ifc4x3(entity_name),
80 }
81 }
82
83 pub fn is_subtype_of(self, child: &str, parent: &str) -> bool {
85 let mut current = self.entity_info(child);
86 while let Some(info) = current {
87 if info.name.eq_ignore_ascii_case(parent) {
88 return true;
89 }
90 current = info.parent.and_then(|name| self.entity_info(name));
91 }
92 false
93 }
94}
95
96fn is_schema_family(label: &str, family: &str) -> bool {
99 let Some(suffix) = label.strip_prefix(family) else {
100 return false;
101 };
102 if suffix.is_empty() {
103 return true;
104 }
105 let Some(revision) = suffix.strip_prefix('_') else {
106 return false;
107 };
108 revision.split('_').all(|component| {
109 ["ADD", "TC", "RC"].iter().any(|prefix| {
110 component.strip_prefix(prefix).is_some_and(|number| {
111 !number.is_empty() && number.bytes().all(|b| b.is_ascii_digit())
112 })
113 })
114 })
115}
116
117fn attribute_names_ifc2x3(name: &str) -> Option<&'static [&'static str]> {
118 let ty = super::ifc2x3::IfcType::from_str(name);
119 if matches!(ty, super::ifc2x3::IfcType::Unknown(_)) {
120 None
121 } else {
122 Some(ty.attribute_names())
123 }
124}
125
126fn entity_info_ifc2x3(name: &str) -> Option<SchemaEntityInfo> {
127 let ty = super::ifc2x3::IfcType::from_str(name);
128 if matches!(ty, super::ifc2x3::IfcType::Unknown(_)) {
129 None
130 } else {
131 Some(SchemaEntityInfo {
132 name: ty.known_as_str()?,
133 parent: ty.parent().and_then(|parent| parent.known_as_str()),
134 is_abstract: ty.is_abstract(),
135 })
136 }
137}
138
139fn attribute_names_ifc4(name: &str) -> Option<&'static [&'static str]> {
140 let ty = super::ifc4::IfcType::from_str(name);
141 if matches!(ty, super::ifc4::IfcType::Unknown(_)) {
142 None
143 } else {
144 Some(ty.attribute_names())
145 }
146}
147
148fn entity_info_ifc4(name: &str) -> Option<SchemaEntityInfo> {
149 let ty = super::ifc4::IfcType::from_str(name);
150 if matches!(ty, super::ifc4::IfcType::Unknown(_)) {
151 None
152 } else {
153 Some(SchemaEntityInfo {
154 name: ty.known_as_str()?,
155 parent: ty.parent().and_then(|parent| parent.known_as_str()),
156 is_abstract: ty.is_abstract(),
157 })
158 }
159}
160
161fn attribute_names_ifc4x1(name: &str) -> Option<&'static [&'static str]> {
162 let ty = super::ifc4x1::IfcType::from_str(name);
163 if matches!(ty, super::ifc4x1::IfcType::Unknown(_)) {
164 None
165 } else {
166 Some(ty.attribute_names())
167 }
168}
169
170fn entity_info_ifc4x1(name: &str) -> Option<SchemaEntityInfo> {
171 let ty = super::ifc4x1::IfcType::from_str(name);
172 if matches!(ty, super::ifc4x1::IfcType::Unknown(_)) {
173 None
174 } else {
175 Some(SchemaEntityInfo {
176 name: ty.known_as_str()?,
177 parent: ty.parent().and_then(|parent| parent.known_as_str()),
178 is_abstract: ty.is_abstract(),
179 })
180 }
181}
182
183fn attribute_names_ifc4x2(name: &str) -> Option<&'static [&'static str]> {
184 let ty = super::ifc4x2::IfcType::from_str(name);
185 if matches!(ty, super::ifc4x2::IfcType::Unknown(_)) {
186 None
187 } else {
188 Some(ty.attribute_names())
189 }
190}
191
192fn entity_info_ifc4x2(name: &str) -> Option<SchemaEntityInfo> {
193 let ty = super::ifc4x2::IfcType::from_str(name);
194 if matches!(ty, super::ifc4x2::IfcType::Unknown(_)) {
195 None
196 } else {
197 Some(SchemaEntityInfo {
198 name: ty.known_as_str()?,
199 parent: ty.parent().and_then(|parent| parent.known_as_str()),
200 is_abstract: ty.is_abstract(),
201 })
202 }
203}
204
205fn attribute_names_ifc4x3(name: &str) -> Option<&'static [&'static str]> {
206 let ty = super::schema::IfcType::from_str(name);
211 if ty.declared_by_canonical_schema() {
212 Some(ty.attribute_names())
213 } else {
214 None
215 }
216}
217
218fn entity_info_ifc4x3(name: &str) -> Option<SchemaEntityInfo> {
219 let ty = super::schema::IfcType::from_str(name);
220 if !ty.declared_by_canonical_schema() {
221 return None;
222 }
223 Some(SchemaEntityInfo {
224 name: ty.known_as_str()?,
225 parent: ty.parent().and_then(|parent| parent.known_as_str()),
226 is_abstract: ty.is_abstract(),
227 })
228}
229
230pub fn attribute_names_for_schema(
232 file_schema: &str,
233 entity_name: &str,
234) -> Option<&'static [&'static str]> {
235 SchemaVersion::from_file_schema(file_schema)?.attribute_names(entity_name)
236}
237
238pub fn entity_info_for_schema(file_schema: &str, entity_name: &str) -> Option<SchemaEntityInfo> {
241 SchemaVersion::from_file_schema(file_schema)?.entity_info(entity_name)
242}
243
244pub fn is_subtype_of_for_schema(file_schema: &str, child: &str, parent: &str) -> bool {
246 SchemaVersion::from_file_schema(file_schema).is_some_and(|schema| schema.is_subtype_of(child, parent))
247}