streamson_lib/handler/
indexer.rs

1//! Handler which stores indexes where matched data are kept.
2//! The data should be within <start_idx, end_idx) range
3//!
4//! # Example
5//! ```
6//! use streamson_lib::{handler, matcher, strategy::{self, Strategy}};
7//! use std::sync::{Arc, Mutex};
8//!
9//! let indexer_handler = Arc::new(Mutex::new(handler::Indexer::new().set_use_path(true)));
10//!
11//! let matcher = matcher::Simple::new(r#"{"users"}[]{"name"}"#).unwrap();
12//!
13//! let mut trigger = strategy::Trigger::new();
14//!
15//! // Set the matcher for trigger
16//! trigger.add_matcher(Box::new(matcher), indexer_handler.clone());
17//!
18//! for input in vec![
19//!     br#"{"users": [{"id": 1, "name": "first"}, {"#.to_vec(),
20//!     br#""id": 2, "name": "second}]}"#.to_vec(),
21//! ] {
22//!     trigger.process(&input).unwrap();
23//!     let mut guard = indexer_handler.lock().unwrap();
24//!     while let Some((path, output)) = guard.pop() {
25//!         // Do something with the data
26//!         println!("{} ({:?})", path.unwrap(), output);
27//!     }
28//! }
29//! ```
30
31use super::Handler;
32use crate::{error, path::Path, streamer::Token};
33use std::{
34    any::Any,
35    collections::VecDeque,
36    str::{self, FromStr},
37};
38
39/// Indexer handler responsible for storing index of the matches
40#[derive(Debug)]
41pub struct Indexer {
42    /// Queue with stored indexes
43    stored: VecDeque<(Option<String>, Token)>,
44
45    /// Not to show path will spare some allocation
46    use_path: bool,
47}
48
49impl Default for Indexer {
50    fn default() -> Self {
51        Self {
52            stored: VecDeque::new(),
53            use_path: false,
54        }
55    }
56}
57
58impl FromStr for Indexer {
59    type Err = error::Handler;
60    fn from_str(input: &str) -> Result<Self, Self::Err> {
61        let splitted: Vec<_> = input.split(',').collect();
62        match splitted.len() {
63            0 => Ok(Self::default()),
64            1 => Ok(Self::default()
65                .set_use_path(FromStr::from_str(splitted[0]).map_err(error::Handler::new)?)),
66            _ => Err(error::Handler::new("Failed to parse")),
67        }
68    }
69}
70
71impl Handler for Indexer {
72    fn start(
73        &mut self,
74        path: &Path,
75        _matcher_idx: usize,
76        token: Token,
77    ) -> Result<Option<Vec<u8>>, error::Handler> {
78        self.stored.push_back((
79            if self.use_path {
80                Some(path.to_string())
81            } else {
82                None
83            },
84            token,
85        ));
86        Ok(None)
87    }
88
89    fn end(
90        &mut self,
91        path: &Path,
92        matcher_idx: usize,
93        token: Token,
94    ) -> Result<Option<Vec<u8>>, error::Handler> {
95        self.start(path, matcher_idx, token) // same as start
96    }
97
98    fn as_any(&self) -> &dyn Any {
99        self
100    }
101}
102
103impl Indexer {
104    /// Creates a new handler which stores indexes within itself
105    pub fn new() -> Self {
106        Self::default()
107    }
108    ///
109    /// Set whether to show path
110    ///
111    /// # Arguments
112    /// * `use_path` - should path be store with data
113    ///
114    /// # Example
115    /// ```
116    /// use streamson_lib::handler;
117    /// let file = handler::Indexer::new().set_use_path(true);
118    /// ```
119    pub fn set_use_path(mut self, use_path: bool) -> Self {
120        self.use_path = use_path;
121        self
122    }
123
124    /// Pops the oldest value in the buffer
125    ///
126    /// # Returns
127    /// * `None` - queue is empty
128    /// * `Some((path, output))` - stored data remove from the queue and returned
129    ///
130    /// # Example
131    /// ```
132    /// use streamson_lib::handler;
133    /// let mut indexer = handler::Indexer::new().set_use_path(true);
134    /// while let Some((path, output)) = indexer.pop() {
135    ///     // Do something with the data
136    ///     println!("{} ({:?})", path.unwrap(), output);
137    /// }
138    ///
139    ///
140    /// ```
141    pub fn pop(&mut self) -> Option<(Option<String>, Token)> {
142        self.stored.pop_front()
143    }
144}
145
146#[cfg(test)]
147mod tests {
148    use super::Indexer;
149    use crate::{
150        handler::{Buffer, Group},
151        matcher::Simple,
152        strategy::{Strategy, Trigger},
153        streamer::{ParsedKind, Token},
154    };
155    use std::sync::{Arc, Mutex};
156
157    #[test]
158    fn indexer_handler() {
159        let mut trigger = Trigger::new();
160
161        let indexer_handler = Arc::new(Mutex::new(Indexer::new()));
162        let buffer_handler = Arc::new(Mutex::new(Buffer::default()));
163        let matcher_all = Simple::new(r#"{"elements"}"#).unwrap();
164        let matcher_elements = Simple::new(r#"{"elements"}[]"#).unwrap();
165
166        trigger.add_matcher(Box::new(matcher_all), indexer_handler.clone());
167        trigger.add_matcher(
168            Box::new(matcher_elements),
169            Arc::new(Mutex::new(
170                Group::new()
171                    .add_handler(indexer_handler.clone())
172                    .add_handler(buffer_handler.clone()),
173            )),
174        );
175
176        trigger.process(br#"{"elements": [1, 2, 3, 4]}"#).unwrap();
177
178        // Test indexer handler
179        let mut guard = indexer_handler.lock().unwrap();
180        assert_eq!(
181            guard.pop().unwrap(),
182            (None, Token::Start(13, ParsedKind::Arr))
183        );
184        assert_eq!(
185            guard.pop().unwrap(),
186            (None, Token::Start(14, ParsedKind::Num))
187        );
188        assert_eq!(
189            guard.pop().unwrap(),
190            (None, Token::End(15, ParsedKind::Num))
191        );
192        assert_eq!(
193            guard.pop().unwrap(),
194            (None, Token::Start(17, ParsedKind::Num))
195        );
196        assert_eq!(
197            guard.pop().unwrap(),
198            (None, Token::End(18, ParsedKind::Num))
199        );
200        assert_eq!(
201            guard.pop().unwrap(),
202            (None, Token::Start(20, ParsedKind::Num))
203        );
204        assert_eq!(
205            guard.pop().unwrap(),
206            (None, Token::End(21, ParsedKind::Num))
207        );
208        assert_eq!(
209            guard.pop().unwrap(),
210            (None, Token::Start(23, ParsedKind::Num))
211        );
212        assert_eq!(
213            guard.pop().unwrap(),
214            (None, Token::End(24, ParsedKind::Num))
215        );
216        assert_eq!(
217            guard.pop().unwrap(),
218            (None, Token::End(25, ParsedKind::Arr))
219        );
220
221        // Test whether buffer handler contains the right data
222        let mut guard = buffer_handler.lock().unwrap();
223        assert_eq!(guard.pop().unwrap(), (None, vec![b'1']));
224        assert_eq!(guard.pop().unwrap(), (None, vec![b'2']));
225        assert_eq!(guard.pop().unwrap(), (None, vec![b'3']));
226        assert_eq!(guard.pop().unwrap(), (None, vec![b'4']));
227    }
228}