toml_input/
schema.rs

1use crate::comment::Comment;
2use crate::config::TomlConfig;
3use crate::util;
4use crate::value::PrimValue;
5use crate::TomlValue;
6use crate::{block::Block, section::Section};
7
8#[derive(Debug, Clone, Default)]
9pub struct Meta {
10    pub config: TomlConfig,
11    pub defined_docs: String,
12    pub valued_docs: String,
13    pub wrap_type: String,
14    pub inner_type: String,
15    pub inner_default: PrimValue,
16    pub is_array: bool,
17}
18
19impl Meta {
20    pub fn comment(&self) -> Comment {
21        Comment {
22            config: self.config.clone(),
23            defined_docs: self.defined_docs.clone(),
24            valued_docs: self.valued_docs.clone(),
25            inner_type: self.inner_type.clone(),
26            inner_default: self.inner_default.clone(),
27            ..Default::default()
28        }
29    }
30}
31
32#[derive(Debug, Clone, Default)]
33pub struct VariantSchema {
34    pub docs: String,
35    pub value: PrimValue,
36    pub config: TomlConfig,
37}
38
39#[derive(Debug, Clone, Default)]
40pub struct PrimSchema {
41    pub meta: Meta,
42    pub variants: Vec<VariantSchema>,
43}
44
45impl PrimSchema {
46    pub fn flatten(self) -> Section {
47        let PrimSchema { meta, variants } = self;
48        let array_index = if meta.is_array { Some(0) } else { None };
49        let block = Block {
50            meta,
51            variants,
52            ..Default::default()
53        };
54        Section {
55            array_index,
56            blocks: vec![block],
57            ..Default::default()
58        }
59    }
60}
61
62#[derive(Debug, Clone, Default)]
63pub struct TableSchema {
64    pub meta: Meta,
65    pub fields: Vec<FieldSchema>,
66}
67
68impl TableSchema {
69    pub fn flatten(self) -> Vec<Section> {
70        let TableSchema { meta, fields } = self;
71        let mut sections = Vec::new();
72        for field in fields {
73            sections.append(&mut field.flatten());
74        }
75        Section::reduce(&mut sections);
76        for section in &mut sections {
77            if section.is_root() {
78                section.meta = meta.clone();
79                section.array_index = if meta.is_array { Some(0) } else { None };
80            }
81        }
82        sections
83    }
84}
85
86#[derive(Debug, Clone, Default)]
87pub struct FieldSchema {
88    pub ident: String,
89    pub docs: String,
90    pub flat: bool,
91    pub schema: Schema,
92    pub config: TomlConfig,
93}
94
95impl FieldSchema {
96    pub fn flatten(self) -> Vec<Section> {
97        let FieldSchema {
98            ident,
99            docs,
100            flat,
101            schema,
102            config,
103        } = self;
104        let mut sections = schema.flatten();
105        if !flat {
106            for section in &mut sections {
107                section.meta.valued_docs = docs.clone();
108                section.meta.config = config.clone();
109                if section.is_value() {
110                    for block in &mut section.blocks {
111                        block.meta.valued_docs = docs.clone();
112                        block.meta.config.merge_parent(&config);
113                        block.key = ident.clone();
114                        block.ident = ident.clone();
115                    }
116                } else {
117                    util::increase_key(&mut section.key, &ident);
118                    for block in &mut section.blocks {
119                        util::increase_key(&mut block.key, &ident);
120                    }
121                }
122            }
123        }
124        sections
125    }
126
127    pub fn set_inner_default(&mut self, raw: TomlValue) {
128        let meta = self.schema.meta_mut();
129        meta.inner_default.raw = Some(raw);
130    }
131}
132
133#[derive(Debug, Clone)]
134pub enum Schema {
135    Prim(PrimSchema),
136    Table(TableSchema),
137}
138
139impl Default for Schema {
140    fn default() -> Self {
141        Schema::Prim(PrimSchema::default())
142    }
143}
144
145impl Schema {
146    pub fn flatten(self) -> Vec<Section> {
147        match self {
148            Schema::Prim(prim) => vec![prim.flatten()],
149            Schema::Table(table) => table.flatten(),
150        }
151    }
152    pub fn new_table() -> Schema {
153        Schema::Table(TableSchema::default())
154    }
155
156    pub fn is_prim(&self) -> bool {
157        matches!(&self, Schema::Prim(_))
158    }
159
160    pub fn is_table(&self) -> bool {
161        matches!(&self, Schema::Table(_))
162    }
163
164    pub fn meta_mut(&mut self) -> &mut Meta {
165        match self {
166            Schema::Prim(schema) => &mut schema.meta,
167            Schema::Table(schema) => &mut schema.meta,
168        }
169    }
170    pub fn set_wrap_type(&mut self, new: String) -> String {
171        let meta = self.meta_mut();
172        std::mem::replace(&mut meta.wrap_type, new)
173    }
174}