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 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}