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
use std::collections::HashMap;

use crate::common::FilePosition;
use crate::idl;

use super::errors::ValidationError;
use super::fqtn::FQTN;
use super::namespace::Namespace;
use super::r#struct::Field;
use super::r#type::{TypeRef, UserDefinedType};
use super::typemap::TypeMap;

pub struct Fieldset {
    pub fqtn: FQTN,
    pub generics: Vec<String>,
    pub r#struct: TypeRef,
    pub fields: Vec<FieldsetField>,
}

pub struct FieldsetField {
    pub name: String,
    pub optional: bool,
    pub field: Option<Field>,
}

impl Fieldset {
    pub(crate) fn from_idl(ifieldset: &idl::Fieldset, ns: &Namespace) -> Self {
        Self {
            fqtn: FQTN::new(&ifieldset.name, ns),
            generics: ifieldset.generics.clone(),
            r#struct: TypeRef::from_idl(&ifieldset.r#struct, ns),
            fields: ifieldset
                .fields
                .iter()
                .map(|ifield| FieldsetField {
                    name: ifield.name.clone(),
                    optional: ifield.optional,
                    field: None,
                })
                .collect(),
        }
    }
    pub(crate) fn resolve(&mut self, type_map: &TypeMap) -> Result<(), ValidationError> {
        self.r#struct.resolve(type_map)?;
        let struct_ = self.r#struct.type_.upgrade().unwrap();
        if let UserDefinedType::Struct(struct_) = &*struct_.borrow() {
            let field_map = struct_
                .fields
                .iter()
                .map(|f| (f.name.clone(), f))
                .collect::<HashMap<_, _>>();
            for field in self.fields.iter_mut() {
                if let Some(&struct_field) = field_map.get(&field.name) {
                    field.field.replace(struct_field.clone());
                } else {
                    return Err(ValidationError::NoSuchField {
                        position: FilePosition { line: 0, column: 0 },
                        fieldset: self.fqtn.clone(),
                        r#struct: struct_.fqtn.clone(),
                        field: field.name.clone(),
                    });
                }
            }
        } else {
            return Err(ValidationError::FieldsetExtendsNonStruct {
                position: FilePosition { line: 0, column: 0 },
                fieldset: self.fqtn.clone(),
                r#struct: struct_.borrow().fqtn().clone(),
            });
        }
        // FIXME fields need to be resolved, too.
        Ok(())
    }
}