1use crate::models::utils::indent_literal;
2use serde::Deserialize;
3
4use super::{data_ty_to_literal, DataType};
5
6#[derive(Clone, Debug, Deserialize)]
7pub struct ProjectMeta {
8 input: Option<DataType>,
9 from: Option<String>,
10 expr: Option<String>,
11 alias: Option<String>,
12}
13
14#[derive(Clone, Debug, Deserialize)]
15pub struct ConvertMeta {
16 input: Option<DataType>,
17 from: Option<String>,
18}
19
20#[derive(Clone, Debug, Deserialize)]
21pub struct FilterMeta {
22 predicate: String,
23 alias: Option<String>,
24}
25
26#[derive(Clone, Debug, Deserialize)]
27pub struct IntoAttributesMeta {
28 alias: String,
29}
30
31#[derive(Clone, Debug, Deserialize)]
32pub enum DeriveMeta {
33 Clone,
34 Convert,
35 Debug,
36 Display,
37 Serialize,
38 Deserialize,
39 Eq,
40 Equal,
41 PartialEq,
42 Project,
43 Filter,
44 FieldAccept,
45 HashedBy,
46 OrderedBy,
47 AggregateAs,
48 GroupAs,
49 LeftRight,
50 Render,
51 IntoAttributes,
52}
53
54#[derive(Clone, Debug, Deserialize)]
55pub enum Tag {
56 Hash,
57 Group,
58 Order,
59 Visit,
60 Equal,
61 Left,
62 Right,
63}
64
65#[derive(Clone, Debug, Deserialize)]
66pub enum AggregateMeta {
67 Top,
68 Sum,
69 Count32(Option<String>),
70 Avgf32(Option<String>),
71}
72
73#[derive(Clone, Debug, Deserialize)]
74pub struct RenderMeta {
75 template: Option<String>,
76 pos: Option<i32>,
77}
78
79#[derive(Clone, Debug, Deserialize)]
80pub struct SerdeMeta {
81 with: String,
82}
83
84#[derive(Clone, Debug, Deserialize)]
85#[serde(untagged)]
86pub enum MetaValue {
87 Str { value: String, raw: bool },
89 Int { value: i32 },
90 Usize { value: usize },
91}
92
93#[derive(Clone, Debug, Deserialize)]
94#[serde(untagged)]
95pub enum Meta {
96 Value { name: String, meta: MetaValue },
98 List { name: String, metas: Vec<Meta> },
99 Path { name: String },
100 Derive { derives: Vec<DeriveMeta> },
102 Project { project: ProjectMeta },
103 Filter { filter: FilterMeta },
104 Aggregate { agg: AggregateMeta },
105 Tag { tag: Tag },
106 Render { render: RenderMeta },
107 Convert { convert: ConvertMeta },
108 IntoAttributes { attribute: IntoAttributesMeta },
109 Serde { serde: SerdeMeta },
110}
111
112pub(crate) fn meta_value_str(name: &str, value: &str, raw: bool) -> Meta {
113 Meta::Value {
114 name: name.to_owned(),
115 meta: MetaValue::Str {
116 value: value.to_owned(),
117 raw,
118 },
119 }
120}
121
122fn meta_value_int(name: &str, value: &i32) -> Meta {
123 Meta::Value {
124 name: name.to_owned(),
125 meta: MetaValue::Int {
126 value: value.to_owned(),
127 },
128 }
129}
130
131pub(crate) fn meta_value_usize(name: &str, value: &usize) -> Meta {
132 Meta::Value {
133 name: name.to_owned(),
134 meta: MetaValue::Usize {
135 value: value.to_owned(),
136 },
137 }
138}
139
140fn new_path(name: String) -> Meta {
141 Meta::Path { name }
142}
143
144fn expand_derive(derive: &DeriveMeta) -> Meta {
145 let name = match derive {
146 DeriveMeta::Convert => "Convert",
147 DeriveMeta::Clone => "Clone",
148 DeriveMeta::Debug => "Debug",
149 DeriveMeta::Display => "Display",
150 DeriveMeta::Serialize => "Serialize",
151 DeriveMeta::Deserialize => "Deserialize",
152 DeriveMeta::Eq => "Eq",
153 DeriveMeta::Equal => "Equal",
154 DeriveMeta::PartialEq => "PartialEq",
155 DeriveMeta::Project => "Project",
156 DeriveMeta::Filter => "Filter",
157 DeriveMeta::FieldAccept => "FieldAccept",
158 DeriveMeta::HashedBy => "HashedBy",
159 DeriveMeta::OrderedBy => "OrderedBy",
160 DeriveMeta::AggregateAs => "AggregateAs",
161 DeriveMeta::GroupAs => "GroupAs",
162 DeriveMeta::LeftRight => "LeftRight",
163 DeriveMeta::Render => "Render",
164 DeriveMeta::IntoAttributes => "IntoAttributes",
165 };
166 new_path(name.to_owned())
167}
168
169fn expand_derives(derives: &[DeriveMeta]) -> Meta {
170 let metas: Vec<Meta> = derives.iter().map(expand_derive).collect();
171 Meta::List {
172 name: "derive".to_owned(),
173 metas,
174 }
175}
176
177fn expand_project_meta(meta: &ProjectMeta) -> Meta {
178 let mut metas: Vec<Meta> = Vec::new();
179 if let Some(ref input) = meta.input {
180 metas.push(meta_value_str("input", &data_ty_to_literal(input), false))
181 }
182 if let Some(ref from) = meta.from {
183 metas.push(meta_value_str("from", from, false))
184 }
185 if let Some(ref expr) = meta.expr {
186 metas.push(meta_value_str("expr", expr, true))
187 }
188 if let Some(ref alias) = meta.alias {
189 metas.push(meta_value_str("alias", alias, false))
190 };
191 Meta::List {
192 name: "project".to_owned(),
193 metas,
194 }
195}
196
197fn expand_convert_meta(meta: &ConvertMeta) -> Meta {
198 let mut metas: Vec<Meta> = Vec::new();
199 if let Some(ref input) = meta.input {
200 metas.push(meta_value_str("input", &data_ty_to_literal(input), false))
201 }
202 if let Some(ref from) = meta.from {
203 metas.push(meta_value_str("from", from, false))
204 }
205 Meta::List {
206 name: "convert".to_owned(),
207 metas,
208 }
209}
210
211fn expand_filter_meta(meta: &FilterMeta) -> Meta {
212 let mut metas: Vec<Meta> = vec![meta_value_str("predicate", &meta.predicate, true)];
213 if let Some(ref alias) = meta.alias {
214 metas.push(meta_value_str("alias", alias, false))
215 }
216 Meta::List {
217 name: "filter".to_owned(),
218 metas,
219 }
220}
221
222fn expand_into_attributes_meta(meta: &IntoAttributesMeta) -> Meta {
223 let metas = vec![meta_value_str("alias", &meta.alias, false)];
224 Meta::List {
225 name: "attribute".to_owned(),
226 metas,
227 }
228}
229
230fn expand_tag(tag: &Tag) -> Meta {
231 match tag {
232 Tag::Hash => new_path("hash".to_owned()),
233 Tag::Group => new_path("group".to_owned()),
234 Tag::Order => new_path("order".to_owned()),
235 Tag::Visit => new_path("visit".to_owned()),
236 Tag::Equal => new_path("equal".to_owned()),
237 Tag::Left => new_path("left".to_owned()),
238 Tag::Right => new_path("right".to_owned()),
239 }
240}
241
242fn expand_avgf32(avgf32_ty: Option<String>) -> Meta {
243 match avgf32_ty {
244 Some(ty) => meta_value_str("avgf32", &ty, false),
245 None => new_path("avgf32".to_owned()),
246 }
247}
248
249fn expand_count32(count32_ty: Option<String>) -> Meta {
250 match count32_ty {
251 Some(ty) => meta_value_str("count32", &ty, false),
252 None => new_path("count32".to_owned()),
253 }
254}
255
256fn expand_sum() -> Meta {
257 new_path("sum".to_owned())
258}
259
260fn expand_top() -> Meta {
261 new_path("top".to_owned())
262}
263
264fn expand_aggregate(agg: &AggregateMeta) -> Meta {
265 let meta = match agg {
266 AggregateMeta::Sum => expand_sum(),
267 AggregateMeta::Top => expand_top(),
268 AggregateMeta::Count32(ty) => expand_count32(ty.to_owned()),
269 AggregateMeta::Avgf32(ty) => expand_avgf32(ty.to_owned()),
270 };
271 Meta::List {
272 name: "agg".to_owned(),
273 metas: vec![meta],
274 }
275}
276
277fn expand_render(render: &RenderMeta) -> Meta {
278 let mut metas: Vec<Meta> = Vec::new();
279 if let Some(ref template) = render.template {
280 metas.push(meta_value_str("template", template, true))
281 }
282 if let Some(ref pos) = render.pos {
283 metas.push(meta_value_int("pos", pos))
284 }
285 Meta::List {
286 name: "render".to_owned(),
287 metas,
288 }
289}
290
291fn expand_serde(serde: &SerdeMeta) -> Meta {
292 let metas: Vec<Meta> = vec![meta_value_str("with", &serde.with, false)];
293 Meta::List {
294 name: "serde".to_owned(),
295 metas,
296 }
297}
298
299fn meta_path_to_lit(name: &str, indent: usize, compact: bool) -> String {
300 let lit = name.to_owned();
301 if compact {
302 return lit;
303 }
304 format!("{}{}", indent_literal(indent), lit)
305}
306
307fn meta_str_value_to_lit(
308 name: &str,
309 value: &str,
310 raw: &bool,
311 indent: usize,
312 compact: bool,
313) -> String {
314 let lit = match raw {
315 true => format!(r##"{} = r#"{}"#"##, name, value),
316 false => format!(r#"{} = "{}""#, name, value),
317 };
318 if compact {
319 return lit;
320 }
321 format!("{}{}", indent_literal(indent), lit)
322}
323
324fn meta_int_value_to_lit(name: &str, value: &i32, indent: usize, compact: bool) -> String {
325 let lit = format!("{} = {}", name, value);
326 if compact {
327 return lit;
328 }
329 format!("{}{}", indent_literal(indent), lit)
330}
331
332fn meta_usize_value_to_lit(name: &str, value: &usize, indent: usize, compact: bool) -> String {
333 let lit = format!("{} = {}", name, value);
334 if compact {
335 return lit;
336 }
337 format!("{}{}", indent_literal(indent), lit)
338}
339
340fn expand_meta_lit(meta: &Meta, indent: usize, compact: bool) -> String {
341 let (name, metas) = match meta {
342 Meta::Path { name } => return meta_path_to_lit(name, indent, compact),
343 Meta::Value { name, meta } => match meta {
344 MetaValue::Str { value, raw } => {
345 return meta_str_value_to_lit(name, value, raw, indent, compact)
346 }
347 MetaValue::Int { value } => return meta_int_value_to_lit(name, value, indent, compact),
348 MetaValue::Usize { value } => {
349 return meta_usize_value_to_lit(name, value, indent, compact)
350 }
351 },
352 Meta::Derive { derives } => {
353 let meta = expand_derives(derives);
354 return expand_meta_lit(&meta, indent, compact);
355 }
356 Meta::Project { project } => {
357 let meta = expand_project_meta(project);
358 return expand_meta_lit(&meta, indent, compact);
359 }
360 Meta::Filter { filter } => {
361 let meta = expand_filter_meta(filter);
362 return expand_meta_lit(&meta, indent, compact);
363 }
364 Meta::Aggregate { agg } => {
365 let meta = expand_aggregate(agg);
366 return expand_meta_lit(&meta, indent, compact);
367 }
368 Meta::Tag { tag } => {
369 let meta = expand_tag(tag);
370 return expand_meta_lit(&meta, indent, compact);
371 }
372 Meta::Render { render } => {
373 let meta = expand_render(render);
374 return expand_meta_lit(&meta, indent, compact);
375 }
376 Meta::Convert { convert } => {
377 let meta = expand_convert_meta(convert);
378 return expand_meta_lit(&meta, indent, compact);
379 }
380 Meta::IntoAttributes { attribute } => {
381 let meta = expand_into_attributes_meta(attribute);
382 return expand_meta_lit(&meta, indent, compact);
383 }
384 Meta::Serde { serde } => {
385 let meta = expand_serde(serde);
386 return expand_meta_lit(&meta, indent, compact);
387 }
388 Meta::List { name, metas } => (name, metas),
389 };
390 let nested_metas_lits: Vec<String> = metas
391 .iter()
392 .map(|meta| expand_meta_lit(meta, indent + 1, compact))
393 .collect();
394 let nested_metas_lit = join_meta_lits(nested_metas_lits, compact);
395 let left = get_left_parenthesis(compact);
396 let right = get_right_parenthesis(compact, indent);
397 let lit = format!("{}{}{}{}", name, left, nested_metas_lit, right);
398 match compact {
399 true => lit,
400 false => format!("{}{}", indent_literal(indent), lit),
401 }
402}
403
404pub(crate) fn meta_to_literal(meta: &Meta, indent: usize) -> String {
405 let indent_lit = indent_literal(indent);
406 let meta_lit = expand_meta_lit(meta, indent + 1, false);
407 format!("{}#[\n{}\n{}]", indent_lit, meta_lit, indent_lit)
408}
409
410pub(crate) fn metas_to_literal(metas: &[Meta], indent: usize) -> String {
411 let metas_literal: Vec<String> = metas
412 .iter()
413 .map(|meta| meta_to_literal(meta, indent))
414 .collect();
415 metas_literal.join("\n")
416}
417
418pub(crate) fn meta_to_display(meta: &Meta) -> String {
419 expand_meta_lit(meta, 0, true)
420}
421
422pub(crate) fn metas_to_display(metas: &[Meta]) -> String {
423 let metas_display: Vec<String> = metas.iter().map(meta_to_display).collect();
424 metas_display.join(" ")
425}
426
427fn get_left_parenthesis(compact: bool) -> String {
428 match compact {
429 true => "(".to_owned(),
430 false => "(\n".to_owned(),
431 }
432}
433
434fn get_right_parenthesis(compact: bool, indent: usize) -> String {
435 match compact {
436 true => ")".to_owned(),
437 false => {
438 let indent_lit = indent_literal(indent);
439 format!("\n{})", indent_lit)
440 }
441 }
442}
443
444fn join_meta_lits(meta_lits: Vec<String>, compact: bool) -> String {
445 match compact {
446 true => meta_lits.join(","),
447 false => meta_lits.join(",\n"),
448 }
449}