ftd/
or_type.rs

1#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
2pub struct OrType {
3    pub name: String,
4    pub variants: Vec<ftd::p2::Record>,
5}
6
7impl OrType {
8    pub fn from_p1(p1: &ftd::p1::Section, doc: &ftd::p2::TDoc) -> ftd::p1::Result<Self> {
9        let or_type_name = ftd::p2::utils::get_name("or-type", p1.name.as_str(), doc.name)?;
10        let name = doc.format_name(or_type_name);
11        let mut variants: Vec<ftd::p2::Record> = Default::default();
12        for s in p1.sub_sections.0.iter() {
13            if s.is_commented {
14                continue;
15            }
16            variants.push(ftd::p2::Record::from_p1(
17                format!("record {}.{}", or_type_name, s.name.as_str()).as_str(),
18                &s.header,
19                doc,
20                p1.line_number,
21            )?);
22        }
23        Ok(OrType { name, variants })
24    }
25
26    pub fn create(
27        &self,
28        p1: &ftd::p1::Section,
29        variant: String,
30        doc: &ftd::p2::TDoc,
31    ) -> ftd::p1::Result<ftd::PropertyValue> {
32        // todo: check if the its reference to other variable
33        for v in self.variants.iter() {
34            if v.name
35                == doc.resolve_name(
36                    p1.line_number,
37                    format!("{}.{}", self.name, variant.as_str()).as_str(),
38                )?
39            {
40                return Ok(ftd::PropertyValue::Value {
41                    value: ftd::Value::OrType {
42                        variant,
43                        name: self.name.to_string(),
44                        fields: v.fields(p1, doc)?,
45                    },
46                });
47            }
48        }
49
50        ftd::p2::utils::e2(
51            format!("{} is not a valid variant for {}", variant, self.name),
52            doc.name,
53            p1.line_number,
54        )
55    }
56}
57
58#[cfg(test)]
59mod test {
60    use ftd::test::*;
61
62    #[test]
63    fn basic() {
64        let mut bag = default_bag();
65
66        bag.insert(s("foo/bar#entity"), entity());
67        bag.insert(
68            s("foo/bar#abrar"),
69            ftd::p2::Thing::Variable(ftd::Variable {
70                name: s("abrar"),
71                flags: ftd::VariableFlags::default(),
72                value: ftd::PropertyValue::Value {
73                    value: ftd::Value::OrType {
74                        name: s("foo/bar#entity"),
75                        variant: s("person"),
76                        fields: abrar(),
77                    },
78                },
79                conditions: vec![],
80            }),
81        );
82        bag.insert(
83            "foo/bar#x".to_string(),
84            ftd::p2::Thing::Variable(ftd::Variable {
85                flags: ftd::VariableFlags::default(),
86                name: "x".to_string(),
87                value: ftd::PropertyValue::Value {
88                    value: ftd::Value::Integer { value: 10 },
89                },
90                conditions: vec![],
91            }),
92        );
93
94        p!(
95            "
96            -- integer x: 10
97
98            -- or-type entity:
99
100            --- person:
101            caption name:
102            string address:
103            body bio:
104            integer age:
105
106            --- company:
107            caption name:
108            string industry:
109
110            -- entity.person abrar: Abrar Khan2
111            age: $x
112            address: Bihar2
113
114            Software developer working at fifthtry2.
115            ",
116            (bag, default_column()),
117        );
118    }
119}