asn1_compiler/parser/asn/structs/
module.rs

1//! ASN.1 Module Level Structures and other functionality
2
3use std::collections::{hash_map::Iter, HashMap};
4
5use topological_sort::TopologicalSort;
6
7use crate::parser::asn::structs::{defs::Asn1Definition, oid::ObjectIdentifier};
8
9#[derive(Debug, PartialEq, Eq)]
10pub enum Asn1ModuleTag {
11    Explicit,
12    Implicit,
13    Automatic,
14}
15
16impl Default for Asn1ModuleTag {
17    fn default() -> Self {
18        Self::Explicit
19    }
20}
21
22#[derive(Debug, Default, Clone)]
23pub struct Asn1ModuleName {
24    pub(in crate::parser) name: String,
25    pub(in crate::parser) oid: Option<ObjectIdentifier>,
26}
27
28impl Asn1ModuleName {
29    pub fn new(name: String, oid: Option<ObjectIdentifier>) -> Self {
30        Self { name, oid }
31    }
32
33    pub fn name(&self) -> String {
34        self.name.clone()
35    }
36
37    pub fn name_as_str(&self) -> &str {
38        &self.name
39    }
40
41    pub fn oid(&self) -> Option<ObjectIdentifier> {
42        self.oid.clone()
43    }
44}
45
46/// Definition of a 'parsed' ASN Module
47///
48/// When an ASN module is successfully parsed, it contains a set of definitions that result from
49/// parsing the assignments in a given module (Definitions within 'BEGIN' and 'END' tags.
50/// Optionally, the module may have some definitions, that are imported from other modules and the
51/// module may even 'export' some defintions. A module is uniquely identified by a name and object
52/// identifier. In addition a module may support 'tagging' internal sequence values differently, so
53/// information about it is kept as well.
54#[derive(Debug, Default)]
55pub struct Asn1Module {
56    pub(in crate::parser) imports: HashMap<String, Asn1ModuleName>,
57    pub(in crate::parser) _exports: Option<Vec<Asn1Definition>>,
58    pub(in crate::parser) name: Asn1ModuleName,
59    pub(in crate::parser) _tags: Asn1ModuleTag,
60    pub(in crate::parser) definitions: HashMap<String, Asn1Definition>,
61    pub(in crate::parser) _exports_all: bool,
62}
63
64impl Asn1Module {
65    pub fn name(self, name: Asn1ModuleName) -> Self {
66        Self { name, ..self }
67    }
68
69    pub fn tags(self, _tags: Asn1ModuleTag) -> Self {
70        Self { _tags, ..self }
71    }
72
73    pub fn imports(self, imports: HashMap<String, Asn1ModuleName>) -> Self {
74        Self { imports, ..self }
75    }
76
77    pub(crate) fn definitions(self, definitions: HashMap<String, Asn1Definition>) -> Self {
78        Self {
79            definitions,
80            ..self
81        }
82    }
83
84    // Get all the definitions in the current module in the Topologically Sorted order.
85    //
86    // To 'sort' the definitions topologically, we are finding out all the 'dependents' on a given
87    // definition (ie. those that are 'Referenced' in a given definition (like a Referenced Type in
88    // a Type definition or a Class Name in an object definition and so on. We don't include the
89    // 'import'ed definitions in these because, they will already be 'Resolved' because the modules
90    // are already in a Topologically sorted order!
91    pub(crate) fn definitions_sorted(&mut self) -> Vec<String> {
92        let mut ts = TopologicalSort::<String>::new();
93
94        for (k, v) in self.definitions.iter() {
95            for r in v.dependent_references() {
96                if self.imports.get(&r).is_none() {
97                    ts.add_dependency(r.clone(), k.clone());
98                }
99            }
100            ts.insert(k);
101        }
102
103        let mut out_vec = vec![];
104        loop {
105            let popped = ts.pop_all();
106            if popped.is_empty() {
107                break;
108            } else {
109                out_vec.extend(popped);
110            }
111        }
112        out_vec
113    }
114
115    #[inline(always)]
116    pub(crate) fn get_module_name(&self) -> String {
117        self.name.name.clone()
118    }
119
120    // FIXME: Add filtering criteria
121    #[inline(always)]
122    pub(crate) fn get_definitions(&self) -> &HashMap<String, Asn1Definition> {
123        &self.definitions
124    }
125
126    #[inline(always)]
127    pub(crate) fn get_definition_mut(&mut self, key: &str) -> Option<&mut Asn1Definition> {
128        self.definitions.get_mut(key)
129    }
130
131    #[inline(always)]
132    pub(crate) fn get_imported_defs(&self) -> Iter<'_, String, Asn1ModuleName> {
133        self.imports.iter()
134    }
135}