1pub mod constraints;
10pub mod encoding_rules;
11pub mod error;
12pub mod information_object;
13pub mod macros;
14pub mod parameterization;
15pub mod types;
16pub mod utils;
17
18use std::{borrow::Cow, cell::RefCell, collections::BTreeMap, ops::Add, rc::Rc};
19
20use crate::common::INTERNAL_IO_FIELD_REF_TYPE_NAME_PREFIX;
21use constraints::Constraint;
22use error::{GrammarError, GrammarErrorType};
23use information_object::{
24 ObjectClassAssignment, ObjectClassFieldType, ToplevelInformationDefinition,
25};
26#[cfg(test)]
27use internal_macros::EnumDebug;
28use macros::ToplevelMacroDefinition;
29use parameterization::Parameterization;
30use quote::{quote, ToTokens, TokenStreamExt};
31use types::*;
32
33#[cfg(doc)]
34use crate::Backend;
35
36pub const BLOCK_COMMENT_START: &str = "/*";
38pub const BLOCK_COMMENT_END: &str = "*/";
39pub const LINE_COMMENT: &str = "--";
40
41pub const LEFT_PARENTHESIS: char = '(';
43pub const RIGHT_PARENTHESIS: char = ')';
44pub const LEFT_BRACKET: char = '[';
45pub const RIGHT_BRACKET: char = ']';
46pub const LEFT_BRACE: char = '{';
47pub const RIGHT_BRACE: char = '}';
48pub const LEFT_CHEVRON: char = '<';
49pub const RIGHT_CHEVRON: char = '>';
50
51pub const NULL: &str = "NULL";
53pub const BOOLEAN: &str = "BOOLEAN";
54pub const INTEGER: &str = "INTEGER";
55pub const REAL: &str = "REAL";
56pub const BIT_STRING: &str = "BIT STRING";
57pub const OCTET_STRING: &str = "OCTET STRING";
58pub const IA5_STRING: &str = "IA5String";
59pub const UTF8_STRING: &str = "UTF8String";
60pub const NUMERIC_STRING: &str = "NumericString";
61pub const VISIBLE_STRING: &str = "VisibleString";
62pub const TELETEX_STRING: &str = "TeletexString";
63pub const T61_STRING: &str = "T61String";
64pub const VIDEOTEX_STRING: &str = "VideotexString";
65pub const GRAPHIC_STRING: &str = "GraphicString";
66pub const GENERAL_STRING: &str = "GeneralString";
67pub const UNIVERSAL_STRING: &str = "UniversalString";
68pub const BMP_STRING: &str = "BMPString";
69pub const PRINTABLE_STRING: &str = "PrintableString";
70pub const GENERALIZED_TIME: &str = "GeneralizedTime";
71pub const UTC_TIME: &str = "UTCTime";
72pub const ENUMERATED: &str = "ENUMERATED";
73pub const CHOICE: &str = "CHOICE";
74pub const SEQUENCE: &str = "SEQUENCE";
75pub const SEQUENCE_OF: &str = "SEQUENCE OF";
76pub const SET_OF: &str = "SET OF";
77pub const OF: &str = "OF";
78pub const ALL: &str = "ALL";
79pub const SET: &str = "SET";
80pub const OBJECT_IDENTIFIER: &str = "OBJECT IDENTIFIER";
81pub const COMPONENTS_OF: &str = "COMPONENTS OF";
82pub const ANY: &str = "ANY";
83pub const DEFINED: &str = "DEFINED";
84pub const BY: &str = "BY";
85
86pub const UNIVERSAL: &str = "UNIVERSAL";
88pub const PRIVATE: &str = "PRIVATE";
89pub const APPLICATION: &str = "APPLICATION";
90
91pub const TRUE: &str = "TRUE";
93pub const FALSE: &str = "FALSE";
94
95pub const BEGIN: &str = "BEGIN";
97pub const END: &str = "END";
98pub const DEFINITIONS: &str = "DEFINITIONS";
99pub const AUTOMATIC: &str = "AUTOMATIC";
100pub const EXPLICIT: &str = "EXPLICIT";
101pub const IMPLICIT: &str = "IMPLICIT";
102pub const IMPORTS: &str = "IMPORTS";
103pub const EXPORTS: &str = "EXPORTS";
104pub const FROM: &str = "FROM";
105pub const INSTRUCTIONS: &str = "INSTRUCTIONS";
106pub const TAGS: &str = "TAGS";
107pub const EXTENSIBILITY_IMPLIED: &str = "EXTENSIBILITY IMPLIED";
108pub const WITH_SUCCESSORS: &str = "WITH SUCCESSORS";
109pub const WITH_DESCENDANTS: &str = "WITH DESCENDANTS";
110pub const SEMICOLON: char = ';';
111
112pub const AMPERSAND: char = '&';
114pub const CLASS: &str = "CLASS";
115pub const UNIQUE: &str = "UNIQUE";
116pub const WITH_SYNTAX: &str = "WITH SYNTAX";
117pub const AT: char = '@';
118pub const DOT: char = '.';
119
120pub const SIZE: &str = "SIZE";
122pub const CONSTRAINED_BY: &str = "CONSTRAINED BY";
123pub const PATTERN: &str = "PATTERN";
124pub const DEFAULT: &str = "DEFAULT";
125pub const CONTAINING: &str = "CONTAINING";
126pub const ENCODED_BY: &str = "ENCODED BY";
127pub const OPTIONAL: &str = "OPTIONAL";
128pub const WITH_COMPONENTS: &str = "WITH COMPONENTS";
129pub const WITH_COMPONENT: &str = "WITH COMPONENT";
130pub const UNION: &str = "UNION";
131pub const EXCEPT: &str = "EXCEPT";
132pub const INTERSECTION: &str = "INTERSECTION";
133pub const ABSENT: &str = "ABSENT";
134pub const PRESENT: &str = "PRESENT";
135pub const INCLUDES: &str = "INCLUDES";
136pub const MIN: &str = "MIN";
137pub const MAX: &str = "MAX";
138pub const LESS_THAN: char = '<';
139pub const GREATER_THAN: char = '>';
140pub const PIPE: &str = "|";
141pub const CARET: &str = "^";
142
143pub const MACRO: &str = "MACRO";
145
146pub const ASSIGN: &str = "::=";
147pub const RANGE: &str = "..";
148pub const ELLIPSIS: &str = "...";
149pub const COMMA: char = ',';
150pub const COLON: char = ':';
151pub const SINGLE_QUOTE: char = '\'';
152
153pub const ABSTRACT_SYNTAX: &str = "ABSTRACT-SYNTAX";
155pub const BIT: &str = "BIT";
156pub const CHARACTER: &str = "CHARACTER";
157pub const DATE: &str = "DATE";
158pub const DATE_TIME: &str = "DATE-TIME";
159pub const DURATION: &str = "DURATION";
160pub const EMBEDDED_PDV: &str = "EMBEDDED PDV";
161pub const EXTERNAL: &str = "EXTERNAL";
162pub const INSTANCE_OF: &str = "INSTANCE OF";
163pub const MINUS_INFINITY: &str = "MINUS-INFINITY";
164pub const NOT_A_NUMBER: &str = "NOT-A-NUMBER";
165pub const OBJECT: &str = "OBJECT";
166pub const OCTET: &str = "OCTET";
167pub const OID_IRI: &str = "OID-IRI";
168pub const PLUS_INFINITY: &str = "PLUS-INFINITY";
169pub const RELATIVE_OID: &str = "RELATIVE-OID";
170pub const RELATIVE_OID_IRI: &str = "RELATIVE-OID-IRI";
171pub const TIME: &str = "TIME";
172pub const TIME_OF_DAY: &str = "TIME-OF-DAY";
173pub const TYPE_IDENTIFIER: &str = "TYPE-IDENTIFIER";
174pub const ENCODING_CONTROL: &str = "ENCODING-CONTROL";
175
176pub const ASN1_KEYWORDS: [&str; 67] = [
177 ABSTRACT_SYNTAX,
178 BIT,
179 CHARACTER,
180 CONTAINING,
181 DATE,
182 DATE_TIME,
183 DURATION,
184 EMBEDDED_PDV,
185 EXTERNAL,
186 INSTANCE_OF,
187 MINUS_INFINITY,
188 NOT_A_NUMBER,
189 OBJECT,
190 OCTET,
191 OID_IRI,
192 PLUS_INFINITY,
193 RELATIVE_OID,
194 RELATIVE_OID_IRI,
195 TIME,
196 TIME_OF_DAY,
197 TYPE_IDENTIFIER,
198 SIZE,
199 DEFAULT,
200 OPTIONAL,
201 WITH_COMPONENTS,
202 WITH_COMPONENT,
203 UNION,
204 EXCEPT,
205 INTERSECTION,
206 ABSENT,
207 PRESENT,
208 INCLUDES,
209 MIN,
210 MAX,
211 CLASS,
212 UNIQUE,
213 WITH_SYNTAX,
214 NULL,
215 BOOLEAN,
216 INTEGER,
217 REAL,
218 ENUMERATED,
219 CHOICE,
220 SEQUENCE,
221 OF,
222 ALL,
223 SET,
224 OBJECT_IDENTIFIER,
225 UNIVERSAL,
226 PRIVATE,
227 APPLICATION,
228 TRUE,
229 FALSE,
230 BEGIN,
231 END,
232 DEFINITIONS,
233 AUTOMATIC,
234 EXPLICIT,
235 IMPLICIT,
236 IMPORTS,
237 FROM,
238 INSTRUCTIONS,
239 TAGS,
240 MACRO,
241 ANY,
242 BY,
243 DEFINED,
244];
245
246macro_rules! grammar_error {
247 ($kind:ident, $($arg:tt)*) => {
248 GrammarError::new(&format!($($arg)*),GrammarErrorType::$kind)
249 };
250}
251
252#[derive(Debug, Clone, PartialEq)]
253pub struct EncodingReferenceDefault(pub String);
254
255impl From<&str> for EncodingReferenceDefault {
256 fn from(value: &str) -> Self {
257 Self(value.into())
258 }
259}
260
261#[cfg_attr(test, derive(EnumDebug))]
262#[cfg_attr(not(test), derive(Debug))]
263#[derive(Clone, Copy, PartialEq, Default)]
264pub enum TaggingEnvironment {
265 Automatic,
266 #[default]
267 Implicit,
268 Explicit,
269}
270
271impl Add<&TaggingEnvironment> for &TaggingEnvironment {
272 type Output = TaggingEnvironment;
273
274 fn add(self, rhs: &TaggingEnvironment) -> Self::Output {
275 match (self, rhs) {
276 (t, TaggingEnvironment::Automatic) => *t,
277 (_, t) => *t,
278 }
279 }
280}
281
282#[cfg_attr(test, derive(EnumDebug))]
285#[cfg_attr(not(test), derive(Debug))]
286#[derive(Clone, Copy, PartialEq, Default)]
287pub enum ExtensibilityEnvironment {
288 Implied,
289 #[default]
290 Explicit,
291}
292
293#[cfg_attr(test, derive(EnumDebug))]
296#[cfg_attr(not(test), derive(Debug))]
297#[derive(Clone, PartialEq)]
298pub enum With {
299 Successors,
300 Descendants,
301}
302
303#[derive(Debug, Clone, PartialEq)]
306pub struct ExternalValueReference {
307 pub module_reference: String,
308 pub value_reference: String,
309}
310
311#[derive(Debug, Clone, PartialEq)]
314pub struct GlobalModuleReference {
315 pub module_reference: String,
316 pub assigned_identifier: AssignedIdentifier,
317}
318
319impl From<(&str, AssignedIdentifier)> for GlobalModuleReference {
320 fn from(value: (&str, AssignedIdentifier)) -> Self {
321 Self {
322 module_reference: value.0.to_owned(),
323 assigned_identifier: value.1,
324 }
325 }
326}
327
328#[cfg_attr(test, derive(EnumDebug))]
331#[cfg_attr(not(test), derive(Debug))]
332#[derive(Clone, PartialEq)]
333pub enum AssignedIdentifier {
334 ObjectIdentifierValue(ObjectIdentifierValue),
335 ExternalValueReference(ExternalValueReference),
336 ValueReference(String),
337 ParameterizedValue {
338 value_reference: String,
339 actual_parameter_list: String,
340 },
341 Empty,
342}
343
344#[derive(Debug, Clone, PartialEq)]
347pub struct Import {
348 pub types: Vec<String>,
349 pub global_module_reference: GlobalModuleReference,
350 pub with: Option<With>,
351}
352
353impl From<(Vec<&str>, (GlobalModuleReference, Option<&str>))> for Import {
354 fn from(value: (Vec<&str>, (GlobalModuleReference, Option<&str>))) -> Self {
355 Self {
356 types: value.0.into_iter().map(String::from).collect(),
357 global_module_reference: value.1 .0,
358 with: value.1 .1.map(|with| {
359 if with == WITH_SUCCESSORS {
360 With::Successors
361 } else {
362 With::Descendants
363 }
364 }),
365 }
366 }
367}
368
369#[cfg_attr(test, derive(EnumDebug))]
372#[cfg_attr(not(test), derive(Debug))]
373#[derive(Clone, PartialEq)]
374pub enum Exports {
375 Identifier(Vec<String>),
376 All,
377}
378
379impl From<Vec<&str>> for Exports {
380 fn from(value: Vec<&str>) -> Self {
381 Self::Identifier(value.iter().map(ToString::to_string).collect())
382 }
383}
384
385#[cfg_attr(test, derive(EnumDebug))]
388#[cfg_attr(not(test), derive(Debug))]
389#[derive(Clone, PartialEq)]
390pub enum DefinitiveIdentifier {
391 DefinitiveOID(ObjectIdentifierValue),
392 DefinitiveOIDandIRI {
393 oid: ObjectIdentifierValue,
394 iri: String,
395 },
396}
397
398impl From<(ObjectIdentifierValue, Option<&str>)> for DefinitiveIdentifier {
399 fn from(value: (ObjectIdentifierValue, Option<&str>)) -> Self {
400 if let Some(iri_value) = value.1 {
401 Self::DefinitiveOIDandIRI {
402 oid: value.0,
403 iri: iri_value.to_owned(),
404 }
405 } else {
406 Self::DefinitiveOID(value.0)
407 }
408 }
409}
410
411#[derive(Debug, Clone, PartialEq)]
414pub struct ModuleHeader {
415 pub name: String,
416 pub module_identifier: Option<DefinitiveIdentifier>,
417 pub encoding_reference_default: Option<EncodingReferenceDefault>,
418 pub tagging_environment: TaggingEnvironment,
419 pub extensibility_environment: ExtensibilityEnvironment,
420 pub imports: Vec<Import>,
421 pub exports: Option<Exports>,
422}
423
424impl ModuleHeader {
425 pub fn find_import(&self, identifier: &str) -> Option<&String> {
427 self.imports
428 .iter()
429 .find_map(|i| i.types.iter().find(|id| *id == identifier))
430 }
431}
432
433impl
434 From<(
435 &str,
436 Option<DefinitiveIdentifier>,
437 Option<(
438 Option<EncodingReferenceDefault>,
439 TaggingEnvironment,
440 ExtensibilityEnvironment,
441 )>,
442 Option<Exports>,
443 Option<Vec<Import>>,
444 )> for ModuleHeader
445{
446 fn from(
447 value: (
448 &str,
449 Option<DefinitiveIdentifier>,
450 Option<(
451 Option<EncodingReferenceDefault>,
452 TaggingEnvironment,
453 ExtensibilityEnvironment,
454 )>,
455 Option<Exports>,
456 Option<Vec<Import>>,
457 ),
458 ) -> Self {
459 let (encoding_reference_default, tagging_environment, extensibility_environment) =
460 value.2.unwrap_or((
461 None,
462 TaggingEnvironment::Explicit,
463 ExtensibilityEnvironment::Explicit,
464 ));
465 Self {
466 name: value.0.into(),
467 module_identifier: value.1,
468 encoding_reference_default,
469 tagging_environment,
470 extensibility_environment,
471 exports: value.3,
472 imports: value.4.unwrap_or_default(),
473 }
474 }
475}
476
477#[derive(Debug, Clone, PartialEq)]
480pub struct ObjectIdentifierValue(pub Vec<ObjectIdentifierArc>);
481
482impl From<Vec<ObjectIdentifierArc>> for ObjectIdentifierValue {
483 fn from(value: Vec<ObjectIdentifierArc>) -> Self {
484 Self(value)
485 }
486}
487
488#[derive(Debug, Clone, PartialEq)]
491pub struct ObjectIdentifierArc {
492 pub name: Option<String>,
493 pub number: Option<u128>,
494}
495
496impl ObjectIdentifierArc {
497 const ITU_T: u128 = 0;
498 const ISO: u128 = 1;
499 const JOINT_ISO_ITU_T: u128 = 2;
500 const JOINT_ISO_CCITT: u128 = 2;
501 const RECOMMENDATION: u128 = 0;
502 const QUESTION: u128 = 1;
503 const ADMINISTRATION: u128 = 2;
504 const NETWORK_OPERATOR: u128 = 3;
505 const ITU_T_IDENTIFIED_ORGANIZATION: u128 = 4;
506 const R_RECOMMENDATION: u128 = 5;
507 const STANDARD: u128 = 0;
508 const REGISTRATION_AUTHORITY: u128 = 1;
509 const MEMBER_BODY: u128 = 2;
510 const ISO_IDENTIFIED_ORGANIZATION: u128 = 3;
511
512 pub(crate) fn well_known(name: Option<&String>, root: Option<u8>) -> Option<u128> {
513 match (root, name.map(|s| s.as_str())) {
514 (_, Some("itu-t")) => Some(Self::ITU_T),
515 (_, Some("iso")) => Some(Self::ISO),
516 (_, Some("joint-iso-itu-t")) => Some(Self::JOINT_ISO_ITU_T),
517 (_, Some("joint-iso-ccitt")) => Some(Self::JOINT_ISO_CCITT),
518 (Some(0), Some("recommendation")) => Some(Self::RECOMMENDATION),
519 (Some(0), Some("question")) => Some(Self::QUESTION),
520 (Some(0), Some("administration")) => Some(Self::ADMINISTRATION),
521 (Some(0), Some("network-operator")) => Some(Self::NETWORK_OPERATOR),
522 (Some(0), Some("identified-organization")) => Some(Self::ITU_T_IDENTIFIED_ORGANIZATION),
523 (Some(0), Some("r-recommendation")) => Some(Self::R_RECOMMENDATION),
524 (Some(1), Some("standard")) => Some(Self::STANDARD),
525 (Some(1), Some("registration-authority")) => Some(Self::REGISTRATION_AUTHORITY),
526 (Some(1), Some("member-body")) => Some(Self::MEMBER_BODY),
527 (Some(1), Some("identified-organization")) => Some(Self::ISO_IDENTIFIED_ORGANIZATION),
528 _ => None,
529 }
530 }
531}
532
533impl From<u128> for ObjectIdentifierArc {
534 fn from(value: u128) -> Self {
535 Self {
536 name: None,
537 number: Some(value),
538 }
539 }
540}
541
542impl From<&str> for ObjectIdentifierArc {
543 fn from(value: &str) -> Self {
544 Self {
545 name: Some(value.into()),
546 number: None,
547 }
548 }
549}
550
551impl From<(&str, u128)> for ObjectIdentifierArc {
552 fn from(value: (&str, u128)) -> Self {
553 Self {
554 name: Some(value.0.into()),
555 number: Some(value.1),
556 }
557 }
558}
559
560#[cfg_attr(test, derive(EnumDebug))]
566#[cfg_attr(not(test), derive(Debug))]
567#[derive(Clone, PartialEq)]
568pub enum ToplevelDefinition {
569 Type(ToplevelTypeDefinition),
571 Value(ToplevelValueDefinition),
573 Class(ObjectClassAssignment),
575 Object(ToplevelInformationDefinition),
577 Macro(ToplevelMacroDefinition),
579}
580
581impl ToplevelDefinition {
582 pub(crate) fn has_enum_value(&self, type_name: Option<&String>, identifier: &String) -> bool {
583 if let ToplevelDefinition::Type(ToplevelTypeDefinition {
584 name,
585 ty: ASN1Type::Enumerated(e),
586 ..
587 }) = self
588 {
589 if type_name.is_some() && Some(name) != type_name {
590 return false;
591 }
592 e.members.iter().any(|m| &m.name == identifier)
593 } else {
594 false
595 }
596 }
597
598 pub(crate) fn set_module_header(&mut self, module_header: Rc<RefCell<ModuleHeader>>) {
599 match self {
600 ToplevelDefinition::Type(ref mut t) => {
601 t.module_header = Some(module_header);
602 }
603 ToplevelDefinition::Value(ref mut v) => {
604 v.module_header = Some(module_header);
605 }
606 ToplevelDefinition::Class(ref mut c) => {
607 c.module_header = Some(module_header);
608 }
609 ToplevelDefinition::Object(ref mut o) => {
610 o.module_header = Some(module_header);
611 }
612 ToplevelDefinition::Macro(ref mut m) => {
613 m.module_header = Some(module_header);
614 }
615 }
616 }
617
618 pub(crate) fn get_module_header(&self) -> Option<Rc<RefCell<ModuleHeader>>> {
619 match self {
620 ToplevelDefinition::Type(ref t) => t.module_header.as_ref().cloned(),
621 ToplevelDefinition::Value(ref v) => v.module_header.as_ref().cloned(),
622 ToplevelDefinition::Class(ref c) => c.module_header.as_ref().cloned(),
623 ToplevelDefinition::Object(ref o) => o.module_header.as_ref().cloned(),
624 ToplevelDefinition::Macro(ref m) => m.module_header.as_ref().cloned(),
625 }
626 }
627
628 pub(crate) fn apply_tagging_environment(&mut self, environment: &TaggingEnvironment) {
629 if let (env, ToplevelDefinition::Type(ty)) = (environment, self) {
630 ty.tag = ty.tag.as_ref().map(|t| AsnTag {
631 environment: env + &t.environment,
632 tag_class: t.tag_class,
633 id: t.id,
634 });
635 match &mut ty.ty {
636 ASN1Type::Sequence(s) | ASN1Type::Set(s) => s.members.iter_mut().for_each(|m| {
637 m.tag = m.tag.as_ref().map(|t| AsnTag {
638 environment: env + &t.environment,
639 tag_class: t.tag_class,
640 id: t.id,
641 });
642 }),
643 ASN1Type::Choice(c) => c.options.iter_mut().for_each(|o| {
644 o.tag = o.tag.as_ref().map(|t| AsnTag {
645 environment: env + &t.environment,
646 tag_class: t.tag_class,
647 id: t.id,
648 });
649 }),
650 _ => (),
651 }
652 }
653 }
654
655 pub fn name(&self) -> &String {
677 match self {
678 ToplevelDefinition::Class(c) => &c.name,
679 ToplevelDefinition::Object(o) => &o.name,
680 ToplevelDefinition::Type(t) => &t.name,
681 ToplevelDefinition::Value(v) => &v.name,
682 ToplevelDefinition::Macro(v) => &v.name,
683 }
684 }
685}
686
687#[derive(Debug, Clone, PartialEq)]
690pub struct ToplevelValueDefinition {
691 pub comments: String,
692 pub name: String,
693 pub associated_type: ASN1Type,
694 pub parameterization: Option<Parameterization>,
695 pub value: ASN1Value,
696 pub module_header: Option<Rc<RefCell<ModuleHeader>>>,
697}
698
699impl From<(&str, ASN1Value, ASN1Type)> for ToplevelValueDefinition {
700 fn from(value: (&str, ASN1Value, ASN1Type)) -> Self {
701 Self {
702 comments: String::new(),
703 name: value.0.to_owned(),
704 associated_type: value.2.to_owned(),
705 parameterization: None,
706 value: value.1,
707 module_header: None,
708 }
709 }
710}
711
712impl
713 From<(
714 Vec<&str>,
715 &str,
716 Option<Parameterization>,
717 ASN1Type,
718 ASN1Value,
719 )> for ToplevelValueDefinition
720{
721 fn from(
722 value: (
723 Vec<&str>,
724 &str,
725 Option<Parameterization>,
726 ASN1Type,
727 ASN1Value,
728 ),
729 ) -> Self {
730 Self {
731 comments: value.0.join("\n"),
732 name: value.1.into(),
733 parameterization: value.2,
734 associated_type: value.3,
735 value: value.4,
736 module_header: None,
737 }
738 }
739}
740
741#[derive(Debug, Clone, PartialEq)]
742pub struct ToplevelTypeDefinition {
743 pub comments: String,
744 pub tag: Option<AsnTag>,
745 pub name: String,
746 pub ty: ASN1Type,
747 pub parameterization: Option<Parameterization>,
748 pub module_header: Option<Rc<RefCell<ModuleHeader>>>,
749}
750
751impl ToplevelTypeDefinition {
752 pub fn pdu(&self) -> &ASN1Type {
753 &self.ty
754 }
755}
756
757impl From<(&str, ASN1Type)> for ToplevelTypeDefinition {
758 fn from(value: (&str, ASN1Type)) -> Self {
759 Self {
760 comments: String::new(),
761 tag: None,
762 name: value.0.to_owned(),
763 ty: value.1,
764 parameterization: None,
765 module_header: None,
766 }
767 }
768}
769
770impl
771 From<(
772 Vec<&str>,
773 &str,
774 Option<Parameterization>,
775 (Option<AsnTag>, ASN1Type),
776 )> for ToplevelTypeDefinition
777{
778 fn from(
779 value: (
780 Vec<&str>,
781 &str,
782 Option<Parameterization>,
783 (Option<AsnTag>, ASN1Type),
784 ),
785 ) -> Self {
786 Self {
787 comments: value.0.join("\n"),
788 name: value.1.into(),
789 parameterization: value.2,
790 ty: value.3 .1,
791 tag: value.3 .0,
792 module_header: None,
793 }
794 }
795}
796
797#[cfg_attr(test, derive(EnumDebug))]
801#[cfg_attr(not(test), derive(Debug))]
802#[derive(Clone, PartialEq)]
803pub enum ASN1Type {
804 Null,
805 Boolean(Boolean),
806 Integer(Integer),
807 Real(Real),
808 BitString(BitString),
809 OctetString(OctetString),
810 CharacterString(CharacterString),
811 Enumerated(Enumerated),
812 Choice(Choice),
813 Sequence(SequenceOrSet),
814 SequenceOf(SequenceOrSetOf),
815 Set(SequenceOrSet),
816 SetOf(SequenceOrSetOf),
817 Time(Time),
818 GeneralizedTime(GeneralizedTime),
819 UTCTime(UTCTime),
820 Any,
821 ElsewhereDeclaredType(DeclarationElsewhere),
822 ChoiceSelectionType(ChoiceSelectionType),
823 ObjectIdentifier(ObjectIdentifier),
824 ObjectClassField(ObjectClassFieldType),
825 EmbeddedPdv,
826 External,
827}
828
829impl ASN1Type {
830 pub fn as_str(&self) -> Cow<'_, str> {
831 match self {
832 ASN1Type::Null => Cow::Borrowed(NULL),
833 ASN1Type::Boolean(_) => Cow::Borrowed(BOOLEAN),
834 ASN1Type::Integer(_) => Cow::Borrowed(INTEGER),
835 ASN1Type::Real(_) => Cow::Borrowed(REAL),
836 ASN1Type::BitString(_) => Cow::Borrowed(BIT_STRING),
837 ASN1Type::OctetString(_) => Cow::Borrowed(OCTET_STRING),
838 ASN1Type::CharacterString(CharacterString {
839 ty: CharacterStringType::BMPString,
840 ..
841 }) => Cow::Borrowed(BMP_STRING),
842 ASN1Type::CharacterString(CharacterString {
843 ty: CharacterStringType::UTF8String,
844 ..
845 }) => Cow::Borrowed(UTF8_STRING),
846 ASN1Type::CharacterString(CharacterString {
847 ty: CharacterStringType::PrintableString,
848 ..
849 }) => Cow::Borrowed(PRINTABLE_STRING),
850 ASN1Type::CharacterString(CharacterString {
851 ty: CharacterStringType::TeletexString,
852 ..
853 }) => Cow::Borrowed(TELETEX_STRING),
854 ASN1Type::CharacterString(CharacterString {
855 ty: CharacterStringType::IA5String,
856 ..
857 }) => Cow::Borrowed(IA5_STRING),
858 ASN1Type::CharacterString(CharacterString {
859 ty: CharacterStringType::UniversalString,
860 ..
861 }) => Cow::Borrowed(UNIVERSAL_STRING),
862 ASN1Type::CharacterString(CharacterString {
863 ty: CharacterStringType::VisibleString,
864 ..
865 }) => Cow::Borrowed(VISIBLE_STRING),
866 ASN1Type::CharacterString(CharacterString {
867 ty: CharacterStringType::GeneralString,
868 ..
869 }) => Cow::Borrowed(GENERAL_STRING),
870 ASN1Type::CharacterString(CharacterString {
871 ty: CharacterStringType::VideotexString,
872 ..
873 }) => Cow::Borrowed(VIDEOTEX_STRING),
874 ASN1Type::CharacterString(CharacterString {
875 ty: CharacterStringType::GraphicString,
876 ..
877 }) => Cow::Borrowed(GRAPHIC_STRING),
878 ASN1Type::CharacterString(CharacterString {
879 ty: CharacterStringType::NumericString,
880 ..
881 }) => Cow::Borrowed(NUMERIC_STRING),
882 ASN1Type::Enumerated(_) => Cow::Borrowed(ENUMERATED),
883 ASN1Type::Choice(_) => Cow::Borrowed(CHOICE),
884 ASN1Type::Sequence(_) => Cow::Borrowed(SEQUENCE),
885 ASN1Type::SequenceOf(_) => Cow::Borrowed(SEQUENCE_OF),
886 ASN1Type::Set(_) => Cow::Borrowed(SET),
887 ASN1Type::SetOf(_) => Cow::Borrowed(SET_OF),
888 ASN1Type::Time(_) => Cow::Borrowed(TIME),
889 ASN1Type::GeneralizedTime(_) => Cow::Borrowed(GENERALIZED_TIME),
890 ASN1Type::UTCTime(_) => Cow::Borrowed(UTC_TIME),
891 ASN1Type::Any => Cow::Borrowed(ANY),
892 ASN1Type::ElsewhereDeclaredType(DeclarationElsewhere { identifier, .. }) => {
893 Cow::Borrowed(identifier)
894 }
895 ASN1Type::ChoiceSelectionType(_) => todo!(),
896 ASN1Type::ObjectIdentifier(_) => Cow::Borrowed(OBJECT_IDENTIFIER),
897 ASN1Type::ObjectClassField(ifr) => Cow::Owned(format!(
898 "{INTERNAL_IO_FIELD_REF_TYPE_NAME_PREFIX}{}${}",
899 ifr.class,
900 ifr.field_path_as_str()
901 )),
902 ASN1Type::EmbeddedPdv => Cow::Borrowed(EMBEDDED_PDV),
903 ASN1Type::External => Cow::Borrowed(EXTERNAL),
904 }
905 }
906
907 pub fn is_builtin_type(&self) -> bool {
908 !matches!(
909 self,
910 ASN1Type::ElsewhereDeclaredType(_)
911 | ASN1Type::ChoiceSelectionType(_)
912 | ASN1Type::ObjectClassField(_)
913 )
914 }
915
916 pub fn constraints(&self) -> Option<&Vec<Constraint>> {
917 match self {
918 ASN1Type::Boolean(b) => Some(b.constraints()),
919 ASN1Type::Real(r) => Some(r.constraints()),
920 ASN1Type::Integer(i) => Some(i.constraints()),
921 ASN1Type::BitString(b) => Some(b.constraints()),
922 ASN1Type::OctetString(o) => Some(o.constraints()),
923 ASN1Type::CharacterString(c) => Some(c.constraints()),
924 ASN1Type::Enumerated(e) => Some(e.constraints()),
925 ASN1Type::Time(t) => Some(t.constraints()),
926 ASN1Type::Choice(c) => Some(c.constraints()),
927 ASN1Type::Set(s) | ASN1Type::Sequence(s) => Some(s.constraints()),
928 ASN1Type::SetOf(s) | ASN1Type::SequenceOf(s) => Some(s.constraints()),
929 ASN1Type::ElsewhereDeclaredType(e) => Some(e.constraints()),
930 ASN1Type::ObjectClassField(f) => Some(f.constraints()),
931 _ => None,
932 }
933 }
934
935 pub fn constraints_mut(&mut self) -> Option<&mut Vec<Constraint>> {
936 match self {
937 ASN1Type::Boolean(b) => Some(b.constraints_mut()),
938 ASN1Type::Real(r) => Some(r.constraints_mut()),
939 ASN1Type::Integer(i) => Some(i.constraints_mut()),
940 ASN1Type::BitString(b) => Some(b.constraints_mut()),
941 ASN1Type::OctetString(o) => Some(o.constraints_mut()),
942 ASN1Type::CharacterString(c) => Some(c.constraints_mut()),
943 ASN1Type::Enumerated(e) => Some(e.constraints_mut()),
944 ASN1Type::Time(t) => Some(t.constraints_mut()),
945 ASN1Type::Choice(c) => Some(c.constraints_mut()),
946 ASN1Type::Set(s) | ASN1Type::Sequence(s) => Some(s.constraints_mut()),
947 ASN1Type::SetOf(s) | ASN1Type::SequenceOf(s) => Some(s.constraints_mut()),
948 ASN1Type::ElsewhereDeclaredType(e) => Some(e.constraints_mut()),
949 ASN1Type::ObjectClassField(f) => Some(f.constraints_mut()),
950 _ => None,
951 }
952 }
953}
954
955pub const NUMERIC_STRING_CHARSET: [char; 11] =
956 [' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
957pub const PRINTABLE_STRING_CHARSET: [char; 74] = [
958 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
959 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
960 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4',
961 '5', '6', '7', '8', '9', ' ', '\'', '(', ')', '+', ',', '-', '.', '/', ':', '=', '?',
962];
963
964#[cfg_attr(test, derive(EnumDebug))]
966#[cfg_attr(not(test), derive(Debug))]
967#[derive(Clone, PartialEq, Copy)]
968pub enum CharacterStringType {
969 NumericString,
970 VisibleString,
971 IA5String,
972 TeletexString,
973 VideotexString,
974 GraphicString,
975 GeneralString,
976 UniversalString,
977 UTF8String,
978 BMPString,
979 PrintableString,
980}
981
982impl CharacterStringType {
983 pub fn character_set(&self) -> BTreeMap<usize, char> {
984 match self {
985 CharacterStringType::NumericString => {
986 NUMERIC_STRING_CHARSET.into_iter().enumerate().collect()
987 }
988 CharacterStringType::VisibleString | CharacterStringType::PrintableString => {
989 PRINTABLE_STRING_CHARSET.into_iter().enumerate().collect()
990 }
991 CharacterStringType::IA5String => (0..128u32)
992 .map(|i| char::from_u32(i).unwrap())
993 .enumerate()
994 .collect(),
995 _ => (0..u16::MAX as u32)
996 .filter_map(char::from_u32)
997 .enumerate()
998 .collect(),
999 }
1000 }
1001}
1002
1003#[derive(Debug, Clone, Copy, PartialEq)]
1005pub enum IntegerType {
1006 Int8,
1007 Uint8,
1008 Int16,
1009 Uint16,
1010 Int32,
1011 Uint32,
1012 Int64,
1013 Uint64,
1014 Unbounded,
1015}
1016
1017impl ToTokens for IntegerType {
1018 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1019 match self {
1020 IntegerType::Int8 => tokens.append_all(quote!(i8)),
1021 IntegerType::Uint8 => tokens.append_all(quote!(u8)),
1022 IntegerType::Int16 => tokens.append_all(quote!(i16)),
1023 IntegerType::Uint16 => tokens.append_all(quote!(u16)),
1024 IntegerType::Int32 => tokens.append_all(quote!(i32)),
1025 IntegerType::Uint32 => tokens.append_all(quote!(u32)),
1026 IntegerType::Int64 => tokens.append_all(quote!(i64)),
1027 IntegerType::Uint64 => tokens.append_all(quote!(u64)),
1028 IntegerType::Unbounded => tokens.append_all(quote!(Integer)),
1029 }
1030 }
1031}
1032
1033impl IntegerType {
1034 pub fn is_unbounded(&self) -> bool {
1035 self == &IntegerType::Unbounded
1036 }
1037 pub fn max_restrictive(self, rhs: IntegerType) -> IntegerType {
1042 match (self, rhs) {
1043 (x, y) if x == y => x,
1044 (IntegerType::Uint8, _) | (_, IntegerType::Uint8) => IntegerType::Uint8,
1045 (IntegerType::Int8, _) | (_, IntegerType::Int8) => IntegerType::Int8,
1046 (IntegerType::Uint16, _) | (_, IntegerType::Uint16) => IntegerType::Uint16,
1047 (IntegerType::Int16, _) | (_, IntegerType::Int16) => IntegerType::Int16,
1048 (IntegerType::Uint32, _) | (_, IntegerType::Uint32) => IntegerType::Uint32,
1049 (IntegerType::Int32, _) | (_, IntegerType::Int32) => IntegerType::Int32,
1050 (IntegerType::Uint64, _) | (_, IntegerType::Uint64) => IntegerType::Uint64,
1051 (IntegerType::Int64, _) | (_, IntegerType::Int64) => IntegerType::Int64,
1052 _ => IntegerType::Unbounded,
1053 }
1054 }
1055}
1056
1057#[cfg_attr(test, derive(EnumDebug))]
1059#[cfg_attr(not(test), derive(Debug))]
1060#[derive(Clone, PartialEq)]
1061pub enum ASN1Value {
1062 All,
1063 Null,
1064 Boolean(bool),
1065 Choice {
1066 type_name: Option<String>,
1067 variant_name: String,
1068 inner_value: Box<ASN1Value>,
1069 },
1070 SequenceOrSet(Vec<(Option<String>, Box<ASN1Value>)>),
1073 Integer(i128),
1074 Real(f64),
1075 String(String),
1076 BitString(Vec<bool>),
1077 BitStringNamedBits(Vec<String>),
1078 OctetString(Vec<u8>),
1079 EnumeratedValue {
1080 enumerated: String,
1081 enumerable: String,
1082 },
1083 Time(String),
1084 ElsewhereDeclaredValue {
1085 module: Option<String>,
1086 parent: Option<String>,
1087 identifier: String,
1088 },
1089 ObjectIdentifier(ObjectIdentifierValue),
1090 LinkedNestedValue {
1103 supertypes: Vec<String>,
1105 value: Box<ASN1Value>,
1106 },
1107 LinkedIntValue {
1109 integer_type: IntegerType,
1110 value: i128,
1111 },
1112 LinkedStructLikeValue(Vec<(String, ASN1Type, StructLikeFieldValue)>),
1115 LinkedArrayLikeValue(Vec<Box<ASN1Value>>),
1117 LinkedCharStringValue(CharacterStringType, String),
1119 LinkedElsewhereDefinedValue {
1120 parent: Option<String>,
1121 identifier: String,
1122 can_be_const: bool,
1123 },
1124}
1125
1126#[cfg_attr(test, derive(EnumDebug))]
1128#[cfg_attr(not(test), derive(Debug))]
1129#[derive(Clone, PartialEq)]
1130pub enum StructLikeFieldValue {
1131 Explicit(Box<ASN1Value>),
1132 Implicit(Box<ASN1Value>),
1133}
1134
1135impl StructLikeFieldValue {
1136 pub fn into_value(self) -> ASN1Value {
1137 match self {
1138 StructLikeFieldValue::Explicit(v) | StructLikeFieldValue::Implicit(v) => *v,
1139 }
1140 }
1141
1142 pub fn value(&self) -> &ASN1Value {
1143 match self {
1144 StructLikeFieldValue::Explicit(v) | StructLikeFieldValue::Implicit(v) => v,
1145 }
1146 }
1147
1148 pub fn value_mut(&mut self) -> &mut ASN1Value {
1149 match self {
1150 StructLikeFieldValue::Explicit(ref mut v)
1151 | StructLikeFieldValue::Implicit(ref mut v) => &mut *v,
1152 }
1153 }
1154}
1155
1156impl AsMut<ASN1Value> for ASN1Value {
1157 fn as_mut(&mut self) -> &mut ASN1Value {
1158 self
1159 }
1160}
1161
1162impl ASN1Value {
1163 pub fn max(
1164 &self,
1165 other: &ASN1Value,
1166 char_set: Option<&BTreeMap<usize, char>>,
1167 ) -> Result<ASN1Value, GrammarError> {
1168 self.min_max(other, char_set, false)
1169 }
1170
1171 pub fn min(
1172 &self,
1173 other: &ASN1Value,
1174 char_set: Option<&BTreeMap<usize, char>>,
1175 ) -> Result<ASN1Value, GrammarError> {
1176 self.min_max(other, char_set, true)
1177 }
1178
1179 fn min_max(
1180 &self,
1181 other: &ASN1Value,
1182 char_set: Option<&BTreeMap<usize, char>>,
1183 getting_mininum: bool,
1184 ) -> Result<ASN1Value, GrammarError> {
1185 match (self, other, char_set) {
1186 (ASN1Value::Integer(s), ASN1Value::Integer(o), _) => {
1187 if getting_mininum {
1188 Ok(ASN1Value::Integer(*s.min(o)))
1189 } else {
1190 Ok(ASN1Value::Integer(*s.max(o)))
1191 }
1192 }
1193 (ASN1Value::String(s), ASN1Value::String(o), Some(set)) => {
1194 if s.len() != 1 || o.len() != 1 {
1195 return Err(grammar_error!(
1196 UnpackingError,
1197 "Unsupported operation for ASN1Values {self:?} and {other:?}"
1198 ));
1199 }
1200 let s_as_char = s.chars().next().unwrap();
1201 let o_as_char = o.chars().next().unwrap();
1202 match (
1203 set.iter().find(|(_, c)| s_as_char == **c),
1204 set.iter().find(|(_, c)| o_as_char == **c),
1205 ) {
1206 (Some((self_i, _)), Some((other_i, _))) => {
1207 let return_self = if getting_mininum {
1208 self_i <= other_i
1209 } else {
1210 self_i >= other_i
1211 };
1212 if return_self {
1213 Ok(self.clone())
1214 } else {
1215 Ok(other.clone())
1216 }
1217 }
1218 _ => Err(grammar_error!(
1219 UnpackingError,
1220 "Failed to find ASN1Values {self:?} and {other:?} in character set {char_set:?}",
1221 )),
1222 }
1223 }
1224 _ => Err(grammar_error!(
1225 UnpackingError,
1226 "Unsupported operation for ASN1Values {self:?} and {other:?}",
1227 )),
1228 }
1229 }
1230
1231 pub fn unwrap_as_integer(&self) -> Result<i128, GrammarError> {
1232 if let ASN1Value::Integer(i) = self {
1233 Ok(*i)
1234 } else {
1235 Err(grammar_error!(
1236 UnpackingError,
1237 "Cannot unwrap {self:?} as integer!"
1238 ))
1239 }
1240 }
1241}
1242
1243#[derive(Debug, Clone, PartialEq)]
1247pub struct DeclarationElsewhere {
1248 pub parent: Option<String>,
1250 pub module: Option<String>,
1252 pub identifier: String,
1253 pub constraints: Vec<Constraint>,
1254}
1255
1256#[derive(Debug, Clone, Copy, PartialEq)]
1258pub enum TagClass {
1259 Universal,
1260 Application,
1261 Private,
1262 ContextSpecific,
1263}
1264
1265#[derive(Debug, Clone, PartialEq)]
1267pub struct AsnTag {
1268 pub environment: TaggingEnvironment,
1269 pub tag_class: TagClass,
1270 pub id: u64,
1271}
1272
1273impl From<((Option<&str>, u64), Option<TaggingEnvironment>)> for AsnTag {
1274 fn from(value: ((Option<&str>, u64), Option<TaggingEnvironment>)) -> Self {
1275 let tag_class = match value.0 .0 {
1276 Some("APPLICATION") => TagClass::Application,
1277 Some("UNIVERSAL") => TagClass::Universal,
1278 Some("PRIVATE") => TagClass::Private,
1279 _ => TagClass::ContextSpecific,
1280 };
1281 AsnTag {
1282 tag_class,
1283 id: value.0 .1,
1284 environment: value.1.unwrap_or(TaggingEnvironment::Automatic),
1285 }
1286 }
1287}