pipegen/models/
meta.rs

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    // String Literal, Generate as raw or not
88    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    // Base Meta
97    Value { name: String, meta: MetaValue },
98    List { name: String, metas: Vec<Meta> },
99    Path { name: String },
100    // Extended Meta
101    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}