asn1rs_model/model/
asn.rs

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    /// ITU-T X.680 | ISO/IEC 8824-1, 18
120    Boolean,
121    /// ITU-T X.680 | ISO/IEC 8824-1, 19
122    Integer(Integer<RS::RangeType>),
123    String(Size<RS::SizeType>, Charset),
124    /// ITU-T X.680 | ISO/IEC 8824-1, 23
125    OctetString(Size<RS::SizeType>),
126    /// ITU-T X.680 | ISO/IEC 8824-1, 22
127    BitString(BitString<RS::SizeType>),
128    /// ITU-T X.680 | ISO/IEC 8824-1, 24
129    Null,
130
131    Optional(Box<Type<RS>>),
132    Default(Box<Type<RS>>, LiteralValue),
133
134    /// ITU-T X.680 | ISO/IEC 8824-1, 25
135    Sequence(ComponentTypeList<RS>),
136    /// ITU-T X.680 | ISO/IEC 8824-1, 26
137    SequenceOf(Box<Type<RS>>, Size<RS::SizeType>),
138    /// ITU-T X.680 | ISO/IEC 8824-1, 27
139    Set(ComponentTypeList<RS>),
140    /// ITU-T X.680 | ISO/IEC 8824-1, 28
141    SetOf(Box<Type<RS>>, Size<RS::SizeType>),
142    /// ITU-T X.680 | ISO/IEC 8824-1, 20
143    Enumerated(Enumerated),
144    /// ITU-T X.680 | ISO/IEC 8824-1, 29
145    Choice(Choice<RS>),
146
147    /// ITU-T X.680 | ISO/IEC 8824-1, 16
148    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}