use std::marker::PhantomData;
use crate::marker::IndentWriteMarker;
pub(crate) trait IndentWrite<M: IndentWriteMarker> {
type Error;
fn write_char(&mut self, c: char) -> Result<(), Self::Error>;
fn write_str(&mut self, str: &str) -> Result<(), Self::Error>;
fn flush(&mut self) -> Result<(), Self::Error>;
}
pub(crate) struct IndentWriterImpl<'w, M: IndentWriteMarker, W: IndentWrite<M>>
{
indent_delta: usize,
current_indent: String,
last_was_newline: bool,
pub(crate) wrapped: &'w mut W,
_marker: PhantomData<M>,
}
impl<'w, M: IndentWriteMarker, W: IndentWrite<M>> IndentWriterImpl<'w, M, W> {
pub(crate) fn new(wrapped: &'w mut W, indent_delta: usize) -> Self {
Self {
indent_delta,
current_indent: String::new(),
last_was_newline: false,
wrapped,
_marker: PhantomData,
}
}
#[inline]
pub(crate) fn increase_indent(&mut self) {
for _ in 0..self.indent_delta {
self.current_indent.push(' ');
}
}
#[inline]
pub(crate) fn decrease_indent(&mut self) {
let new_length = self.current_indent.len() - self.indent_delta;
self.current_indent.truncate(new_length);
}
#[inline]
pub(crate) fn indent_if_needed(
&mut self,
) -> Result<(), <Self as IndentWrite<M>>::Error> {
if self.last_was_newline {
self.wrapped.write_str(&self.current_indent)?;
self.last_was_newline = false;
}
Ok(())
}
}
impl<M: IndentWriteMarker, W: IndentWrite<M>> IndentWrite<M>
for IndentWriterImpl<'_, M, W>
{
type Error = W::Error;
#[inline]
fn write_char(&mut self, c: char) -> Result<(), Self::Error> {
self.indent_if_needed()?;
self.wrapped.write_char(c)?;
self.last_was_newline = c == '\n';
Ok(())
}
#[inline]
fn write_str(&mut self, str: &str) -> Result<(), Self::Error> {
for c in str.chars() {
self.write_char(c)?;
}
Ok(())
}
#[inline]
fn flush(&mut self) -> Result<(), Self::Error> {
self.wrapped.flush()
}
}
pub trait IndentWriterCommon {
fn increase_indent(&mut self);
fn decrease_indent(&mut self);
fn indent_if_needed(&mut self);
}