1use std::{
2 cmp::Ordering,
3 ops::Range,
4 path::{Path, PathBuf},
5 rc::Rc,
6};
7
8#[derive(Debug)]
9struct IndexEntry {
10 name: Rc<PathBuf>,
11 start: usize,
12 range: Range<usize>,
13}
14
15pub struct Index {
17 segs: Vec<IndexEntry>,
18 size: usize,
19}
20
21impl Index {
22 fn new() -> Self {
23 Self {
24 segs: Vec::new(),
25 size: 0,
26 }
27 }
28
29 fn push(&mut self, name: Rc<PathBuf>, start: usize, size: usize) {
30 self.segs.push(IndexEntry {
31 name,
32 start,
33 range: self.size..(self.size + size),
34 });
35 self.size += size;
36 }
37
38 fn append(&mut self, mut index: Index) {
39 for seg in index.segs.iter_mut() {
40 let r = &mut seg.range;
41 r.start += self.size;
42 r.end += self.size;
43 }
44 self.segs.append(&mut index.segs);
45 self.size += index.size;
46 }
47
48 pub fn search(&self, pos: usize) -> Option<(PathBuf, usize)> {
50 match self.segs.binary_search_by(|seg| {
51 if pos < seg.range.start {
52 Ordering::Greater
53 } else if pos >= seg.range.end {
54 Ordering::Less
55 } else {
56 Ordering::Equal
57 }
58 }) {
59 Ok(i) => {
60 let seg = &self.segs[i];
61 Some(((*seg.name).clone(), pos - seg.range.start + seg.start))
62 }
63 Err(_) => None,
64 }
65 }
66}
67
68pub struct Node {
70 name: PathBuf,
71 inner: Vec<(Node, usize)>,
72 text: String,
73 index: Vec<Range<usize>>,
74}
75
76impl Node {
77 pub(crate) fn new(name: &Path) -> Self {
78 Self {
79 name: name.to_path_buf(),
80 inner: Vec::new(),
81 text: String::new(),
82 index: Vec::new(),
83 }
84 }
85
86 pub fn name(&self) -> &Path {
87 &self.name
88 }
89
90 pub(crate) fn add_line(&mut self, line: &str) {
91 let plen = self.text.len();
92 self.text.push_str(line.trim_end());
93 self.text.push('\n');
94 self.index.push(plen..self.text.len());
95 }
96
97 pub(crate) fn add_child(&mut self, node: Node) {
98 self.add_line("");
99 self.inner.push((node, self.index.len() - 1));
100 }
101
102 pub fn lines_count(&self) -> usize {
103 self.index.len()
104 }
105
106 pub fn collect(&self) -> (String, Index) {
108 let mut accum = String::new();
109 let mut index = Index::new();
110
111 let name = Rc::new(self.name.clone());
112
113 let mut ppos = 0;
114 for (node, pos) in self.inner.iter() {
115 let start = self.index[ppos].start;
116 let end = self.index[*pos].end;
117
118 accum.push_str(&self.text[start..end]);
119 index.push(name.clone(), ppos, pos - ppos + 1);
120
121 let (child_str, child_index) = node.collect();
122 accum.push_str(&child_str);
123 index.append(child_index);
124
125 ppos = *pos + 1;
126 }
127
128 if ppos < self.index.len() {
129 accum.push_str(&self.text[self.index[ppos].start..]);
130 index.push(name, ppos, self.index.len() - ppos);
131 }
132
133 (accum, index)
134 }
135}