use std::cmp::min;
use std::io;
use std::mem::MaybeUninit;
#[derive(Debug)]
pub struct Writer<'buf> {
buffer: &'buf mut [MaybeUninit<u8>],
written: usize,
}
impl<'buf> Writer<'buf> {
#[inline]
pub fn new(buffer: &'buf mut [MaybeUninit<u8>]) -> Self {
Self { buffer, written: 0 }
}
#[inline]
pub fn written(&self) -> &[u8] {
let slice = &self.buffer[0..self.written];
unsafe { &*(slice as *const [MaybeUninit<u8>] as *const [u8]) }
}
#[inline]
pub fn reset(&mut self) {
self.written = 0;
}
}
impl io::Write for Writer<'_> {
#[inline]
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
let len = min(data.len(), self.buffer.len() - self.written);
let ptr = self.buffer[self.written..].as_mut_ptr().cast::<u8>();
let () = unsafe { ptr.copy_from_nonoverlapping(data.as_ptr(), len) };
self.written += len;
Ok(len)
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write as _;
#[test]
fn stack_writing() {
let mut buffer = [MaybeUninit::<u8>::uninit(); 8];
let mut writer = Writer::new(&mut buffer);
assert_eq!(writer.written(), []);
let n = writer.write(b"1").unwrap();
assert_eq!(n, 1);
assert_eq!(writer.written(), [b'1']);
let n = writer.write(b"23").unwrap();
assert_eq!(n, 2);
assert_eq!(writer.written(), [b'1', b'2', b'3']);
let () = writer.reset();
assert_eq!(writer.written(), []);
let n = writer.write(b"456").unwrap();
assert_eq!(n, 3);
assert_eq!(writer.written(), [b'4', b'5', b'6']);
let n = writer.write(b"123456").unwrap();
assert_eq!(n, 5);
assert_eq!(
writer.written(),
[b'4', b'5', b'6', b'1', b'2', b'3', b'4', b'5']
);
let n = writer.write(b"1337").unwrap();
assert_eq!(n, 0);
assert_eq!(
writer.written(),
[b'4', b'5', b'6', b'1', b'2', b'3', b'4', b'5']
);
}
}