imara_diff/myers/
slice.rs

1use std::mem::take;
2use std::ops::RangeBounds;
3
4use crate::intern::Token;
5use crate::myers::preprocess::PreprocessedFile;
6use crate::util::common_edges;
7
8#[derive(Default)]
9pub struct FileSlice<'a> {
10    pub tokens: &'a [Token],
11    indices: &'a [u32],
12    changed: &'a mut [bool],
13}
14
15impl<'a> FileSlice<'a> {
16    pub fn new(file: &'a PreprocessedFile, changed: &'a mut [bool]) -> Self {
17        Self {
18            tokens: &file.tokens,
19            indices: &file.indices,
20            changed,
21        }
22    }
23
24    pub fn mark_changed(&mut self) {
25        for &i in self.indices {
26            self.changed[i as usize] = true;
27        }
28    }
29
30    pub fn borrow(&mut self) -> FileSlice {
31        FileSlice {
32            tokens: self.tokens,
33            changed: self.changed,
34            indices: self.indices,
35        }
36    }
37
38    pub fn slice<R: RangeBounds<u32>>(self, range: R) -> Self {
39        let start = match range.start_bound() {
40            std::ops::Bound::Included(&start) => start,
41            std::ops::Bound::Excluded(&start) => start + 1,
42            std::ops::Bound::Unbounded => 0,
43        };
44
45        let end = match range.end_bound() {
46            std::ops::Bound::Included(&end) => end + 1,
47            std::ops::Bound::Excluded(&end) => end,
48            std::ops::Bound::Unbounded => self.len(),
49        };
50
51        Self {
52            tokens: &self.tokens[start as usize..end as usize],
53            changed: self.changed,
54            indices: &self.indices[start as usize..end as usize],
55        }
56    }
57
58    pub fn strip_common(&mut self, other: &mut Self) {
59        let (start, common_postfix) = common_edges(self.tokens, other.tokens);
60        let end = self.len() - common_postfix;
61        *self = take(self).slice(start..end);
62        let end = other.len() - common_postfix;
63        *other = take(other).slice(start..end)
64    }
65
66    pub fn len(&self) -> u32 {
67        self.tokens.len() as u32
68    }
69
70    pub fn is_empty(&self) -> bool {
71        self.tokens.is_empty()
72    }
73}