#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MemoryBioError;
impl core::fmt::Display for MemoryBioError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("cannot write() after write_eof()")
}
}
impl core::error::Error for MemoryBioError {}
#[derive(Debug, Default)]
pub struct MemoryBio {
buffer: Vec<u8>,
start: usize,
eof_written: bool,
}
impl MemoryBio {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn pending(&self) -> usize {
self.buffer.len() - self.start
}
#[must_use]
pub fn eof(&self) -> bool {
self.eof_written && self.pending() == 0
}
#[must_use]
pub fn eof_written(&self) -> bool {
self.eof_written
}
pub fn read(&mut self, size: usize) -> Vec<u8> {
let count = size.min(self.pending());
let end = self.start + count;
let out = self.buffer[self.start..end].to_vec();
self.start = end;
self.compact();
out
}
pub fn write(&mut self, data: &[u8]) -> Result<usize, MemoryBioError> {
if self.eof_written {
return Err(MemoryBioError);
}
self.compact();
self.buffer.extend_from_slice(data);
Ok(data.len())
}
pub fn write_eof(&mut self) {
self.eof_written = true;
}
fn compact(&mut self) {
if self.start == self.buffer.len() {
self.buffer.clear();
self.start = 0;
} else if self.start >= 4096 && self.start * 2 >= self.buffer.len() {
self.buffer.copy_within(self.start.., 0);
self.buffer.truncate(self.buffer.len() - self.start);
self.start = 0;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read_write_and_eof() {
let mut bio = MemoryBio::new();
assert_eq!(bio.write(b"abcd").unwrap(), 4);
assert_eq!(bio.read(2), b"ab");
assert_eq!(bio.pending(), 2);
bio.write_eof();
assert!(!bio.eof());
assert_eq!(bio.read(8), b"cd");
assert!(bio.eof());
assert_eq!(bio.write(b"x"), Err(MemoryBioError));
}
}