serde_filter/
matches.rs

1/// A Matchable type is a type that can be matched against a JSON value
2pub trait Matchable
3where
4    Self: std::fmt::Debug
5        + serde::Serialize
6        + serde::de::DeserializeOwned
7        + Clone
8        + std::fmt::Debug
9        + PartialEq,
10{
11    fn from_json(json: serde_json::Value) -> Option<Self>;
12}
13
14/// The Match filter
15#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, PartialEq)]
16pub struct Match<M> {
17    key: String,
18    values: Option<Vec<M>>,
19}
20
21impl<M> Match<M>
22where
23    M: Matchable,
24{
25    pub fn new(key: &str) -> Self {
26        Self {
27            key: key.to_owned(),
28            values: None,
29        }
30    }
31}
32
33impl<M> crate::filter::Filter for Match<M>
34where
35    M: Matchable,
36{
37    type Output = Vec<M>;
38    fn filter(&self, json: serde_json::Value) -> Result<Self::Output, anyhow::Error> {
39        let key = self.key.clone();
40        let mut result = Vec::new();
41        let mut stack = Vec::new();
42        stack.push(json);
43        while let Some(value) = stack.pop() {
44            match value {
45                serde_json::Value::Object(map) => {
46                    for (k, v) in map {
47                        if k == key {
48                            if !v.is_null() {
49                                result.push(M::from_json(v).unwrap());
50                            }
51                        } else {
52                            stack.push(v);
53                        }
54                    }
55                }
56                serde_json::Value::Array(array) => {
57                    for v in array {
58                        stack.push(v);
59                    }
60                }
61                _ => {}
62            }
63        }
64
65        Ok(result)
66    }
67}
68
69impl Matchable for String {
70    fn from_json(json: serde_json::Value) -> Option<Self> {
71        json.as_str().map(|s| s.to_owned())
72    }
73}
74
75impl Matchable for i64 {
76    fn from_json(json: serde_json::Value) -> Option<Self> {
77        json.as_i64()
78    }
79}
80
81impl Matchable for i32 {
82    fn from_json(json: serde_json::Value) -> Option<Self> {
83        json.as_i64().map(|i| i as i32)
84    }
85}
86
87impl Matchable for i16 {
88    fn from_json(json: serde_json::Value) -> Option<Self> {
89        json.as_i64().map(|i| i as i16)
90    }
91}
92
93impl Matchable for u64 {
94    fn from_json(json: serde_json::Value) -> Option<Self> {
95        json.as_u64()
96    }
97}
98
99impl Matchable for u32 {
100    fn from_json(json: serde_json::Value) -> Option<Self> {
101        json.as_u64().map(|u| u as u32)
102    }
103}
104
105impl Matchable for u16 {
106    fn from_json(json: serde_json::Value) -> Option<Self> {
107        json.as_u64().map(|u| u as u16)
108    }
109}
110
111impl Matchable for f64 {
112    fn from_json(json: serde_json::Value) -> Option<Self> {
113        json.as_f64()
114    }
115}
116
117impl Matchable for f32 {
118    fn from_json(json: serde_json::Value) -> Option<Self> {
119        json.as_f64().map(|f| f as f32)
120    }
121}
122
123impl Matchable for bool {
124    fn from_json(json: serde_json::Value) -> Option<Self> {
125        json.as_bool()
126    }
127}
128
129impl Matchable for (String, String) {
130    fn from_json(json: serde_json::Value) -> Option<Self> {
131        if let serde_json::Value::Object(map) = json {
132            if let (Some(k), Some(v)) = (map.get("key"), map.get("value")) {
133                if let (Some(k), Some(v)) = (k.as_str(), v.as_str()) {
134                    return Some((k.to_owned(), v.to_owned()));
135                }
136            }
137        }
138        None
139    }
140}