asn1rs_model/model/
enumerated.rs1use crate::model::{Error, PeekableTokens};
2use crate::parser::Token;
3use std::convert::TryFrom;
4use std::iter::Peekable;
5
6#[derive(Debug, Clone, PartialOrd, PartialEq, Eq)]
7pub struct Enumerated {
8 variants: Vec<EnumeratedVariant>,
9 extension_after: Option<usize>,
10}
11
12impl From<Vec<EnumeratedVariant>> for Enumerated {
13 fn from(variants: Vec<EnumeratedVariant>) -> Self {
14 Self {
15 variants,
16 extension_after: None,
17 }
18 }
19}
20
21impl Enumerated {
22 pub fn from_variants(variants: impl Into<Vec<EnumeratedVariant>>) -> Self {
23 Self {
24 variants: variants.into(),
25 extension_after: None,
26 }
27 }
28
29 pub fn from_names<I: ToString>(variants: impl Iterator<Item = I>) -> Self {
30 Self {
31 variants: variants.map(EnumeratedVariant::from_name).collect(),
32 extension_after: None,
33 }
34 }
35
36 pub const fn with_extension_after(mut self, extension_after: usize) -> Self {
37 self.extension_after = Some(extension_after);
38 self
39 }
40
41 pub const fn with_maybe_extension_after(mut self, extension_after: Option<usize>) -> Self {
42 self.extension_after = extension_after;
43 self
44 }
45
46 pub fn len(&self) -> usize {
47 self.variants.len()
48 }
49
50 pub fn is_empty(&self) -> bool {
51 self.variants.is_empty()
52 }
53
54 pub fn variants(&self) -> impl Iterator<Item = &EnumeratedVariant> {
55 self.variants.iter()
56 }
57
58 pub fn is_extensible(&self) -> bool {
59 self.extension_after.is_some()
60 }
61
62 pub fn extension_after_index(&self) -> Option<usize> {
63 self.extension_after
64 }
65}
66
67impl<T: Iterator<Item = Token>> TryFrom<&mut Peekable<T>> for Enumerated {
68 type Error = Error;
69
70 fn try_from(iter: &mut Peekable<T>) -> Result<Self, Self::Error> {
71 iter.next_separator_eq_or_err('{')?;
72 let mut enumerated = Self {
73 variants: Vec::new(),
74 extension_after: None,
75 };
76
77 loop {
78 if let Ok(extension_marker) = iter.next_if_separator_and_eq('.') {
79 if enumerated.variants.is_empty() || enumerated.extension_after.is_some() {
80 return Err(Error::invalid_position_for_extension_marker(
81 extension_marker,
82 ));
83 } else {
84 iter.next_separator_eq_or_err('.')?;
85 iter.next_separator_eq_or_err('.')?;
86 enumerated.extension_after = Some(enumerated.variants.len() - 1);
87 loop_ctrl_separator!(iter.next_or_err()?);
88 }
89 } else {
90 let variant_name = iter.next_text_or_err()?;
91 let token = iter.next_or_err()?;
92
93 if token.eq_separator(',') || token.eq_separator('}') {
94 enumerated
95 .variants
96 .push(EnumeratedVariant::from_name(variant_name));
97 loop_ctrl_separator!(token);
98 } else if token.eq_separator('(') {
99 let token = iter.next_or_err()?;
100 let number = token
101 .text()
102 .and_then(|t| t.parse::<usize>().ok())
103 .ok_or_else(|| Error::invalid_number_for_enum_variant(token))?;
104 iter.next_separator_eq_or_err(')')?;
105 enumerated
106 .variants
107 .push(EnumeratedVariant::from_name_number(variant_name, number));
108 loop_ctrl_separator!(iter.next_or_err()?);
109 } else {
110 loop_ctrl_separator!(token);
111 }
112 }
113 }
114
115 Ok(enumerated)
116 }
117}
118
119#[derive(Debug, Clone, PartialOrd, PartialEq, Eq)]
120pub struct EnumeratedVariant {
121 pub(crate) name: String,
122 pub(crate) number: Option<usize>,
123}
124
125#[cfg(test)]
126impl<S: ToString> From<S> for EnumeratedVariant {
127 fn from(s: S) -> Self {
128 EnumeratedVariant::from_name(s)
129 }
130}
131
132impl EnumeratedVariant {
133 pub fn from_name<I: ToString>(name: I) -> Self {
134 Self {
135 name: name.to_string(),
136 number: None,
137 }
138 }
139
140 pub fn from_name_number<I: ToString>(name: I, number: usize) -> Self {
141 Self {
142 name: name.to_string(),
143 number: Some(number),
144 }
145 }
146
147 pub const fn with_number(self, number: usize) -> Self {
148 self.with_number_opt(Some(number))
149 }
150
151 pub const fn with_number_opt(mut self, number: Option<usize>) -> Self {
152 self.number = number;
153 self
154 }
155
156 pub fn name(&self) -> &str {
157 &self.name
158 }
159
160 pub fn number(&self) -> Option<usize> {
161 self.number
162 }
163}