framework/inner/
choice.rs

1use parse::{
2    LowerName,
3    Map,
4    UpperName,
5};
6use parse::xml::*;
7use std::collections::BTreeMap;
8use std::ops::Range;
9
10use crate::pass0::{
11    Choice0,
12    ChoiceItem0,
13};
14
15use crate::{
16    ChoiceId,
17    ChoiceItemId,
18    ChoiceSortBy,
19    Error,
20};
21
22pub struct Choice {
23    pub identifier_length: Option<usize>,
24    pub memory: bool,
25    pub name: UpperName,
26    pub sort_by: ChoiceSortBy,
27    pub title: String,
28
29    pub (crate) items: Map<LowerName, ChoiceItem, ChoiceItemId>,
30}
31
32pub struct ChoiceItem {
33    pub abbreviation: String,
34    pub identifier: Option<String>,
35    pub index: usize,
36    pub name: LowerName,
37    pub title: String,
38}
39
40impl Choice {
41    pub (crate) fn map(
42        from: &ParsedEntry<UpperName, Choice0, ChoiceId>,
43        errors: &mut Vec<Error>,
44    ) -> Option<Self> {
45        let choice0 = &from.value;
46
47        let mut identifiers = BTreeMap::new();
48        let Some(items) = choice0.items.map_cx_mut(
49            ChoiceItem::map,
50            &from.value.identifier_length,
51            &mut identifiers,
52            errors,
53        ) else {
54            return None;
55        };
56
57        Some(Choice {
58            identifier_length: choice0.identifier_length.clone(),
59            memory: choice0.memory.clone(),
60            name: from.name.clone(),
61            sort_by: choice0.sort_by.clone(),
62            title: choice0.title.clone(),
63
64            items,
65        })
66    }
67}
68
69impl ChoiceItem {
70    pub (crate) fn map(
71        from: &ParsedEntry<LowerName, ChoiceItem0, ChoiceItemId>,
72        identifier_length: &Option<usize>,
73        identifiers: &mut BTreeMap<String, Range<usize>>,
74        errors: &mut Vec<Error>,
75    ) -> Option<Self> {
76        let item0 = &from.value;
77
78        if let Some(identifier_length) = &identifier_length {
79            if let Some(identifier) = &item0.identifier {
80                if identifier.value.len() > *identifier_length {
81                    errors.push(Error::IdentifierTooLong {
82                        parent: identifier.range.clone().into(),
83                    });
84
85                    None
86                } else if let Some(existing) = identifiers.get(&identifier.value) {
87                    duplicate_element("identifier", identifier.range.clone(), existing.clone(), errors);
88
89                    None
90                } else {
91                    identifiers.insert(identifier.value.clone(), identifier.range.clone());
92
93                    Some(ChoiceItem {
94                        abbreviation: item0.abbreviation.clone(),
95                        identifier: Some(identifier.value.clone()),
96                        index: from.index.index(),
97                        name: from.name.clone(),
98                        title: item0.title.clone(),
99                    })
100                }
101            } else {
102                missing_element_range("identifier", from.range.clone(), errors);
103
104                None
105            }
106        } else {
107            if let Some(identifier) = &item0.identifier {
108                unexpected_element_range(identifier.range.clone(), errors);
109
110                None
111            } else {
112                Some(ChoiceItem {
113                    abbreviation: item0.abbreviation.clone(),
114                    identifier: None,
115                    index: from.index.index(),
116                    name: from.name.clone(),
117                    title: item0.title.clone(),
118                })
119            }
120        }
121    }
122}
123