elegance 0.4.0

A pretty-printing library for Rust with a focus on speed and compactness.
Documentation
use std::io;

use elegance::{
    core::Printer,
    render::{Io, Render},
};

enum Value {
    Null,
    Bool(bool),
    Number(f64),
    String(String),
    Array(Vec<Value>),
    Object(Vec<(String, Value)>),
}

impl Value {
    pub fn print<R: Render>(&self, pp: &mut Printer<R>) -> Result<(), R::Error> {
        match self {
            Value::Null => pp.text("null")?,
            Value::Bool(true) => pp.text("true")?,
            Value::Bool(false) => pp.text("false")?,
            Value::Number(x) => pp.text_owned(format!("{}", x))?,
            Value::String(s) => pp.text_owned(format!("\"{}\"", s))?,
            Value::Array(arr) => pp.igroup(2, |pp| {
                pp.text("[")?;
                if let Some((first, rest)) = arr.split_first() {
                    pp.zero_break()?;
                    first.print(pp)?;
                    for v in rest {
                        pp.text(",")?;
                        pp.space()?;
                        v.print(pp)?;
                    }
                    pp.scan_break(0, -2)?;
                }
                pp.text("]")
            })?,
            Value::Object(obj) => pp.cgroup(2, |pp| {
                let mut obj = obj.iter();
                pp.text("{")?;
                if let Some((k, v)) = obj.next() {
                    pp.zero_break()?;
                    pp.text_owned(format!("\"{}\": ", k))?;
                    v.print(pp)?;
                    for (k, v) in obj {
                        pp.text(",")?;
                        pp.space()?;
                        pp.text_owned(format!("\"{}\": ", k))?;
                        v.print(pp)?;
                    }
                    pp.scan_break(0, -2)?;
                }
                pp.text("}")
            })?,
        };
        Ok(())
    }
}

fn main() -> io::Result<()> {
    let obj = Value::Object(vec![
        ("name".into(), Value::String("hello".into())),
        ("age".into(), Value::Number(10.0)),
        ("is_ok".into(), Value::Bool(true)),
        ("null".into(), Value::Null),
        (
            "arr".into(),
            Value::Array((0..20).map(|i| Value::String(format!("{}", i))).collect()),
        ),
    ]);

    let mut printer = Printer::new(Io(io::stdout()), 40);
    obj.print(&mut printer)?;
    printer.finish()?;

    Ok(())
}