toml_input/
schema.rs

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