use std::borrow::Cow;
use crate::exception_public::MontyException;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PrintStream {
Stdout,
Stderr,
}
pub enum PrintWriter<'a> {
Disabled,
Stdout,
CollectString(&'a mut String),
CollectStreams(&'a mut Vec<(PrintStream, String)>),
Callback(&'a mut dyn PrintWriterCallback),
}
impl PrintWriter<'_> {
pub fn reborrow(&mut self) -> PrintWriter<'_> {
match self {
Self::Disabled => PrintWriter::Disabled,
Self::Stdout => PrintWriter::Stdout,
Self::CollectString(buf) => PrintWriter::CollectString(buf),
Self::CollectStreams(buf) => PrintWriter::CollectStreams(buf),
Self::Callback(cb) => PrintWriter::Callback(&mut **cb),
}
}
pub fn stdout_write(&mut self, output: Cow<'_, str>) -> Result<(), MontyException> {
match self {
Self::Disabled => Ok(()),
Self::Stdout => {
print!("{output}");
Ok(())
}
Self::CollectString(buf) => {
buf.push_str(&output);
Ok(())
}
Self::CollectStreams(buf) => {
append_streams_str(buf, PrintStream::Stdout, &output);
Ok(())
}
Self::Callback(cb) => cb.stdout_write(output),
}
}
pub fn stdout_push(&mut self, end: char) -> Result<(), MontyException> {
match self {
Self::Disabled => Ok(()),
Self::Stdout => {
print!("{end}");
Ok(())
}
Self::CollectString(buf) => {
buf.push(end);
Ok(())
}
Self::CollectStreams(buf) => {
append_streams_char(buf, PrintStream::Stdout, end);
Ok(())
}
Self::Callback(cb) => cb.stdout_push(end),
}
}
}
fn append_streams_str(buf: &mut Vec<(PrintStream, String)>, stream: PrintStream, text: &str) {
match buf.last_mut() {
Some((s, existing)) if *s == stream => existing.push_str(text),
_ => buf.push((stream, text.to_owned())),
}
}
fn append_streams_char(buf: &mut Vec<(PrintStream, String)>, stream: PrintStream, ch: char) {
match buf.last_mut() {
Some((s, existing)) if *s == stream => existing.push(ch),
_ => buf.push((stream, String::from(ch))),
}
}
pub trait PrintWriterCallback {
fn stdout_write(&mut self, output: Cow<'_, str>) -> Result<(), MontyException>;
fn stdout_push(&mut self, end: char) -> Result<(), MontyException>;
}