streamson_lib/
lib.rs

1#![crate_name = "streamson_lib"]
2
3//! This library is able to process large JSON data.
4//!
5//! It can have various matchers which matches the path (see [matcher](matcher/index.html))
6//!
7//! And various handlers to do something with found data (see [handlers](handler/index.html))
8//!
9//! # Examples
10//! ```
11//! use streamson_lib::{handler::{self, Handler}, matcher, strategy::{self, Strategy}};
12//! use std::{io, fs, sync::{Arc, Mutex}};
13//!
14//! let stdout_handler = Arc::new(Mutex::new(handler::Output::new(io::stdout())));
15//!
16//! let file = fs::File::create("out.txt").unwrap();
17//! let handler = handler::Group::new()
18//!     .add_handler(Arc::new(Mutex::new(handler::Output::new(file))))
19//!     .add_handler(stdout_handler.clone());
20//!
21//! let first_matcher = matcher::Simple::new(r#"{"users"}[]"#).unwrap();
22//! let second_matcher = matcher::Simple::new(r#"{"groups"}[]"#).unwrap();
23//!
24//! let mut trigger = strategy::Trigger::new();
25//!
26//! // exports users to stdout and out.txt
27//! trigger.add_matcher(
28//!     Box::new(first_matcher),
29//!     Arc::new(Mutex::new(handler.clone())),
30//! );
31//!
32//! // groups are going to be expoted only to stdout
33//! trigger.add_matcher(
34//!     Box::new(second_matcher),
35//!     stdout_handler,
36//! );
37//!
38//! for input in vec![
39//!     br#"{"users": [1,2]"#.to_vec(),
40//!     br#", "groups": [3, 4]}"#.to_vec(),
41//! ] {
42//!     trigger.process(&input).unwrap();
43//! }
44//! ```
45//!
46//! ```
47//! use streamson_lib::{handler::{self, Handler}, matcher, strategy::{Strategy, self}};
48//! use std::{fs, io, sync::{Arc, Mutex}};
49//!
50//! let file = fs::File::create("out.txt").unwrap();
51//! let file_handler = Arc::new(
52//!     Mutex::new(handler::Output::new(file))
53//! );
54//! let stdout_handler = Arc::new(Mutex::new(handler::Output::new(io::stdout())));
55//! let handler = handler::Group::new()
56//!     .add_handler(stdout_handler)
57//!     .add_handler(file_handler);
58//!
59//! let first_matcher = matcher::Depth::new(1, Some(2));
60//! let second_matcher = matcher::Simple::new(r#"{"users"}[]"#).unwrap();
61//! let matcher = matcher::Combinator::new(first_matcher) |
62//!     matcher::Combinator::new(second_matcher);
63//!
64//! let mut trigger = strategy::Trigger::new();
65//!
66//! // Paths with depths 1, 2 are exported to out.txt
67//! trigger.add_matcher(
68//!     Box::new(matcher),
69//!     Arc::new(Mutex::new(handler)),
70//! );
71//!
72//! for input in vec![
73//!     br#"{"users": [1,2]"#.to_vec(),
74//!     br#", "groups": [3, 4]}"#.to_vec(),
75//! ] {
76//!     trigger.process(&input).unwrap();
77//! }
78//! ```
79//!
80//! ```
81//! use streamson_lib::{handler::{self, Handler}, matcher, strategy::{Strategy, self}};
82//! use std::{io, fs, sync::{Arc, Mutex}};
83//!
84//! let file = fs::File::create("out.txt").unwrap();
85//! let file_handler = Arc::new(
86//!     Mutex::new(handler::Output::new(file))
87//! );
88//! let stdout_handler = Arc::new(Mutex::new(handler::Output::new(io::stdout())));
89//! let handler = handler::Group::new()
90//!     .add_handler(stdout_handler)
91//!     .add_handler(file_handler);
92//!
93//! let matcher = matcher::Depth::new(1, Some(2));
94//!
95//! let mut trigger = strategy::Trigger::new();
96//!
97//! // Paths with depths 1, 2 are exported to out.txt
98//! trigger.add_matcher(
99//!     Box::new(matcher),
100//!     Arc::new(Mutex::new(handler)),
101//! );
102//!
103//! for input in vec![
104//!     br#"{"users": [1,2]"#.to_vec(),
105//!     br#", "groups": [3, 4]}"#.to_vec(),
106//! ] {
107//!     trigger.process(&input).unwrap();
108//! }
109//! ```
110
111pub mod error;
112pub mod handler;
113pub mod matcher;
114pub mod path;
115pub mod strategy;
116pub mod streamer;
117
118pub use handler::Handler;
119pub use path::Path;
120pub use streamer::{Streamer, Token};
121
122#[cfg(doctest)]
123mod test_readme {
124    macro_rules! external_doc_test {
125        ($x:expr) => {
126            #[doc = $x]
127            extern "C" {}
128        };
129    }
130    external_doc_test!(include_str!("../README.md"));
131}
132
133#[cfg(test)]
134pub mod test {
135    pub trait Splitter {
136        fn split(&self, input: Vec<u8>) -> Vec<Vec<Vec<u8>>>;
137    }
138
139    pub(crate) struct Single;
140
141    impl Single {
142        pub fn new() -> Self {
143            Self
144        }
145    }
146
147    impl Splitter for Single {
148        fn split(&self, input: Vec<u8>) -> Vec<Vec<Vec<u8>>> {
149            vec![input.iter().map(|e| vec![*e]).collect()]
150        }
151    }
152
153    pub(crate) struct Window {
154        size: usize,
155    }
156
157    impl Window {
158        pub fn new(size: usize) -> Self {
159            Self { size }
160        }
161    }
162
163    impl Splitter for Window {
164        fn split(&self, input: Vec<u8>) -> Vec<Vec<Vec<u8>>> {
165            if input.len() <= self.size {
166                return vec![vec![input]];
167            }
168            let out_count = input.len() - self.size;
169            let mut res = vec![];
170            for i in 0..=out_count {
171                res.push(vec![
172                    input[0..i].to_vec(),
173                    input[i..self.size + i].to_vec(),
174                    input[self.size + i..input.len()].to_vec(),
175                ]);
176            }
177            res
178        }
179    }
180}