diff options
Diffstat (limited to 'src/grid')
-rw-r--r-- | src/grid/mod.rs | 2 | ||||
-rw-r--r-- | src/grid/storage.rs | 108 |
2 files changed, 62 insertions, 48 deletions
diff --git a/src/grid/mod.rs b/src/grid/mod.rs index f3c8ea79..87ac3d05 100644 --- a/src/grid/mod.rs +++ b/src/grid/mod.rs @@ -125,7 +125,7 @@ impl<T: Copy + Clone> Grid<T> { // TODO (jwilm) Allocating each line at this point is expensive and // delays startup. A nice solution might be having `Row` delay // allocation until it's actually used. - for _ in 0..raw.capacity() { + for _ in 0..raw.len() { raw.push(Row::new(cols, &template)); } diff --git a/src/grid/storage.rs b/src/grid/storage.rs index 323d8ec4..a50e8076 100644 --- a/src/grid/storage.rs +++ b/src/grid/storage.rs @@ -20,6 +20,8 @@ pub struct Storage<T> { inner: Vec<T>, zero: usize, visible_lines: Line, + #[serde(skip)] + len: usize, } impl<T: PartialEq> ::std::cmp::PartialEq for Storage<T> { @@ -70,58 +72,49 @@ impl<T> Storage<T> { inner: Vec::with_capacity(cap), zero: 0, visible_lines: lines - 1, + len: cap, } } - #[inline] - pub fn capacity(&self) -> usize { - self.inner.capacity() - } - /// Increase the number of lines in the buffer pub fn grow_visible_lines(&mut self, next: Line, template_row: T) where T: Clone, { - // Calculate insert position (before the first line) - let offset = self.zero % self.inner.len(); - - // Insert new template row for every line grown + // Number of lines the buffer needs to grow let lines_to_grow = (next - (self.visible_lines + 1)).0; - for _ in 0..lines_to_grow { - self.inner.insert(offset, template_row.clone()); - } - // Set zero to old zero + lines grown - self.zero = offset + lines_to_grow; + // Only grow if there are not enough lines still hidden + if lines_to_grow > (self.inner.len() - self.len) { + // Lines to grow additionally to invisible lines + let new_lines_to_grow = lines_to_grow - (self.inner.len() - self.len); - // Update visible lines - self.visible_lines = next - 1; - } + // Get the position of the start of the buffer + let offset = self.zero % self.inner.len(); - /// Decrease the number of lines in the buffer - pub fn shrink_visible_lines(&mut self, next: Line) { - // Calculate shrinkage and last line of buffer - let shrinkage = (self.visible_lines + 1 - next).0; - let offset = (self.zero + self.inner.len() - 1) % self.inner.len(); + // Split off the beginning of the raw inner buffer + let mut start_buffer = self.inner.split_off(offset); - // Generate range of lines that have to be deleted before the zero line - let start = offset.saturating_sub(shrinkage - 1); - let shrink_before = start..(offset + 1); + // Insert new template rows at the end of the raw inner buffer + let mut new_lines = vec![template_row; new_lines_to_grow]; + self.inner.append(&mut new_lines); - // Generate range of lines that have to be deleted after the zero line - let shrink_after = (self.inner.len() + offset + 1 - shrinkage)..self.inner.len(); + // Add the start to the raw inner buffer again + self.inner.append(&mut start_buffer); - // Delete all lines in reverse order - for i in shrink_before.chain(shrink_after).rev() { - self.inner.remove(i); + // Update the zero to after the lines we just inserted + self.zero = offset + lines_to_grow; } - // Check if zero has moved (not the first line in the buffer) - if self.zero % (self.inner.len() + shrinkage) != 0 { - // Set zero to the first deleted line in the buffer - self.zero = start; - } + // Update visible lines and raw buffer length + self.len += lines_to_grow; + self.visible_lines = next - 1; + } + + /// Decrease the number of lines in the buffer + pub fn shrink_visible_lines(&mut self, next: Line) { + // Shrink the size without removing any lines + self.len -= (self.visible_lines - (next - 1)).0; // Update visible lines self.visible_lines = next - 1; @@ -134,17 +127,17 @@ impl<T> Storage<T> { #[inline] pub fn len(&self) -> usize { - self.inner.len() + self.len } /// Compute actual index in underlying storage given the requested index. #[inline] fn compute_index(&self, requested: usize) -> usize { - (requested + self.zero) % self.len() + (requested + self.zero) % self.inner.len() } fn compute_line_index(&self, requested: Line) -> usize { - ((self.len() + self.zero + *self.visible_lines) - *requested) % self.len() + ((self.inner.len() + self.zero + *self.visible_lines) - *requested) % self.inner.len() } pub fn swap_lines(&mut self, a: Line, b: Line) { @@ -158,14 +151,14 @@ impl<T> Storage<T> { } pub fn rotate(&mut self, count: isize) { - let len = self.len(); + let len = self.inner.len(); assert!(count.abs() as usize <= len); self.zero += (count + len as isize) as usize % len; } // Fast path pub fn rotate_up(&mut self, count: usize) { - self.zero = (self.zero + count) % self.len(); + self.zero = (self.zero + count) % self.inner.len(); } } @@ -243,6 +236,7 @@ fn grow_after_zero() { inner: vec!["0", "1", "-"], zero: 0, visible_lines: Line(2), + len: 3, }; // Grow buffer @@ -253,9 +247,11 @@ fn grow_after_zero() { inner: vec!["-", "0", "1", "-"], zero: 1, visible_lines: Line(0), + len: 4, }; assert_eq!(storage.inner, expected.inner); assert_eq!(storage.zero, expected.zero); + assert_eq!(storage.len, expected.len); } /// Grow the buffer one line at the start of the buffer @@ -276,6 +272,7 @@ fn grow_before_zero() { inner: vec!["-", "0", "1"], zero: 1, visible_lines: Line(2), + len: 3, }; // Grow buffer @@ -286,9 +283,11 @@ fn grow_before_zero() { inner: vec!["-", "-", "0", "1"], zero: 2, visible_lines: Line(0), + len: 4, }; assert_eq!(storage.inner, expected.inner); assert_eq!(storage.zero, expected.zero); + assert_eq!(storage.len, expected.len); } /// Shrink the buffer one line at the start of the buffer @@ -298,6 +297,7 @@ fn grow_before_zero() { /// 1: 0 <- Zero /// 2: 1 /// After: +/// 0: 2 <- Hidden /// 0: 0 <- Zero /// 1: 1 #[test] @@ -307,6 +307,7 @@ fn shrink_before_zero() { inner: vec!["2", "0", "1"], zero: 1, visible_lines: Line(2), + len: 3, }; // Shrink buffer @@ -314,12 +315,14 @@ fn shrink_before_zero() { // Make sure the result is correct let expected = Storage { - inner: vec!["0", "1"], - zero: 0, + inner: vec!["2", "0", "1"], + zero: 1, visible_lines: Line(0), + len: 2, }; assert_eq!(storage.inner, expected.inner); assert_eq!(storage.zero, expected.zero); + assert_eq!(storage.len, expected.len); } /// Shrink the buffer one line at the end of the buffer @@ -331,6 +334,7 @@ fn shrink_before_zero() { /// After: /// 0: 0 <- Zero /// 1: 1 +/// 2: 2 <- Hidden #[test] fn shrink_after_zero() { // Setup storage area @@ -338,6 +342,7 @@ fn shrink_after_zero() { inner: vec!["0", "1", "2"], zero: 0, visible_lines: Line(2), + len: 3, }; // Shrink buffer @@ -345,12 +350,14 @@ fn shrink_after_zero() { // Make sure the result is correct let expected = Storage { - inner: vec!["0", "1"], + inner: vec!["0", "1", "2"], zero: 0, visible_lines: Line(0), + len: 2, }; assert_eq!(storage.inner, expected.inner); assert_eq!(storage.zero, expected.zero); + assert_eq!(storage.len, expected.len); } /// Shrink the buffer at the start and end of the buffer @@ -363,8 +370,12 @@ fn shrink_after_zero() { /// 4: 2 /// 5: 3 /// After: -/// 0: 0 <- Zero -/// 1: 1 +/// 0: 4 <- Hidden +/// 1: 5 <- Hidden +/// 2: 0 <- Zero +/// 3: 1 +/// 4: 2 <- Hidden +/// 5: 3 <- Hidden #[test] fn shrink_before_and_after_zero() { // Setup storage area @@ -372,6 +383,7 @@ fn shrink_before_and_after_zero() { inner: vec!["4", "5", "0", "1", "2", "3"], zero: 2, visible_lines: Line(5), + len: 6, }; // Shrink buffer @@ -379,10 +391,12 @@ fn shrink_before_and_after_zero() { // Make sure the result is correct let expected = Storage { - inner: vec!["0", "1"], - zero: 0, + inner: vec!["4", "5", "0", "1", "2", "3"], + zero: 2, visible_lines: Line(0), + len: 2, }; assert_eq!(storage.inner, expected.inner); assert_eq!(storage.zero, expected.zero); + assert_eq!(storage.len, expected.len); } |