1use std::cell::Cell;
2use std::ops::{Range, RangeInclusive};
3use std::rc::Rc;
4
5use crate::elements::{CommentImpl, DocumentInternals, ElementImpl};
6use crate::queries::{
7 EmbedQuery, EmbedQueryImpl, EmbedQueryParent, FieldQuery, FieldQueryImpl, FieldQueryParent,
8 FlagQuery, FlagQueryImpl, FlagQueryParent, Matches, SectionElements, SectionQuery,
9 SectionQueryImpl, SectionQueryParent,
10};
11use crate::{Element, Embed, Error, Field, Flag, Printer};
12
13#[derive(Debug)]
14pub struct Section {
15 document_internals: Rc<DocumentInternals>,
16 elements: Vec<Box<dyn SectionElement>>,
17 key_range: Range<usize>,
18 line_begin_index: usize,
19 pub line_number: u32,
20 operator_range: Range<usize>,
21 touched: Cell<bool>,
22}
23
24pub trait SectionElement: std::fmt::Debug + Element + ElementImpl {
25 fn as_element(&self) -> &dyn Element;
26
27 fn as_mut_embed(&mut self) -> Option<&mut Embed> {
29 None
30 }
31 fn as_mut_field(&mut self) -> Option<&mut Field> {
32 None
33 }
34 fn as_mut_flag(&mut self) -> Option<&mut Flag> {
35 None
36 }
37 fn as_mut_section(&mut self) -> Option<&mut Section> {
38 None
39 }
40
41 fn key(&self) -> &str;
42}
43
44pub trait SectionImpl {
45 fn get_elements(&self) -> &[Box<dyn SectionElement>];
46 fn get_elements_mut(&mut self) -> &mut Vec<Box<dyn SectionElement>>;
47 fn get_elements_ref(&self) -> &Vec<Box<dyn SectionElement>>;
48 #[allow(clippy::new_ret_no_self)]
49 fn new(
50 document_internals: Rc<DocumentInternals>,
51 elements: Vec<Box<dyn SectionElement>>,
52 key_range: Range<usize>,
53 line_begin_index: usize,
54 line_number: u32,
55 operator_range: Range<usize>,
56 ) -> Section;
57}
58
59impl Section {
60 pub fn elements(&self) -> &[Box<dyn SectionElement>] {
61 for element in &self.elements {
62 element.touch();
63 }
64 self.elements.as_slice()
65 }
66
67 pub fn embed(&self, key: &str) -> Result<EmbedQuery, Error> {
68 let element_option = match self.elements.single_embed_with_key(key) {
69 Matches::None => None,
70 Matches::One(embed) => Some(embed),
71 Matches::Multiple(_first, second) => {
72 return Err(Error::new(
73 "Only a single embed was expected".to_string(),
74 second.line_number,
75 ))
76 }
77 Matches::WrongType(element) => {
78 return Err(Error::new(
79 "An embed was expected".to_string(),
80 element.line_number(),
81 ))
82 }
83 };
84
85 Ok(EmbedQuery::new(
87 element_option,
88 Some(key.to_string()),
89 EmbedQueryParent::Section(self),
90 ))
91 }
92
93 pub fn field(&self, key: &str) -> Result<FieldQuery, Error> {
94 let element_option = match self.elements.single_field_with_key(key) {
95 Matches::None => None,
96 Matches::One(field) => Some(field),
97 Matches::Multiple(_first, second) => {
98 return Err(Error::new(
99 "Only a single field was expected".to_string(),
100 second.line_number,
101 ))
102 }
103 Matches::WrongType(element) => {
104 return Err(Error::new(
105 "A field was expected".to_string(),
106 element.line_number(),
107 ))
108 }
109 };
110
111 Ok(FieldQuery::new(
112 element_option,
113 Some(key.to_string()),
114 FieldQueryParent::Section(self),
115 ))
116 }
117
118 pub fn flag(&self, key: &str) -> Result<FlagQuery, Error> {
119 let element_option = match self.elements.single_flag_with_key(key) {
120 Matches::None => None,
121 Matches::One(flag) => Some(flag),
122 Matches::Multiple(_first, second) => {
123 return Err(Error::new(
124 "Only a single flag was expected".to_string(),
125 second.line_number,
126 ))
127 }
128 Matches::WrongType(element) => {
129 return Err(Error::new(
130 "A flag was expected".to_string(),
131 element.line_number(),
132 ))
133 }
134 };
135
136 Ok(FlagQuery::new(
137 element_option,
138 Some(key.to_string()),
139 FlagQueryParent::Section(self),
140 ))
141 }
142
143 pub fn len(&self) -> usize {
144 self.elements.len()
145 }
146
147 pub fn is_empty(&self) -> bool {
148 self.elements.is_empty()
149 }
150
151 pub fn optional_embed(&self, key: &str) -> Result<Option<&Embed>, Error> {
152 match self.elements.single_embed_with_key(key) {
153 Matches::None => Ok(None),
154 Matches::One(embed) => {
155 embed.touch();
156 Ok(Some(embed))
157 }
158 Matches::Multiple(_first, second) => Err(Error::new(
159 "Only a single embed was expected".to_string(),
160 second.line_number,
161 )),
162 Matches::WrongType(element) => Err(Error::new(
163 "A embed was expected".to_string(),
164 element.line_number(),
165 )),
166 }
167 }
168
169 pub fn optional_field(&self, key: &str) -> Result<Option<&Field>, Error> {
170 match self.elements.single_field_with_key(key) {
171 Matches::None => Ok(None),
172 Matches::One(field) => {
173 field.touch();
174 Ok(Some(field))
175 }
176 Matches::Multiple(_first, second) => Err(Error::new(
177 "Only a single field was expected".to_string(),
178 second.line_number,
179 )),
180 Matches::WrongType(element) => Err(Error::new(
181 "A field was expected".to_string(),
182 element.line_number(),
183 )),
184 }
185 }
186
187 pub fn optional_flag(&self, key: &str) -> Result<Option<&Flag>, Error> {
188 match self.elements.single_flag_with_key(key) {
189 Matches::None => Ok(None),
190 Matches::One(flag) => {
191 flag.touch();
192 Ok(Some(flag))
193 }
194 Matches::Multiple(_first, second) => Err(Error::new(
195 "Only a single flag was expected".to_string(),
196 second.line_number,
197 )),
198 Matches::WrongType(element) => Err(Error::new(
199 "A flag was expected".to_string(),
200 element.line_number(),
201 )),
202 }
203 }
204
205 pub fn optional_section(&self, key: &str) -> Result<Option<&Section>, Error> {
206 match self.elements.single_section_with_key(key) {
207 Matches::None => Ok(None),
208 Matches::One(section) => {
209 section.touch();
210 Ok(Some(section))
211 }
212 Matches::Multiple(_first, second) => Err(Error::new(
213 "Only a single section was expected".to_string(),
214 second.line_number,
215 )),
216 Matches::WrongType(element) => Err(Error::new(
217 "A section was expected".to_string(),
218 element.line_number(),
219 )),
220 }
221 }
222
223 pub fn required_embed(&self, key: &str) -> Result<&Embed, Error> {
224 match self.elements.single_embed_with_key(key) {
225 Matches::None => Err(Error::new("Not found".to_string(), self.line_number)),
226 Matches::One(embed) => {
227 embed.touch();
228 Ok(embed)
229 }
230 Matches::Multiple(_first, second) => Err(Error::new(
231 format!("Only a single embed with key {} was expected", key),
232 second.line_number,
233 )),
234 Matches::WrongType(element) => Err(Error::new(
235 "A embed was expected".to_string(),
236 element.line_number(),
237 )),
238 }
239 }
240
241 pub fn required_field(&self, key: &str) -> Result<&Field, Error> {
242 match self.elements.single_field_with_key(key) {
243 Matches::None => Err(Error::new("Not found".to_string(), self.line_number)),
244 Matches::One(field) => {
245 field.touch();
246 Ok(field)
247 }
248 Matches::Multiple(_first, second) => Err(Error::new(
249 format!("Only a single field with key {} was expected", key),
250 second.line_number,
251 )),
252 Matches::WrongType(element) => Err(Error::new(
253 "A field was expected".to_string(),
254 element.line_number(),
255 )),
256 }
257 }
258
259 pub fn required_flag(&self, key: &str) -> Result<&Flag, Error> {
260 match self.elements.single_flag_with_key(key) {
261 Matches::None => Err(Error::new("Not found".to_string(), self.line_number)),
262 Matches::One(flag) => {
263 flag.touch();
264 Ok(flag)
265 }
266 Matches::Multiple(_first, second) => Err(Error::new(
267 format!("Only a single flag with key {} was expected", key),
268 second.line_number,
269 )),
270 Matches::WrongType(element) => Err(Error::new(
271 "A flag was expected".to_string(),
272 element.line_number(),
273 )),
274 }
275 }
276
277 pub fn required_section(&self, key: &str) -> Result<&Section, Error> {
278 match self.elements.single_section_with_key(key) {
279 Matches::None => Err(Error::new("Not found".to_string(), self.line_number)),
280 Matches::One(section) => {
281 section.touch();
282 Ok(section)
283 }
284 Matches::Multiple(_first, second) => Err(Error::new(
285 format!("Only a single section with key {} was expected", key),
286 second.line_number,
287 )),
288 Matches::WrongType(element) => Err(Error::new(
289 "A section was expected".to_string(),
290 element.line_number(),
291 )),
292 }
293 }
294
295 pub fn section(&self, key: &str) -> Result<SectionQuery, Error> {
296 let element_option = match self.elements.single_section_with_key(key) {
297 Matches::None => None,
298 Matches::One(section) => Some(section),
299 Matches::Multiple(_first, second) => {
300 return Err(Error::new(
301 "Only a single section was expected".to_string(),
302 second.line_number,
303 ))
304 }
305 Matches::WrongType(element) => {
306 return Err(Error::new(
307 "A section was expected".to_string(),
308 element.line_number(),
309 ))
310 }
311 };
312
313 Ok(SectionQuery::new(
314 element_option,
315 Some(key.to_string()),
316 SectionQueryParent::Section(self),
317 ))
318 }
319
320 pub fn untouched_elements(&self) -> Vec<&dyn Element> {
321 self.elements.untouched()
322 }
323}
324
325impl Element for Section {
326 fn as_section(&self) -> Option<&Section> {
327 Some(self)
328 }
329
330 fn is_section(&self) -> bool {
331 true
332 }
333
334 fn line_number(&self) -> u32 {
335 self.line_number
336 }
337
338 fn snippet(&self) -> String {
339 self.snippet_with_options(&*self.document_internals.default_printer, true)
340 }
341
342 fn snippet_with_options(&self, printer: &dyn Printer, gutter: bool) -> String {
343 let mut out = String::new();
344
345 if gutter {
346 out.push_str(&printer.gutter(self.line_number));
347 }
348
349 out.push_str(
350 &self.document_internals.content[self.line_begin_index..self.operator_range.start],
351 );
352 out.push_str(
353 &printer.operator(&self.document_internals.content[self.operator_range.clone()]),
354 );
355 out.push_str(
356 &self.document_internals.content[self.operator_range.end..self.key_range.start],
357 );
358 out.push_str(&printer.key(&self.document_internals.content[self.key_range.clone()]));
359
360 let mut line_number = self.line_number + 1;
361
362 for element in &self.elements {
363 out.push('\n');
364
365 let element_line_range = element.line_range();
366
367 while line_number < *element_line_range.start() {
368 if let Some(comment) = self
369 .document_internals
370 .comments
371 .borrow()
372 .iter()
373 .find(|comment| comment.line_number == line_number)
374 {
375 out.push_str(&comment.snippet_with_options(printer, gutter));
376 } else if gutter {
377 out.push_str(&printer.gutter(line_number));
378 }
379
380 out.push('\n');
381
382 line_number += 1;
383 }
384
385 out.push_str(&element.snippet_with_options(printer, gutter));
386
387 line_number = *element_line_range.end() + 1;
388 }
389
390 out
391 }
392
393 fn touch(&self) {
394 self.touched.set(true);
395 }
396}
397
398impl ElementImpl for Section {
399 fn line_range(&self) -> RangeInclusive<u32> {
400 match self.elements.last() {
401 Some(element) => self.line_number..=*element.line_range().end(),
402 None => self.line_number..=self.line_number,
403 }
404 }
405
406 fn touched(&self) -> bool {
407 self.touched.get()
408 }
409}
410
411impl SectionElement for Section {
412 fn as_element(&self) -> &dyn Element {
413 self
414 }
415
416 fn as_mut_section(&mut self) -> Option<&mut Section> {
417 Some(self)
418 }
419
420 fn key(&self) -> &str {
421 &self.document_internals.content[self.key_range.clone()]
422 }
423}
424
425impl SectionImpl for Section {
426 fn get_elements(&self) -> &[Box<dyn SectionElement>] {
427 self.elements.as_slice()
428 }
429
430 fn get_elements_mut(&mut self) -> &mut Vec<Box<dyn SectionElement>> {
431 &mut self.elements
432 }
433
434 fn get_elements_ref(&self) -> &Vec<Box<dyn SectionElement>> {
435 &self.elements
436 }
437
438 fn new(
439 document_internals: Rc<DocumentInternals>,
440 elements: Vec<Box<dyn SectionElement>>,
441 key_range: Range<usize>,
442 line_begin_index: usize,
443 line_number: u32,
444 operator_range: Range<usize>,
445 ) -> Section {
446 Section {
447 document_internals,
448 elements,
449 key_range,
450 line_begin_index,
451 line_number,
452 operator_range,
453 touched: Cell::new(false),
454 }
455 }
456}