use std::collections::{hash_map::Iter, HashMap};
use topological_sort::TopologicalSort;
use crate::parser::asn::structs::{defs::Asn1Definition, oid::ObjectIdentifier};
#[derive(Debug, PartialEq)]
pub enum Asn1ModuleTag {
Explicit,
Implicit,
Automatic,
}
impl Default for Asn1ModuleTag {
fn default() -> Self {
Self::Explicit
}
}
#[derive(Debug, Default, Clone)]
pub struct Asn1ModuleName {
pub(in crate::parser) name: String,
pub(in crate::parser) oid: Option<ObjectIdentifier>,
}
impl Asn1ModuleName {
pub fn new(name: String, oid: Option<ObjectIdentifier>) -> Self {
Self { name, oid }
}
pub fn name(&self) -> String {
self.name.clone()
}
pub fn name_as_str(&self) -> &str {
&self.name
}
pub fn oid(&self) -> Option<ObjectIdentifier> {
self.oid.clone()
}
}
#[derive(Debug, Default)]
pub struct Asn1Module {
pub(in crate::parser) imports: HashMap<String, Asn1ModuleName>,
pub(in crate::parser) exports: Option<Vec<Asn1Definition>>,
pub(in crate::parser) name: Asn1ModuleName,
pub(in crate::parser) tags: Asn1ModuleTag,
pub(in crate::parser) definitions: HashMap<String, Asn1Definition>,
pub(in crate::parser) exports_all: bool,
}
impl Asn1Module {
pub fn name(self, name: Asn1ModuleName) -> Self {
Self { name, ..self }
}
pub fn tags(self, tags: Asn1ModuleTag) -> Self {
Self { tags, ..self }
}
pub fn imports(self, imports: HashMap<String, Asn1ModuleName>) -> Self {
Self { imports, ..self }
}
pub(crate) fn definitions(self, definitions: HashMap<String, Asn1Definition>) -> Self {
Self {
definitions,
..self
}
}
pub(crate) fn definitions_sorted(&mut self) -> Vec<String> {
let mut ts = TopologicalSort::<String>::new();
for (k, v) in self.definitions.iter() {
for r in v.dependent_references() {
if self.imports.get(&r).is_none() {
ts.add_dependency(r.clone(), k.clone());
}
}
ts.insert(k);
}
let mut out_vec = vec![];
loop {
let popped = ts.pop_all();
if popped.is_empty() {
break;
} else {
out_vec.extend(popped);
}
}
out_vec
}
#[inline(always)]
pub(crate) fn get_module_name(&self) -> String {
self.name.name.clone()
}
#[inline(always)]
pub(crate) fn get_definitions(&self) -> &HashMap<String, Asn1Definition> {
&self.definitions
}
#[inline(always)]
pub(crate) fn get_definition_mut(&mut self, key: &str) -> Option<&mut Asn1Definition> {
self.definitions.get_mut(key)
}
#[inline(always)]
pub(crate) fn get_imported_defs(&self) -> Iter<'_, String, Asn1ModuleName> {
self.imports.iter()
}
}