1use crate::model::lor::{Error as ResolveError, TryResolve, Unresolved};
2use crate::model::lor::{ResolveState, Resolved, Resolver};
3use crate::model::{
4 BitString, Charset, Choice, ChoiceVariant, ComponentTypeList, Enumerated, Field, Integer,
5 LitOrRef, LiteralValue, Range, Size, Tag, TagProperty, Target,
6};
7use std::fmt::Debug;
8
9#[derive(Debug, Clone, PartialOrd, PartialEq)]
10pub struct Asn<RS: ResolveState = Resolved> {
11 pub tag: Option<Tag>,
12 pub r#type: Type<RS>,
13 pub default: Option<RS::ConstType>,
14}
15
16impl<RS: ResolveState> Target for Asn<RS> {
17 type DefinitionType = Self;
18 type ValueReferenceType = Self;
19}
20
21impl<RS: ResolveState> Asn<RS> {
22 pub fn make_optional(&mut self) {
23 let optional = self.r#type.clone().optional();
24 self.r#type = optional;
25 }
26
27 pub fn set_default(&mut self, value: RS::ConstType) {
28 self.default = Some(value);
29 }
30
31 pub fn opt_tagged(tag: Option<Tag>, r#type: Type<RS>) -> Self {
32 Self {
33 tag,
34 r#type,
35 default: None,
36 }
37 }
38
39 pub fn untagged(r#type: Type<RS>) -> Self {
40 Self::opt_tagged(None, r#type)
41 }
42
43 pub fn tagged(tag: Tag, r#type: Type<RS>) -> Self {
44 Self::opt_tagged(Some(tag), r#type)
45 }
46}
47
48impl From<Type> for Asn {
49 fn from(r#type: Type) -> Self {
50 Self::untagged(r#type)
51 }
52}
53
54impl TagProperty for Asn {
55 fn tag(&self) -> Option<Tag> {
56 self.tag
57 }
58
59 fn set_tag(&mut self, tag: Tag) {
60 self.tag = Some(tag)
61 }
62
63 fn reset_tag(&mut self) {
64 self.tag = None
65 }
66}
67
68impl Asn<Unresolved> {
69 pub fn try_resolve<
70 R: Resolver<<Resolved as ResolveState>::SizeType>
71 + Resolver<<Resolved as ResolveState>::RangeType>
72 + Resolver<<Resolved as ResolveState>::ConstType>
73 + Resolver<Type<Unresolved>>,
74 >(
75 &self,
76 resolver: &R,
77 ) -> Result<Asn<Resolved>, ResolveError> {
78 let r#type = self.r#type.try_resolve(resolver)?;
79 Ok(Asn {
80 tag: self.tag,
81 default: self
82 .default
83 .as_ref()
84 .map(|d| match d {
85 LitOrRef::Lit(_) => resolver.resolve(d),
86 LitOrRef::Ref(name) => {
87 if let Type::TypeReference(referenced_name, _tag) = &r#type {
88 if let Ok(Type::Enumerated(enumerated)) =
89 resolver.resolve(&LitOrRef::Ref(referenced_name.to_string()))
90 {
91 if let Some(lit) =
92 enumerated.variants().find(|v| name.eq(v.name())).map(|v| {
93 LiteralValue::EnumeratedVariant(
94 referenced_name.to_string(),
95 v.name().to_string(),
96 )
97 })
98 {
99 Ok(lit)
100 } else {
101 resolver.resolve(d)
102 }
103 } else {
104 resolver.resolve(d)
105 }
106 } else {
107 resolver.resolve(d)
108 }
109 }
110 })
111 .transpose()?,
112 r#type,
113 })
114 }
115}
116
117#[derive(Debug, Clone, PartialOrd, PartialEq)]
118pub enum Type<RS: ResolveState = Resolved> {
119 Boolean,
121 Integer(Integer<RS::RangeType>),
123 String(Size<RS::SizeType>, Charset),
124 OctetString(Size<RS::SizeType>),
126 BitString(BitString<RS::SizeType>),
128 Null,
130
131 Optional(Box<Type<RS>>),
132 Default(Box<Type<RS>>, LiteralValue),
133
134 Sequence(ComponentTypeList<RS>),
136 SequenceOf(Box<Type<RS>>, Size<RS::SizeType>),
138 Set(ComponentTypeList<RS>),
140 SetOf(Box<Type<RS>>, Size<RS::SizeType>),
142 Enumerated(Enumerated),
144 Choice(Choice<RS>),
146
147 TypeReference(String, Option<Tag>),
149}
150
151impl Type {
152 pub fn unconstrained_integer() -> Self {
153 Self::integer_with_range_opt(Range::none())
154 }
155
156 pub const fn sequence_from_fields(fields: Vec<Field<Asn>>) -> Self {
157 Self::Sequence(ComponentTypeList {
158 fields,
159 extension_after: None,
160 })
161 }
162}
163
164impl<RS: ResolveState> Type<RS> {
165 pub fn unconstrained_utf8string() -> Self {
166 Self::String(Size::Any, Charset::Utf8)
167 }
168
169 pub fn unconstrained_octetstring() -> Self {
170 Self::OctetString(Size::Any)
171 }
172
173 pub fn integer_with_range(range: Range<Option<RS::RangeType>>) -> Self {
174 Self::Integer(Integer {
175 range,
176 constants: Vec::new(),
177 })
178 }
179
180 pub fn integer_with_range_opt(range: Range<Option<RS::RangeType>>) -> Self {
181 Self::Integer(Integer {
182 range,
183 constants: Vec::new(),
184 })
185 }
186
187 pub fn bit_vec_with_size(size: Size<RS::SizeType>) -> Self {
188 Self::BitString(BitString {
189 size,
190 constants: Vec::new(),
191 })
192 }
193
194 pub fn choice_from_variants(variants: Vec<ChoiceVariant<RS>>) -> Self {
195 Self::Choice(Choice::from(variants))
196 }
197
198 pub fn optional(self) -> Self {
199 Self::Optional(Box::new(self))
200 }
201
202 pub fn opt_tagged(self, tag: Option<Tag>) -> Asn<RS> {
203 Asn::opt_tagged(tag, self)
204 }
205
206 pub fn tagged(self, tag: Tag) -> Asn<RS> {
207 Asn::tagged(tag, self)
208 }
209
210 pub fn untagged(self) -> Asn<RS> {
211 Asn::untagged(self)
212 }
213
214 pub fn no_optional_mut(&mut self) -> &mut Self {
215 if let Self::Optional(inner) = self {
216 inner.no_optional_mut()
217 } else {
218 self
219 }
220 }
221}
222
223impl Type<Unresolved> {
224 pub fn try_resolve<
225 R: Resolver<<Resolved as ResolveState>::SizeType>
226 + Resolver<<Resolved as ResolveState>::RangeType>
227 + Resolver<<Resolved as ResolveState>::ConstType>
228 + Resolver<Type<Unresolved>>,
229 >(
230 &self,
231 resolver: &R,
232 ) -> Result<Type<Resolved>, ResolveError> {
233 Ok(match self {
234 Type::Boolean => Type::Boolean,
235 Type::Integer(integer) => Type::Integer(integer.try_resolve(resolver)?),
236 Type::String(size, charset) => Type::String(size.try_resolve(resolver)?, *charset),
237 Type::OctetString(size) => Type::OctetString(size.try_resolve(resolver)?),
238 Type::BitString(string) => Type::BitString(string.try_resolve(resolver)?),
239 Type::Null => Type::Null,
240 Type::Optional(inner) => Type::Optional(Box::new(inner.try_resolve(resolver)?)),
241 Type::Default(inner, default) => {
242 Type::Default(Box::new(inner.try_resolve(resolver)?), default.clone())
243 }
244 Type::Sequence(seq) => Type::Sequence(seq.try_resolve(resolver)?),
245 Type::SequenceOf(inner, size) => Type::SequenceOf(
246 Box::new(inner.try_resolve(resolver)?),
247 size.try_resolve(resolver)?,
248 ),
249 Type::Set(set) => Type::Set(set.try_resolve(resolver)?),
250 Type::SetOf(inner, size) => Type::SetOf(
251 Box::new(inner.try_resolve(resolver)?),
252 size.try_resolve(resolver)?,
253 ),
254 Type::Enumerated(e) => Type::Enumerated(e.clone()),
255 Type::Choice(c) => Type::Choice(c.try_resolve(resolver)?),
256 Type::TypeReference(name, tag) => Type::TypeReference(name.clone(), *tag),
257 })
258 }
259}
260
261impl LiteralValue {
262 pub fn try_from_asn_str(asn: &str) -> Option<LiteralValue> {
263 Some(match asn {
264 bool if bool.eq_ignore_ascii_case("true") => LiteralValue::Boolean(true),
265 bool if bool.eq_ignore_ascii_case("false") => LiteralValue::Boolean(false),
266 slice if slice.starts_with('"') && slice.ends_with('"') => {
267 LiteralValue::String(slice[1..slice.len() - 1].to_owned())
268 }
269 slice
270 if slice.chars().all(|c| c.is_ascii_digit())
271 || (slice.starts_with('-')
272 && slice.len() > 1
273 && slice.chars().skip(1).all(|c| c.is_ascii_digit())) =>
274 {
275 LiteralValue::Integer(slice.parse().ok()?)
276 }
277 slice
278 if slice.starts_with('\'') && (slice.ends_with("'h") || slice.ends_with("'H")) =>
279 {
280 let hex = &slice[1..slice.len() - 2];
281 if hex.chars().all(|c| c.is_ascii_hexdigit()) {
282 let mut vec = Vec::with_capacity((hex.len() + 1) / 2);
283 let offset = hex.len() % 2;
284
285 if offset > 0 {
286 let init = &hex[..offset];
287 vec.push(u8::from_str_radix(init, 16).ok()?);
288 }
289
290 for i in 0..hex.len() / 2 {
291 let position = offset + (2 * i);
292 vec.push(u8::from_str_radix(&hex[position..position + 2], 16).ok()?);
293 }
294
295 LiteralValue::OctetString(vec)
296 } else {
297 return None;
298 }
299 }
300 slice
301 if slice.starts_with('\'') && (slice.ends_with("'b") || slice.ends_with("'B")) =>
302 {
303 let bits = &slice[1..slice.len() - 2];
304 let mut vec = vec![0x00u8; (bits.len() + 7) / 8];
305
306 for (i, bit) in bits.chars().rev().enumerate() {
307 if bit == '1' {
308 let target_index = vec.len() - 1 - (i / 8);
309 let value = 2u8.pow((i % 8) as u32);
310 vec[target_index] += value;
311 } else if bit != '0' {
312 return None;
313 }
314 }
315
316 LiteralValue::OctetString(vec)
317 }
318
319 _ => return None,
320 })
321 }
322}