1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use std::ops::RangeFrom;
use std::collections::BTreeMap;

pub struct LineCache<T> {
    lines: BTreeMap<usize, T>
}

impl<T> LineCache<T> {
    pub fn new() -> Self {
        Self {
            lines: BTreeMap::new()
        }
    }

    #[allow(dead_code)]
    pub fn len(&self) -> usize {
        self.lines.len()
    }

    #[allow(dead_code)]
    pub fn is_empty(&self) -> bool {
        self.lines.len() == 0
    }

    pub fn cache(&mut self, line_idx: usize, line: T) {
        self.lines.insert(line_idx, line);
    }

    pub fn get(&self, line_idx: usize) -> Option<&T> {
        self.lines.get(&line_idx)
    }

    /// Returns whether the line was cached.
    pub fn invalidate_line(&mut self, line_idx: usize) -> bool {
        self.lines.remove(&line_idx).is_some()
    }

    /// Returns whether at least one line was cached.
    // TODO name invalidate_lines() instead with RangeArgument once stable
    pub fn invalidate_lines_from(&mut self, line_idc: RangeFrom<usize>) -> bool {
        let mut changed = false;
        for line_idx in line_idc.start..self.lines.keys().max().unwrap_or(&line_idc.start) + 1 {
            changed |= self.invalidate_line(line_idx);
        }
        changed
    }
}