jsonstat/
lib.rs

1use std::{collections::BTreeMap, fmt::Display};
2
3use serde::Serialize;
4use serde_json::{json, Map, Value};
5
6#[derive(Serialize, Clone)]
7struct MaxMinCount<T> {
8    count: usize,
9    max: T,
10    min: T,
11}
12impl<T: PartialOrd + Default + Clone> MaxMinCount<T> {
13    fn new() -> Self {
14        Self {
15            count: 0,
16            max: T::default(),
17            min: T::default(),
18        }
19    }
20    fn add(&mut self, new_value: &T) {
21        if self.count == 0 {
22            self.max = new_value.clone();
23            self.min = new_value.clone();
24        } else {
25            if new_value > &self.max {
26                self.max = new_value.clone();
27            }
28            if new_value < &self.min {
29                self.min = new_value.clone();
30            }
31        }
32        self.count += 1;
33    }
34    fn merge(&mut self, other: &Self) {
35        if self.count == 0 {
36            self.max = other.max.clone();
37            self.min = other.min.clone();
38        } else {
39            if other.max > self.max {
40                self.max = other.max.clone();
41            }
42            if other.min < self.min {
43                self.min = other.min.clone();
44            }
45        }
46        self.count += other.count;
47    }
48}
49
50#[derive(Serialize, Clone)]
51struct Count {
52    count: usize,
53}
54impl Count {
55    fn new() -> Self {
56        Self { count: 0 }
57    }
58
59    fn add(&mut self) {
60        self.count += 1;
61    }
62    fn merge(&mut self, other: &Self) {
63        self.count += other.count;
64    }
65}
66
67#[derive(Serialize, Clone)]
68struct JsonStatItem {
69    string: MaxMinCount<usize>,
70    int: MaxMinCount<i64>,
71    float: MaxMinCount<f64>,
72    bool: Count,
73    null: Count,
74    object: Count,
75    array: MaxMinCount<usize>,
76}
77impl JsonStatItem {
78    fn new() -> Self {
79        JsonStatItem {
80            string: MaxMinCount::new(),
81            int: MaxMinCount::new(),
82            float: MaxMinCount::new(),
83            bool: Count::new(),
84            null: Count::new(),
85            object: Count::new(),
86            array: MaxMinCount::new(),
87        }
88    }
89    fn merge(&mut self, other: &Self) {
90        self.string.merge(&other.string);
91        self.int.merge(&other.int);
92        self.float.merge(&other.float);
93        self.bool.merge(&other.bool);
94        self.null.merge(&other.null);
95        self.object.merge(&other.object);
96        self.array.merge(&other.array);
97    }
98    fn stat(&mut self, key: &str, data: &Value) -> Vec<(String, Value)> {
99        let mut ret = Vec::new();
100        match data {
101            Value::String(s) => {
102                self.string.add(&s.len());
103            }
104            Value::Number(n) => {
105                if let Some(num) = n.as_i64() {
106                    self.int.add(&num);
107                } else if let Some(num) = n.as_f64() {
108                    self.float.add(&num);
109                }
110            }
111            Value::Null => {
112                self.null.add();
113            }
114            Value::Bool(_) => {
115                self.bool.add();
116            }
117            Value::Array(arr) => {
118                self.array.add(&arr.len());
119                let k = format!("{}[]", key);
120                for item in arr {
121                    ret.push((k.clone(), item.clone()));
122                }
123            }
124            Value::Object(obj) => {
125                self.object.add();
126                for (k, v) in obj {
127                    ret.push((format!("{}.{}", key, k), v.clone()));
128                }
129            }
130        }
131        ret
132    }
133    fn to_json_value(&self) -> Value {
134        let mut ret = Map::new();
135        if self.null.count > 0 {
136            ret.insert("null".to_string(), json!({"count": self.null.count}));
137        }
138        if self.bool.count > 0 {
139            ret.insert("bool".to_string(), json!({"count": self.bool.count}));
140        }
141        if self.int.count > 0 {
142            ret.insert(
143                "int".to_string(),
144                json!({
145                    "count": self.int.count,
146                    "min": self.int.min,
147                    "max": self.int.max,
148                }),
149            );
150        }
151        if self.float.count > 0 {
152            ret.insert(
153                "float".to_string(),
154                json!({
155                    "count": self.float.count,
156                    "min": self.float.min,
157                    "max": self.float.max,
158                }),
159            );
160        }
161        if self.string.count > 0 {
162            ret.insert(
163                "string".to_string(),
164                json!({
165                    "count": self.string.count,
166                    "min": self.string.min,
167                    "max": self.string.max,
168                }),
169            );
170        }
171        if self.array.count > 0 {
172            ret.insert(
173                "array".to_string(),
174                json!({
175                    "count": self.array.count,
176                    "min": self.array.min,
177                    "max": self.array.max,
178                }),
179            );
180        }
181        if self.object.count > 0 {
182            ret.insert("object".to_string(), json!({"count": self.object.count}));
183        }
184        Value::Object(ret)
185    }
186}
187
188impl Display for JsonStatItem {
189    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190        if self.null.count > 0 {
191            write!(f, "null:{};", self.null.count)?;
192        }
193        if self.bool.count > 0 {
194            write!(f, "bool:{};", self.bool.count)?;
195        }
196        if self.int.count > 0 {
197            write!(
198                f,
199                "int:{}({}~{});",
200                self.int.count, self.int.min, self.int.max
201            )?;
202        }
203        if self.float.count > 0 {
204            write!(
205                f,
206                "float:{}({}~{});",
207                self.float.count, self.float.min, self.float.max
208            )?;
209        }
210        if self.string.count > 0 {
211            write!(
212                f,
213                "string:{}({}~{});",
214                self.string.count, self.string.min, self.string.max
215            )?;
216        }
217        if self.array.count > 0 {
218            write!(
219                f,
220                "array:{}({}~{});",
221                self.array.count, self.array.min, self.array.max
222            )?;
223        }
224        if self.object.count > 0 {
225            write!(f, "object:{}", self.object.count)?;
226        }
227        Ok(())
228    }
229}
230pub struct JsonStat {
231    items: BTreeMap<String, JsonStatItem>,
232    group_key: Option<String>,
233}
234impl JsonStat {
235    pub fn new() -> Self {
236        JsonStat {
237            items: BTreeMap::new(),
238            group_key: None,
239        }
240    }
241    pub fn new_by_group(group_key: &str) -> Self {
242        JsonStat {
243            items: BTreeMap::new(),
244            group_key: Some(group_key.to_string()),
245        }
246    }
247    pub fn stat_str(&mut self, line: &str) -> bool {
248        if let Ok(value) = serde_json::from_str(line) {
249            self.stat_value(&value)
250        } else {
251            false
252        }
253    }
254    fn get_group_key(&self, value: &Value) -> String {
255        if let Some(key) = &self.group_key {
256            let mut val = value;
257            for k in key.split('.') {
258                val = match val.as_object() {
259                    Some(v) => match v.get(k) {
260                        Some(_v) => _v,
261                        None => {
262                            return "".to_string();
263                        }
264                    },
265                    None => {
266                        return "".to_string();
267                    }
268                }
269            }
270            if let Some(r) = val.as_str() {
271                r.to_string()
272            } else {
273                "".to_string()
274            }
275        } else {
276            "".to_string()
277        }
278    }
279    pub fn stat_value(&mut self, value: &Value) -> bool {
280        let mut todo_list = Vec::new();
281        todo_list.push((self.get_group_key(value), value.clone()));
282        while let Some((k, v)) = todo_list.pop() {
283            let (item, list) = self.stat_key_value(&k, &v);
284            if !list.is_empty() {
285                todo_list.extend(list);
286            }
287            if let Some(v) = self.items.get_mut(&k) {
288                v.merge(&item);
289            } else {
290                self.items.insert(k, item);
291            }
292        }
293        true
294    }
295    fn stat_key_value(&self, key: &str, value: &Value) -> (JsonStatItem, Vec<(String, Value)>) {
296        let mut item = JsonStatItem::new();
297        let ret = item.stat(key, value);
298        (item, ret)
299    }
300    pub fn merge(&mut self, other: &Self) {
301        for (k, v) in other.items.iter() {
302            if let Some(v1) = self.items.get_mut(k) {
303                v1.merge(v);
304            } else {
305                self.items.insert(k.clone(), v.clone());
306            }
307        }
308    }
309    pub fn to_json_str(&self, full: bool) -> String {
310        if full {
311            serde_json::to_string(&self.items).unwrap()
312        } else {
313            let mut map = Map::new();
314            for (k, v) in self.items.iter() {
315                map.insert(k.clone(), v.to_json_value());
316            }
317            Value::Object(map).to_string()
318        }
319    }
320}
321impl Display for JsonStat {
322    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
323        for (k, v) in self.items.iter() {
324            writeln!(f, "{} : {}", if k.is_empty() { "." } else { k }, v)?;
325        }
326        Ok(())
327    }
328}
329impl Default for JsonStat {
330    fn default() -> Self {
331        Self::new()
332    }
333}