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