use std::mem;
#[derive(Debug)]
pub(crate) struct Writer<P> {
rest: usize,
data: P,
}
impl<P> Writer<P> {
#[inline]
pub fn new(data: P) -> Self
where
P: AsRef<[u8]>,
{
let rest = data.as_ref().len();
Self { rest, data }
}
pub fn write_to(&mut self, output: &mut &mut [u8]) -> bool
where
P: Produce,
{
let n = usize::min(self.rest, output.len());
let (left, right) = mem::take(output).split_at_mut(n);
*output = right;
self.data.produce(self.rest, left);
self.rest -= n;
self.rest == 0
}
}
pub(crate) trait Produce {
fn produce(&self, rest: usize, output: &mut [u8]);
}
impl<P> Produce for P
where
P: AsRef<[u8]>,
{
fn produce(&self, rest: usize, output: &mut [u8]) {
let inner = self.as_ref();
let step = inner.len() - rest;
output.copy_from_slice(&inner[step..step + output.len()]);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn write() {
let mut w = Writer::new([0, 1, 2, 3]);
assert_eq!(w.rest, 4);
let mut buf = [0; 2];
let mut output = buf.as_mut_slice();
assert!(!w.write_to(&mut output));
assert_eq!(w.rest, 2);
assert!(output.is_empty());
assert_eq!(buf, [0, 1]);
let mut output = buf.as_mut_slice();
assert!(w.write_to(&mut output));
assert_eq!(w.rest, 0);
assert!(output.is_empty());
assert_eq!(buf, [2, 3]);
let mut output = buf.as_mut_slice();
assert!(w.write_to(&mut output));
assert_eq!(w.rest, 0);
assert_eq!(output.len(), 2);
assert_eq!(buf, [2, 3]);
}
}