use std::{fmt, io};
use crate::text::SPACES;
use super::Render;
pub struct IoWrite<W> {
upstream: W,
}
impl<W> IoWrite<W> {
pub fn new(upstream: W) -> IoWrite<W> {
IoWrite { upstream }
}
}
impl<W> Render for IoWrite<W>
where
W: io::Write,
{
type Error = io::Error;
fn write_str(&mut self, s: &str) -> io::Result<usize> {
self.upstream.write(s.as_bytes())
}
fn write_str_all(&mut self, s: &str) -> io::Result<()> {
self.upstream.write_all(s.as_bytes())
}
fn fail_doc(&self) -> Self::Error {
io::Error::other("Document failed to render")
}
}
pub struct FmtWrite<W> {
upstream: W,
}
impl<W> FmtWrite<W> {
pub fn new(upstream: W) -> FmtWrite<W> {
FmtWrite { upstream }
}
}
impl<W> Render for FmtWrite<W>
where
W: fmt::Write,
{
type Error = fmt::Error;
fn write_str(&mut self, s: &str) -> Result<usize, fmt::Error> {
self.write_str_all(s).map(|_| s.len())
}
fn write_str_all(&mut self, s: &str) -> fmt::Result {
self.upstream.write_str(s)
}
fn fail_doc(&self) -> Self::Error {
fmt::Error
}
}
pub(super) struct BufferWrite {
buffer: String,
}
impl BufferWrite {
pub(super) fn new() -> Self {
BufferWrite {
buffer: String::new(),
}
}
pub(super) fn render<W>(&mut self, render: &mut W) -> Result<(), W::Error>
where
W: ?Sized + Render,
{
render.write_str_all(&self.buffer)?;
Ok(())
}
}
impl Render for BufferWrite {
type Error = ();
fn write_str(&mut self, s: &str) -> Result<usize, Self::Error> {
self.buffer.push_str(s);
Ok(s.len())
}
fn write_str_all(&mut self, s: &str) -> Result<(), Self::Error> {
self.buffer.push_str(s);
Ok(())
}
fn fail_doc(&self) -> Self::Error {}
}
pub(super) fn write_newline<W>(ind: usize, out: &mut W) -> Result<(), W::Error>
where
W: ?Sized + Render,
{
out.write_str_all("\n")?;
write_spaces(ind, out)
}
pub(super) fn write_spaces<W>(spaces: usize, out: &mut W) -> Result<(), W::Error>
where
W: ?Sized + Render,
{
let mut inserted = 0;
while inserted < spaces {
let insert = SPACES.len().min(spaces - inserted);
inserted += out.write_str(&SPACES[..insert])?;
}
Ok(())
}