1pub mod protobuf;
2pub mod rust;
3pub mod sql;
4
5pub use self::rust::Rust;
6pub use self::rust::RustType;
7
8pub use self::protobuf::Protobuf;
9pub use self::protobuf::ProtobufType;
10
11use crate::parser::{Location, Token};
12use std::convert::TryFrom;
13use std::fmt::Debug;
14use std::iter::Peekable;
15use std::vec::IntoIter;
16
17macro_rules! loop_ctrl_separator {
18 ($token:expr) => {
19 match $token {
20 t if t.eq_separator(',') => continue,
21 t if t.eq_separator('}') => break,
22 t => return Err(Error::unexpected_token(t)),
23 }
24 };
25}
26
27mod asn;
28mod bit_string;
29mod charset;
30mod choice;
31mod components;
32mod definition;
33mod enumerated;
34mod err;
35mod int;
36mod itc;
37pub mod lor;
38mod oid;
39mod parse;
40mod range;
41mod rs;
42mod size;
43mod tag;
44mod tag_resolver;
45
46use crate::model::itc::InnerTypeConstraints;
47use crate::model::lor::{ResolveState, Resolved, Resolver, Unresolved};
48pub use asn::Asn;
49pub use asn::Type;
50pub use bit_string::BitString;
51pub use charset::Charset;
52pub use choice::Choice;
53pub use choice::ChoiceVariant;
54pub use components::ComponentTypeList;
55pub use definition::Definition;
56pub use enumerated::Enumerated;
57pub use enumerated::EnumeratedVariant;
58pub use err::Error;
59pub use err::ErrorKind;
60pub use int::Integer;
61pub use lor::Error as ResolveError;
62pub use lor::LitOrRef;
63pub use oid::{ObjectIdentifier, ObjectIdentifierComponent};
64pub use parse::PeekableTokens;
65pub use range::Range;
66pub use rs::MultiModuleResolver;
67pub use size::Size;
68pub use tag::Tag;
69pub use tag::TagProperty;
70pub use tag_resolver::TagResolver;
71
72#[derive(Debug, Clone)]
73pub struct Model<T: Target> {
74 pub name: String,
75 pub oid: Option<ObjectIdentifier>,
76 pub imports: Vec<Import>,
77 pub definitions: Vec<Definition<T::DefinitionType>>,
78 pub value_references: Vec<ValueReference<T::ValueReferenceType>>,
79}
80
81pub trait Target {
82 type DefinitionType;
83 type ValueReferenceType;
84}
85
86impl<T: Target> Default for Model<T> {
87 fn default() -> Self {
88 Model {
89 name: Default::default(),
90 oid: None,
91 imports: Default::default(),
92 definitions: Default::default(),
93 value_references: Vec::default(),
94 }
95 }
96}
97
98impl Model<Asn<Unresolved>> {
99 pub fn try_from(value: Vec<Token>) -> Result<Self, Error> {
100 let mut model = Model::default();
101 let mut iter = value.into_iter().peekable();
102
103 model.name = Self::read_name(&mut iter)?;
104 model.oid = Self::maybe_read_oid(&mut iter)?;
105 Self::skip_until_after_text_ignore_ascii_case(&mut iter, "BEGIN")?;
106
107 while let Some(token) = iter.next() {
108 if token.eq_text_ignore_ascii_case("END") {
109 model.make_names_nice();
110 return Ok(model);
111 } else if token.eq_text_ignore_ascii_case("IMPORTS") {
112 Self::read_imports(&mut iter)?
113 .into_iter()
114 .for_each(|i| model.imports.push(i));
115 } else if iter.peek_is_separator_eq(':') {
116 model.definitions.push(Self::read_definition(
117 &mut iter,
118 token.into_text_or_else(Error::unexpected_token)?,
119 )?);
120 } else {
121 model.value_references.push(Self::read_value_reference(
122 &mut iter,
123 token.into_text_or_else(Error::unexpected_token)?,
124 )?);
125 }
126 }
127 Err(Error::unexpected_end_of_stream())
128 }
129
130 fn read_name(iter: &mut Peekable<IntoIter<Token>>) -> Result<String, Error> {
131 iter.next()
132 .and_then(|token| token.into_text())
133 .ok_or_else(Error::missing_module_name)
134 }
135
136 fn maybe_read_oid(
137 iter: &mut Peekable<IntoIter<Token>>,
138 ) -> Result<Option<ObjectIdentifier>, Error> {
139 if iter.next_is_separator_and_eq('{') {
140 Ok(Some(Self::read_oid(iter)?))
141 } else {
142 Ok(None)
143 }
144 }
145
146 fn read_oid(iter: &mut Peekable<IntoIter<Token>>) -> Result<ObjectIdentifier, Error> {
147 let mut vec = Vec::default();
148 while let Some(token) = iter.next() {
149 if token.eq_separator('}') {
150 break;
151 } else if let Some(identifier) = token.text() {
152 if identifier.chars().all(char::is_numeric) {
153 vec.push(ObjectIdentifierComponent::NumberForm(
154 identifier
155 .parse()
156 .map_err(|_| Error::invalid_int_value(token))?,
157 ));
158 } else if iter.next_is_separator_and_eq('(') {
159 let number = match iter.next_text_or_err()?.parse::<u64>() {
160 Ok(number) => number,
161 Err(_) => return Err(Error::invalid_int_value(token)),
162 };
163 iter.next_separator_eq_or_err(')')?;
164 vec.push(ObjectIdentifierComponent::NameAndNumberForm(
165 identifier.to_string(),
166 number,
167 ));
168 } else {
169 vec.push(ObjectIdentifierComponent::NameForm(identifier.to_string()));
170 }
171 } else {
172 return Err(Error::unexpected_token(token));
173 }
174 }
175 Ok(ObjectIdentifier(vec))
176 }
177
178 fn skip_until_after_text_ignore_ascii_case(
179 iter: &mut Peekable<IntoIter<Token>>,
180 text: &str,
181 ) -> Result<(), Error> {
182 for t in iter {
183 if t.eq_text_ignore_ascii_case(text) {
184 return Ok(());
185 }
186 }
187 Err(Error::unexpected_end_of_stream())
188 }
189
190 fn read_imports(iter: &mut Peekable<IntoIter<Token>>) -> Result<Vec<Import>, Error> {
191 let mut imports = Vec::new();
192 let mut import = Import::default();
193 while let Some(token) = iter.next() {
194 if token.eq_separator(';') {
195 return Ok(imports);
196 } else {
197 let text = token.into_text_or_else(Error::unexpected_token)?;
198 import.what.push(text);
199 let token = iter.next_or_err()?;
200 if token.eq_separator(',') {
201 } else if token.eq_text_ignore_ascii_case("FROM") {
203 import.from = iter.next_text_or_err()?;
204 import.from_oid = Self::maybe_read_oid(iter)?;
205 imports.push(import);
206 import = Import::default();
207 }
208 }
209 }
210 Err(Error::unexpected_end_of_stream())
211 }
212 fn read_definition(
213 iter: &mut Peekable<IntoIter<Token>>,
214 name: String,
215 ) -> Result<Definition<Asn<Unresolved>>, Error> {
216 iter.next_separator_eq_or_err(':')?;
217 iter.next_separator_eq_or_err(':')?;
218 iter.next_separator_eq_or_err('=')?;
219
220 let (token, tag) = Self::next_with_opt_tag(iter)?;
221
222 if token.eq_text_ignore_ascii_case("SEQUENCE") {
223 Ok(Definition(
224 name,
225 Self::read_sequence_or_sequence_of(iter)?.opt_tagged(tag),
226 ))
227 } else if token.eq_text_ignore_ascii_case("SET") {
228 Ok(Definition(
229 name,
230 Self::read_set_or_set_of(iter)?.opt_tagged(tag),
231 ))
232 } else if token.eq_text_ignore_ascii_case("ENUMERATED") {
233 Ok(Definition(
234 name,
235 Type::Enumerated(Enumerated::try_from(iter)?).opt_tagged(tag),
236 ))
237 } else if token.eq_text_ignore_ascii_case("CHOICE") {
238 Ok(Definition(
239 name,
240 Type::Choice(Choice::try_from(iter)?).opt_tagged(tag),
241 ))
242 } else if let Some(text) = token.text() {
243 Ok(Definition(
244 name,
245 Self::read_role_given_text(iter, text.to_string())?.opt_tagged(tag),
246 ))
247 } else {
248 Err(Error::unexpected_token(token))
249 }
250 }
251
252 fn read_value_reference<T: Iterator<Item = Token>>(
253 iter: &mut Peekable<T>,
254 name: String,
255 ) -> Result<ValueReference<Asn<Unresolved>>, Error> {
256 let r#type = Self::read_role(iter)?;
257 Ok(ValueReference {
258 name,
259 value: {
260 iter.next_separator_eq_or_err(':')?;
261 iter.next_separator_eq_or_err(':')?;
262 iter.next_separator_eq_or_err('=')?;
263 Self::read_literal(iter)?
264 },
265 role: Asn {
266 tag: None,
267 r#type,
268 default: None,
269 },
270 })
271 }
272
273 fn read_literal<T: Iterator<Item = Token>>(
274 iter: &mut Peekable<T>,
275 ) -> Result<LiteralValue, ErrorKind> {
276 let location = iter.peek_or_err()?.location();
277 let string = {
278 #[allow(clippy::blocks_in_if_conditions)]
280 if iter.peek_is_text_eq_ignore_case("true")
281 || iter.peek_is_text_eq_ignore_case("false")
282 || iter.peek_is_text_and_satisfies(|slice| {
283 slice.chars().all(|c| c.is_ascii_digit())
284 || (slice.starts_with('-')
285 && slice.len() > 1
286 && slice.chars().skip(1).all(|c| c.is_ascii_digit()))
287 })
288 {
289 iter.next_text_or_err()?
290 } else if iter.peek_is_separator_eq('"') {
291 Self::read_string_literal(iter, '"')?
292 } else if iter.peek_is_separator_eq('\'') {
293 Self::read_hex_or_bit_string_literal(iter)?
294 } else {
295 return Err(ErrorKind::UnsupportedLiteral(iter.peek_or_err()?.clone()));
296 }
297 };
298 LiteralValue::try_from_asn_str(&string)
299 .ok_or(ErrorKind::InvalidLiteral(Token::Text(location, string)))
300 }
301
302 fn read_string_literal<T: Iterator<Item = Token>>(
303 iter: &mut Peekable<T>,
304 delimiter: char,
305 ) -> Result<String, ErrorKind> {
306 iter.next_separator_eq_or_err(delimiter)?;
307 let token = iter.next_or_err()?;
308
309 let first_text = token.text().unwrap_or_default();
310 let mut string = String::from(delimiter);
311 string.push_str(first_text);
312 let mut prev_loc = Location::at(
313 token.location().line(),
314 token.location().column() + first_text.chars().count(),
315 );
316
317 loop {
318 match iter.next_or_err()? {
319 t if t.eq_separator(delimiter) => break,
320 Token::Text(loc, str) => {
321 for _ in prev_loc.column()..loc.column() {
322 string.push(' ');
323 }
324 string.push_str(&str);
325 prev_loc = Location::at(loc.line(), loc.column() + str.chars().count())
326 }
327 Token::Separator(loc, char) => {
328 for _ in prev_loc.column()..loc.column() {
329 string.push(' ');
330 }
331 string.push(char);
332 prev_loc = Location::at(loc.line(), loc.column() + 1)
333 }
334 }
335 }
336
337 string.push(delimiter);
338
339 Ok(string)
340 }
341
342 fn read_hex_or_bit_string_literal<T: Iterator<Item = Token>>(
343 iter: &mut Peekable<T>,
344 ) -> Result<String, ErrorKind> {
345 let mut string = Self::read_string_literal(iter, '\'')?;
346 match iter.next_text_eq_any_ignore_case_or_err(&["H", "B"])? {
347 Token::Text(_, suffix) => string.push_str(&suffix),
348 t => return Err(ErrorKind::UnexpectedToken(t)),
349 };
350 Ok(string)
351 }
352
353 fn next_with_opt_tag<T: Iterator<Item = Token>>(
354 iter: &mut Peekable<T>,
355 ) -> Result<(Token, Option<Tag>), Error> {
356 let token = iter.next_or_err()?;
357 if token.eq_separator('[') {
358 let tag = Tag::try_from(&mut *iter)?;
359 iter.next_separator_eq_or_err(']')?;
360 let token = iter.next_or_err()?;
361 Ok((token, Some(tag)))
362 } else {
363 Ok((token, None))
364 }
365 }
366
367 fn read_role<T: Iterator<Item = Token>>(
368 iter: &mut Peekable<T>,
369 ) -> Result<Type<Unresolved>, Error> {
370 let text = iter.next_text_or_err()?;
371 Self::read_role_given_text(iter, text)
372 }
373
374 fn read_role_given_text<T: Iterator<Item = Token>>(
375 iter: &mut Peekable<T>,
376 text: String,
377 ) -> Result<Type<Unresolved>, Error> {
378 Ok(match text.to_ascii_lowercase().as_ref() {
379 "integer" => Type::Integer(Integer::try_from(iter)?),
380 "boolean" => Type::Boolean,
381 "null" => Type::Null,
382 "utf8string" => Type::String(Self::maybe_read_size(iter)?, Charset::Utf8),
383 "ia5string" => Type::String(Self::maybe_read_size(iter)?, Charset::Ia5),
384 "numericstring" => Type::String(Self::maybe_read_size(iter)?, Charset::Numeric),
385 "printablestring" => Type::String(Self::maybe_read_size(iter)?, Charset::Printable),
386 "visiblestring" => Type::String(Self::maybe_read_size(iter)?, Charset::Visible),
387 "octet" => {
388 iter.next_text_eq_ignore_case_or_err("STRING")?;
389 Type::OctetString(Self::maybe_read_size(iter)?)
390 }
391 "bit" => {
392 iter.next_text_eq_ignore_case_or_err("STRING")?;
393 Type::BitString(BitString::try_from(iter)?)
394 }
395 "enumerated" => Type::Enumerated(Enumerated::try_from(iter)?),
396 "choice" => Type::Choice(Choice::try_from(iter)?),
397 "sequence" => Self::read_sequence_or_sequence_of(iter)?,
398 "set" => Self::read_set_or_set_of(iter)?,
399 _ => {
400 let _ = Self::maybe_read_with_components_constraint(iter)?;
404 Type::TypeReference(text, None)
405 }
406 })
407 }
408
409 fn maybe_read_with_components_constraint<T: Iterator<Item = Token>>(
410 iter: &mut Peekable<T>,
411 ) -> Result<Option<InnerTypeConstraints>, Error> {
412 if iter.next_is_separator_and_eq('(') {
413 let result = InnerTypeConstraints::try_from(&mut *iter)?;
414 iter.next_separator_eq_or_err(')')?;
415 Ok(Some(result))
416 } else {
417 Ok(None)
418 }
419 }
420
421 fn maybe_read_size<T: Iterator<Item = Token>>(
422 iter: &mut Peekable<T>,
423 ) -> Result<Size<<Unresolved as ResolveState>::SizeType>, Error> {
424 if iter.next_is_separator_and_eq('(') {
425 let result = Size::try_from(&mut *iter)?;
426 iter.next_separator_eq_or_err(')')?;
427 Ok(result)
428 } else if iter.peek_is_text_eq_ignore_case("SIZE") {
429 Size::try_from(iter)
430 } else {
431 Ok(Size::Any)
432 }
433 }
434
435 fn read_sequence_or_sequence_of<T: Iterator<Item = Token>>(
436 iter: &mut Peekable<T>,
437 ) -> Result<Type<Unresolved>, Error> {
438 let size = Self::maybe_read_size(iter)?;
439
440 if iter.next_is_text_and_eq_ignore_case("OF") {
441 Ok(Type::SequenceOf(Box::new(Self::read_role(iter)?), size))
442 } else {
443 Ok(Type::Sequence(ComponentTypeList::try_from(iter)?))
444 }
445 }
446
447 fn read_set_or_set_of<T: Iterator<Item = Token>>(
448 iter: &mut Peekable<T>,
449 ) -> Result<Type<Unresolved>, Error> {
450 let size = Self::maybe_read_size(iter)?;
451
452 if iter.next_is_text_and_eq_ignore_case("OF") {
453 Ok(Type::SetOf(Box::new(Self::read_role(iter)?), size))
454 } else {
455 Ok(Type::Set(ComponentTypeList::try_from(iter)?))
456 }
457 }
458
459 fn read_field<T: Iterator<Item = Token>>(
460 iter: &mut Peekable<T>,
461 ) -> Result<(Field<Asn<Unresolved>>, bool), Error> {
462 let name = iter.next_text_or_err()?;
463 let (token, tag) = Self::next_with_opt_tag(iter)?;
464 let mut field = Field {
465 name,
466 role: Self::read_role_given_text(iter, token.into_text_or_else(Error::no_text)?)?
467 .opt_tagged(tag),
468 };
469
470 let token = {
471 let token = iter.next_or_err()?;
472 if token.eq_text_ignore_ascii_case("OPTIONAL") {
473 field.role.make_optional();
474 iter.next_or_err()?
475 } else if token.eq_text_ignore_ascii_case("DEFAULT") {
476 if cfg!(feature = "debug-proc-macro") {
477 println!("TOKEN:::: {:?}", token);
478 }
479 field.role.set_default(match Self::read_literal(iter) {
480 Ok(value) => LitOrRef::Lit(value),
481 Err(ErrorKind::UnsupportedLiteral(token, ..)) if token.is_text() => {
482 LitOrRef::Ref(iter.next_text_or_err()?)
483 }
484 Err(e) => return Err(e.into()),
485 });
486 if cfg!(feature = "debug-proc-macro") {
487 println!(" :::: {:?}", field);
488 }
489 iter.next_or_err()?
490 } else {
491 token
492 }
493 };
494
495 let (continues, ends) = token
496 .separator()
497 .map_or((false, false), |s| (s == ',', s == '}'));
498
499 if continues || ends {
500 Ok((field, continues))
501 } else {
502 Err(Error::unexpected_token(token))
503 }
504 }
505}
506
507impl Model<Asn<Resolved>> {
508 pub fn to_rust(&self) -> Model<rust::Rust> {
509 let scope: &[&Self] = &[];
510 Model::to_rust_with_scope(self, scope)
511 }
512
513 pub fn to_rust_keep_names(&self) -> Model<rust::Rust> {
514 let scope: &[&Self] = &[];
515 Model::to_rust_keep_names_with_scope(self, scope)
516 }
517
518 pub fn to_rust_with_scope(&self, scope: &[&Self]) -> Model<rust::Rust> {
519 Model::convert_asn_to_rust(self, scope, true)
520 }
521
522 pub fn to_rust_keep_names_with_scope(&self, scope: &[&Self]) -> Model<rust::Rust> {
523 Model::convert_asn_to_rust(self, scope, false)
524 }
525}
526
527impl<RS: ResolveState> Model<Asn<RS>> {
528 pub fn make_names_nice(&mut self) {
529 Self::make_name_nice(&mut self.name);
530 for import in &mut self.imports {
531 Self::make_name_nice(&mut import.from);
532 }
533 }
534
535 fn make_name_nice(name: &mut String) {
536 const TO_REMOVE_AT_END: &[&str] = &["_Module", "Module"];
537 for to_remove in TO_REMOVE_AT_END.iter() {
538 if name.ends_with(to_remove) {
539 let new_len = name.len() - to_remove.len();
540 name.truncate(new_len);
541 }
542 }
543 }
544
545 fn maybe_read_constants<R, F: Fn(Token) -> Result<R, Error>, T: Iterator<Item = Token>>(
546 iter: &mut Peekable<T>,
547 parser: F,
548 ) -> Result<Vec<(String, R)>, Error> {
549 let mut constants = Vec::default();
550 if iter.next_is_separator_and_eq('{') {
551 loop {
552 constants.push(Self::read_constant(iter, &parser)?);
553 loop_ctrl_separator!(iter.next_or_err()?);
554 }
555 }
556 Ok(constants)
557 }
558
559 fn read_constant<R, F: Fn(Token) -> Result<R, Error>, T: Iterator<Item = Token>>(
560 iter: &mut Peekable<T>,
561 parser: F,
562 ) -> Result<(String, R), Error> {
563 let name = iter.next_text_or_err()?;
564 iter.next_separator_eq_or_err('(')?;
565 let value = iter.next_or_err()?;
566 iter.next_separator_eq_or_err(')')?;
567 Ok((name, parser(value)?))
568 }
569
570 fn constant_i64_parser(token: Token) -> Result<i64, Error> {
571 let parsed = token.text().and_then(|s| s.parse().ok());
572 parsed.ok_or_else(|| Error::invalid_value_for_constant(token))
573 }
574
575 fn constant_u64_parser(token: Token) -> Result<u64, Error> {
576 let parsed = token.text().and_then(|s| s.parse().ok());
577 parsed.ok_or_else(|| Error::invalid_value_for_constant(token))
578 }
579}
580
581#[derive(Debug, Clone, PartialOrd, PartialEq, Eq)]
582pub struct ValueReference<T> {
583 pub name: String,
584 pub role: T,
585 pub value: LiteralValue,
586}
587
588#[derive(Debug, Clone, PartialOrd, PartialEq, Eq)]
589pub enum LiteralValue {
590 Boolean(bool),
591 String(String),
592 Integer(i64),
593 OctetString(Vec<u8>),
594 EnumeratedVariant(String, String),
595}
596
597impl LiteralValue {
598 pub fn to_integer(&self) -> Option<i64> {
599 if let LiteralValue::Integer(int) = self {
600 Some(*int)
601 } else {
602 None
603 }
604 }
605}
606
607#[derive(Debug, Default, Clone, PartialOrd, PartialEq, Eq)]
608pub struct Import {
609 pub what: Vec<String>,
610 pub from: String,
611 pub from_oid: Option<ObjectIdentifier>,
612}
613
614#[derive(Debug, Clone, PartialOrd, PartialEq, Eq)]
615pub struct Field<T> {
616 pub name: String,
617 pub role: T,
618}
619
620impl<T: TagProperty> TagProperty for Field<T> {
621 fn tag(&self) -> Option<Tag> {
622 self.role.tag()
623 }
624
625 fn set_tag(&mut self, tag: Tag) {
626 self.role.set_tag(tag)
627 }
628
629 fn reset_tag(&mut self) {
630 self.role.reset_tag()
631 }
632}
633
634impl Field<Asn<Unresolved>> {
635 pub fn try_resolve<
636 R: Resolver<<Resolved as ResolveState>::SizeType>
637 + Resolver<<Resolved as ResolveState>::RangeType>
638 + Resolver<<Resolved as ResolveState>::ConstType>
639 + Resolver<Type<Unresolved>>,
640 >(
641 &self,
642 resolver: &R,
643 ) -> Result<Field<Asn<Resolved>>, ResolveError> {
644 Ok(Field {
645 name: self.name.clone(),
646 role: self.role.try_resolve(resolver)?,
647 })
648 }
649}
650
651#[cfg(test)]
652pub(crate) mod tests {
653 use crate::parser::{Location, Tokenizer};
654
655 use super::*;
656
657 pub(crate) const SIMPLE_INTEGER_STRUCT_ASN: &str = r"
658 SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
659 BEGIN
660
661 Simple ::= SEQUENCE {
662 small INTEGER(0..255),
663 bigger INTEGER(0..65535),
664 negative INTEGER(-1..255),
665 unlimited INTEGER(0..MAX) OPTIONAL
666 }
667 END
668 ";
669
670 #[test]
671 fn test_simple_asn_sequence_represented_correctly_as_asn_model() {
672 let model = Model::try_from(Tokenizer::default().parse(SIMPLE_INTEGER_STRUCT_ASN))
673 .unwrap()
674 .try_resolve()
675 .unwrap();
676
677 assert_eq!("SimpleSchema", model.name);
678 assert_eq!(true, model.imports.is_empty());
679 assert_eq!(1, model.definitions.len());
680 assert_eq!(
681 Definition(
682 "Simple".into(),
683 Type::sequence_from_fields(vec![
684 Field {
685 name: "small".into(),
686 role: Type::integer_with_range(Range::inclusive(Some(0), Some(255)))
687 .untagged(),
688 },
689 Field {
690 name: "bigger".into(),
691 role: Type::integer_with_range(Range::inclusive(Some(0), Some(65535)))
692 .untagged(),
693 },
694 Field {
695 name: "negative".into(),
696 role: Type::integer_with_range(Range::inclusive(Some(-1), Some(255)))
697 .untagged(),
698 },
699 Field {
700 name: "unlimited".into(),
701 role: Type::unconstrained_integer().optional().untagged(),
702 }
703 ])
704 .untagged(),
705 ),
706 model.definitions[0]
707 );
708 }
709
710 pub(crate) const INLINE_ASN_WITH_ENUM: &str = r"
711 SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
712 BEGIN
713
714 Woah ::= SEQUENCE {
715 decision ENUMERATED {
716 ABORT,
717 RETURN,
718 CONFIRM,
719 MAYDAY,
720 THE_CAKE_IS_A_LIE
721 } OPTIONAL
722 }
723 END
724 ";
725
726 #[test]
727 fn test_inline_asn_enumerated_represented_correctly_as_asn_model() {
728 let model = Model::try_from(Tokenizer::default().parse(INLINE_ASN_WITH_ENUM))
729 .unwrap()
730 .try_resolve()
731 .unwrap();
732
733 assert_eq!("SimpleSchema", model.name);
734 assert_eq!(true, model.imports.is_empty());
735 assert_eq!(1, model.definitions.len());
736 assert_eq!(
737 Definition(
738 "Woah".into(),
739 Type::sequence_from_fields(vec![Field {
740 name: "decision".into(),
741 role: Type::Enumerated(Enumerated::from_names(
742 ["ABORT", "RETURN", "CONFIRM", "MAYDAY", "THE_CAKE_IS_A_LIE",].iter()
743 ))
744 .optional()
745 .untagged(),
746 }])
747 .untagged(),
748 ),
749 model.definitions[0]
750 );
751 }
752
753 pub(crate) const INLINE_ASN_WITH_SEQUENCE_OF: &str = r"
754 SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
755 BEGIN
756
757 Ones ::= SEQUENCE OF INTEGER(0..1)
758
759 NestedOnes ::= SEQUENCE OF SEQUENCE OF INTEGER(0..1)
760
761 Woah ::= SEQUENCE {
762 also-ones SEQUENCE OF INTEGER(0..1),
763 nesteds SEQUENCE OF SEQUENCE OF INTEGER(0..1),
764 optionals SEQUENCE OF SEQUENCE OF INTEGER(0..MAX) OPTIONAL
765 }
766 END
767 ";
768
769 #[test]
770 fn test_inline_asn_sequence_of_represented_correctly_as_asn_model() {
771 let model = Model::try_from(Tokenizer::default().parse(INLINE_ASN_WITH_SEQUENCE_OF))
772 .unwrap()
773 .try_resolve()
774 .unwrap();
775
776 assert_eq!("SimpleSchema", model.name);
777 assert_eq!(true, model.imports.is_empty());
778 assert_eq!(3, model.definitions.len());
779 assert_eq!(
780 Definition(
781 "Ones".into(),
782 Type::SequenceOf(
783 Box::new(Type::integer_with_range(Range::inclusive(Some(0), Some(1)))),
784 Size::Any,
785 )
786 .untagged(),
787 ),
788 model.definitions[0]
789 );
790 assert_eq!(
791 Definition(
792 "NestedOnes".into(),
793 Type::SequenceOf(
794 Box::new(Type::SequenceOf(
795 Box::new(Type::integer_with_range(Range::inclusive(Some(0), Some(1)))),
796 Size::Any,
797 )),
798 Size::Any,
799 )
800 .untagged(),
801 ),
802 model.definitions[1]
803 );
804 assert_eq!(
805 Definition(
806 "Woah".into(),
807 Type::sequence_from_fields(vec![
808 Field {
809 name: "also-ones".into(),
810 role: Type::SequenceOf(
811 Box::new(Type::integer_with_range(Range::inclusive(Some(0), Some(1)))),
812 Size::Any,
813 )
814 .untagged(),
815 },
816 Field {
817 name: "nesteds".into(),
818 role: Type::SequenceOf(
819 Box::new(Type::SequenceOf(
820 Box::new(Type::integer_with_range(Range::inclusive(
821 Some(0),
822 Some(1),
823 ))),
824 Size::Any,
825 )),
826 Size::Any,
827 )
828 .untagged(),
829 },
830 Field {
831 name: "optionals".into(),
832 role: Type::SequenceOf(
833 Box::new(Type::SequenceOf(
834 Box::new(Type::unconstrained_integer()),
835 Size::Any,
836 )),
837 Size::Any,
838 )
839 .optional()
840 .untagged(),
841 },
842 ])
843 .untagged(),
844 ),
845 model.definitions[2]
846 );
847 }
848
849 pub(crate) const INLINE_ASN_WITH_CHOICE: &str = r"
850 SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
851 BEGIN
852
853 This ::= SEQUENCE OF INTEGER(0..1)
854
855 That ::= SEQUENCE OF SEQUENCE OF INTEGER(0..1)
856
857 Neither ::= ENUMERATED {
858 ABC,
859 DEF
860 }
861
862 Woah ::= SEQUENCE {
863 decision CHOICE {
864 this This,
865 that That,
866 neither Neither
867 }
868 }
869 END
870 ";
871
872 #[test]
873 fn test_inline_asn_choice_represented_correctly_as_asn_model() {
874 let model = Model::try_from(Tokenizer::default().parse(INLINE_ASN_WITH_CHOICE))
875 .unwrap()
876 .try_resolve()
877 .unwrap();
878
879 assert_eq!("SimpleSchema", model.name);
880 assert_eq!(true, model.imports.is_empty());
881 assert_eq!(4, model.definitions.len());
882 assert_eq!(
883 Definition(
884 "This".into(),
885 Type::SequenceOf(
886 Box::new(Type::integer_with_range(Range::inclusive(Some(0), Some(1)))),
887 Size::Any,
888 )
889 .untagged(),
890 ),
891 model.definitions[0]
892 );
893 assert_eq!(
894 Definition(
895 "That".into(),
896 Type::SequenceOf(
897 Box::new(Type::SequenceOf(
898 Box::new(Type::integer_with_range(Range::inclusive(Some(0), Some(1)))),
899 Size::Any,
900 )),
901 Size::Any,
902 )
903 .untagged(),
904 ),
905 model.definitions[1]
906 );
907 assert_eq!(
908 Definition(
909 "Neither".into(),
910 Type::Enumerated(Enumerated::from_names(["ABC", "DEF"].iter())).untagged(),
911 ),
912 model.definitions[2]
913 );
914 assert_eq!(
915 Definition(
916 "Woah".into(),
917 Type::sequence_from_fields(vec![Field {
918 name: "decision".into(),
919 role: Type::choice_from_variants(vec![
920 ChoiceVariant::name_type("this", Type::TypeReference("This".into(), None)),
921 ChoiceVariant::name_type("that", Type::TypeReference("That".into(), None)),
922 ChoiceVariant::name_type(
923 "neither",
924 Type::TypeReference("Neither".into(), None)
925 ),
926 ])
927 .untagged(),
928 }])
929 .untagged(),
930 ),
931 model.definitions[3]
932 );
933 }
934
935 pub(crate) const INLINE_ASN_WITH_SEQUENCE: &str = r"
936 SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
937 BEGIN
938
939 Woah ::= SEQUENCE {
940 complex SEQUENCE {
941 ones INTEGER(0..1),
942 list-ones SEQUENCE OF INTEGER(0..1),
943 optional-ones SEQUENCE OF INTEGER(0..1) OPTIONAL
944 } OPTIONAL
945 }
946 END
947 ";
948
949 #[test]
950 fn test_inline_asn_sequence_represented_correctly_as_asn_model() {
951 let model = Model::try_from(Tokenizer::default().parse(INLINE_ASN_WITH_SEQUENCE))
952 .unwrap()
953 .try_resolve()
954 .unwrap();
955
956 assert_eq!("SimpleSchema", model.name);
957 assert_eq!(true, model.imports.is_empty());
958 assert_eq!(1, model.definitions.len());
959 assert_eq!(
960 Definition(
961 "Woah".into(),
962 Type::sequence_from_fields(vec![Field {
963 name: "complex".into(),
964 role: Type::sequence_from_fields(vec![
965 Field {
966 name: "ones".into(),
967 role: Type::integer_with_range(Range::inclusive(Some(0), Some(1)))
968 .untagged(),
969 },
970 Field {
971 name: "list-ones".into(),
972 role: Type::SequenceOf(
973 Box::new(Type::integer_with_range(Range::inclusive(
974 Some(0),
975 Some(1),
976 ))),
977 Size::Any,
978 )
979 .untagged(),
980 },
981 Field {
982 name: "optional-ones".into(),
983 role: Type::SequenceOf(
984 Box::new(Type::integer_with_range(Range::inclusive(
985 Some(0),
986 Some(1),
987 ))),
988 Size::Any,
989 )
990 .optional()
991 .untagged(),
992 },
993 ])
994 .optional()
995 .untagged(),
996 }])
997 .untagged(),
998 ),
999 model.definitions[0]
1000 );
1001 }
1002
1003 #[test]
1004 fn test_nice_names() {
1005 let mut model = Model::default();
1006
1007 model.name = "SimpleTest".into();
1008 model.make_names_nice();
1009 assert_eq!("simple_test", model.to_rust().name);
1010
1011 model.name = "SIMPLE_Test".into();
1012 model.make_names_nice();
1013 assert_eq!("simple_test", model.to_rust().name);
1014
1015 model.name = "DRY_Module".into();
1016 model.make_names_nice();
1017 assert_eq!("dry", model.to_rust().name);
1018
1019 model.name = "DRYModule".into();
1020 model.make_names_nice();
1021 assert_eq!("dry", model.to_rust().name);
1022 }
1023
1024 #[test]
1025 pub fn test_integer_type_with_range() {
1026 let model = Model::try_from(Tokenizer::default().parse(
1027 r"
1028 SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
1029 BEGIN
1030
1031 SimpleTypeWithRange ::= Integer (0..65535)
1032
1033 END
1034 ",
1035 ))
1036 .expect("Failed to parse")
1037 .try_resolve()
1038 .expect("Failed to resolve");
1039
1040 assert_eq!("SimpleSchema", &model.name);
1041 assert_eq!(
1042 &[Definition(
1043 "SimpleTypeWithRange".to_string(),
1044 Type::integer_with_range(Range::inclusive(Some(0), Some(65_535))).untagged(),
1045 )][..],
1046 &model.definitions[..]
1047 )
1048 }
1049
1050 #[test]
1051 pub fn test_string_type() {
1052 let model = Model::try_from(Tokenizer::default().parse(
1053 r"
1054 SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
1055 BEGIN
1056
1057 SimpleStringType ::= UTF8String
1058
1059 END
1060 ",
1061 ))
1062 .expect("Failed to parse")
1063 .try_resolve()
1064 .expect("Failed to resolve");
1065
1066 assert_eq!("SimpleSchema", &model.name);
1067 assert_eq!(
1068 &[Definition(
1069 "SimpleStringType".to_string(),
1070 Type::unconstrained_utf8string().untagged(),
1071 )][..],
1072 &model.definitions[..]
1073 )
1074 }
1075
1076 #[test]
1077 pub fn test_enumerated_advanced() {
1078 let model = Model::try_from(Tokenizer::default().parse(
1079 r"SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
1080 BEGIN
1081
1082 Basic ::= ENUMERATED {
1083 abc,
1084 def
1085 }
1086
1087 WithExplicitNumber ::= ENUMERATED {
1088 abc(1),
1089 def(9)
1090 }
1091
1092 WithExplicitNumberAndDefaultMark ::= ENUMERATED {
1093 abc(4),
1094 def(7),
1095 ...
1096 }
1097
1098 WithExplicitNumberAndDefaultMarkV2 ::= ENUMERATED {
1099 abc(8),
1100 def(1),
1101 ...,
1102 v2(11)
1103 }
1104
1105 END
1106 ",
1107 ))
1108 .expect("Failed to parse")
1109 .try_resolve()
1110 .expect("Failed to resolve");
1111
1112 assert_eq!("SimpleSchema", &model.name);
1113 assert_eq!(
1114 &[
1115 Definition(
1116 "Basic".to_string(),
1117 Type::Enumerated(Enumerated::from_names(["abc", "def"].iter())).untagged(),
1118 ),
1119 Definition(
1120 "WithExplicitNumber".to_string(),
1121 Type::Enumerated(Enumerated::from(vec![
1122 EnumeratedVariant::from_name_number("abc", 1),
1123 EnumeratedVariant::from_name_number("def", 9)
1124 ]))
1125 .untagged(),
1126 ),
1127 Definition(
1128 "WithExplicitNumberAndDefaultMark".to_string(),
1129 Type::Enumerated(
1130 Enumerated::from(vec![
1131 EnumeratedVariant::from_name_number("abc", 4),
1132 EnumeratedVariant::from_name_number("def", 7),
1133 ],)
1134 .with_extension_after(1)
1135 )
1136 .untagged(),
1137 ),
1138 Definition(
1139 "WithExplicitNumberAndDefaultMarkV2".to_string(),
1140 Type::Enumerated(
1141 Enumerated::from(vec![
1142 EnumeratedVariant::from_name_number("abc", 8),
1143 EnumeratedVariant::from_name_number("def", 1),
1144 EnumeratedVariant::from_name_number("v2", 11)
1145 ],)
1146 .with_extension_after(1)
1147 )
1148 .untagged(),
1149 )
1150 ][..],
1151 &model.definitions[..]
1152 )
1153 }
1154
1155 #[test]
1156 pub fn test_enumerated_tags() {
1157 let model = Model::try_from(Tokenizer::default().parse(
1158 r"SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
1159 BEGIN
1160
1161 Universal ::= [UNIVERSAL 2] ENUMERATED {
1162 abc,
1163 def
1164 }
1165
1166 Application ::= [APPLICATION 7] ENUMERATED {
1167 abc,
1168 def
1169 }
1170
1171 Private ::= [PRIVATE 11] ENUMERATED {
1172 abc,
1173 def
1174 }
1175
1176 ContextSpecific ::= [8] ENUMERATED {
1177 abc,
1178 def
1179 }
1180
1181 END
1182 ",
1183 ))
1184 .expect("Failed to parse")
1185 .try_resolve()
1186 .expect("Failed to resolve");
1187
1188 assert_eq!("SimpleSchema", &model.name);
1189 assert_eq!(
1190 &[
1191 Definition(
1192 "Universal".to_string(),
1193 Type::Enumerated(Enumerated::from_names(["abc", "def"].iter()))
1194 .tagged(Tag::Universal(2)),
1195 ),
1196 Definition(
1197 "Application".to_string(),
1198 Type::Enumerated(Enumerated::from_names(["abc", "def"].iter()))
1199 .tagged(Tag::Application(7)),
1200 ),
1201 Definition(
1202 "Private".to_string(),
1203 Type::Enumerated(Enumerated::from_names(["abc", "def"].iter()))
1204 .tagged(Tag::Private(11)),
1205 ),
1206 Definition(
1207 "ContextSpecific".to_string(),
1208 Type::Enumerated(Enumerated::from_names(["abc", "def"].iter()))
1209 .tagged(Tag::ContextSpecific(8)),
1210 ),
1211 ][..],
1212 &model.definitions[..]
1213 )
1214 }
1215
1216 #[test]
1217 pub fn test_parsing_tags_in_front_of_definitions_does_not_fail() {
1218 let model = Model::try_from(Tokenizer::default().parse(
1219 r"SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
1220 BEGIN
1221
1222 Universal ::= [UNIVERSAL 2] SEQUENCE {
1223 abc [1] INTEGER(0..MAX),
1224 def [2] INTEGER(0..255)
1225 }
1226
1227 Application ::= [APPLICATION 7] SEQUENCE OF UTF8String
1228
1229 Private ::= [PRIVATE 11] ENUMERATED {
1230 abc,
1231 def
1232 }
1233
1234 ContextSpecific ::= [8] INTEGER(0..MAX)
1235
1236 END
1237 ",
1238 ))
1239 .expect("Failed to parse")
1240 .try_resolve()
1241 .expect("Failed to resolve");
1242
1243 assert_eq!("SimpleSchema", &model.name);
1244 assert_eq!(
1245 &[
1246 Definition(
1247 "Universal".to_string(),
1248 Type::sequence_from_fields(vec![
1249 Field {
1250 name: "abc".to_string(),
1251 role: Type::unconstrained_integer().tagged(Tag::ContextSpecific(1)),
1252 },
1253 Field {
1254 name: "def".to_string(),
1255 role: Type::integer_with_range(Range::inclusive(Some(0), Some(255)))
1256 .tagged(Tag::ContextSpecific(2)),
1257 }
1258 ])
1259 .tagged(Tag::Universal(2)),
1260 ),
1261 Definition(
1262 "Application".to_string(),
1263 Type::SequenceOf(Box::new(Type::unconstrained_utf8string()), Size::Any)
1264 .tagged(Tag::Application(7)),
1265 ),
1266 Definition(
1267 "Private".to_string(),
1268 Type::Enumerated(Enumerated::from_names(["abc", "def"].iter()))
1269 .tagged(Tag::Private(11)),
1270 ),
1271 Definition(
1272 "ContextSpecific".to_string(),
1273 Type::unconstrained_integer().tagged(Tag::ContextSpecific(8)),
1274 ),
1275 ][..],
1276 &model.definitions[..]
1277 )
1278 }
1279
1280 #[test]
1281 pub fn test_parsing_of_extensible_choices() {
1282 let model = Model::try_from(Tokenizer::default().parse(
1283 r"SimpleSchema DEFINITIONS AUTOMATIC TAGS ::=
1284 BEGIN
1285
1286 WithoutMarker ::= CHOICE {
1287 abc UTF8String,
1288 def UTF8String
1289 }
1290
1291 WithoutExtensionPresent ::= CHOICE {
1292 abc UTF8String,
1293 def UTF8String,
1294 ...
1295 }
1296
1297 WithExtensionPresent ::= CHOICE {
1298 abc UTF8String,
1299 def UTF8String,
1300 ...,
1301 ghi UTF8String
1302 }
1303
1304 END
1305 ",
1306 ))
1307 .expect("Failed to parse")
1308 .try_resolve()
1309 .expect("Failed to resolve");
1310
1311 assert_eq!("SimpleSchema", model.name.as_str());
1312 assert_eq!(
1313 &[
1314 Definition::new(
1315 "WithoutMarker",
1316 Type::Choice(Choice::from(vec![
1317 ChoiceVariant::name_type("abc", Type::unconstrained_utf8string()),
1318 ChoiceVariant::name_type("def", Type::unconstrained_utf8string()),
1319 ]))
1320 .untagged(),
1321 ),
1322 Definition::new(
1323 "WithoutExtensionPresent",
1324 Type::Choice(
1325 Choice::from(vec![
1326 ChoiceVariant::name_type("abc", Type::unconstrained_utf8string()),
1327 ChoiceVariant::name_type("def", Type::unconstrained_utf8string()),
1328 ])
1329 .with_extension_after(1),
1330 )
1331 .untagged(),
1332 ),
1333 Definition::new(
1334 "WithExtensionPresent",
1335 Type::Choice(
1336 Choice::from(vec![
1337 ChoiceVariant::name_type("abc", Type::unconstrained_utf8string()),
1338 ChoiceVariant::name_type("def", Type::unconstrained_utf8string()),
1339 ChoiceVariant::name_type("ghi", Type::unconstrained_utf8string()),
1340 ])
1341 .with_extension_after(1),
1342 )
1343 .untagged(),
1344 )
1345 ][..],
1346 &model.definitions[..]
1347 )
1348 }
1349
1350 #[test]
1351 pub fn test_parsing_of_extensible_with_markers_at_invalid_locations() {
1352 assert_eq!(
1353 Error::invalid_position_for_extension_marker(Token::Separator(
1354 Location::at(4, 21),
1355 '.',
1356 )),
1357 Model::try_from(Tokenizer::default().parse(
1358 r"SimpleSchema DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1359
1360 Invalid ::= CHOICE {
1361 ...
1362 }
1363
1364 END",
1365 ))
1366 .expect_err("Parsed invalid definition")
1367 );
1368
1369 assert_eq!(
1370 Error::invalid_position_for_extension_marker(Token::Separator(
1371 Location::at(4, 21),
1372 '.',
1373 )),
1374 Model::try_from(Tokenizer::default().parse(
1375 r"SimpleSchema DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1376
1377 Invalid ::= CHOICE {
1378 ...,
1379 abc UTF8String
1380 }
1381
1382 END",
1383 ))
1384 .expect_err("Parsed invalid definition")
1385 );
1386
1387 assert_eq!(
1388 Error::invalid_position_for_extension_marker(Token::Separator(
1389 Location::at(4, 21),
1390 '.',
1391 )),
1392 Model::try_from(Tokenizer::default().parse(
1393 r"SimpleSchema DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1394
1395 Invalid ::= ENUMERATED {
1396 ...
1397 }
1398
1399 END",
1400 ))
1401 .expect_err("Parsed invalid definition")
1402 );
1403
1404 assert_eq!(
1405 Error::invalid_position_for_extension_marker(Token::Separator(
1406 Location::at(4, 21),
1407 '.',
1408 )),
1409 Model::try_from(Tokenizer::default().parse(
1410 r"SimpleSchema DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1411
1412 Invalid ::= ENUMERATED {
1413 ...,
1414 abc(77)
1415 }
1416
1417 END",
1418 ))
1419 .expect_err("Parsed invalid definition")
1420 );
1421 }
1422
1423 #[test]
1424 pub fn test_parsing_module_definition_oid() {
1425 let model = Model::try_from(Tokenizer::default().parse(
1426 "SomeName { very(1) clever oid(4) 1337 } DEFINITIONS AUTOMATIC TAGS ::= BEGIN END",
1427 ))
1428 .expect("Failed to load model");
1429 assert_eq!(
1430 ObjectIdentifier(vec![
1431 ObjectIdentifierComponent::NameAndNumberForm("very".to_string(), 1),
1432 ObjectIdentifierComponent::NameForm("clever".to_string()),
1433 ObjectIdentifierComponent::NameAndNumberForm("oid".to_string(), 4),
1434 ObjectIdentifierComponent::NumberForm(1337),
1435 ]),
1436 model.oid.expect("ObjectIdentifier is missing")
1437 )
1438 }
1439
1440 #[test]
1441 pub fn test_parsing_module_definition_oid_in_import_from() {
1442 let model = Model::try_from(Tokenizer::default().parse(
1443 r"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1444 IMPORTS
1445 SomeData, OtherDef, Wowz
1446 FROM TheOtherModule { very(1) official(2) oid 42 };
1447 END",
1448 ))
1449 .expect("Failed to load model");
1450 assert_eq!(
1451 &ObjectIdentifier(vec![
1452 ObjectIdentifierComponent::NameAndNumberForm("very".to_string(), 1),
1453 ObjectIdentifierComponent::NameAndNumberForm("official".to_string(), 2),
1454 ObjectIdentifierComponent::NameForm("oid".to_string()),
1455 ObjectIdentifierComponent::NumberForm(42),
1456 ]),
1457 model.imports[0]
1458 .from_oid
1459 .as_ref()
1460 .expect("ObjectIdentifier is missing")
1461 )
1462 }
1463
1464 #[test]
1465 pub fn test_parsing_module_definition_with_integer_constant() {
1466 let model = Model::try_from(Tokenizer::default().parse(
1467 r"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1468 TheGreatStruct ::= SEQUENCE {
1469 inline INTEGER { ab(1), cd(2), ef(3) },
1470 eff-u8 INTEGER { gh(1), ij(4), kl(9) } (0..255),
1471 tagged [7] INTEGER { mn(5), op(4), qr(9) } (0..255)
1472 }
1473
1474 SeAlias ::= INTEGER { wow(1), much(2), great(3) }
1475
1476 OhAlias ::= [APPLICATION 9] INTEGER { oh(1), lul(2) } (0..255)
1477 END",
1478 ))
1479 .expect("Failed to load model")
1480 .try_resolve()
1481 .expect("Failed to resolve");
1482 assert_eq!(
1483 vec![
1484 Definition(
1485 "TheGreatStruct".to_string(),
1486 Type::sequence_from_fields(vec![
1487 Field {
1488 name: "inline".to_string(),
1489 role: Type::Integer(Integer {
1490 range: Range::none(),
1491 constants: vec![
1492 ("ab".to_string(), 1),
1493 ("cd".to_string(), 2),
1494 ("ef".to_string(), 3)
1495 ],
1496 })
1497 .untagged(),
1498 },
1499 Field {
1500 name: "eff-u8".to_string(),
1501 role: Type::Integer(Integer {
1502 range: Range::inclusive(Some(0), Some(255)),
1503 constants: vec![
1504 ("gh".to_string(), 1),
1505 ("ij".to_string(), 4),
1506 ("kl".to_string(), 9)
1507 ],
1508 })
1509 .untagged(),
1510 },
1511 Field {
1512 name: "tagged".to_string(),
1513 role: Type::Integer(Integer {
1514 range: Range::inclusive(Some(0), Some(255)),
1515 constants: vec![
1516 ("mn".to_string(), 5),
1517 ("op".to_string(), 4),
1518 ("qr".to_string(), 9)
1519 ],
1520 })
1521 .tagged(Tag::ContextSpecific(7)),
1522 },
1523 ])
1524 .untagged(),
1525 ),
1526 Definition(
1527 "SeAlias".to_string(),
1528 Type::Integer(Integer {
1529 range: Range::none(),
1530 constants: vec![
1531 ("wow".to_string(), 1),
1532 ("much".to_string(), 2),
1533 ("great".to_string(), 3),
1534 ],
1535 })
1536 .untagged(),
1537 ),
1538 Definition(
1539 "OhAlias".to_string(),
1540 Type::Integer(Integer {
1541 range: Range::inclusive(Some(0), Some(255)),
1542 constants: vec![("oh".to_string(), 1), ("lul".to_string(), 2),],
1543 })
1544 .tagged(Tag::Application(9)),
1545 )
1546 ],
1547 model.definitions
1548 )
1549 }
1550
1551 #[test]
1552 pub fn test_parsing_module_definition_with_extensible_integer() {
1553 let model = Model::try_from(Tokenizer::default().parse(
1554 r"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1555 RangedOptional ::= SEQUENCE {
1556 value INTEGER { gh(1), ij(4), kl(9) } (0..255,...) OPTIONAL
1557 }
1558
1559 END",
1560 ))
1561 .expect("Failed to load model")
1562 .try_resolve()
1563 .expect("Failed to resolve");
1564 assert_eq!(
1565 vec![Definition(
1566 "RangedOptional".to_string(),
1567 Type::sequence_from_fields(vec![Field {
1568 name: "value".to_string(),
1569 role: Type::Integer(Integer {
1570 range: Range::inclusive(Some(0), Some(255)).with_extensible(true),
1571 constants: vec![
1572 ("gh".to_string(), 1),
1573 ("ij".to_string(), 4),
1574 ("kl".to_string(), 9)
1575 ],
1576 })
1577 .optional()
1578 .untagged(),
1579 }])
1580 .untagged(),
1581 )],
1582 model.definitions
1583 )
1584 }
1585
1586 #[test]
1587 pub fn test_resolve_tag() {
1588 let external = Model::try_from(Tokenizer::default().parse(
1589 r"ExternalModule DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1590 External ::= [APPLICATION 1] INTEGER
1591 END
1592 ",
1593 ))
1594 .expect("Failed to parse module")
1595 .try_resolve()
1596 .expect("Failed to resolve");
1597 let model = Model::try_from(Tokenizer::default().parse(
1598 r"InternalModul DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1599 IMPORTS
1600 External
1601 FROM ExternalModule;
1602
1603 Implicit ::= SEQUENCE {
1604 implicit INTEGER OPTIONAL,
1605 explicit [4] INTEGER
1606 }
1607
1608 Explicit ::= [APPLICATION 8] ENUMERATED {
1609 abc,
1610 def
1611 }
1612
1613 Composed ::= CHOICE {
1614 first-but-greater-tag-value [APPLICATION 99] INTEGER,
1615 second-but-indirect-lower-tag Explicit
1616 }
1617
1618 ExternallyComposed ::= CHOICE {
1619 internal Explicit,
1620 extenral External
1621 }
1622
1623 END",
1624 ))
1625 .expect("Failed to load model")
1626 .try_resolve()
1627 .expect("Failed to resolve");
1628 let rust = model.to_rust_with_scope(&[&external]);
1629
1630 if let Rust::Struct {
1631 ordering: _,
1632 fields,
1633 tag,
1634 extension_after: _,
1635 } = rust.definitions[0].value()
1636 {
1637 assert_eq!("Implicit", rust.definitions[0].0.as_str());
1638 assert_eq!(None, *tag); assert_eq!(None, fields[0].tag()); assert_eq!(Some(Tag::ContextSpecific(4)), fields[1].tag()); } else {
1642 panic!("Expected Rust::Struct for ASN.1 SEQUENCE");
1643 }
1644
1645 if let Rust::Enum(plain) = rust.definitions[1].value() {
1646 assert_eq!("Explicit", rust.definitions[1].0.as_str());
1647 assert_eq!(2, plain.len());
1648 assert_eq!(Some(Tag::Application(8)), plain.tag()); } else {
1650 panic!("Expected Rust::Enum for ASN.1 ENUMERATED")
1651 }
1652
1653 if let Rust::DataEnum(data) = rust.definitions[2].value() {
1654 assert_eq!("Composed", rust.definitions[2].0.as_str());
1655 assert_eq!(2, data.len());
1656 assert_eq!(None, data.tag()); } else {
1658 panic!("Expected Rust::DataEnum for ASN.1 CHOICE")
1659 }
1660
1661 if let Rust::DataEnum(data) = rust.definitions[3].value() {
1662 assert_eq!("ExternallyComposed", rust.definitions[3].0.as_str());
1663 assert_eq!(2, data.len());
1664 assert_eq!(None, data.tag()); } else {
1666 panic!("Expected Rust::DataEnum for ASN.1 CHOICE")
1667 }
1668
1669 assert_eq!(4, rust.definitions.len());
1670 }
1671
1672 #[test]
1673 pub fn test_value_reference_boolean() {
1674 let model = Model::try_from(Tokenizer::default().parse(
1675 r"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1676
1677 somethingYes BOOLEAN ::= TRUE
1678 somethingNo BOOLEAN ::= FALSE
1679
1680 END",
1681 ))
1682 .expect("Failed to load model");
1683 assert_eq!(
1684 &[
1685 ValueReference {
1686 name: "somethingYes".to_string(),
1687 role: Type::Boolean.untagged(),
1688 value: LiteralValue::Boolean(true)
1689 },
1690 ValueReference {
1691 name: "somethingNo".to_string(),
1692 role: Type::Boolean.untagged(),
1693 value: LiteralValue::Boolean(false)
1694 },
1695 ],
1696 &model.value_references[..]
1697 )
1698 }
1699
1700 #[test]
1701 pub fn test_value_reference_integer() {
1702 let model = Model::try_from(Tokenizer::default().parse(
1703 r"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1704
1705 maxSomethingSomething INTEGER ::= 1337
1706
1707 END",
1708 ))
1709 .expect("Failed to load model");
1710 assert_eq!(
1711 ValueReference {
1712 name: "maxSomethingSomething".to_string(),
1713 role: Type::Integer(Integer {
1714 range: Default::default(),
1715 constants: Vec::default()
1716 })
1717 .untagged(),
1718 value: LiteralValue::Integer(1337)
1719 },
1720 model.value_references[0]
1721 )
1722 }
1723
1724 #[test]
1725 pub fn test_value_reference_bit_string() {
1726 let model = Model::try_from(Tokenizer::default().parse(
1727 r"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1728
1729 magicFlags BIT STRING ::= 'a711'H
1730
1731 magicFlags2 BIT STRING ::= '1001'B
1732
1733 END",
1734 ))
1735 .expect("Failed to load model");
1736 assert_eq!(
1737 ValueReference {
1738 name: "magicFlags".to_string(),
1739 role: Type::BitString(BitString {
1740 size: Size::Any,
1741 constants: Vec::default()
1742 })
1743 .untagged(),
1744 value: LiteralValue::OctetString(vec![0xa7, 0x11])
1745 },
1746 model.value_references[0]
1747 );
1748 assert_eq!(
1749 ValueReference {
1750 name: "magicFlags2".to_string(),
1751 role: Type::BitString(BitString {
1752 size: Size::Any,
1753 constants: Vec::default()
1754 })
1755 .untagged(),
1756 value: LiteralValue::OctetString(vec![0x09])
1757 },
1758 model.value_references[1]
1759 );
1760 }
1761
1762 #[test]
1763 pub fn test_value_reference_octet_string() {
1764 let model = Model::try_from(Tokenizer::default().parse(
1765 r"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1766
1767 answers OCTET STRING ::= '42'h
1768
1769 END",
1770 ))
1771 .expect("Failed to load model");
1772 assert_eq!(
1773 ValueReference {
1774 name: "answers".to_string(),
1775 role: Type::OctetString(Size::Any).untagged(),
1776 value: LiteralValue::OctetString(vec![0x42])
1777 },
1778 model.value_references[0]
1779 )
1780 }
1781
1782 #[test]
1783 pub fn test_value_reference_string() {
1784 let model = Model::try_from(Tokenizer::default().parse(
1785 r#"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1786
1787 utf8 UTF8String ::= "häw äre yöu .. .. doing"
1788 ia5 IA5String ::= "how are you"
1789
1790 END"#,
1791 ))
1792 .expect("Failed to load model");
1793 assert_eq!(
1794 &[
1795 ValueReference {
1796 name: "utf8".to_string(),
1797 role: Type::String(Size::Any, Charset::Utf8).untagged(),
1798 value: LiteralValue::String("häw äre yöu .. .. doing".to_string())
1799 },
1800 ValueReference {
1801 name: "ia5".to_string(),
1802 role: Type::String(Size::Any, Charset::Ia5).untagged(),
1803 value: LiteralValue::String("how are you".to_string())
1804 }
1805 ],
1806 &model.value_references[..]
1807 );
1808 }
1809
1810 #[test]
1811 pub fn test_value_reference_in_size() {
1812 let model = Model::try_from(Tokenizer::default().parse(
1813 r#"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1814
1815 se_min INTEGER ::= 42
1816 se_max INTEGER ::= 1337
1817
1818 seq-fix ::= SEQUENCE (SIZE(se_min)) OF INTEGER
1819 seq-min-max ::= SEQUENCE (SIZE(se_min..se_max)) OF INTEGER
1820 seq-min-max-ext ::= SEQUENCE (SIZE(se_min..se_max,...)) OF INTEGER
1821
1822 mixed-min-max ::= SEQUENCE (SIZE(se_min..4711)) OF INTEGER
1823 mixed-min-max-ext ::= SEQUENCE (SIZE(420..se_max,...)) OF INTEGER
1824
1825 END"#,
1826 ))
1827 .expect("Failed to load model")
1828 .try_resolve()
1829 .expect("Failed to resolve");
1830 assert_eq!(
1831 &[
1832 Definition(
1833 "seq-fix".to_string(),
1834 Type::<Resolved>::SequenceOf(
1835 Box::new(Type::Integer(Integer::default())),
1836 Size::Fix(42_usize, false)
1837 )
1838 .untagged()
1839 ),
1840 Definition(
1841 "seq-min-max".to_string(),
1842 Type::<Resolved>::SequenceOf(
1843 Box::new(Type::Integer(Integer::default())),
1844 Size::Range(42_usize, 1337, false)
1845 )
1846 .untagged()
1847 ),
1848 Definition(
1849 "seq-min-max-ext".to_string(),
1850 Type::<Resolved>::SequenceOf(
1851 Box::new(Type::Integer(Integer::default())),
1852 Size::Range(42_usize, 1337, true)
1853 )
1854 .untagged()
1855 ),
1856 Definition(
1857 "mixed-min-max".to_string(),
1858 Type::<Resolved>::SequenceOf(
1859 Box::new(Type::Integer(Integer::default())),
1860 Size::Range(42_usize, 4711, false)
1861 )
1862 .untagged()
1863 ),
1864 Definition(
1865 "mixed-min-max-ext".to_string(),
1866 Type::<Resolved>::SequenceOf(
1867 Box::new(Type::Integer(Integer::default())),
1868 Size::Range(420_usize, 1337, true)
1869 )
1870 .untagged()
1871 )
1872 ],
1873 &model.definitions[..]
1874 );
1875 }
1876
1877 #[test]
1878 pub fn test_value_reference_in_range() {
1879 let model = Model::try_from(Tokenizer::default().parse(
1880 r#"SomeName DEFINITIONS AUTOMATIC TAGS ::= BEGIN
1881
1882 se_min INTEGER ::= 42
1883 se_max INTEGER ::= 1337
1884
1885 seq-min-max ::= INTEGER(se_min..se_max)
1886 seq-min-max-ext ::= INTEGER(se_min..se_max,...)
1887
1888 mixed-min-max ::= INTEGER(se_min..4711)
1889 mixed-min-max-ext ::= INTEGER(-42069..se_max,...)
1890
1891 END"#,
1892 ))
1893 .expect("Failed to load model")
1894 .try_resolve()
1895 .expect("Failed to resolve");
1896 assert_eq!(
1897 &[
1898 Definition(
1899 "seq-min-max".to_string(),
1900 Type::<Resolved>::Integer(Integer::with_range(Range::inclusive(
1901 Some(42),
1902 Some(1337)
1903 )))
1904 .untagged()
1905 ),
1906 Definition(
1907 "seq-min-max-ext".to_string(),
1908 Type::<Resolved>::Integer(Integer::with_range(
1909 Range::inclusive(Some(42), Some(1337)).with_extensible(true)
1910 ))
1911 .untagged()
1912 ),
1913 Definition(
1914 "mixed-min-max".to_string(),
1915 Type::<Resolved>::Integer(Integer::with_range(Range::inclusive(
1916 Some(42),
1917 Some(4711)
1918 )))
1919 .untagged()
1920 ),
1921 Definition(
1922 "mixed-min-max-ext".to_string(),
1923 Type::<Resolved>::Integer(Integer::with_range(
1924 Range::inclusive(Some(-42069), Some(1337)).with_extensible(true)
1925 ))
1926 .untagged()
1927 )
1928 ],
1929 &model.definitions[..]
1930 );
1931 }
1932}