toml/ser/document/
buffer.rs

1use toml_writer::TomlWrite as _;
2
3use crate::alloc_prelude::*;
4
5/// TOML Document serialization buffer
6#[derive(Debug, Default)]
7pub struct Buffer {
8    tables: Vec<Option<Table>>,
9}
10
11impl Buffer {
12    /// Initialize a new serialization buffer
13    pub fn new() -> Self {
14        Default::default()
15    }
16
17    /// Reset the buffer for serializing another document
18    pub fn clear(&mut self) {
19        self.tables.clear();
20    }
21
22    pub(crate) fn root_table(&mut self) -> Table {
23        self.new_table(None)
24    }
25
26    pub(crate) fn child_table(&mut self, parent: &mut Table, key: String) -> Table {
27        parent.has_children = true;
28        let mut key_path = parent.key.clone();
29        key_path.get_or_insert_with(Vec::new).push(key);
30        self.new_table(key_path)
31    }
32
33    pub(crate) fn element_table(&mut self, parent: &mut Table, key: String) -> Table {
34        let mut table = self.child_table(parent, key);
35        table.array = true;
36        table
37    }
38
39    pub(crate) fn new_table(&mut self, key: Option<Vec<String>>) -> Table {
40        let pos = self.tables.len();
41        let table = Table {
42            key,
43            body: String::new(),
44            has_children: false,
45            pos,
46            array: false,
47        };
48        self.tables.push(None);
49        table
50    }
51
52    pub(crate) fn push(&mut self, table: Table) {
53        let pos = table.pos;
54        self.tables[pos] = Some(table);
55    }
56}
57
58impl core::fmt::Display for Buffer {
59    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
60        let mut tables = self
61            .tables
62            .iter()
63            .filter_map(|t| t.as_ref())
64            .filter(|t| required_table(t));
65        if let Some(table) = tables.next() {
66            table.fmt(f)?;
67        }
68        for table in tables {
69            f.newline()?;
70            table.fmt(f)?;
71        }
72        Ok(())
73    }
74}
75
76fn required_table(table: &Table) -> bool {
77    if table.key.is_none() {
78        !table.body.is_empty()
79    } else {
80        table.array || !table.body.is_empty() || !table.has_children
81    }
82}
83
84#[derive(Clone, Debug)]
85pub(crate) struct Table {
86    key: Option<Vec<String>>,
87    body: String,
88    has_children: bool,
89    array: bool,
90    pos: usize,
91}
92
93impl Table {
94    pub(crate) fn body_mut(&mut self) -> &mut String {
95        &mut self.body
96    }
97
98    pub(crate) fn has_children(&mut self, yes: bool) {
99        self.has_children = yes;
100    }
101}
102
103impl core::fmt::Display for Table {
104    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
105        if let Some(key) = &self.key {
106            if self.array {
107                f.open_array_of_tables_header()?;
108            } else {
109                f.open_table_header()?;
110            }
111            let mut key = key.iter();
112            if let Some(key) = key.next() {
113                write!(f, "{key}")?;
114            }
115            for key in key {
116                f.key_sep()?;
117                write!(f, "{key}")?;
118            }
119            if self.array {
120                f.close_array_of_tables_header()?;
121            } else {
122                f.close_table_header()?;
123            }
124            f.newline()?;
125        }
126
127        self.body.fmt(f)?;
128
129        Ok(())
130    }
131}