streamson_lib/handler/
shorten.rs1use super::Handler;
29use crate::{error, path::Path, streamer::Token};
30use std::{any::Any, str::FromStr};
31
32#[derive(Debug)]
35pub struct Shorten {
36    max_length: usize,
38
39    used: usize,
41
42    terminator: String,
45}
46
47impl Shorten {
48    pub fn new(max_length: usize, terminator: String) -> Self {
50        Self {
51            max_length,
52            terminator,
53            used: 0,
54        }
55    }
56}
57
58impl FromStr for Shorten {
59    type Err = error::Handler;
60    fn from_str(input: &str) -> Result<Self, Self::Err> {
61        let splitted: Vec<_> = input.split(',').collect();
62        if splitted.len() == 2 {
63            Ok(Self::new(
64                splitted[0].parse().map_err(error::Handler::new)?,
65                splitted[1].to_string(),
66            ))
67        } else {
68            Err(error::Handler::new("Failed to parse"))
69        }
70    }
71}
72
73impl Handler for Shorten {
74    fn start(
75        &mut self,
76        _path: &Path,
77        _matcher_idx: usize,
78        _token: Token,
79    ) -> Result<Option<Vec<u8>>, error::Handler> {
80        self.used = 0;
82
83        Ok(None)
84    }
85
86    fn feed(
87        &mut self,
88        data: &[u8],
89        _matcher_idx: usize,
90    ) -> Result<Option<Vec<u8>>, error::Handler> {
91        if self.used >= self.max_length {
93            return Ok(None);
94        }
95
96        if data.len() <= (self.max_length - self.used) {
98            self.used += data.len();
99            return Ok(Some(data.to_vec()));
100        }
101
102        let result: Vec<u8> = data[..(self.max_length - self.used + 1)]
104            .iter()
105            .cloned()
106            .chain(self.terminator.as_bytes().iter().cloned())
107            .collect();
108
109        self.used = self.max_length;
110
111        Ok(Some(result))
112    }
113
114    fn is_converter(&self) -> bool {
115        true
116    }
117
118    fn as_any(&self) -> &dyn Any {
119        self
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    use super::Shorten;
126    use crate::{
127        matcher::Simple,
128        strategy::{Convert, OutputConverter, Strategy},
129    };
130    use std::sync::{Arc, Mutex};
131
132    #[test]
133    fn shorten_handler() {
134        let mut convert = Convert::new();
135        let shorten_handler = Arc::new(Mutex::new(Shorten::new(10, "..\"".to_string())));
136        let matcher = Simple::new(r#"[]{"description"}"#).unwrap();
137
138        convert.add_matcher(Box::new(matcher), shorten_handler.clone());
139        let output: Vec<u8> = OutputConverter::new()
140            .convert(
141                &convert
142                    .process(
143                        br#"[{"description": "too long description"}, {"description": "short"}]"#,
144                    )
145                    .unwrap(),
146            )
147            .into_iter()
148            .map(|e| e.1)
149            .flatten()
150            .collect();
151
152        assert_eq!(
153            String::from_utf8(output).unwrap(),
154            r#"[{"description": "too long d.."}, {"description": "short"}]"#
155        );
156    }
157
158    #[test]
159    fn shorten_handler_parts() {
160        let mut convert = Convert::new();
161        let shorten_handler = Arc::new(Mutex::new(Shorten::new(10, "..\"".to_string())));
162        let matcher = Simple::new(r#"[]{"description"}"#).unwrap();
163
164        convert.add_matcher(Box::new(matcher), shorten_handler.clone());
165        let mut output = convert.process(br#"[{"description": "t"#).unwrap();
166
167        output.extend(convert.process(br#"oo long d"#).unwrap());
168
169        output.extend(
170            convert
171                .process(br#"escription"}, {"description": "short"}]"#)
172                .unwrap(),
173        );
174
175        let output: Vec<u8> = OutputConverter::new()
176            .convert(&output)
177            .into_iter()
178            .map(|e| e.1)
179            .flatten()
180            .collect();
181
182        assert_eq!(
183            String::from_utf8(output).unwrap(),
184            r#"[{"description": "too long d.."}, {"description": "short"}]"#
185        );
186    }
187}