1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! Resolver Struct and it's implementation
use std::collections::{BTreeMap, HashMap};
use crate::error::Error;
use crate::parser::asn::structs::{defs::Asn1Definition, module::Asn1Module};
use crate::resolver::asn::structs::{defs::Asn1ResolvedDefinition, types::Asn1ResolvedType};
use crate::resolver::asn::defs::resolve_definition;
#[derive(Debug, Clone)]
pub(crate) struct Resolver {
// Resolved definitions
pub(crate) resolved_defs: BTreeMap<String, Asn1ResolvedDefinition>,
// Unresolved Parameterized Definitions used by individual 'Type's to resolve themselves.
pub(crate) parameterized_defs: HashMap<String, Asn1Definition>,
// Object Classes: Used by Objects and Object Sets to resolves themselves.
pub(crate) classes: HashMap<String, Asn1Definition>,
}
impl Resolver {
pub fn new() -> Self {
Resolver {
resolved_defs: BTreeMap::new(),
parameterized_defs: HashMap::new(),
classes: HashMap::new(),
}
}
// Resolve Definitions: Algorithm
//
// First we need to resolve classes in the current module, because we need to resolve Object
// and ObjectSets before we can process definitions. The Objects and ObjectSets need to be
// handled before other definitions because Objects may refer to some Types that may be
// required later on while resolving some other Types and if those 'Type's remain hidden within
// Objects, we can always end up having some missing definition(s).
//
// These first two steps are actually part of parsing, which can only be done when all Class
// definitions are avaiable (Think of it as macro invocation in Rust, which is before the Type
// resolution, but after an individual file is parsed!).
//
// After that we resolve definitions in a Topologically sorted order. Fairly straight forward.
// We do not need to do any `Pending` definitions, as we were doing before.
pub(crate) fn resolve_definitions(&mut self, module: &mut Asn1Module) -> Result<(), Error> {
// We need to first get Classes in the current module - resolved
self.resolve_classes_in_current_module(module);
module.resolve_object_classes(&self.classes)?;
let definitions_sorted = module.definitions_sorted();
for k in definitions_sorted {
let parsed_def = module.get_definition_mut(&k);
if parsed_def.is_none() {
eprintln!(
"Definition '{}' Not found! It's Okay for certain Dummy References",
k
);
continue;
}
let parsed_def = parsed_def.unwrap();
if parsed_def.params.is_some() {
self.parameterized_defs
.insert(k.to_string(), parsed_def.clone());
parsed_def.resolved = true;
} else if parsed_def.is_class_assignment() {
self.classes.insert(k.to_string(), parsed_def.clone());
parsed_def.resolved = true;
} else {
let resolved_def = resolve_definition(parsed_def, self)?;
self.resolved_defs.insert(k.clone(), resolved_def);
}
parsed_def.resolved = true;
}
for k in module.definitions_sorted() {
let parsed_def = module.get_definition_mut(&k);
if parsed_def.is_none() {
eprintln!(
"Definition '{}' Not found! It's Okay for certain Dummy References",
k
);
continue;
}
let parsed_def = parsed_def.unwrap();
if !parsed_def.resolved {
println!(
"UNRESOLVED: Definition: {} in module : {} not resolved!",
k,
module.get_module_name()
);
}
}
Ok(())
}
pub(crate) fn get_resolved_types(&self) -> Vec<(&String, &Asn1ResolvedType)> {
self.resolved_defs
.iter()
.filter_map(|(k, v)| match v {
Asn1ResolvedDefinition::Type(ref t) => Some((k, t)),
_ => None,
})
.collect::<Vec<(&String, &Asn1ResolvedType)>>()
}
fn resolve_classes_in_current_module(&mut self, module: &Asn1Module) -> () {
for (k, def) in module.get_definitions() {
if def.is_class_assignment() {
self.classes.insert(k.clone(), def.clone());
}
}
}
}