framework/inner/
choice.rs1use 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