#![deny(missing_docs)]
#[derive(Debug, Default, Clone)]
pub struct Recombiner {
pending: Vec<u8>,
}
impl Recombiner {
pub fn new() -> Self {
Self::default()
}
pub fn push(&mut self, bytes: &[u8]) -> String {
self.pending.extend_from_slice(bytes);
let split = longest_valid_utf8_prefix(&self.pending);
let prefix: Vec<u8> = self.pending.drain(..split).collect();
String::from_utf8(prefix).unwrap_or_default()
}
pub fn flush(&mut self) -> String {
let out = String::from_utf8_lossy(&self.pending).into_owned();
self.pending.clear();
out
}
pub fn pending(&self) -> usize {
self.pending.len()
}
}
fn longest_valid_utf8_prefix(bytes: &[u8]) -> usize {
for tail in 0..=3 {
if tail > bytes.len() {
break;
}
let end = bytes.len() - tail;
if std::str::from_utf8(&bytes[..end]).is_ok() {
return end;
}
}
0
}