use std::fmt;
#[derive(Debug, Clone)]
pub struct IndentWriter<'i, W> {
writer: W,
indent: &'i str,
need_indent: bool,
}
impl<'i, W: fmt::Write> IndentWriter<'i, W> {
pub fn new(indent: &'i str, writer: W) -> Self {
Self {
writer,
indent,
need_indent: true,
}
}
pub fn into_inner(self) -> W {
self.writer
}
pub fn get_ref(&self) -> &W {
&self.writer
}
pub fn indent(&self) -> &'i str {
self.indent
}
}
impl<'i, W: fmt::Write> fmt::Write for IndentWriter<'i, W> {
fn write_str(&mut self, mut s: &str) -> fmt::Result {
loop {
match self.need_indent {
false => match s.as_bytes().iter().position(|&b| b == b'\n') {
None => break self.writer.write_str(s),
Some(len) => {
let (head, tail) = s.split_at(len + 1);
self.writer.write_str(head)?;
self.need_indent = true;
s = tail;
}
},
true => match s.as_bytes().iter().position(|&b| b != b'\n') {
None => break self.writer.write_str(s),
Some(len) => {
let (head, tail) = s.split_at(len);
self.writer.write_str(head)?;
self.writer.write_str(self.indent)?;
self.need_indent = false;
s = tail;
}
},
}
}
}
fn write_char(&mut self, c: char) -> fmt::Result {
if self.need_indent && c != '\n' {
self.writer.write_str(self.indent)?;
self.need_indent = false;
}
if !self.need_indent && c == '\n' {
self.need_indent = true;
}
self.writer.write_char(c)
}
}