diff options
Diffstat (limited to 'src/grid/storage.rs')
-rw-r--r-- | src/grid/storage.rs | 207 |
1 files changed, 190 insertions, 17 deletions
diff --git a/src/grid/storage.rs b/src/grid/storage.rs index 87a129d0..6a119ead 100644 --- a/src/grid/storage.rs +++ b/src/grid/storage.rs @@ -12,11 +12,11 @@ /// implementation is provided. Anything from Vec that should be exposed must be /// done so manually. use std::ops::{Index, IndexMut}; -use std::slice; use static_assertions::assert_eq_size; -use crate::index::Line; +use crate::index::{Column, Line}; +use crate::grid::GridCell; use super::Row; /// Maximum number of invisible lines before buffer is resized @@ -196,6 +196,7 @@ impl<T> Storage<T> { self.len } + #[inline] /// Compute actual index in underlying storage given the requested index. fn compute_index(&self, requested: usize) -> usize { debug_assert!(requested < self.len); @@ -250,18 +251,7 @@ impl<T> Storage<T> { } } - /// Iterate over *all* entries in the underlying buffer - /// - /// This includes hidden entries. - /// - /// XXX This suggests that Storage is a leaky abstraction. Ultimately, this - /// is needed because of the grow lines functionality implemented on - /// this type, and maybe that's where the leak is necessitating this - /// accessor. - pub fn iter_mut_raw<'a>(&'a mut self) -> slice::IterMut<'a, Row<T>> { - self.inner.iter_mut() - } - + #[inline] pub fn rotate(&mut self, count: isize) { debug_assert!(count.abs() as usize <= self.inner.len()); @@ -270,9 +260,75 @@ impl<T> Storage<T> { } // Fast path + #[inline] pub fn rotate_up(&mut self, count: usize) { self.zero = (self.zero + count) % self.inner.len(); } + + #[inline] + pub fn insert(&mut self, index: usize, row: Row<T>, max_lines: usize) { + let index = self.compute_index(index); + self.inner.insert(index, row); + + if index < self.zero { + self.zero += 1; + } + + if self.len < max_lines { + self.len += 1; + } + } + + #[inline] + pub fn remove(&mut self, index: usize) -> Row<T> { + let index = self.compute_index(index); + if index < self.zero { + self.zero -= 1; + } + self.len -= 1; + + self.inner.remove(index) + } + + /// Shrink columns of hidden buffered lines. + /// + /// XXX This suggests that Storage is a leaky abstraction. Ultimately, this + /// is needed because of the grow/shrink lines functionality. + #[inline] + pub fn shrink_hidden(&mut self, cols: Column) + where + T: GridCell + Copy + { + let start = self.zero + self.len; + let end = self.zero + self.inner.len(); + for mut i in start..end { + if i >= self.inner.len() { + i -= self.inner.len(); + } + + self.inner[i].shrink(cols); + } + } + + /// Grow columns of hidden buffered lines. + /// + /// XXX This suggests that Storage is a leaky abstraction. Ultimately, this + /// is needed because of the grow/shrink lines functionality. + #[inline] + pub fn grow_hidden(&mut self, cols: Column, template: &T) + where + T: Copy + Clone + { + let start = self.zero + self.len; + let end = self.zero + self.inner.len(); + for mut i in start..end { + if i >= self.inner.len() { + i -= self.inner.len(); + } + + self.inner[i].grow(cols, template); + } + } } impl<T> Index<usize> for Storage<T> { @@ -308,9 +364,6 @@ impl<T> IndexMut<Line> for Storage<T> { } } -#[cfg(test)] -use crate::index::Column; - /// Grow the buffer one line at the end of the buffer /// /// Before: @@ -693,3 +746,123 @@ fn initialize() { assert_eq!(storage.zero, shrinking_expected.zero); assert_eq!(storage.len, shrinking_expected.len); } + +#[test] +fn insert() { + // Setup storage area + let mut storage = Storage { + inner: vec![ + Row::new(Column(1), &'4'), + Row::new(Column(1), &'5'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'3'), + ], + zero: 2, + visible_lines: Line(0), + len: 6, + }; + + // Initialize additional lines + storage.insert(2, Row::new(Column(1), &'-'), 100); + + // Make sure the lines are present and at the right location + let shrinking_expected = Storage { + inner: vec![ + Row::new(Column(1), &'4'), + Row::new(Column(1), &'5'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'-'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'3'), + ], + zero: 2, + visible_lines: Line(0), + len: 7, + }; + assert_eq!(storage.inner, shrinking_expected.inner); + assert_eq!(storage.zero, shrinking_expected.zero); + assert_eq!(storage.len, shrinking_expected.len); +} + +#[test] +fn insert_truncate_max() { + // Setup storage area + let mut storage = Storage { + inner: vec![ + Row::new(Column(1), &'4'), + Row::new(Column(1), &'5'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'3'), + ], + zero: 2, + visible_lines: Line(0), + len: 6, + }; + + // Initialize additional lines + storage.insert(2, Row::new(Column(1), &'-'), 6); + + // Make sure the lines are present and at the right location + let shrinking_expected = Storage { + inner: vec![ + Row::new(Column(1), &'4'), + Row::new(Column(1), &'5'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'-'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'3'), + ], + zero: 2, + visible_lines: Line(0), + len: 6, + }; + assert_eq!(storage.inner, shrinking_expected.inner); + assert_eq!(storage.zero, shrinking_expected.zero); + assert_eq!(storage.len, shrinking_expected.len); +} + +#[test] +fn insert_at_zero() { + // Setup storage area + let mut storage = Storage { + inner: vec![ + Row::new(Column(1), &'4'), + Row::new(Column(1), &'5'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'3'), + ], + zero: 2, + visible_lines: Line(0), + len: 6, + }; + + // Initialize additional lines + storage.insert(0, Row::new(Column(1), &'-'), 6); + + // Make sure the lines are present and at the right location + let shrinking_expected = Storage { + inner: vec![ + Row::new(Column(1), &'4'), + Row::new(Column(1), &'5'), + Row::new(Column(1), &'-'), + Row::new(Column(1), &'0'), + Row::new(Column(1), &'1'), + Row::new(Column(1), &'2'), + Row::new(Column(1), &'3'), + ], + zero: 2, + visible_lines: Line(0), + len: 6, + }; + assert_eq!(storage.inner, shrinking_expected.inner); + assert_eq!(storage.zero, shrinking_expected.zero); + assert_eq!(storage.len, shrinking_expected.len); +} |