use std::collections::VecDeque;
use std::io::{Read, Write};
pub trait ConsoleIo: Send + Sync {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize>;
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize>;
fn flush(&mut self) -> std::io::Result<()>;
}
pub struct StdioConsole;
impl ConsoleIo for StdioConsole {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
std::io::stdin().read(buf)
}
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
std::io::stdout().write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
std::io::stdout().flush()
}
}
pub struct BufferConsole {
pub input: VecDeque<u8>,
pub output: Vec<u8>,
}
impl BufferConsole {
#[must_use]
pub const fn new() -> Self {
Self {
input: VecDeque::new(),
output: Vec::new(),
}
}
pub fn push_input(&mut self, data: &[u8]) {
self.input.extend(data);
}
pub fn take_output(&mut self) -> Vec<u8> {
std::mem::take(&mut self.output)
}
}
impl Default for BufferConsole {
fn default() -> Self {
Self::new()
}
}
impl ConsoleIo for BufferConsole {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let len = buf.len().min(self.input.len());
for (i, byte) in self.input.drain(..len).enumerate() {
buf[i] = byte;
}
Ok(len)
}
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.output.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_buffer_console() {
let mut buffer = BufferConsole::new();
buffer.push_input(b"Hello");
let mut buf = [0u8; 10];
let n = buffer.read(&mut buf).unwrap();
assert_eq!(n, 5);
assert_eq!(&buf[..n], b"Hello");
buffer.write(b"World").unwrap();
let output = buffer.take_output();
assert_eq!(&output, b"World");
}
#[test]
fn test_buffer_console_empty_read() {
let mut buffer = BufferConsole::new();
let mut buf = [0u8; 10];
let n = buffer.read(&mut buf).unwrap();
assert_eq!(n, 0);
}
#[test]
fn test_buffer_console_partial_read() {
let mut buffer = BufferConsole::new();
buffer.push_input(b"Hello, World!");
let mut buf = [0u8; 5];
let n = buffer.read(&mut buf).unwrap();
assert_eq!(n, 5);
assert_eq!(&buf, b"Hello");
let mut buf2 = [0u8; 10];
let n2 = buffer.read(&mut buf2).unwrap();
assert_eq!(n2, 8);
assert_eq!(&buf2[..n2], b", World!");
}
#[test]
fn test_buffer_console_multiple_writes() {
let mut buffer = BufferConsole::new();
buffer.write(b"Hello").unwrap();
buffer.write(b" ").unwrap();
buffer.write(b"World").unwrap();
let output = buffer.take_output();
assert_eq!(&output, b"Hello World");
}
#[test]
fn test_buffer_console_flush() {
let mut buffer = BufferConsole::new();
assert!(buffer.flush().is_ok());
}
#[test]
fn test_buffer_console_default() {
let buffer = BufferConsole::default();
assert!(buffer.input.is_empty());
assert!(buffer.output.is_empty());
}
}