1use std::fmt::{Debug, Display, Formatter};
5use std::fs::File;
6use std::io::{BufRead, BufReader, Lines};
7
8#[derive(Debug, Clone)]
9pub struct SnippetError<'a> {
10 message: &'a str
11}
12
13impl<'a> Display for SnippetError<'a> {
14 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
15 write!(f, "{}", self.message)
16 }
17}
18
19impl<'a> std::error::Error for SnippetError<'a> {}
20
21#[derive(Debug)]
23pub struct SnippetParser<'a> {
24 path: Option<&'a str>,
25 iter_reader: Option<Lines<BufReader<File>>>,
26 snippets: Option<Vec<Snippet>>,
27 snippet_index: usize
28}
29
30impl<'a> SnippetParser<'a> {
32 pub fn new() -> Self {
34 Self { path: None, iter_reader: None, snippets: None, snippet_index: 0 }
35 }
36
37 pub fn read(path: &'a str) -> std::io::Result<Self> {
39 let file = File::open(path);
40 if file.is_err() {
41 return Err(file.err().unwrap());
42 }
43 let reader = BufReader::new(file.unwrap());
44 Ok(Self { path: Some(path), iter_reader: Some(reader.lines()), snippets: None, snippet_index: 0 })
45 }
46
47 pub fn from_snippets(snips: Vec<Snippet>) -> Self {
49 Self { path: None, iter_reader: None, snippets: Some(snips), snippet_index: 0 }
50 }
51}
52
53impl<'a> SnippetParser<'a> {
54 pub fn add_snippet(&mut self, snip: Snippet) {
56 if let Some(snippets) = &mut self.snippets {
57 snippets.push(snip);
58 } else {
59 self.snippets = Some(vec![snip]);
60 }
61 }
62
63 pub fn get_snippets(&self) -> std::io::Result<Vec<Snippet>> {
66 return if self.path.is_some() {
67 let file = File::open(self.path.unwrap());
68 if file.is_err() {
69 return Err(file.err().unwrap());
70 }
71 let reader = BufReader::new(file.unwrap());
72 let copy_of_self = Self {
73 path: Some(self.path.unwrap()),
74 iter_reader: Some(reader.lines()),
75 snippets: self.snippets.clone(),
76 snippet_index: 0
77 };
78 let file_snippets: Vec<Snippet> = copy_of_self.into_iter().map(|snippet| snippet.clone()).collect();
79 Ok(file_snippets)
80 } else {
81 if let Some(snippets) = &self.snippets {
82 Ok(snippets.clone())
83 } else {
84 Ok(Vec::new())
85 }
86 }
87 }
88
89 pub fn get_snippet(&self, title: &str) -> std::io::Result<Option<Snippet>> {
98 let snippets = self.get_snippets();
99 if let Ok(snippets) = snippets {
100 let found_snippet: Option<&Snippet> = snippets.iter().find_map(|snippet| {
101 if &snippet.title == title {
102 Some(snippet)
103 } else {
104 None
105 }
106 });
107 return if let Some(found_snippet) = found_snippet {
108 Ok(Some(found_snippet.clone()))
109 } else {
110 Ok(None)
111 }
112 } else {
113 Err(snippets.err().unwrap())
114 }
115 }
116}
117
118impl Iterator for SnippetParser<'_> {
119 type Item = Snippet;
120
121 fn next(&mut self) -> Option<Self::Item> {
122 if self.iter_reader.is_some() {
123 return if let Some(snippet) = &self.read_next_snippet() {
124 Some(snippet.clone())
126 } else {
127 self.read_next_from_snippets()
129 }
130 } else {
131 self.read_next_from_snippets()
133 }
134 }
135}
136
137#[cfg(test)]
138#[test]
139fn read_next_snippet_test() {
140 let mut parser = SnippetParser::read("./tests/snippets/snippet_test.snip").unwrap();
141 let first_snip = "\
142Are we human?
143Or are we dancer?\
144";
145 let second_snip = "\
146This is my church.
147This is where I heal my hurts.";
148
149 let third_snip = "\
150Never gonna give you up
151Never gonna let you down
152Never gonna run around and desert you
153
154Never gonna make you cry
155Never gonna say goodbye
156Never gonna tell a lie and hurt you
157\
158";
159 let first_read_snip = parser.read_next_snippet().unwrap();
160 let second_read_snip = parser.read_next_snippet().unwrap();
161 let third_read_snip = parser.read_next_snippet().unwrap();
162
163 assert_eq!(first_snip, first_read_snip.s);
164 assert_eq!(second_snip, second_read_snip.s);
165 assert_eq!(third_snip, third_read_snip.s);
166 assert_eq!("snippet1", first_read_snip.title);
167 assert_eq!("snippet2", second_read_snip.title);
168 assert_eq!("snippet3 with space", third_read_snip.title);
169 assert_eq!(None, parser.read_next_snippet());
170}
171
172#[cfg(test)]
173#[test]
174fn read_next_snippet_test_with_adding_snippet() {
175 let mut parser = SnippetParser::read("./tests/snippets/snippet_test.snip").unwrap();
178 let first_snip = "\
179Are we human?
180Or are we dancer?\
181";
182 let second_snip = "\
183This is my church.
184This is where I heal my hurts.";
185
186 let third_snip = "\
187Never gonna give you up
188Never gonna let you down
189Never gonna run around and desert you
190
191Never gonna make you cry
192Never gonna say goodbye
193Never gonna tell a lie and hurt you
194\
195";
196
197 let fourth_snip = "\
198Are you on the square?
199Are you on the hammer?
200Are you ready to stand right here right now
201Before the devil?
202\
203";
204 let fourth_snippet = Snippet::new("Square Hammer".to_string(), fourth_snip.to_string());
205
206 parser.add_snippet(fourth_snippet);
207 println!("{:?}", parser);
208 let first_read_snip = parser.read_next_snippet().unwrap();
209 let second_read_snip = parser.read_next_snippet().unwrap();
210 let third_read_snip = parser.read_next_snippet().unwrap();
211
212 let fourth_read_snip = parser.read_next_snippet();
213
214 assert_eq!(first_snip, first_read_snip.s);
215 assert_eq!(second_snip, second_read_snip.s);
216 assert_eq!(third_snip, third_read_snip.s);
217 assert_eq!("snippet1", first_read_snip.title);
218 assert_eq!("snippet2", second_read_snip.title);
219 assert_eq!("snippet3 with space", third_read_snip.title);
220 assert_eq!(None, fourth_read_snip);
223 assert_eq!(None, parser.read_next_snippet());
224}
225
226impl<'a> SnippetParser<'a> {
228 fn read_next_snippet(&mut self) -> Option<Snippet> {
231 let mut title: String = String::new();
232 let mut started = false;
233 let mut lines: Vec<String> = Vec::new();
234 loop {
236 if let Some(_lines) = &mut self.iter_reader {
237 let line = _lines.next();
238 if let Some(line) = line {
239 if line.is_err() {
240 return None;
241 }
242 if started == false {
243 if line.as_ref().unwrap().contains("--") {
244 let _title = line.unwrap().replace("--", "");
246 title = _title.trim().to_string();
247 started = true;
248 }
249 } else {
250 if line.as_ref().unwrap().contains("-- end --") {
252 break; } else {
254 lines.push(line.unwrap());
256 }
257 }
258 } else {
259 return None;
260 }
261 } else {
262 return None;
263 }
264 }
265
266 let len_of_lines = lines.len();
267 let s: String = lines
268 .into_iter()
269 .enumerate()
270 .flat_map(|(index, line)| {
271 let mut line = line;
272 if index != len_of_lines - 1 {
273 line.push_str("\n");
274 }
275 line.chars().collect::<Vec<char>>()
276 }).collect();
277 Some(Snippet::new(title, s))
278 }
279
280 fn read_next_from_snippets(&mut self) -> Option<Snippet> {
282 if let Some(snippets) = &self.snippets {
283 let snippet = snippets.get(self.snippet_index);
284 self.snippet_index += 1;
285 if let Some(snippet) = snippet {
286 Some(snippet.clone())
287 } else {
288 None
289 }
290 } else {
291 None
292 }
293 }
294}
295
296impl ToString for SnippetParser<'_> {
297 fn to_string(&self) -> String {
298 let mut s = String::new();
299 for snip in self.get_snippets().unwrap() {
300 s.push_str(snip.to_string().as_str());
301 s.push_str("\n");
302 }
303
304 s
305 }
306}
307
308#[derive(Clone, PartialEq, Debug)]
309pub struct Snippet {
311 title: String,
312 s: String
313}
314
315impl ToString for Snippet {
322 fn to_string(&self) -> String {
323 String::from(
324 format!("-- {} --\n{}\n-- end --", self.title, self.s)
325 )
326 }
327}
328
329impl Snippet {
330 pub fn new(title: String, s: String) -> Snippet {
332 Snippet { title, s }
333 }
334
335 pub fn append(&mut self, s: &str) {
337 self.s += s;
338 }
339
340 pub fn get_string(&self) -> &str {
342 &self.s
343 }
344}