use crate::capabilities::held_suffix_len;
use crate::records::JsonValue;
#[derive(Debug, Clone)]
pub struct StopMatcher {
stops: Vec<String>,
buffer: String,
stopped: bool,
}
impl StopMatcher {
pub fn new(stops: Vec<String>) -> Self {
Self {
stops: stops.into_iter().filter(|stop| !stop.is_empty()).collect(),
buffer: String::new(),
stopped: false,
}
}
pub fn is_active(&self) -> bool {
!self.stops.is_empty()
}
pub fn is_stopped(&self) -> bool {
self.stopped
}
pub fn feed(&mut self, chunk: &str) -> String {
if !self.is_active() {
return chunk.to_owned();
}
if self.stopped {
return String::new();
}
self.buffer.push_str(chunk);
if let Some(position) = self.earliest_stop() {
let emit = self.buffer[..position].to_owned();
self.buffer.clear();
self.stopped = true;
return emit;
}
let held = held_suffix_len(&self.buffer, &self.stops);
let split = self.buffer.len() - held;
let emit = self.buffer[..split].to_owned();
self.buffer.drain(..split);
emit
}
pub fn flush(&mut self) -> String {
if self.stopped {
return String::new();
}
std::mem::take(&mut self.buffer)
}
fn earliest_stop(&self) -> Option<usize> {
self.stops
.iter()
.filter_map(|stop| self.buffer.find(stop.as_str()))
.min()
}
}
pub fn stop_strings(value: Option<&JsonValue>) -> Vec<String> {
match value {
Some(JsonValue::String(single)) => vec![single.clone()],
Some(JsonValue::Array(items)) => items
.iter()
.filter_map(|item| item.as_str().map(str::to_owned))
.collect(),
_ => Vec::new(),
}
}