streamson_lib/handler/
analyser.rs1use std::{any::Any, collections::HashMap, str::FromStr};
4
5use super::Handler;
6use crate::{
7 error,
8 path::{Element, Path},
9 streamer::Token,
10};
11
12#[derive(Debug, Default)]
13pub struct Analyser {
14 paths: HashMap<String, usize>,
16}
17
18fn to_recuded_array_str(path: &Path) -> String {
21 path.get_path()
22 .iter()
23 .map(|e| match e {
24 Element::Key(key) => format!(r#"{{"{}"}}"#, key),
25 Element::Index(_) => "[]".to_string(),
26 })
27 .collect()
28}
29
30impl Handler for Analyser {
31 fn start(
32 &mut self,
33 path: &Path,
34 _matcher_idx: usize,
35 _token: Token,
36 ) -> Result<Option<Vec<u8>>, error::Handler> {
37 *self.paths.entry(to_recuded_array_str(path)).or_insert(0) += 1;
38 Ok(None)
39 }
40
41 fn as_any(&self) -> &dyn Any {
42 self
43 }
44}
45
46impl FromStr for Analyser {
47 type Err = error::Handler;
48 fn from_str(input: &str) -> Result<Self, Self::Err> {
49 if input.is_empty() {
50 Ok(Self::new())
51 } else {
52 Err(error::Handler::new("Analyser handler accepts no argument"))
53 }
54 }
55}
56
57impl Analyser {
58 pub fn new() -> Self {
61 Self::default()
62 }
63
64 pub fn results(&self) -> Vec<(String, usize)> {
66 let mut res: Vec<(String, usize)> = self
67 .paths
68 .iter()
69 .map(|(path, count)| (path.to_string(), *count))
70 .collect();
71 res.sort_by(|(a_path, _), (b_path, _)| a_path.cmp(b_path));
72 res
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::Analyser;
79 use crate::strategy::{All, Strategy};
80 use std::sync::{Arc, Mutex};
81
82 #[test]
83 fn analyser_handler() {
84 let mut all = All::new();
85
86 let analyser_handler = Arc::new(Mutex::new(Analyser::new()));
87
88 all.add_handler(analyser_handler.clone());
89
90 all.process(br#"{"elements": [1, 2, 3, [41, 42, {"sub1": {"subsub": 1}, "sub2": null}]], "after": true, "last": [{"aaa": 1, "cc": "dd"}, {"aaa": 2, "extra": false}]}"#).unwrap();
91
92 let results = analyser_handler.lock().unwrap().results();
94 assert_eq!(results.len(), 13);
95 assert_eq!(results[0], ("".to_string(), 1));
96 assert_eq!(results[1], (r#"{"after"}"#.to_string(), 1));
97 assert_eq!(results[2], (r#"{"elements"}"#.to_string(), 1));
98 assert_eq!(results[3], (r#"{"elements"}[]"#.to_string(), 4));
99 assert_eq!(results[4], (r#"{"elements"}[][]"#.to_string(), 3));
100 assert_eq!(results[5], (r#"{"elements"}[][]{"sub1"}"#.to_string(), 1));
101 assert_eq!(
102 results[6],
103 (r#"{"elements"}[][]{"sub1"}{"subsub"}"#.to_string(), 1)
104 );
105 assert_eq!(results[7], (r#"{"elements"}[][]{"sub2"}"#.to_string(), 1));
106 assert_eq!(results[8], (r#"{"last"}"#.to_string(), 1));
107 assert_eq!(results[9], (r#"{"last"}[]"#.to_string(), 2));
108 assert_eq!(results[10], (r#"{"last"}[]{"aaa"}"#.to_string(), 2));
109 assert_eq!(results[11], (r#"{"last"}[]{"cc"}"#.to_string(), 1));
110 assert_eq!(results[12], (r#"{"last"}[]{"extra"}"#.to_string(), 1));
111 }
112}