1use std::cell::RefCell;
2use std::ops::RangeInclusive;
3use std::rc::Rc;
4
5use crate::elements::{Comment, CommentImpl};
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, Section, SectionElement};
12
13#[derive(Debug)]
14pub struct Document {
15 document_internals: Rc<DocumentInternals>,
16 elements: Vec<Box<dyn SectionElement>>,
17 number_of_lines: u32,
18}
19
20#[derive(Debug)]
21pub struct DocumentInternals {
22 pub comments: RefCell<Vec<Comment>>,
23 pub content: String,
24 pub default_printer: Box<dyn Printer>,
25}
26
27pub trait DocumentImpl {
28 fn append_comment(&mut self, comment: Comment);
29 fn append_elements(&mut self, elements: &mut Vec<Box<dyn SectionElement>>);
30 fn clone_internals(&self) -> Rc<DocumentInternals>;
31 fn get_elements(&self) -> &[Box<dyn SectionElement>];
32 fn get_elements_mut(&mut self) -> &mut Vec<Box<dyn SectionElement>>;
33 fn get_number_of_lines(&self) -> u32;
34 #[allow(clippy::new_ret_no_self)]
35 fn new(content: &str, default_printer: Box<dyn Printer>) -> Document;
36 fn set_number_of_lines(&mut self, number_of_lines: u32);
37}
38
39impl Document {
40 pub const LINE_NUMBER: u32 = 1;
41
42 pub fn elements(&self) -> &[Box<dyn SectionElement>] {
43 for element in &self.elements {
44 element.touch();
45 }
46 self.elements.as_slice()
47 }
48
49 pub fn embed(&self, key: &str) -> Result<EmbedQuery, Error> {
50 let element_option = match self.elements.single_embed_with_key(key) {
51 Matches::None => None,
52 Matches::One(embed) => Some(embed),
53 Matches::Multiple(_first, second) => {
54 return Err(Error::new(
55 "Only a single embed was expected".to_owned(),
56 second.line_number,
57 ))
58 }
59 Matches::WrongType(element) => {
60 return Err(Error::new(
61 "An embed was expected".to_owned(),
62 element.line_number(),
63 ))
64 }
65 };
66
67 Ok(EmbedQuery::new(
69 element_option,
70 Some(key.to_string()),
71 EmbedQueryParent::Document(self),
72 ))
73 }
74
75 pub fn field(&self, key: &str) -> Result<FieldQuery, Error> {
76 let element_option = match self.elements.single_field_with_key(key) {
77 Matches::None => None,
78 Matches::One(field) => Some(field),
79 Matches::Multiple(_first, second) => {
80 return Err(Error::new(
81 "Only a single field was expected".to_owned(),
82 second.line_number,
83 ))
84 }
85 Matches::WrongType(element) => {
86 return Err(Error::new(
87 "A field was expected".to_owned(),
88 element.line_number(),
89 ))
90 }
91 };
92
93 Ok(FieldQuery::new(
94 element_option,
95 Some(key.to_string()),
96 FieldQueryParent::Document(self),
97 ))
98 }
99
100 pub fn flag(&self, key: &str) -> Result<FlagQuery, Error> {
101 let element_option = match self.elements.single_flag_with_key(key) {
102 Matches::None => None,
103 Matches::One(flag) => Some(flag),
104 Matches::Multiple(_first, second) => {
105 return Err(Error::new(
106 "Only a single flag was expected".to_string(),
107 second.line_number,
108 ))
109 }
110 Matches::WrongType(element) => {
111 return Err(Error::new(
112 "A flag was expected".to_string(),
113 element.line_number(),
114 ))
115 }
116 };
117
118 Ok(FlagQuery::new(
119 element_option,
120 Some(key.to_string()),
121 FlagQueryParent::Document(self),
122 ))
123 }
124
125 pub fn line_range(&self) -> RangeInclusive<u32> {
126 1..=self.number_of_lines
127 }
128
129 pub fn optional_embed(&self, key: &str) -> Result<Option<&Embed>, Error> {
130 match self.elements.single_embed_with_key(key) {
131 Matches::None => Ok(None),
132 Matches::One(embed) => {
133 embed.touch();
134 Ok(Some(embed))
135 }
136 Matches::Multiple(_first, second) => Err(Error::new(
137 "Only a single embed was expected".to_string(),
138 second.line_number,
139 )),
140 Matches::WrongType(element) => Err(Error::new(
141 "A embed was expected".to_string(),
142 element.line_number(),
143 )),
144 }
145 }
146
147 pub fn optional_field(&self, key: &str) -> Result<Option<&Field>, Error> {
148 match self.elements.single_field_with_key(key) {
149 Matches::None => Ok(None),
150 Matches::One(field) => {
151 field.touch();
152 Ok(Some(field))
153 }
154 Matches::Multiple(_first, second) => Err(Error::new(
155 "Only a single field was expected".to_string(),
156 second.line_number,
157 )),
158 Matches::WrongType(element) => Err(Error::new(
159 "A field was expected".to_string(),
160 element.line_number(),
161 )),
162 }
163 }
164
165 pub fn optional_flag(&self, key: &str) -> Result<Option<&Flag>, Error> {
166 match self.elements.single_flag_with_key(key) {
167 Matches::None => Ok(None),
168 Matches::One(flag) => {
169 flag.touch();
170 Ok(Some(flag))
171 }
172 Matches::Multiple(_first, second) => Err(Error::new(
173 "Only a single flag was expected".to_string(),
174 second.line_number,
175 )),
176 Matches::WrongType(element) => Err(Error::new(
177 "A flag was expected".to_string(),
178 element.line_number(),
179 )),
180 }
181 }
182
183 pub fn optional_section(&self, key: &str) -> Result<Option<&Section>, Error> {
184 match self.elements.single_section_with_key(key) {
185 Matches::None => Ok(None),
186 Matches::One(section) => Ok(Some(section)),
187 Matches::Multiple(_first, second) => Err(Error::new(
188 "Only a single section was expected".to_string(),
189 second.line_number,
190 )),
191 Matches::WrongType(element) => Err(Error::new(
192 "A section was expected".to_string(),
193 element.line_number(),
194 )),
195 }
196 }
197
198 pub fn required_section(&self, key: &str) -> Result<&Section, Error> {
199 match self.elements.single_section_with_key(key) {
200 Matches::None => Err(Error::new("Not found".to_string(), Document::LINE_NUMBER)),
201 Matches::One(section) => Ok(section),
202 Matches::Multiple(_first, second) => Err(Error::new(
203 "Only a single section was expected".to_string(),
204 second.line_number,
205 )),
206 Matches::WrongType(element) => Err(Error::new(
207 "A section was expected".to_string(),
208 element.line_number(),
209 )),
210 }
211 }
212
213 pub fn section(&self, key: &str) -> Result<SectionQuery, Error> {
214 let element_option = match self.elements.single_section_with_key(key) {
215 Matches::None => None,
216 Matches::One(section) => Some(section),
217 Matches::Multiple(_first, second) => {
218 return Err(Error::new(
219 "Only a single section was expected".to_string(),
220 second.line_number,
221 ))
222 }
223 Matches::WrongType(element) => {
224 return Err(Error::new(
225 "A section was expected".to_string(),
226 element.line_number(),
227 ))
228 }
229 };
230
231 Ok(SectionQuery::new(
232 element_option,
233 Some(key.to_string()),
234 SectionQueryParent::Document(self),
235 ))
236 }
237
238 pub fn snippet(&self) -> String {
239 self.snippet_with_options(&*self.document_internals.default_printer, true)
240 }
241
242 pub fn snippet_with_options(&self, printer: &dyn Printer, gutter: bool) -> String {
243 let mut out = String::new();
244 let mut line_number = 1;
245
246 for element in &self.elements {
247 if line_number > 1 {
248 out.push('\n');
249 }
250
251 let element_line_range = element.line_range();
252
253 while line_number < *element_line_range.start() {
254 if let Some(comment) = self
255 .document_internals
256 .comments
257 .borrow()
258 .iter()
259 .find(|comment| comment.line_number == line_number)
260 {
261 out.push_str(&comment.snippet_with_options(printer, gutter));
262 } else if gutter {
263 out.push_str(&printer.gutter(line_number));
264 }
265
266 out.push('\n');
267
268 line_number += 1;
269 }
270
271 out.push_str(&element.snippet_with_options(printer, gutter));
272
273 line_number = *element_line_range.end() + 1;
274 }
275
276 while line_number <= self.number_of_lines {
277 if line_number > 1 {
278 out.push('\n');
279 }
280
281 if let Some(comment) = self
282 .document_internals
283 .comments
284 .borrow()
285 .iter()
286 .find(|comment| comment.line_number == line_number)
287 {
288 out.push_str(&comment.snippet_with_options(printer, gutter));
289 } else if gutter {
290 out.push_str(&printer.gutter(line_number));
291 }
292
293 line_number += 1;
294 }
295
296 out
297 }
298
299 pub fn untouched_elements(&self) -> Vec<&dyn Element> {
300 self.elements.untouched()
301 }
302}
303
304impl DocumentImpl for Document {
305 fn append_comment(&mut self, comment: Comment) {
306 self.document_internals.comments.borrow_mut().push(comment);
307 }
308
309 fn append_elements(&mut self, elements: &mut Vec<Box<dyn SectionElement>>) {
310 self.elements.append(elements);
311 }
312
313 fn clone_internals(&self) -> Rc<DocumentInternals> {
314 self.document_internals.clone()
315 }
316
317 fn get_elements(&self) -> &[Box<dyn SectionElement>] {
318 self.elements.as_slice()
319 }
320
321 fn get_elements_mut(&mut self) -> &mut Vec<Box<dyn SectionElement>> {
322 &mut self.elements
323 }
324
325 fn get_number_of_lines(&self) -> u32 {
326 self.number_of_lines
327 }
328
329 fn new(content: &str, default_printer: Box<dyn Printer>) -> Document {
330 Document {
331 document_internals: Rc::new(DocumentInternals::new(content, default_printer)),
332 elements: Vec::new(),
333 number_of_lines: 1,
334 }
335 }
336
337 fn set_number_of_lines(&mut self, number_of_lines: u32) {
338 self.number_of_lines = number_of_lines;
339 }
340}
341
342impl DocumentInternals {
343 fn new(content: &str, default_printer: Box<dyn Printer>) -> DocumentInternals {
344 DocumentInternals {
345 comments: RefCell::new(Vec::new()),
346 content: content.to_owned(),
347 default_printer,
348 }
349 }
350}