1use std::ops::Range;
2
3use collections::HashMap;
4
5#[cfg(test)]
6#[ctor::ctor]
7fn init_logger() {
8 if std::env::var("RUST_LOG").is_ok() {
9 env_logger::init();
10 }
11}
12
13pub fn marked_text_by(
14 marked_text: &str,
15 markers: Vec<char>,
16) -> (String, HashMap<char, Vec<usize>>) {
17 let mut extracted_markers: HashMap<char, Vec<usize>> = Default::default();
18 let mut unmarked_text = String::new();
19
20 for char in marked_text.chars() {
21 if markers.contains(&char) {
22 let char_offsets = extracted_markers.entry(char).or_insert(Vec::new());
23 char_offsets.push(unmarked_text.len());
24 } else {
25 unmarked_text.push(char);
26 }
27 }
28
29 (unmarked_text, extracted_markers)
30}
31
32pub fn marked_text(marked_text: &str) -> (String, Vec<usize>) {
33 let (unmarked_text, mut markers) = marked_text_by(marked_text, vec!['|']);
34 (unmarked_text, markers.remove(&'|').unwrap_or_else(Vec::new))
35}
36
37pub fn marked_text_ranges(
38 marked_text: &str,
39 range_markers: Vec<(char, char)>,
40) -> (String, Vec<Range<usize>>) {
41 let mut marker_chars = Vec::new();
42 for (start, end) in range_markers.iter() {
43 marker_chars.push(*start);
44 marker_chars.push(*end);
45 }
46 let (unmarked_text, markers) = marked_text_by(marked_text, marker_chars);
47 let ranges = range_markers
48 .iter()
49 .map(|(start_marker, end_marker)| {
50 let start = markers.get(start_marker).unwrap()[0];
51 let end = markers.get(end_marker).unwrap()[0];
52 start..end
53 })
54 .collect();
55 (unmarked_text, ranges)
56}