use std::io::Write; use std::marker::PhantomData; use crate::syntax::*; use crate::ser::error::Result; use super::{Format, FormatEngine, FastRealFormat}; pub type DefaultPrettyFormat = PrettyFormat; pub trait IndentStyle { const LEVEL: &'static [u8]; } pub struct OneTab; pub struct TwoSpaces; pub struct FourSpaces; impl IndentStyle for OneTab { const LEVEL: &'static [u8] = &[ WHITESPACE_TAB_CHAR ]; } impl IndentStyle for TwoSpaces { const LEVEL: &'static [u8] = &[ WHITESPACE_SPACE_CHAR, WHITESPACE_SPACE_CHAR ]; } impl IndentStyle for FourSpaces { const LEVEL: &'static [u8] = &[ WHITESPACE_SPACE_CHAR, WHITESPACE_SPACE_CHAR, WHITESPACE_SPACE_CHAR, WHITESPACE_SPACE_CHAR ]; } pub struct PrettyFormat { indent_style: PhantomData } impl PrettyFormat { fn style_before_write(e: &mut PrettyFormatEngine, w: &mut Write) -> Result<()> { match e.delim { DICT_END_CHAR | LIST_END_CHAR => { e.level -= 1; Self::write_newline(w)?; Self::write_indentation(e, w)?; }, _ => () } Ok(()) } fn style_after_write(e: &mut PrettyFormatEngine, w: &mut Write) -> Result<()> { match e.delim { DICT_START_CHAR | LIST_START_CHAR => { e.level += 1; Self::write_newline(w)?; Self::write_indentation(e, w)?; }, DICT_KV_SEPARATOR_CHAR => { Self::write_space(w)?; }, COMMA_CHAR => { Self::write_newline(w)?; Self::write_indentation(e, w)?; }, _ => () } e.delim = 0; Ok(()) } fn write_space(w: &mut Write) -> Result<()> { w.write(&[WHITESPACE_SPACE_CHAR])?; Ok(()) } fn write_newline(w: &mut Write) -> Result<()> { w.write(&[NEWLINE_LF_CHAR])?; Ok(()) } fn write_indentation(e: &mut PrettyFormatEngine, w: &mut Write) -> Result<()> { for _ in 0..e.level { w.write(I::LEVEL)?; } Ok(()) } } #[derive(Default)] pub struct PrettyFormatEngine { level: usize, delim: u8 } impl FormatEngine for PrettyFormatEngine { fn mark_delim(&mut self, delim: u8) { self.delim = delim; } } impl Format for PrettyFormat { type Engine = PrettyFormatEngine; type RealFormat = FastRealFormat; fn write(e: &mut PrettyFormatEngine, w: &mut Write, bytes: &[u8]) -> Result<()> { Self::style_before_write(e, w)?; w.write(bytes)?; Self::style_after_write(e, w) } }