rasn_compiler/validator/linking/
information_object.rs1use std::collections::BTreeMap;
2
3use crate::intermediate::{information_object::*, *};
4
5use super::{
6 utils::{resolve_custom_syntax, walk_object_field_ref_path},
7 GrammarError, GrammarErrorType,
8};
9
10impl ToplevelInformationDefinition {
11 pub fn resolve_class_reference(mut self, tlds: &BTreeMap<String, ToplevelDefinition>) -> Self {
12 if let ClassLink::ByName(name) = &self.class {
13 if let Some(ToplevelDefinition::Class(c)) = tlds.get(name) {
14 self.class = ClassLink::ByReference(c.definition.clone());
15 }
16 }
17 self
18 }
19
20 pub fn collect_supertypes(
24 &mut self,
25 tlds: &BTreeMap<String, ToplevelDefinition>,
26 ) -> Result<(), GrammarError> {
27 match (&mut self.value, &self.class) {
28 (ASN1Information::Object(ref mut o), ClassLink::ByReference(class)) => {
29 match resolve_and_link(&mut o.fields, class, tlds)? {
30 Some(ToplevelInformationDefinition {
31 value: ASN1Information::Object(obj),
32 ..
33 }) => {
34 self.value = ASN1Information::ObjectSet(ObjectSet {
35 values: vec![ObjectSetValue::Inline(obj.fields.clone())],
36 extensible: None,
37 });
38 }
39 Some(ToplevelInformationDefinition {
40 value: ASN1Information::ObjectSet(set),
41 ..
42 }) => {
43 self.value = ASN1Information::ObjectSet(set.clone());
44 }
45 _ => (),
46 }
47 Ok(())
48 }
49 (ASN1Information::ObjectSet(ref mut o), ClassLink::ByReference(class)) => {
50 o.values.iter_mut().try_for_each(|value| match value {
51 ObjectSetValue::Reference(_) => Ok(()),
52 ObjectSetValue::Inline(ref mut fields) => {
53 resolve_custom_syntax(fields, class)?;
54 link_object_fields(fields, class, tlds)
55 }
56 })
57 }
58 _ => Ok(()),
59 }
60 }
61}
62
63fn resolve_and_link(
64 fields: &mut InformationObjectFields,
65 class: &ObjectClassDefn,
66 tlds: &BTreeMap<String, ToplevelDefinition>,
67) -> Result<Option<ToplevelInformationDefinition>, GrammarError> {
68 match resolve_custom_syntax(fields, class) {
69 Ok(()) => link_object_fields(fields, class, tlds).map(|_| None),
70 Err(
71 err @ GrammarError {
72 kind: GrammarErrorType::SyntaxMismatch,
73 ..
74 },
75 ) => {
76 if let InformationObjectFields::CustomSyntax(c) = &fields {
77 if let Some(id) = c.first().and_then(SyntaxApplication::as_str_or_none) {
78 if let Some(ToplevelDefinition::Object(tld)) = tlds.get(id) {
79 let mut tld_clone = tld.clone().resolve_class_reference(tlds);
80 tld_clone.collect_supertypes(tlds)?;
81 return Ok(Some(tld_clone));
82 }
83 }
84 }
85 Err(err)
86 }
87 Err(e) => Err(e),
88 }
89}
90
91fn link_object_fields(
92 fields: &mut InformationObjectFields,
93 class: &ObjectClassDefn,
94 tlds: &BTreeMap<String, ToplevelDefinition>,
95) -> Result<(), GrammarError> {
96 match fields {
97 InformationObjectFields::DefaultSyntax(ref mut fields) => {
98 fields.iter_mut().try_for_each(|field| match field {
99 InformationObjectField::FixedValueField(fixed) => class
100 .fields
101 .iter()
102 .find_map(|f| {
103 (f.identifier
104 == ObjectFieldIdentifier::SingleValue(fixed.identifier.clone()))
105 .then_some(f.ty.as_ref())
106 })
107 .flatten()
108 .ok_or_else(|| {
109 GrammarError::new(
110 &format!(
111 "Could not determine type of fixed value field {}",
112 fixed.identifier
113 ),
114 GrammarErrorType::LinkerError,
115 )
116 })
117 .and_then(|ty| {
118 fixed
119 .value
120 .link_with_type(tlds, ty, Some(&ty.as_str().to_string()))
121 }),
122 InformationObjectField::ObjectSetField(_) => Err(GrammarError::new(
123 "Linking object set fields is not yet supported!",
124 GrammarErrorType::NotYetInplemented,
125 )),
126 _ => Ok(()),
127 })
128 }
129 InformationObjectFields::CustomSyntax(_) => Err(GrammarError::new(
130 "Unexpectedly encountered unresolved custom syntax linking information object",
131 GrammarErrorType::LinkerError,
132 )),
133 }
134}
135
136impl ASN1Information {
137 pub fn link_object_set_reference(
138 &mut self,
139 tlds: &BTreeMap<String, ToplevelDefinition>,
140 ) -> bool {
141 match self {
142 ASN1Information::ObjectSet(s) => s.link_object_set_reference(tlds),
143 ASN1Information::Object(o) => o.link_object_set_reference(tlds),
144 }
145 }
146
147 pub fn references_object_set_by_name(&self) -> bool {
148 match self {
149 ASN1Information::ObjectSet(s) => s.references_object_set_by_name(),
150 ASN1Information::Object(o) => o.references_object_set_by_name(),
151 }
152 }
153}
154
155impl SyntaxApplication {
156 pub fn link_object_set_reference(
157 &mut self,
158 tlds: &BTreeMap<String, ToplevelDefinition>,
159 ) -> bool {
160 match self {
161 SyntaxApplication::ObjectSetDeclaration(o) => o.link_object_set_reference(tlds),
162 _ => false,
163 }
164 }
165
166 pub fn references_object_set_by_name(&self) -> bool {
167 match self {
168 SyntaxApplication::ObjectSetDeclaration(o) => o.references_object_set_by_name(),
169 _ => false,
170 }
171 }
172}
173
174impl ObjectClassDefn {
175 pub fn get_field<'a>(
176 &'a self,
177 path: &'a Vec<ObjectFieldIdentifier>,
178 ) -> Option<&'a InformationObjectClassField> {
179 walk_object_field_ref_path(&self.fields, path, 0)
180 }
181}
182
183impl InformationObject {
184 pub fn link_object_set_reference(
185 &mut self,
186 tlds: &BTreeMap<String, ToplevelDefinition>,
187 ) -> bool {
188 match &mut self.fields {
189 InformationObjectFields::DefaultSyntax(d) => d
190 .iter_mut()
191 .any(|field| field.link_object_set_reference(tlds)),
192 InformationObjectFields::CustomSyntax(c) => c
193 .iter_mut()
194 .any(|field| field.link_object_set_reference(tlds)),
195 }
196 }
197
198 pub fn references_object_set_by_name(&self) -> bool {
199 match &self.fields {
200 InformationObjectFields::DefaultSyntax(d) => {
201 d.iter().any(|field| field.references_object_set_by_name())
202 }
203 InformationObjectFields::CustomSyntax(c) => {
204 c.iter().any(|field| field.references_object_set_by_name())
205 }
206 }
207 }
208}
209
210impl ObjectSetValue {
211 pub fn link_object_set_reference(
212 &mut self,
213 tlds: &BTreeMap<String, ToplevelDefinition>,
214 ) -> Option<Vec<ObjectSetValue>> {
215 match self {
216 ObjectSetValue::Reference(id) => match tlds.get(id) {
217 Some(ToplevelDefinition::Object(ToplevelInformationDefinition {
218 value: ASN1Information::Object(obj),
219 ..
220 })) => {
221 *self = ObjectSetValue::Inline(obj.fields.clone());
222 None
223 }
224 Some(ToplevelDefinition::Object(ToplevelInformationDefinition {
225 value: ASN1Information::ObjectSet(obj),
226 ..
227 })) => Some(obj.values.clone()),
228 _ => None,
229 },
230 ObjectSetValue::Inline(InformationObjectFields::CustomSyntax(c)) => {
231 c.iter_mut()
232 .any(|field| field.link_object_set_reference(tlds));
233 None
234 }
235 ObjectSetValue::Inline(InformationObjectFields::DefaultSyntax(d)) => {
236 d.iter_mut()
237 .any(|field| field.link_object_set_reference(tlds));
238 None
239 }
240 }
241 }
242
243 pub fn references_object_set_by_name(&self) -> bool {
244 match self {
245 ObjectSetValue::Reference(_) => true,
246 ObjectSetValue::Inline(InformationObjectFields::CustomSyntax(c)) => {
247 c.iter().any(|field| field.references_object_set_by_name())
248 }
249 ObjectSetValue::Inline(InformationObjectFields::DefaultSyntax(d)) => {
250 d.iter().any(|field| field.references_object_set_by_name())
251 }
252 }
253 }
254}
255
256impl ObjectSet {
257 pub fn link_object_set_reference(
258 &mut self,
259 tlds: &BTreeMap<String, ToplevelDefinition>,
260 ) -> bool {
261 let mut flattened: Vec<_> = self
262 .values
263 .iter_mut()
264 .flat_map(|val| val.link_object_set_reference(tlds).unwrap_or_default())
265 .collect();
266 self.values.append(&mut flattened);
267 true
268 }
269
270 pub fn references_object_set_by_name(&self) -> bool {
271 self.values
272 .iter()
273 .any(|val| val.references_object_set_by_name())
274 }
275
276 pub fn resolve_object_set_references(
277 &mut self,
278 tlds: &BTreeMap<String, ToplevelDefinition>,
279 ) -> Result<(), GrammarError> {
280 let mut flattened_members = Vec::new();
281 let mut needs_recursing = false;
282 'resolving_references: for mut value in std::mem::take(&mut self.values) {
283 if let ObjectSetValue::Reference(id) = value {
284 match tlds.get(&id) {
285 Some(ToplevelDefinition::Object(ToplevelInformationDefinition {
286 value: ASN1Information::ObjectSet(set),
287 ..
288 })) => {
289 set.values
290 .iter()
291 .for_each(|v| flattened_members.push(v.clone()));
292 needs_recursing = true;
293 continue 'resolving_references;
294 }
295 Some(ToplevelDefinition::Object(ToplevelInformationDefinition {
296 value: ASN1Information::Object(obj),
297 ..
298 })) => value = ObjectSetValue::Inline(obj.fields.clone()),
299 _ => {
300 return Err(GrammarError::new(
301 "Failed to resolve reference in object set.",
302 GrammarErrorType::LinkerError,
303 ))
304 }
305 }
306 }
307 flattened_members.push(value)
308 }
309 self.values = flattened_members;
310 if needs_recursing {
311 self.resolve_object_set_references(tlds)
312 } else {
313 Ok(())
314 }
315 }
316}
317
318impl InformationObjectField {
319 pub fn link_object_set_reference(
320 &mut self,
321 tlds: &BTreeMap<String, ToplevelDefinition>,
322 ) -> bool {
323 match self {
324 InformationObjectField::ObjectSetField(ObjectSetField { value, .. }) => {
325 value.link_object_set_reference(tlds)
326 }
327 _ => false,
328 }
329 }
330
331 pub fn references_object_set_by_name(&self) -> bool {
332 match self {
333 InformationObjectField::ObjectSetField(ObjectSetField { value, .. }) => {
334 value.references_object_set_by_name()
335 }
336 _ => false,
337 }
338 }
339}