diff options
Diffstat (limited to 'src/grid.rs')
-rw-r--r-- | src/grid.rs | 79 |
1 files changed, 67 insertions, 12 deletions
diff --git a/src/grid.rs b/src/grid.rs index 085e744..21fb03c 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -152,7 +152,8 @@ impl Grid { pub fn current_row_mut(&mut self) -> &mut crate::row::Row { self.drawing_row_mut(self.pos.row) - .expect("cursor not pointing to a cell") + // we assume self.pos.row is always valid + .unwrap_or_else(|| unreachable!()) } pub fn visible_cell(&self, pos: Pos) -> Option<&crate::cell::Cell> { @@ -209,7 +210,9 @@ impl Grid { let mut prev_pos = Pos::default(); let mut wrapping = false; for (i, row) in self.visible_rows().enumerate() { - let i = i.try_into().unwrap(); + // we limit the number of cols to a u16 (see Size), so + // visible_rows() can never return more rows than will fit + let i = i.try_into().unwrap_or_else(|_| unreachable!()); let (new_pos, new_attrs) = row.write_contents_formatted( contents, 0, @@ -245,7 +248,9 @@ impl Grid { for (i, (row, prev_row)) in self.visible_rows().zip(prev.visible_rows()).enumerate() { - let i = i.try_into().unwrap(); + // we limit the number of cols to a u16 (see Size), so + // visible_rows() can never return more rows than will fit + let i = i.try_into().unwrap_or_else(|_| unreachable!()); let (new_pos, new_attrs) = row.write_contents_diff( contents, prev_row, @@ -289,10 +294,23 @@ impl Grid { row: self.pos.row, col: self.size.cols - 1, }; - if self.drawing_cell(pos).unwrap().is_wide_continuation() { + if self + .drawing_cell(pos) + // we assume self.pos.row is always valid, and self.size.cols + // - 1 is always a valid column + .unwrap_or_else(|| unreachable!()) + .is_wide_continuation() + { pos.col = self.size.cols - 2; } - let cell = self.drawing_cell(pos).unwrap(); + let cell = + // we assume self.pos.row is always valid, and self.size.cols + // - 2 must be a valid column because self.size.cols - 1 is + // always valid and we just checked that the cell at + // self.size.cols - 1 is a wide continuation character, which + // means that the first half of the wide character must be + // before it + self.drawing_cell(pos).unwrap_or_else(|| unreachable!()); if cell.has_contents() { if let Some(prev_pos) = prev_pos { crate::term::MoveFromTo::new(prev_pos, pos) @@ -316,11 +334,27 @@ impl Grid { for i in (0..self.pos.row).rev() { pos.row = i; pos.col = self.size.cols - 1; - if self.drawing_cell(pos).unwrap().is_wide_continuation() + if self + .drawing_cell(pos) + // i is always less than self.pos.row, which we assume + // to be always valid, so it must also be valid. + // self.size.cols - 1 is always a valid col. + .unwrap_or_else(|| unreachable!()) + .is_wide_continuation() { pos.col = self.size.cols - 2; } - let cell = self.drawing_cell(pos).unwrap(); + let cell = self + .drawing_cell(pos) + // i is always less than self.pos.row, which we assume + // to be always valid, so it must also be valid. + // self.size.cols - 2 is valid because self.size.cols + // - 1 is always valid, and col gets set to + // self.size.cols - 2 when the cell at self.size.cols + // - 1 is a wide continuation character, meaning that + // the first half of the wide character must be before + // it + .unwrap_or_else(|| unreachable!()); if cell.has_contents() { if let Some(prev_pos) = prev_pos { if prev_pos.row != i @@ -379,7 +413,11 @@ impl Grid { contents.push(b' '); // we know that the cell has no contents, but it still may // have drawing attributes (background color, etc) - let end_cell = self.drawing_cell(pos).unwrap(); + let end_cell = self + .drawing_cell(pos) + // we assume self.pos.row is always valid, and + // self.size.cols - 1 is always a valid column + .unwrap_or_else(|| unreachable!()); end_cell .attrs() .write_escape_code_diff(contents, &prev_attrs); @@ -449,7 +487,13 @@ impl Grid { let size = self.size; let pos = self.pos; let wide = pos.col < size.cols - && self.drawing_cell(pos).unwrap().is_wide_continuation(); + && self + .drawing_cell(pos) + // we assume self.pos.row is always valid, and we know we are + // not off the end of a row because we just checked pos.col < + // size.cols + .unwrap_or_else(|| unreachable!()) + .is_wide_continuation(); let row = self.current_row_mut(); for _ in 0..count { if wide { @@ -486,7 +530,11 @@ impl Grid { for _ in 0..count { self.rows.remove(self.scroll_bottom as usize); self.rows.insert(self.pos.row as usize, self.new_row()); - self.rows[self.scroll_bottom as usize].wrap(false); + self.rows + .get_mut(self.scroll_bottom as usize) + // self.scroll_bottom is maintained to always be a valid row + .unwrap_or_else(|| unreachable!()) + .wrap(false); } } @@ -520,7 +568,11 @@ impl Grid { for _ in 0..count { self.rows.remove(self.scroll_bottom as usize); self.rows.insert(self.scroll_top as usize, self.new_row()); - self.rows[self.scroll_bottom as usize].wrap(false); + self.rows + .get_mut(self.scroll_bottom as usize) + // self.scroll_bottom is maintained to always be a valid row + .unwrap_or_else(|| unreachable!()) + .wrap(false); } } @@ -625,7 +677,10 @@ impl Grid { prev_pos.row -= scrolled; let new_pos = self.pos; self.drawing_row_mut(prev_pos.row) - .unwrap() + // we assume self.pos.row is always valid, and so prev_pos.row + // must be valid because it is always less than or equal to + // self.pos.row + .unwrap_or_else(|| unreachable!()) .wrap(wrap && prev_pos.row + 1 == new_pos.row); } } |