1pub 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#[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}