toml_input/
block.rs

1use crate::{
2    comment::{Comment, CommentType},
3    schema::{Meta, VariantSchema},
4    util,
5    value::BlockValue,
6    Error, TomlValue, BANG_COMMENT, COMMENT,
7};
8
9#[derive(Debug, Clone, Default)]
10pub struct Block {
11    pub key: String,
12    pub ident: String,
13    pub meta: Meta,
14    pub value: Option<BlockValue>,
15    pub variants: Vec<VariantSchema>,
16}
17
18impl Block {
19    pub fn is_enum(&self) -> bool {
20        !self.variants.is_empty()
21    }
22
23    pub fn is_value(&self) -> bool {
24        self.ident.is_empty()
25    }
26
27    pub fn is_field(&self) -> bool {
28        !self.is_value()
29    }
30
31    pub fn enum_is_expand(&self) -> bool {
32        if !self.is_enum() {
33            return false;
34        }
35        let style = self.meta.config.enum_style.unwrap_or_default();
36        style.can_expand(self.variants.len())
37    }
38
39    pub fn enum_is_fold(&self) -> bool {
40        if !self.is_enum() {
41            return false;
42        }
43        let style = self.meta.config.enum_style.unwrap_or_default();
44        style.can_fold(self.variants.len())
45    }
46
47    pub fn render(&self) -> Result<String, Error> {
48        let mut block_value = self.meta.inner_default.clone().flatten();
49        let mut commented = self.meta.config.block_comment;
50        if let Some(value) = self.value.clone() {
51            block_value = value;
52            commented = false;
53        }
54        let raw_value;
55        if let Some(raw) = block_value.value {
56            raw_value = raw;
57        } else {
58            return Ok(String::new());
59        }
60        let tag = block_value.tag;
61        let text;
62        if self.enum_is_expand() {
63            text = self.render_enum_expand(commented, tag, raw_value)?;
64        } else if self.enum_is_fold() {
65            text = self.render_enum_fold(commented, tag, raw_value)?;
66        } else if self.is_enum() {
67            text = self.render_enum_single(commented, tag, raw_value)?;
68        } else {
69            text = self.render_single(commented, raw_value)?;
70        }
71        Ok(text)
72    }
73
74    fn render_enum_single(
75        &self,
76        commented: bool,
77        tag: String,
78        raw_value: TomlValue,
79    ) -> Result<String, Error> {
80        let mut lines = Vec::new();
81        for variant in &self.variants {
82            let comment = util::comment_lines(&variant.docs);
83            if variant.value.tag == tag {
84                let line = if commented {
85                    format!("{}{} = {}", BANG_COMMENT, self.ident, raw_value)
86                } else {
87                    format!("{} = {}", self.ident, raw_value)
88                };
89                lines.push(comment);
90                lines.push(line);
91                break;
92            }
93        }
94        Ok(lines.join("\n"))
95    }
96
97    fn render_enum_expand(
98        &self,
99        commented: bool,
100        tag: String,
101        raw_value: TomlValue,
102    ) -> Result<String, Error> {
103        if !self.enum_is_expand() {
104            panic!()
105        }
106        let mut lines = Vec::new();
107        for variant in &self.variants {
108            let comment = util::comment_lines(&variant.docs);
109            if variant.value.tag == tag {
110                let line = if commented {
111                    format!("{}{} = {}", BANG_COMMENT, self.ident, raw_value)
112                } else {
113                    format!("{} = {}", self.ident, raw_value)
114                };
115                if comment.len() > 0 {
116                    lines.push(comment);
117                }
118                lines.push(line);
119            } else if let Some(value) = &variant.value.raw {
120                if comment.len() > 0 {
121                    lines.push(comment);
122                }
123                let line = format!("{}{} = {}", BANG_COMMENT, self.ident, value);
124                lines.push(line)
125            }
126        }
127        Ok(lines.join("\n"))
128    }
129
130    fn render_enum_fold(
131        &self,
132        commented: bool,
133        tag: String,
134        raw_value: TomlValue,
135    ) -> Result<String, Error> {
136        if !self.enum_is_fold() {
137            panic!()
138        }
139        let mut lines = Vec::new();
140        let mut values = Vec::new();
141        for variant in &self.variants {
142            let comment = util::comment_lines(&variant.docs);
143            if variant.value.tag == tag {
144                let line = if commented {
145                    format!("{}{} = {}", BANG_COMMENT, self.ident, raw_value)
146                } else {
147                    format!("{} = {}", self.ident, raw_value)
148                };
149                lines.push(comment);
150                lines.push(line);
151            }
152            if let Some(value) = &variant.value.raw {
153                values.push(format!("{value}"))
154            }
155        }
156        if values.len() > 1 {
157            lines.insert(
158                0,
159                format!("{} {} = {}", COMMENT, self.ident, values.join(" | ")),
160            );
161        }
162        Ok(lines.join("\n"))
163    }
164
165    fn render_single(&self, commented: bool, raw_value: TomlValue) -> Result<String, Error> {
166        if self.is_enum() {
167            panic!()
168        }
169        let mut lines = Vec::new();
170        let comment = self.comment();
171        let text = comment.render()?;
172        if !text.is_empty() {
173            lines.push(text);
174        }
175        let line = if commented {
176            format!("{}{} = {}", BANG_COMMENT, self.ident, raw_value)
177        } else {
178            format!("{} = {}", self.ident, raw_value)
179        };
180        lines.push(line);
181        Ok(lines.join("\n"))
182    }
183
184    pub fn comment(&self) -> Comment {
185        let mut comment = self.meta.comment();
186        if self.variants.is_empty() {
187            comment.comment_type = CommentType::BlockField;
188        } else {
189            comment.comment_type = CommentType::BlockVariant;
190        }
191        comment
192    }
193}