sheeter_engine/
transform.rs1use crate::filter::Filter;
2use crate::CanonicalValue;
3
4#[derive(Debug, Clone, Default)]
9pub struct Transforms {
10 pub filter: Option<Filter>,
11 pub select: Option<Vec<String>>,
12 pub rename: Vec<(String, String)>,
13 pub limit: Option<usize>,
14}
15
16impl Transforms {
17 pub fn is_empty(&self) -> bool {
18 self.filter.is_none()
19 && self.select.is_none()
20 && self.rename.is_empty()
21 && self.limit.is_none()
22 }
23
24 pub fn apply_to_row(
27 &self,
28 mut row: Vec<(String, CanonicalValue)>,
29 ) -> Option<Vec<(String, CanonicalValue)>> {
30 if let Some(f) = &self.filter {
31 let wrapped = CanonicalValue::Object(row.clone());
32 if !f.matches(&wrapped) {
33 return None;
34 }
35 }
36 for (from, to) in &self.rename {
37 for (k, _) in row.iter_mut() {
38 if k == from {
39 *k = to.clone();
40 break;
41 }
42 }
43 }
44 if let Some(sel) = &self.select {
45 let mut new_row = Vec::with_capacity(sel.len());
46 for name in sel {
47 match row.iter().find(|(k, _)| k == name) {
48 Some((k, v)) => new_row.push((k.clone(), v.clone())),
49 None => new_row.push((name.clone(), CanonicalValue::Null)),
50 }
51 }
52 row = new_row;
53 }
54 Some(row)
55 }
56
57 pub fn apply_to_array(&self, value: &CanonicalValue) -> CanonicalValue {
59 let rows = match value {
60 CanonicalValue::Array(a) => a,
61 _ => return value.clone(),
62 };
63 let limit = self.limit.unwrap_or(usize::MAX);
64 let mut out = Vec::new();
65 for row in rows {
66 if out.len() >= limit {
67 break;
68 }
69 match row {
70 CanonicalValue::Object(o) => {
71 if let Some(new_row) = self.apply_to_row(o.clone()) {
72 out.push(CanonicalValue::Object(new_row));
73 }
74 }
75 other => out.push(other.clone()),
76 }
77 }
78 CanonicalValue::Array(out)
79 }
80}