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}