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}