use crate::{Render, RenderAnnotated, Text, render::Annotation};
use alloc::rc::Rc;
use color_ansi::AnsiStyle;
use core::fmt::{Debug, Error, Formatter};
pub struct FmtWrite<W> {
upstream: W,
}
#[derive(Debug)]
pub struct BufferWrite<T> {
buffer: Vec<T>,
annotations: Vec<(usize, Annotation<AnsiStyle>)>,
}
impl<'a, T: Text<'a>> BufferWrite<T> {
pub fn new(capacity: usize) -> Self {
BufferWrite { buffer: Vec::with_capacity(capacity), annotations: Vec::new() }
}
pub fn render<W>(&mut self, render: &mut W) -> Result<(), W::Error>
where
W: RenderAnnotated<'a, T>,
W: ?Sized,
{
let mut start = 0;
for (end, annotation) in &self.annotations {
let s = &self.buffer[start..*end];
if !s.is_empty() {
render.write_all(s)?;
}
start = *end;
match annotation {
Annotation::Push(a) => render.push_annotation(a.clone())?,
Annotation::Pop => render.pop_annotation()?,
}
}
let s = &self.buffer[start..];
if !s.is_empty() {
render.write_all(s)?;
}
Ok(())
}
}
impl<'a, T: Clone> Render<'a, T> for BufferWrite<T> {
type Error = Error;
fn write_all(&mut self, s: &[T]) -> Result<(), Self::Error> {
self.buffer.extend(s.iter().cloned());
Ok(())
}
fn fail_doc(&self) -> Self::Error {
Error
}
}
impl<'a, W, T: Text<'a>> RenderAnnotated<'a, T> for FmtWrite<W>
where
W: core::fmt::Write,
{
fn push_annotation(&mut self, _: Rc<AnsiStyle>) -> Result<(), Self::Error> {
Ok(())
}
fn pop_annotation(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
impl<'a, T: Clone> RenderAnnotated<'a, T> for BufferWrite<T> {
fn push_annotation(&mut self, annotation: Rc<AnsiStyle>) -> Result<(), Self::Error> {
self.annotations.push((self.buffer.len(), Annotation::Push(annotation)));
Ok(())
}
fn pop_annotation(&mut self) -> Result<(), Self::Error> {
self.annotations.push((self.buffer.len(), Annotation::Pop));
Ok(())
}
}
impl<W> Debug for FmtWrite<W> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("IoWrite").finish()
}
}
impl<W> FmtWrite<W> {
pub fn new(upstream: W) -> FmtWrite<W> {
FmtWrite { upstream }
}
}
impl<'a, W, T: Text<'a>> Render<'a, T> for FmtWrite<W>
where
W: core::fmt::Write,
{
type Error = Error;
fn write_all(&mut self, s: &[T]) -> core::fmt::Result {
for i in s {
self.upstream.write_str(i.as_str().as_ref())?
}
Ok(())
}
fn fail_doc(&self) -> Self::Error {
Error
}
}