rust-sen/sehn-serde/src/ser/format/pretty.rs

117 lines
2.3 KiB
Rust

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<TwoSpaces>;
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<I: IndentStyle> {
indent_style: PhantomData<I>
}
impl<I: IndentStyle> PrettyFormat<I> {
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<I: IndentStyle> Format for PrettyFormat<I> {
type Engine = PrettyFormatEngine;
type RealFormat = FastRealFormat;
fn write<W: 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)
}
}