ys1r/
text.rs

1use crate::io::process_file_lines;
2use regex::Regex;
3use std::io;
4
5/// Represents a parent line and its associated child lines.
6#[derive(Debug)]
7pub struct ParentAndChild {
8    pub parent: String,
9    pub children: Vec<String>,
10}
11
12impl ParentAndChild {
13    /// Creates a new `ParentAndChild` with the given parent line.
14    pub fn new(parent: String) -> Self {
15        Self {
16            parent,
17            children: Vec::new(),
18        }
19    }
20
21    /// Adds a child line to this `ParentAndChild`.
22    pub fn add_child(&mut self, child: String) {
23        self.children.push(child);
24    }
25}
26
27/// Reads lines from a file and extracts them into `ParentAndChild` objects.
28pub 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}