1use super::*;
2
3pub struct ArrayField {
4 very_inner: String,
5 depth: usize,
6}
7
8impl ArrayField {
9 pub fn depth_from_ty(ty: &JsonType, begin: usize) -> usize {
10 let depth = begin;
11 match ty {
12 JsonType::Array(a) => Self::depth_from_ty(a, depth + 1),
13 _ => depth,
14 }
15 }
16}
17
18enum FieldType {
19 Primitive,
20 Struct,
21 Array(ArrayField),
22}
23
24struct StructItem {
25 acc: String,
26 name: String,
27 fields: Vec<(String, FieldType)>,
28}
29
30#[derive(Default)]
31pub struct DartAccumulator {
32 struct_stack: Vec<StructItem>,
33 done_list: Vec<String>,
34}
35
36impl DartAccumulator {
37 pub fn begin() -> Self {
38 DartAccumulator::default()
39 }
40
41 fn get_current(&mut self) -> &mut StructItem {
42 self.struct_stack.last_mut().unwrap()
43 }
44
45 fn is_builtin_type(s: &str) -> bool {
46 matches!(s, "dynamic" | "bool" | "String" | "double" | "int")
47 }
48
49 fn get_type(&mut self, ty: JsonType) -> String {
50 match ty {
51 JsonType::Null => String::from("dynamic"),
52 JsonType::Number(n) => String::from(self.get_number(n)),
53 JsonType::Boolean => String::from("bool"),
54 JsonType::String => String::from("String"),
55 JsonType::Object(ty) => ty,
56 JsonType::Array(ty) => format!("List<{}>", self.get_type(*ty)),
57 }
58 }
59
60 fn get_without_outer_list(&mut self, ty: JsonType) -> String {
61 match ty {
62 JsonType::Null => String::from("dynamic"),
63 JsonType::Number(n) => String::from(self.get_number(n)),
64 JsonType::Boolean => String::from("bool"),
65 JsonType::String => String::from("String"),
66 JsonType::Object(ty) => ty,
67 JsonType::Array(ty) => self.get_without_outer_list(*ty),
68 }
69 }
70
71 fn get_number(&self, num: Number) -> &'static str {
72 match num {
73 Number::Int => "int",
74 Number::Float => "double",
75 }
76 }
77}
78
79impl TypeAccumulator for DartAccumulator {
80 fn end(&mut self) -> String {
81 let mut end_str = String::new();
82
83 self.done_list.iter().for_each(|done| end_str += done);
84
85 end_str += r#"// import 'dart:convert';
86// var data = jsonDecode("{ ... }");
87// var ty = T.fromJson(data);
88// jsonEncode(ty.toJson());"#;
89
90 end_str
91 }
92
93 fn number(&mut self, key: &str, number: Number) -> Result<(), Error> {
94 let num_ty = self.get_number(number);
95 let acc = self.get_current();
96 acc.acc += &format!("\tfinal {} {};\n", num_ty, key);
97 acc.fields.push((String::from(key), FieldType::Primitive));
98 Ok(())
99 }
100
101 fn boolean(&mut self, key: &str) -> Result<(), Error> {
102 let acc = self.get_current();
103 acc.acc += &format!("\tfinal bool {};\n", key);
104 acc.fields.push((String::from(key), FieldType::Primitive));
105 Ok(())
106 }
107
108 fn string(&mut self, key: &str) -> Result<(), Error> {
109 let acc = self.get_current();
110 acc.acc += &format!("\tfinal String {};\n", key);
111 acc.fields.push((String::from(key), FieldType::Primitive));
112 Ok(())
113 }
114
115 fn unknown(&mut self, key: &str) -> Result<(), Error> {
116 let acc = self.get_current();
117 acc.acc += &format!("\tfinal dynamic {};\n", key);
118 acc.fields.push((String::from(key), FieldType::Primitive));
119 Ok(())
120 }
121
122 fn array(&mut self, key: &str, ty: JsonType) -> Result<(), Error> {
123 let ty_str = self.get_type(ty.clone());
124 let ty_without_outer = self.get_without_outer_list(ty.clone());
125 let acc = self.get_current();
126 let ty_name = format!("List<{}>", ty_str);
127 acc.acc += &format!("\tfinal {} {};\n", ty_name, key);
128 acc.fields.push((
129 String::from(key),
130 FieldType::Array(ArrayField {
131 very_inner: ty_without_outer,
132 depth: ArrayField::depth_from_ty(&ty, 1),
133 }),
134 ));
135 Ok(())
136 }
137
138 fn object(&mut self, key: &str, object_name: &str) -> Result<(), Error> {
139 let acc = self.get_current();
140 acc.acc += &format!("\tfinal {} {};\n", object_name, key);
141 acc.fields.push((String::from(key), FieldType::Struct));
142 Ok(())
143 }
144
145 fn push_object_type(&mut self, object_name: &str) -> Result<(), Error> {
146 self.struct_stack.push(StructItem {
147 acc: String::new(),
148 name: String::from(object_name),
149 fields: vec![],
150 });
151 let acc = self.get_current();
152 acc.acc += &format!("class {} {{\n", object_name);
153 Ok(())
154 }
155
156 fn pop_object_type(&mut self) -> Result<(), Error> {
157 let acc = self.get_current();
158 acc.acc += &format!("\t{}.fromJson(Map<String, dynamic> json):\n", acc.name);
159 acc.fields.iter().for_each(|(field, field_ty)| {
160 acc.acc += &format!(
161 "\t\t{} = {},\n",
162 field,
163 match field_ty {
164 FieldType::Struct | FieldType::Primitive => format!("json['{}']", field),
165 FieldType::Array(s) => {
166 fn list_from_depth(name: &str, depth: usize) -> String {
167 let mut acc = String::from(name);
168 (0..depth + 1).for_each(|_| {
169 acc = format!("List<{}>", acc);
170 });
171 acc
172 }
173 let mut iname = String::from("i");
174 let mut acc = if Self::is_builtin_type(&s.very_inner) {
175 iname.clone()
176 } else {
177 format!("{}.fromJson({})", s.very_inner, iname)
178 };
179 for depth in 0..s.depth {
180 let next_iname = if depth == s.depth - 1 {
181 format!("json['{}']", field)
182 } else {
183 format!("i{}", depth)
184 };
185
186 acc = format!(
187 "{}.from({}.map(({}) => {}))",
188 list_from_depth(&s.very_inner, depth),
189 next_iname,
190 iname,
191 acc
192 );
193 iname = next_iname;
194 }
195 acc
196 }
197 }
198 );
199 });
200 acc.acc.pop();
201 acc.acc.pop();
202 acc.acc += ";\n\n";
203 acc.acc += "\tMap<String, dynamic> toJson() => {";
204 acc.fields.iter().for_each(|(field, field_ty)| {
205 acc.acc += &format!(
206 "\n\t\t'{}': {},",
207 field,
208 &match field_ty {
209 FieldType::Struct => field.to_owned() + ".toJson()",
210 FieldType::Primitive => field.to_owned(),
211 FieldType::Array(s) => {
212 let mut iname = String::from("i");
213 let mut acc = if Self::is_builtin_type(&s.very_inner) {
214 iname.clone()
215 } else {
216 iname.clone() + ".toJson()"
217 };
218 for depth in 0..s.depth {
219 let next_iname = if depth == s.depth - 1 {
220 field.to_owned()
221 } else {
222 format!("i{}", depth)
223 };
224 acc = format!("{}.map(({}) => {}).toList()", next_iname, iname, acc);
225 iname = next_iname;
226 }
227 acc
228 }
229 }
230 );
231 });
232 acc.acc += "\n\t};\n";
233 acc.acc += "}\n\n";
234 let s = self.struct_stack.pop().unwrap();
235 self.done_list.push(s.acc);
236 Ok(())
237 }
238
239 fn prefered_object_name(&self) -> String {
240 String::from("_Type")
241 }
242}