2020-05-05 22:50:23 +00:00
|
|
|
//! Defines the Row type which makes up lines in the grid.
|
2017-10-13 03:01:28 +00:00
|
|
|
|
2019-03-30 16:48:36 +00:00
|
|
|
use std::cmp::{max, min};
|
2018-05-19 18:18:37 +00:00
|
|
|
use std::ops::{Index, IndexMut};
|
2019-03-30 16:48:36 +00:00
|
|
|
use std::ops::{Range, RangeFrom, RangeFull, RangeTo, RangeToInclusive};
|
2020-11-05 04:45:14 +00:00
|
|
|
use std::ptr;
|
2017-10-13 03:01:28 +00:00
|
|
|
use std::slice;
|
|
|
|
|
2019-10-05 00:29:26 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
2019-03-13 18:55:18 +00:00
|
|
|
use crate::grid::GridCell;
|
2018-12-10 17:53:56 +00:00
|
|
|
use crate::index::Column;
|
2020-11-05 04:45:14 +00:00
|
|
|
use crate::term::cell::ResetDiscriminant;
|
2017-10-13 03:01:28 +00:00
|
|
|
|
2020-05-05 22:50:23 +00:00
|
|
|
/// A row in the grid.
|
2020-12-31 05:52:45 +00:00
|
|
|
#[derive(Serialize, Deserialize, Default, Clone, Debug)]
|
2018-05-19 18:18:37 +00:00
|
|
|
pub struct Row<T> {
|
|
|
|
inner: Vec<T>,
|
|
|
|
|
2019-12-09 23:35:13 +00:00
|
|
|
/// Maximum number of occupied entries.
|
2018-05-19 18:18:37 +00:00
|
|
|
///
|
2019-12-09 23:35:13 +00:00
|
|
|
/// This is the upper bound on the number of elements in the row, which have been modified
|
|
|
|
/// since the last reset. All cells after this point are guaranteed to be equal.
|
2018-05-19 18:18:37 +00:00
|
|
|
pub(crate) occ: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: PartialEq> PartialEq for Row<T> {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
self.inner == other.inner
|
|
|
|
}
|
|
|
|
}
|
2017-10-13 03:01:28 +00:00
|
|
|
|
2020-11-05 04:45:14 +00:00
|
|
|
impl<T: Clone + Default> Row<T> {
|
|
|
|
/// Create a new terminal row.
|
|
|
|
///
|
|
|
|
/// Ideally the `template` should be `Copy` in all performance sensitive scenarios.
|
|
|
|
pub fn new(columns: Column) -> Row<T> {
|
|
|
|
debug_assert!(columns.0 >= 1);
|
|
|
|
|
|
|
|
let mut inner: Vec<T> = Vec::with_capacity(columns.0);
|
|
|
|
|
|
|
|
// This is a slightly optimized version of `std::vec::Vec::resize`.
|
|
|
|
unsafe {
|
|
|
|
let mut ptr = inner.as_mut_ptr();
|
|
|
|
|
|
|
|
for _ in 1..columns.0 {
|
|
|
|
ptr::write(ptr, T::default());
|
|
|
|
ptr = ptr.offset(1);
|
|
|
|
}
|
|
|
|
ptr::write(ptr, T::default());
|
|
|
|
|
|
|
|
inner.set_len(columns.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Row { inner, occ: 0 }
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
|
2020-11-05 04:45:14 +00:00
|
|
|
/// Increase the number of columns in the row.
|
|
|
|
#[inline]
|
|
|
|
pub fn grow(&mut self, cols: Column) {
|
2019-03-13 18:55:18 +00:00
|
|
|
if self.inner.len() >= cols.0 {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-11-05 04:45:14 +00:00
|
|
|
self.inner.resize_with(cols.0, T::default);
|
2019-03-13 18:55:18 +00:00
|
|
|
}
|
|
|
|
|
2020-11-05 04:45:14 +00:00
|
|
|
/// Reduce the number of columns in the row.
|
|
|
|
///
|
|
|
|
/// This will return all non-empty cells that were removed.
|
2019-03-13 18:55:18 +00:00
|
|
|
pub fn shrink(&mut self, cols: Column) -> Option<Vec<T>>
|
|
|
|
where
|
2019-03-30 16:48:36 +00:00
|
|
|
T: GridCell,
|
2019-03-13 18:55:18 +00:00
|
|
|
{
|
|
|
|
if self.inner.len() <= cols.0 {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2020-05-05 22:50:23 +00:00
|
|
|
// Split off cells for a new row.
|
2019-03-13 18:55:18 +00:00
|
|
|
let mut new_row = self.inner.split_off(cols.0);
|
|
|
|
let index = new_row.iter().rposition(|c| !c.is_empty()).map(|i| i + 1).unwrap_or(0);
|
|
|
|
new_row.truncate(index);
|
|
|
|
|
2019-07-10 21:17:20 +00:00
|
|
|
self.occ = min(self.occ, cols.0);
|
2018-05-29 18:13:49 +00:00
|
|
|
|
2019-03-13 18:55:18 +00:00
|
|
|
if new_row.is_empty() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(new_row)
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
2018-01-14 18:17:08 +00:00
|
|
|
|
2019-12-09 23:35:13 +00:00
|
|
|
/// Reset all cells in the row to the `template` cell.
|
|
|
|
#[inline]
|
2020-11-05 04:45:14 +00:00
|
|
|
pub fn reset<D>(&mut self, template: &T)
|
2019-07-10 21:17:20 +00:00
|
|
|
where
|
2020-11-05 04:45:14 +00:00
|
|
|
T: ResetDiscriminant<D> + GridCell,
|
|
|
|
D: PartialEq,
|
2019-07-10 21:17:20 +00:00
|
|
|
{
|
2019-12-09 23:35:13 +00:00
|
|
|
debug_assert!(!self.inner.is_empty());
|
|
|
|
|
2020-05-05 22:50:23 +00:00
|
|
|
// Mark all cells as dirty if template cell changed.
|
2019-12-09 23:35:13 +00:00
|
|
|
let len = self.inner.len();
|
2020-11-05 04:45:14 +00:00
|
|
|
if self.inner[len - 1].discriminant() != template.discriminant() {
|
2019-11-18 21:15:25 +00:00
|
|
|
self.occ = len;
|
2018-04-02 15:44:54 +00:00
|
|
|
}
|
2019-12-09 23:35:13 +00:00
|
|
|
|
2020-11-05 04:45:14 +00:00
|
|
|
// Reset every dirty cell in the row.
|
|
|
|
for item in &mut self.inner[0..self.occ] {
|
|
|
|
item.reset(template);
|
2019-12-09 23:35:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
self.occ = 0;
|
2018-01-14 18:17:08 +00:00
|
|
|
}
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
|
2018-12-07 13:58:11 +00:00
|
|
|
#[allow(clippy::len_without_is_empty)]
|
2017-10-13 03:01:28 +00:00
|
|
|
impl<T> Row<T> {
|
2019-03-13 18:55:18 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn from_vec(vec: Vec<T>, occ: usize) -> Row<T> {
|
2019-03-30 16:48:36 +00:00
|
|
|
Row { inner: vec, occ }
|
2018-05-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
2019-03-13 18:55:18 +00:00
|
|
|
#[inline]
|
2018-05-19 18:18:37 +00:00
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
self.inner.len()
|
|
|
|
}
|
|
|
|
|
2019-03-13 18:55:18 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn last(&self) -> Option<&T> {
|
|
|
|
self.inner.last()
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
|
2019-03-13 18:55:18 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn last_mut(&mut self) -> Option<&mut T> {
|
|
|
|
self.occ = self.inner.len();
|
|
|
|
self.inner.last_mut()
|
|
|
|
}
|
2017-10-13 03:01:28 +00:00
|
|
|
|
2019-03-13 18:55:18 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn append(&mut self, vec: &mut Vec<T>)
|
|
|
|
where
|
2019-03-30 16:48:36 +00:00
|
|
|
T: GridCell,
|
2019-03-13 18:55:18 +00:00
|
|
|
{
|
2019-07-10 21:17:20 +00:00
|
|
|
self.occ += vec.len();
|
2019-03-13 18:55:18 +00:00
|
|
|
self.inner.append(vec);
|
|
|
|
}
|
2017-10-13 03:01:28 +00:00
|
|
|
|
|
|
|
#[inline]
|
2019-03-13 18:55:18 +00:00
|
|
|
pub fn append_front(&mut self, mut vec: Vec<T>) {
|
|
|
|
self.occ += vec.len();
|
2019-07-10 21:17:20 +00:00
|
|
|
|
2019-03-13 18:55:18 +00:00
|
|
|
vec.append(&mut self.inner);
|
|
|
|
self.inner = vec;
|
|
|
|
}
|
|
|
|
|
2020-07-01 06:58:06 +00:00
|
|
|
/// Check if all cells in the row are empty.
|
2019-03-13 18:55:18 +00:00
|
|
|
#[inline]
|
2020-07-01 06:58:06 +00:00
|
|
|
pub fn is_clear(&self) -> bool
|
2019-03-13 18:55:18 +00:00
|
|
|
where
|
2019-03-30 16:48:36 +00:00
|
|
|
T: GridCell,
|
2019-03-13 18:55:18 +00:00
|
|
|
{
|
2019-04-11 07:54:26 +00:00
|
|
|
self.inner.iter().all(GridCell::is_empty)
|
2019-03-13 18:55:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn front_split_off(&mut self, at: usize) -> Vec<T> {
|
|
|
|
self.occ = self.occ.saturating_sub(at);
|
|
|
|
|
|
|
|
let mut split = self.inner.split_off(at);
|
|
|
|
std::mem::swap(&mut split, &mut self.inner);
|
|
|
|
split
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, T> IntoIterator for &'a mut Row<T> {
|
|
|
|
type IntoIter = slice::IterMut<'a, T>;
|
2019-03-30 16:48:36 +00:00
|
|
|
type Item = &'a mut T;
|
2017-10-13 03:01:28 +00:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn into_iter(self) -> slice::IterMut<'a, T> {
|
2018-05-19 18:18:37 +00:00
|
|
|
self.occ = self.len();
|
|
|
|
self.inner.iter_mut()
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Index<Column> for Row<T> {
|
|
|
|
type Output = T;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index(&self, index: Column) -> &T {
|
2018-05-19 18:18:37 +00:00
|
|
|
&self.inner[index.0]
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> IndexMut<Column> for Row<T> {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut(&mut self, index: Column) -> &mut T {
|
2018-05-19 18:18:37 +00:00
|
|
|
self.occ = max(self.occ, *index + 1);
|
|
|
|
&mut self.inner[index.0]
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Index<Range<Column>> for Row<T> {
|
|
|
|
type Output = [T];
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index(&self, index: Range<Column>) -> &[T] {
|
2018-05-19 18:18:37 +00:00
|
|
|
&self.inner[(index.start.0)..(index.end.0)]
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> IndexMut<Range<Column>> for Row<T> {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut(&mut self, index: Range<Column>) -> &mut [T] {
|
2018-05-19 18:18:37 +00:00
|
|
|
self.occ = max(self.occ, *index.end);
|
|
|
|
&mut self.inner[(index.start.0)..(index.end.0)]
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Index<RangeTo<Column>> for Row<T> {
|
|
|
|
type Output = [T];
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index(&self, index: RangeTo<Column>) -> &[T] {
|
2018-05-19 18:18:37 +00:00
|
|
|
&self.inner[..(index.end.0)]
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> IndexMut<RangeTo<Column>> for Row<T> {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut(&mut self, index: RangeTo<Column>) -> &mut [T] {
|
2018-05-19 18:18:37 +00:00
|
|
|
self.occ = max(self.occ, *index.end);
|
|
|
|
&mut self.inner[..(index.end.0)]
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Index<RangeFrom<Column>> for Row<T> {
|
|
|
|
type Output = [T];
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index(&self, index: RangeFrom<Column>) -> &[T] {
|
2018-05-19 18:18:37 +00:00
|
|
|
&self.inner[(index.start.0)..]
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> IndexMut<RangeFrom<Column>> for Row<T> {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut(&mut self, index: RangeFrom<Column>) -> &mut [T] {
|
2018-05-19 18:18:37 +00:00
|
|
|
self.occ = self.len();
|
|
|
|
&mut self.inner[(index.start.0)..]
|
2017-10-13 03:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
2017-10-13 03:29:35 +00:00
|
|
|
|
|
|
|
impl<T> Index<RangeFull> for Row<T> {
|
|
|
|
type Output = [T];
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index(&self, _: RangeFull) -> &[T] {
|
2018-05-19 18:18:37 +00:00
|
|
|
&self.inner[..]
|
2017-10-13 03:29:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> IndexMut<RangeFull> for Row<T> {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut(&mut self, _: RangeFull) -> &mut [T] {
|
2018-05-19 18:18:37 +00:00
|
|
|
self.occ = self.len();
|
|
|
|
&mut self.inner[..]
|
2017-10-13 03:29:35 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-17 23:34:56 +00:00
|
|
|
|
|
|
|
impl<T> Index<RangeToInclusive<Column>> for Row<T> {
|
|
|
|
type Output = [T];
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index(&self, index: RangeToInclusive<Column>) -> &[T] {
|
|
|
|
&self.inner[..=(index.end.0)]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> IndexMut<RangeToInclusive<Column>> for Row<T> {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut(&mut self, index: RangeToInclusive<Column>) -> &mut [T] {
|
|
|
|
self.occ = max(self.occ, *index.end);
|
|
|
|
&mut self.inner[..=(index.end.0)]
|
|
|
|
}
|
|
|
|
}
|