asn1rs_model/model/
rs.rs

1use crate::model::lor::{Error, Resolved, Resolver, Unresolved};
2use crate::model::{Asn, Definition, LitOrRef, LiteralValue, Model, Target, Type, ValueReference};
3
4#[derive(Default)]
5pub struct MultiModuleResolver {
6    models: Vec<Model<Asn<Unresolved>>>,
7}
8
9impl MultiModuleResolver {
10    pub fn push(&mut self, model: Model<Asn<Unresolved>>) {
11        self.models.push(model);
12    }
13
14    pub fn try_resolve_all(&self) -> Result<Vec<Model<Asn<Resolved>>>, Error> {
15        self.models
16            .iter()
17            .map(|model| {
18                ResolveScope {
19                    model,
20                    scope: &self.models,
21                }
22                .try_resolve()
23            })
24            .collect::<_>()
25    }
26}
27
28pub(crate) struct ResolveScope<'a> {
29    model: &'a Model<Asn<Unresolved>>,
30    scope: &'a [Model<Asn<Unresolved>>],
31}
32
33impl<'a> From<&'a Model<Asn<Unresolved>>> for ResolveScope<'a> {
34    fn from(model: &'a Model<Asn<Unresolved>>) -> Self {
35        Self {
36            model,
37            scope: core::slice::from_ref(model),
38        }
39    }
40}
41
42impl<'a> ResolveScope<'a> {
43    pub(crate) fn try_resolve(&self) -> Result<Model<Asn<Resolved>>, Error> {
44        let mut result = Model::<Asn<Resolved>> {
45            name: self.model.name.clone(),
46            oid: self.model.oid.clone(),
47            imports: self.model.imports.clone(),
48            definitions: Vec::with_capacity(self.model.definitions.len()),
49            value_references: Vec::with_capacity(self.model.value_references.len()),
50        };
51
52        // copy over all value references
53        for vr in &self.model.value_references {
54            result.value_references.push(ValueReference {
55                name: vr.name.clone(),
56                role: vr.role.try_resolve(self)?,
57                value: vr.value.clone(),
58            })
59        }
60
61        for Definition(name, asn) in &self.model.definitions {
62            result
63                .definitions
64                .push(Definition(name.clone(), asn.try_resolve(self)?))
65        }
66
67        Ok(result)
68    }
69
70    fn model_with_imported_item(&self, item: &str) -> Option<&'a Model<Asn<Unresolved>>> {
71        self.model
72            .imports
73            .iter()
74            .find(|i| i.what.iter().any(|what| what.eq(item)))
75            .and_then(|import| {
76                self.scope.iter().find(|m| {
77                    (m.oid.is_some() && m.oid.eq(&import.from_oid)) || m.name.eq(&import.from)
78                })
79            })
80    }
81
82    fn value_reference(
83        &self,
84        name: &str,
85    ) -> Option<&'a ValueReference<<Asn<Unresolved> as Target>::ValueReferenceType>> {
86        self.model
87            .value_references
88            .iter()
89            .find(|vr| vr.name.eq(name))
90            .or_else(|| {
91                self.model_with_imported_item(name).and_then(|model| {
92                    ResolveScope {
93                        model,
94                        scope: self.scope,
95                    }
96                    .value_reference(name)
97                })
98            })
99    }
100
101    fn definition(&self, name: &str) -> Option<&'a Definition<Asn<Unresolved>>> {
102        self.model
103            .definitions
104            .iter()
105            .find(|def| def.name().eq(name))
106            .or_else(|| {
107                self.model_with_imported_item(name).and_then(|model| {
108                    ResolveScope {
109                        model,
110                        scope: self.scope,
111                    }
112                    .definition(name)
113                })
114            })
115    }
116}
117
118impl Resolver<usize> for ResolveScope<'_> {
119    fn resolve(&self, lor: &LitOrRef<usize>) -> Result<usize, Error> {
120        match lor {
121            LitOrRef::Lit(lit) => Ok(*lit),
122            LitOrRef::Ref(name) => {
123                match self.value_reference(name).map(|vr| vr.value.to_integer()) {
124                    Some(Some(value)) => Ok(value as usize),
125                    Some(None) => Err(Error::FailedToParseLiteral(format!("name: {}", name))),
126                    None => Err(Error::FailedToResolveReference(name.clone())),
127                }
128            }
129        }
130    }
131}
132
133impl Resolver<i64> for ResolveScope<'_> {
134    fn resolve(&self, lor: &LitOrRef<i64>) -> Result<i64, Error> {
135        match lor {
136            LitOrRef::Lit(lit) => Ok(*lit),
137            LitOrRef::Ref(name) => match self.value_reference(name).map(|vr| vr.value.to_integer())
138            {
139                Some(Some(value)) => Ok(value),
140                Some(None) => Err(Error::FailedToParseLiteral(format!("name: {}", name))),
141                None => Err(Error::FailedToResolveReference(name.clone())),
142            },
143        }
144    }
145}
146
147impl Resolver<LiteralValue> for ResolveScope<'_> {
148    fn resolve(&self, lor: &LitOrRef<LiteralValue>) -> Result<LiteralValue, Error> {
149        match lor {
150            LitOrRef::Lit(lit) => Ok(lit.clone()),
151            LitOrRef::Ref(name) => self
152                .value_reference(name)
153                .map(|vr| vr.value.clone())
154                .ok_or_else(|| Error::FailedToResolveReference(name.clone())),
155        }
156    }
157}
158
159impl Resolver<Type<Unresolved>> for ResolveScope<'_> {
160    fn resolve(&self, lor: &LitOrRef<Type<Unresolved>>) -> Result<Type<Unresolved>, Error> {
161        match lor {
162            LitOrRef::Lit(lit) => Ok(lit.clone()),
163            LitOrRef::Ref(name) => self
164                .definition(name)
165                .map(|def| def.1.r#type.clone())
166                .ok_or_else(|| Error::FailedToResolveType(name.clone())),
167        }
168    }
169}