sdml_core/model/definitions/
enums.rs1use crate::{
2 load::ModuleLoader,
3 model::{
4 annotations::{
5 Annotation, AnnotationBuilder, AnnotationOnlyBody, AnnotationProperty, HasAnnotations,
6 },
7 check::{MaybeIncomplete, Validate},
8 identifiers::{Identifier, IdentifierReference},
9 modules::Module,
10 values::Value,
11 HasName, HasOptionalBody, HasSourceSpan, References, Span,
12 },
13 store::ModuleStore,
14};
15use sdml_errors::diagnostics::functions::IdentifierCaseConvention;
16use std::{
17 collections::{BTreeMap, BTreeSet},
18 fmt::Debug,
19};
20use tracing::warn;
21
22#[cfg(feature = "serde")]
23use serde::{Deserialize, Serialize};
24
25#[derive(Clone, Debug)]
31#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
32pub struct EnumDef {
33 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
34 span: Option<Span>,
35 name: Identifier,
36 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
37 body: Option<EnumBody>,
38}
39
40#[derive(Clone, Debug, Default)]
42#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
43pub struct EnumBody {
44 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
45 span: Option<Span>,
46 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
47 annotations: Vec<Annotation>,
48 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "BTreeMap::is_empty"))]
49 variants: BTreeMap<Identifier, ValueVariant>, }
51
52#[derive(Clone, Debug)]
54#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
55pub struct ValueVariant {
56 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
57 span: Option<Span>,
58 name: Identifier,
59 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
60 body: Option<AnnotationOnlyBody>,
61}
62
63impl HasName for EnumDef {
68 fn name(&self) -> &Identifier {
69 &self.name
70 }
71
72 fn set_name(&mut self, name: Identifier) {
73 self.name = name;
74 }
75}
76
77impl HasOptionalBody for EnumDef {
78 type Body = EnumBody;
79
80 fn body(&self) -> Option<&Self::Body> {
81 self.body.as_ref()
82 }
83
84 fn body_mut(&mut self) -> Option<&mut Self::Body> {
85 self.body.as_mut()
86 }
87
88 fn set_body(&mut self, body: Self::Body) {
89 self.body = Some(body);
90 }
91
92 fn unset_body(&mut self) {
93 self.body = None;
94 }
95}
96
97impl HasSourceSpan for EnumDef {
98 fn with_source_span(self, span: Span) -> Self {
99 let mut self_mut = self;
100 self_mut.span = Some(span);
101 self_mut
102 }
103
104 fn source_span(&self) -> Option<&Span> {
105 self.span.as_ref()
106 }
107
108 fn set_source_span(&mut self, span: Span) {
109 self.span = Some(span);
110 }
111
112 fn unset_source_span(&mut self) {
113 self.span = None;
114 }
115}
116
117impl MaybeIncomplete for EnumDef {
118 fn is_incomplete(&self, _: &Module, _: &impl ModuleStore) -> bool {
119 self.body.is_none()
120 }
121}
122
123impl AnnotationBuilder for EnumDef {
124 fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
125 where
126 Self: Sized,
127 I: Into<IdentifierReference>,
128 V: Into<Value>,
129 {
130 let mut self_mut = self;
131 if let Some(ref mut inner) = self_mut.body {
132 inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
133 }
134 self_mut
135 }
136}
137
138impl Validate for EnumDef {
139 fn validate(
140 &self,
141 top: &Module,
142 cache: &impl ModuleStore,
143 loader: &impl ModuleLoader,
144 check_constraints: bool,
145 ) {
146 self.name()
148 .validate(top, loader, Some(IdentifierCaseConvention::TypeDefinition));
149 if let Some(body) = &self.body {
150 body.validate(top, cache, loader, check_constraints);
151 }
152 }
153}
154
155impl References for EnumDef {
156 fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
157 self.body
158 .as_ref()
159 .map(|b| b.referenced_annotations(names))
160 .unwrap_or_default()
161 }
162}
163
164impl EnumDef {
165 pub fn new(name: Identifier) -> Self {
170 Self {
171 span: None,
172 name,
173 body: None,
174 }
175 }
176
177 pub fn with_body(self, body: EnumBody) -> Self {
178 let mut self_mut = self;
179 self_mut.body = Some(body);
180 self_mut
181 }
182}
183
184impl HasAnnotations for EnumBody {
189 fn has_annotations(&self) -> bool {
190 !self.annotations.is_empty()
191 }
192
193 fn annotation_count(&self) -> usize {
194 self.annotations.len()
195 }
196
197 fn annotations(&self) -> impl Iterator<Item = &Annotation> {
198 self.annotations.iter()
199 }
200
201 fn annotations_mut(&mut self) -> impl Iterator<Item = &mut Annotation> {
202 self.annotations.iter_mut()
203 }
204
205 fn add_to_annotations<I>(&mut self, value: I)
206 where
207 I: Into<Annotation>,
208 {
209 self.annotations.push(value.into())
210 }
211
212 fn extend_annotations<I>(&mut self, extension: I)
213 where
214 I: IntoIterator<Item = Annotation>,
215 {
216 self.annotations.extend(extension.into_iter())
217 }
218}
219
220impl HasSourceSpan for EnumBody {
221 fn with_source_span(self, span: Span) -> Self {
222 let mut self_mut = self;
223 self_mut.span = Some(span);
224 self_mut
225 }
226
227 fn source_span(&self) -> Option<&Span> {
228 self.span.as_ref()
229 }
230
231 fn set_source_span(&mut self, span: Span) {
232 self.span = Some(span);
233 }
234
235 fn unset_source_span(&mut self) {
236 self.span = None;
237 }
238}
239
240impl References for EnumBody {
241 fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
242 self.variants()
243 .for_each(|v| v.referenced_annotations(names));
244 }
245}
246
247impl Validate for EnumBody {
248 fn validate(
249 &self,
250 top: &Module,
251 cache: &impl ModuleStore,
252 loader: &impl ModuleLoader,
253 check_constraints: bool,
254 ) {
255 self.annotations()
256 .for_each(|a| a.validate(top, cache, loader, check_constraints));
257 self.variants()
258 .for_each(|v| v.validate(top, cache, loader, check_constraints));
259 }
260}
261
262impl EnumBody {
263 pub fn with_variants<I>(self, variants: I) -> Self
268 where
269 I: IntoIterator<Item = ValueVariant>,
270 {
271 let mut self_mut = self;
272 self_mut.variants = variants
273 .into_iter()
274 .map(|elem| (elem.name().clone(), elem))
275 .collect();
276 self_mut
277 }
278
279 pub fn has_variants(&self) -> bool {
284 !self.variants.is_empty()
285 }
286
287 pub fn variant_count(&self) -> usize {
288 self.variants.len()
289 }
290
291 pub fn contains_variant(&self, name: &Identifier) -> bool {
292 self.variants.contains_key(name)
293 }
294
295 pub fn variant(&self, name: &Identifier) -> Option<&ValueVariant> {
296 self.variants.get(name)
297 }
298
299 pub fn variant_mut(&mut self, name: &Identifier) -> Option<&mut ValueVariant> {
300 self.variants.get_mut(name)
301 }
302
303 pub fn variants(&self) -> impl Iterator<Item = &ValueVariant> {
304 self.variants.values()
305 }
306
307 pub fn variants_mut(&mut self) -> impl Iterator<Item = &mut ValueVariant> {
308 self.variants.values_mut()
309 }
310
311 pub fn variant_names(&self) -> impl Iterator<Item = &Identifier> {
312 self.variants.keys()
313 }
314
315 pub fn add_to_variants(&mut self, value: ValueVariant) -> Option<ValueVariant> {
316 self.variants.insert(value.name().clone(), value)
317 }
318
319 pub fn extend_variants<I>(&mut self, extension: I)
320 where
321 I: IntoIterator<Item = ValueVariant>,
322 {
323 self.variants.extend(
324 extension
325 .into_iter()
326 .map(|elem| (elem.name().clone(), elem)),
327 )
328 }
329}
330
331impl HasName for ValueVariant {
336 fn name(&self) -> &Identifier {
337 &self.name
338 }
339
340 fn set_name(&mut self, name: Identifier) {
341 self.name = name;
342 }
343}
344
345impl HasOptionalBody for ValueVariant {
346 type Body = AnnotationOnlyBody;
347
348 fn body(&self) -> Option<&Self::Body> {
349 self.body.as_ref()
350 }
351
352 fn body_mut(&mut self) -> Option<&mut Self::Body> {
353 self.body.as_mut()
354 }
355
356 fn set_body(&mut self, body: Self::Body) {
357 self.body = Some(body);
358 }
359
360 fn unset_body(&mut self) {
361 self.body = None;
362 }
363}
364
365impl HasSourceSpan for ValueVariant {
366 fn with_source_span(self, span: Span) -> Self {
367 let mut self_mut = self;
368 self_mut.span = Some(span);
369 self_mut
370 }
371
372 fn source_span(&self) -> Option<&Span> {
373 self.span.as_ref()
374 }
375
376 fn set_source_span(&mut self, span: Span) {
377 self.span = Some(span);
378 }
379
380 fn unset_source_span(&mut self) {
381 self.span = None;
382 }
383}
384
385impl AnnotationBuilder for ValueVariant {
386 fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
387 where
388 Self: Sized,
389 I: Into<IdentifierReference>,
390 V: Into<Value>,
391 {
392 let mut self_mut = self;
393 if let Some(ref mut inner) = self_mut.body {
394 inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
395 }
396 self_mut
397 }
398}
399
400impl Validate for ValueVariant {
401 fn validate(
402 &self,
403 top: &Module,
404 _cache: &impl ModuleStore,
405 loader: &impl ModuleLoader,
406 _check_constraints: bool,
407 ) {
408 warn!("Missing validation for ValueVariant values.");
409 self.name()
410 .validate(top, loader, Some(IdentifierCaseConvention::ValueVariant));
411 }
412}
413
414impl References for ValueVariant {
415 fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
416 self.body
417 .as_ref()
418 .map(|b| b.referenced_annotations(names))
419 .unwrap_or_default()
420 }
421}
422
423impl ValueVariant {
424 pub fn new(name: Identifier) -> Self {
429 Self {
430 span: None,
431 name,
432 body: None,
433 }
434 }
435
436 pub fn with_body(self, body: AnnotationOnlyBody) -> Self {
437 let mut self_mut = self;
438 self_mut.body = Some(body);
439 self_mut
440 }
441}