sdml_core/model/definitions/
structures.rs1use crate::{
2 load::ModuleLoader,
3 model::{
4 annotations::{Annotation, AnnotationBuilder, AnnotationProperty, HasAnnotations},
5 check::{MaybeIncomplete, Validate},
6 identifiers::{Identifier, IdentifierReference},
7 members::Member,
8 modules::Module,
9 values::Value,
10 HasName, HasOptionalBody, HasSourceSpan, References, Span,
11 },
12 store::ModuleStore,
13};
14use sdml_errors::diagnostics::functions::IdentifierCaseConvention;
15use std::{
16 collections::{BTreeMap, BTreeSet},
17 fmt::Debug,
18};
19
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Serialize};
22
23#[derive(Clone, Debug)]
29#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
30pub struct StructureDef {
31 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
32 span: Option<Span>,
33 name: Identifier,
34 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
35 body: Option<StructureBody>,
36}
37
38#[derive(Clone, Debug, Default)]
40#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
41pub struct StructureBody {
42 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
43 span: Option<Span>,
44 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
45 annotations: Vec<Annotation>,
46 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "BTreeMap::is_empty"))]
47 members: BTreeMap<Identifier, Member>,
48}
49
50impl HasName for StructureDef {
55 fn name(&self) -> &Identifier {
56 &self.name
57 }
58
59 fn set_name(&mut self, name: Identifier) {
60 self.name = name;
61 }
62}
63
64impl HasOptionalBody for StructureDef {
65 type Body = StructureBody;
66
67 fn body(&self) -> Option<&Self::Body> {
68 self.body.as_ref()
69 }
70
71 fn body_mut(&mut self) -> Option<&mut Self::Body> {
72 self.body.as_mut()
73 }
74
75 fn set_body(&mut self, body: Self::Body) {
76 self.body = Some(body);
77 }
78
79 fn unset_body(&mut self) {
80 self.body = None;
81 }
82}
83
84impl HasSourceSpan for StructureDef {
85 fn with_source_span(self, span: Span) -> Self {
86 let mut self_mut = self;
87 self_mut.span = Some(span);
88 self_mut
89 }
90
91 fn source_span(&self) -> Option<&Span> {
92 self.span.as_ref()
93 }
94
95 fn set_source_span(&mut self, span: Span) {
96 self.span = Some(span);
97 }
98
99 fn unset_source_span(&mut self) {
100 self.span = None;
101 }
102}
103
104impl AnnotationBuilder for StructureDef {
105 fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
106 where
107 Self: Sized,
108 I: Into<IdentifierReference>,
109 V: Into<Value>,
110 {
111 let mut self_mut = self;
112 if let Some(ref mut inner) = self_mut.body {
113 inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
114 }
115 self_mut
116 }
117}
118
119impl References for StructureDef {
120 fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
121 if let Some(inner) = &self.body {
122 inner.referenced_annotations(names);
123 }
124 }
125
126 fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
127 if let Some(inner) = &self.body {
128 inner.referenced_types(names);
129 }
130 }
131}
132
133impl MaybeIncomplete for StructureDef {
134 fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
135 if let Some(body) = &self.body {
136 body.is_incomplete(top, cache)
137 } else {
138 true
139 }
140 }
141}
142
143impl Validate for StructureDef {
144 fn validate(
145 &self,
146 top: &Module,
147 cache: &impl ModuleStore,
148 loader: &impl ModuleLoader,
149 check_constraints: bool,
150 ) {
151 self.name
152 .validate(top, loader, Some(IdentifierCaseConvention::TypeDefinition));
153 if let Some(body) = &self.body {
154 body.validate(top, cache, loader, check_constraints);
155 }
156 }
157}
158
159impl StructureDef {
160 pub fn new(name: Identifier) -> Self {
165 Self {
166 span: None,
167 name,
168 body: None,
169 }
170 }
171 pub fn with_body(self, body: StructureBody) -> Self {
172 let mut self_mut = self;
173 self_mut.body = Some(body);
174 self_mut
175 }
176}
177
178impl HasAnnotations for StructureBody {
183 fn has_annotations(&self) -> bool {
184 !self.annotations.is_empty()
185 }
186
187 fn annotation_count(&self) -> usize {
188 self.annotations.len()
189 }
190
191 fn annotations(&self) -> impl Iterator<Item = &Annotation> {
192 self.annotations.iter()
193 }
194
195 fn annotations_mut(&mut self) -> impl Iterator<Item = &mut Annotation> {
196 self.annotations.iter_mut()
197 }
198
199 fn add_to_annotations<I>(&mut self, value: I)
200 where
201 I: Into<Annotation>,
202 {
203 self.annotations.push(value.into())
204 }
205
206 fn extend_annotations<I>(&mut self, extension: I)
207 where
208 I: IntoIterator<Item = Annotation>,
209 {
210 self.annotations.extend(extension)
211 }
212}
213
214impl HasSourceSpan for StructureBody {
215 fn with_source_span(self, span: Span) -> Self {
216 let mut self_mut = self;
217 self_mut.span = Some(span);
218 self_mut
219 }
220
221 fn source_span(&self) -> Option<&Span> {
222 self.span.as_ref()
223 }
224
225 fn set_source_span(&mut self, span: Span) {
226 self.span = Some(span);
227 }
228
229 fn unset_source_span(&mut self) {
230 self.span = None;
231 }
232}
233
234impl MaybeIncomplete for StructureBody {
235 fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
236 self.members().any(|elem| elem.is_incomplete(top, cache))
237 }
238}
239
240impl Validate for StructureBody {
241 fn validate(
242 &self,
243 top: &Module,
244 cache: &impl ModuleStore,
245 loader: &impl ModuleLoader,
246 check_constraints: bool,
247 ) {
248 self.annotations()
249 .for_each(|a| a.validate(top, cache, loader, check_constraints));
250 self.members()
251 .for_each(|m| m.validate(top, cache, loader, check_constraints));
252 }
253}
254
255impl References for StructureBody {
256 fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
257 self.members().for_each(|m| m.referenced_types(names));
258 }
259
260 fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
261 self.members().for_each(|m| m.referenced_annotations(names));
262 }
263}
264
265impl StructureBody {
266 pub fn with_members<I>(self, members: I) -> Self
271 where
272 I: IntoIterator<Item = Member>,
273 {
274 let mut self_mut = self;
275 self_mut.extend_members(members);
276 self_mut
277 }
278
279 pub fn has_members(&self) -> bool {
284 !self.members.is_empty()
285 }
286
287 pub fn member_count(&self) -> usize {
288 self.members.len()
289 }
290
291 pub fn contains_member(&self, name: &Identifier) -> bool {
292 self.members.contains_key(name)
293 }
294
295 pub fn member(&self, name: &Identifier) -> Option<&Member> {
296 self.members.get(name)
297 }
298
299 pub fn member_mut(&mut self, name: &Identifier) -> Option<&mut Member> {
300 self.members.get_mut(name)
301 }
302
303 pub fn members(&self) -> impl Iterator<Item = &Member> {
304 self.members.values()
305 }
306
307 pub fn members_mut(&mut self) -> impl Iterator<Item = &mut Member> {
308 self.members.values_mut()
309 }
310
311 pub fn member_names(&self) -> impl Iterator<Item = &Identifier> {
312 self.members.keys()
313 }
314
315 pub fn add_to_members(&mut self, value: Member) -> Option<Member> {
316 self.members.insert(value.name().clone(), value)
317 }
318
319 pub fn extend_members<I>(&mut self, extension: I)
320 where
321 I: IntoIterator<Item = Member>,
322 {
323 self.members.extend(
324 extension
325 .into_iter()
326 .map(|elem| (elem.name().clone(), elem)),
327 )
328 }
329}