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