1use crate::io::process_file_lines;
2use regex::Regex;
3use std::io;
4
5#[derive(Debug)]
7pub struct ParentAndChild {
8 pub parent: String,
9 pub children: Vec<String>,
10}
11
12impl ParentAndChild {
13 pub fn new(parent: String) -> Self {
15 Self {
16 parent,
17 children: Vec::new(),
18 }
19 }
20
21 pub fn add_child(&mut self, child: String) {
23 self.children.push(child);
24 }
25}
26
27pub fn extract_with_mark(file_name: &str, start_line: &Regex) -> io::Result<Vec<ParentAndChild>> {
29 let mut array = Vec::new();
30
31 let _ = process_file_lines(file_name, |line| {
32 if start_line.is_match(&line) {
33 array.push(ParentAndChild::new(line.to_string()));
34 } else if let Some(last) = array.last_mut() {
35 last.add_child(line.to_string());
36 }
37 });
38
39 Ok(array)
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use regex::Regex;
46
47 #[test]
48 fn test_extract_with_mark() {
49 let filename = "test_data.txt";
50 std::fs::write(
51 filename,
52 r#"
53Parent A
54Child A.1
55Child A.2
56Parent B
57Child B.1"#,
58 )
59 .unwrap();
60
61 let start_line = Regex::new(r"^Parent \w+$").unwrap();
62 let result = extract_with_mark(filename, &start_line).unwrap();
63
64 assert_eq!(result.len(), 2);
65 assert_eq!(result[0].parent, "Parent A");
66 assert_eq!(result[0].children, vec!["Child A.1", "Child A.2"]);
67 assert_eq!(result[1].parent, "Parent B");
68 assert_eq!(result[1].children, vec!["Child B.1"]);
69
70 std::fs::remove_file(filename).unwrap();
71 }
72}