1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::{Ion, Section, Value};
use std::fmt::{self, Write};

impl fmt::Display for Ion {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        for (name, section) in &self.sections {
            f.write_fmt(format_args!("[{name}]\n"))?;
            section.fmt(f)?;
            f.write_str("\n")?;
        }

        Ok(())
    }
}

impl fmt::Display for Section {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        for (k, v) in &self.dictionary {
            f.write_fmt(format_args!("{k} = {v:#}\n"))?;
        }

        for row in &self.rows {
            for cell in row {
                fmt::Display::fmt(&format!("| {cell} "), f)?;
            }
            f.write_str("|\n")?;
        }

        Ok(())
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            Value::String(v) => {
                if f.alternate() {
                    f.write_char('"')?;
                    for c in v.chars() {
                        match c {
                            '\\' => f.write_str("\\\\")?,
                            '\n' => f.write_str("\\n")?,
                            '\"' => f.write_str("\\\"")?,
                            _ => f.write_char(c)?,
                        }
                    }
                    f.write_char('"')?;
                } else {
                    let mut escaping = false;
                    for c in v.chars() {
                        match (escaping, c) {
                            (false, '\\') => {
                                escaping = true;
                                f.write_char('\\')?;
                                continue;
                            }
                            (false, '\n') => f.write_str("\\n")?,
                            (false, '\t') => f.write_str("\\t")?,
                            (false, '|') => f.write_str("\\|")?,

                            (true, '\\') => f.write_char('\\')?,
                            (true, 'n') => f.write_str("\\n")?,
                            (true, 't') => f.write_str("\\t")?,
                            (true, '|') => f.write_str("\\|")?,

                            (_, c) => f.write_char(c)?,
                        }
                        escaping = false;
                    }
                }
                Ok(())
            }

            Value::Integer(v) => v.fmt(f),
            Value::Float(v) => v.fmt(f),
            Value::Boolean(v) => v.fmt(f),

            Value::Array(v) => {
                f.write_str("[ ")?;

                let mut first = true;

                for i in v {
                    if first {
                        first = false;
                    } else {
                        f.write_str(", ")?
                    }

                    write!(f, "{i:#}")?;
                }

                f.write_str(" ]")
            }

            Value::Dictionary(d) => {
                f.write_str("{ ")?;

                let mut first = true;

                for (k, v) in d {
                    if first {
                        first = false;
                    } else {
                        f.write_str(", ")?
                    }

                    k.fmt(f)?;
                    f.write_str(" = ")?;

                    write!(f, "{v:#}")?;
                }

                f.write_str(" }")
            }
        }
    }
}