use super::Handler;
use crate::{error, path::Path};
use std::collections::VecDeque;
#[derive(Debug)]
pub struct Buffer {
stored: VecDeque<(Option<String>, Vec<u8>)>,
use_path: bool,
current_buffer_size: usize,
max_buffer_size: Option<usize>,
}
impl Default for Buffer {
fn default() -> Self {
Self {
stored: VecDeque::new(),
use_path: false,
current_buffer_size: 0,
max_buffer_size: None,
}
}
}
impl Handler for Buffer {
fn handle(
&mut self,
path: &Path,
_matcher_idx: usize,
data: Option<&[u8]>,
) -> Result<Option<Vec<u8>>, error::Handler> {
let path_opt = if self.use_path {
Some(path.to_string())
} else {
None
};
let data = data.unwrap();
if let Some(limit) = self.max_buffer_size {
if self.current_buffer_size + data.len() > limit {
return Err(error::Handler::new(format!(
"Max buffer size {} was reached",
limit
)));
}
}
self.current_buffer_size += data.len();
self.stored.push_back((path_opt, data.to_vec()));
Ok(None)
}
fn use_path(&self) -> bool {
self.use_path
}
}
impl Buffer {
pub fn new() -> Self {
Self::default()
}
pub fn set_use_path(mut self, use_path: bool) -> Self {
self.use_path = use_path;
self
}
pub fn pop(&mut self) -> Option<(Option<String>, Vec<u8>)> {
let popped = self.stored.pop_front();
if let Some((_, buffer)) = popped.as_ref() {
self.current_buffer_size -= buffer.len();
}
popped
}
pub fn set_max_buffer_size(mut self, max_size: Option<usize>) -> Self {
self.max_buffer_size = max_size;
self
}
}
#[cfg(test)]
mod tests {
use super::Buffer;
use crate::{matcher::Simple, strategy::Trigger};
use std::sync::{Arc, Mutex};
#[test]
fn max_buffer_size_error() {
let mut trigger = Trigger::new();
let buffer_handler = Arc::new(Mutex::new(Buffer::new().set_max_buffer_size(Some(22))));
let matcher = Simple::new(r#"[]{"description"}"#).unwrap();
trigger.add_matcher(Box::new(matcher), &[buffer_handler.clone()]);
assert!(trigger.process(br#"[{"description": "short"}, "#).is_ok());
assert!(trigger
.process(br#"{"description": "too long description"}]"#)
.is_err());
}
#[test]
fn max_buffer_size_consumed() {
let mut trigger = Trigger::new();
let buffer_handler = Arc::new(Mutex::new(Buffer::new().set_max_buffer_size(Some(22))));
let matcher = Simple::new(r#"[]{"description"}"#).unwrap();
trigger.add_matcher(Box::new(matcher), &[buffer_handler.clone()]);
assert!(trigger.process(br#"[{"description": "short"}, "#).is_ok());
assert_eq!(
buffer_handler.lock().unwrap().pop().unwrap(),
(None, br#""short""#.to_vec())
);
assert!(trigger
.process(br#"{"description": "too long description"}]"#)
.is_ok());
assert_eq!(
buffer_handler.lock().unwrap().pop().unwrap(),
(None, br#""too long description""#.to_vec())
);
}
}