pub fn default() -> DefaultOutput {
DefaultOutput::new()
}
pub trait Output {
fn sink(&mut self) -> &mut dyn std::io::Write;
fn draw_target(&self) -> indicatif::ProgressDrawTarget;
}
impl std::io::Write for &mut dyn Output {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.sink().write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.sink().flush()
}
}
#[derive(Debug)]
pub struct DefaultOutput(std::io::Stdout);
impl DefaultOutput {
pub fn new() -> Self {
Self(std::io::stdout())
}
}
impl Default for DefaultOutput {
fn default() -> Self {
Self::new()
}
}
impl Output for DefaultOutput {
fn sink(&mut self) -> &mut dyn std::io::Write {
&mut self.0
}
fn draw_target(&self) -> indicatif::ProgressDrawTarget {
indicatif::ProgressDrawTarget::stderr()
}
}
#[derive(Debug)]
pub struct Sink(std::io::Sink);
impl Sink {
pub fn new() -> Self {
Self(std::io::sink())
}
}
impl Default for Sink {
fn default() -> Self {
Self::new()
}
}
impl Output for Sink {
fn sink(&mut self) -> &mut dyn std::io::Write {
&mut self.0
}
fn draw_target(&self) -> indicatif::ProgressDrawTarget {
indicatif::ProgressDrawTarget::hidden()
}
}
#[derive(Debug)]
pub struct Memory(Vec<u8>);
impl Memory {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn into_inner(self) -> Vec<u8> {
self.0
}
}
impl Default for Memory {
fn default() -> Self {
Self::new()
}
}
impl Output for Memory {
fn sink(&mut self) -> &mut dyn std::io::Write {
&mut self.0
}
fn draw_target(&self) -> indicatif::ProgressDrawTarget {
indicatif::ProgressDrawTarget::hidden()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
#[test]
fn test_memory() {
let mut buf = Memory::new();
{
let mut output: &mut dyn Output = &mut buf;
writeln!(output, "hello world").unwrap();
writeln!(output, "test: {}", 10).unwrap();
output.flush().unwrap();
assert!(output.draw_target().is_hidden());
}
let bytes = buf.into_inner();
let message = str::from_utf8(&bytes).unwrap();
let mut lines = message.lines();
let first = lines.next().unwrap();
assert_eq!(first, "hello world");
let second = lines.next().unwrap();
assert_eq!(second, "test: 10");
assert!(lines.next().is_none());
}
#[test]
fn test_default() {
let mut d = default();
let mut s = &mut d as &mut dyn Output;
writeln!(s, "test").unwrap();
}
#[test]
fn test_sink() {
let mut d = Sink::new();
let mut s = &mut d as &mut dyn Output;
assert!(s.draw_target().is_hidden());
writeln!(s, "test").unwrap();
}
}