aboutsummaryrefslogtreecommitdiff
path: root/src/grid/storage.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/grid/storage.rs')
-rw-r--r--src/grid/storage.rs207
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);
+}