term_model/grid/
row.rs

1// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Defines the Row type which makes up lines in the grid
16
17use std::cmp::{max, min};
18use std::ops::{Index, IndexMut};
19use std::ops::{Range, RangeFrom, RangeFull, RangeTo, RangeToInclusive};
20use std::slice;
21
22use serde::{Deserialize, Serialize};
23
24use crate::grid::GridCell;
25use crate::index::Column;
26
27/// A row in the grid
28#[derive(Default, Clone, Debug, Serialize, Deserialize)]
29pub struct Row<T> {
30    inner: Vec<T>,
31
32    /// Maximum number of occupied entries.
33    ///
34    /// This is the upper bound on the number of elements in the row, which have been modified
35    /// since the last reset. All cells after this point are guaranteed to be equal.
36    pub(crate) occ: usize,
37}
38
39impl<T: PartialEq> PartialEq for Row<T> {
40    fn eq(&self, other: &Self) -> bool {
41        self.inner == other.inner
42    }
43}
44
45impl<T: Copy> Row<T> {
46    pub fn new(columns: Column, template: &T) -> Row<T>
47    where
48        T: GridCell,
49    {
50        let occ = if template.is_empty() { 0 } else { columns.0 };
51        Row { inner: vec![*template; columns.0], occ }
52    }
53
54    pub fn grow(&mut self, cols: Column, template: &T) {
55        if self.inner.len() >= cols.0 {
56            return;
57        }
58
59        self.inner.append(&mut vec![*template; cols.0 - self.len()]);
60    }
61
62    pub fn shrink(&mut self, cols: Column) -> Option<Vec<T>>
63    where
64        T: GridCell,
65    {
66        if self.inner.len() <= cols.0 {
67            return None;
68        }
69
70        // Split off cells for a new row
71        let mut new_row = self.inner.split_off(cols.0);
72        let index = new_row.iter().rposition(|c| !c.is_empty()).map(|i| i + 1).unwrap_or(0);
73        new_row.truncate(index);
74
75        self.occ = min(self.occ, cols.0);
76
77        if new_row.is_empty() {
78            None
79        } else {
80            Some(new_row)
81        }
82    }
83
84    /// Reset all cells in the row to the `template` cell.
85    #[inline]
86    pub fn reset(&mut self, template: &T)
87    where
88        T: GridCell + PartialEq,
89    {
90        debug_assert!(!self.inner.is_empty());
91
92        let template = *template;
93
94        // Mark all cells as dirty if template cell changed
95        let len = self.inner.len();
96        if !self.inner[len - 1].fast_eq(template) {
97            self.occ = len;
98        }
99
100        // Reset every dirty in the row
101        // let template = *template;
102        for item in &mut self.inner[..self.occ] {
103            *item = template;
104        }
105
106        self.occ = 0;
107    }
108}
109
110#[allow(clippy::len_without_is_empty)]
111impl<T> Row<T> {
112    #[inline]
113    pub fn from_vec(vec: Vec<T>, occ: usize) -> Row<T> {
114        Row { inner: vec, occ }
115    }
116
117    #[inline]
118    pub fn len(&self) -> usize {
119        self.inner.len()
120    }
121
122    #[inline]
123    pub fn last(&self) -> Option<&T> {
124        self.inner.last()
125    }
126
127    #[inline]
128    pub fn last_mut(&mut self) -> Option<&mut T> {
129        self.occ = self.inner.len();
130        self.inner.last_mut()
131    }
132
133    #[inline]
134    pub fn append(&mut self, vec: &mut Vec<T>)
135    where
136        T: GridCell,
137    {
138        self.occ += vec.len();
139        self.inner.append(vec);
140    }
141
142    #[inline]
143    pub fn append_front(&mut self, mut vec: Vec<T>) {
144        self.occ += vec.len();
145
146        vec.append(&mut self.inner);
147        self.inner = vec;
148    }
149
150    #[inline]
151    pub fn is_empty(&self) -> bool
152    where
153        T: GridCell,
154    {
155        self.inner.iter().all(GridCell::is_empty)
156    }
157
158    #[inline]
159    pub fn front_split_off(&mut self, at: usize) -> Vec<T> {
160        self.occ = self.occ.saturating_sub(at);
161
162        let mut split = self.inner.split_off(at);
163        std::mem::swap(&mut split, &mut self.inner);
164        split
165    }
166}
167
168impl<'a, T> IntoIterator for &'a mut Row<T> {
169    type IntoIter = slice::IterMut<'a, T>;
170    type Item = &'a mut T;
171
172    #[inline]
173    fn into_iter(self) -> slice::IterMut<'a, T> {
174        self.occ = self.len();
175        self.inner.iter_mut()
176    }
177}
178
179impl<T> Index<Column> for Row<T> {
180    type Output = T;
181
182    #[inline]
183    fn index(&self, index: Column) -> &T {
184        &self.inner[index.0]
185    }
186}
187
188impl<T> IndexMut<Column> for Row<T> {
189    #[inline]
190    fn index_mut(&mut self, index: Column) -> &mut T {
191        self.occ = max(self.occ, *index + 1);
192        &mut self.inner[index.0]
193    }
194}
195
196// -----------------------------------------------------------------------------
197// Index ranges of columns
198// -----------------------------------------------------------------------------
199
200impl<T> Index<Range<Column>> for Row<T> {
201    type Output = [T];
202
203    #[inline]
204    fn index(&self, index: Range<Column>) -> &[T] {
205        &self.inner[(index.start.0)..(index.end.0)]
206    }
207}
208
209impl<T> IndexMut<Range<Column>> for Row<T> {
210    #[inline]
211    fn index_mut(&mut self, index: Range<Column>) -> &mut [T] {
212        self.occ = max(self.occ, *index.end);
213        &mut self.inner[(index.start.0)..(index.end.0)]
214    }
215}
216
217impl<T> Index<RangeTo<Column>> for Row<T> {
218    type Output = [T];
219
220    #[inline]
221    fn index(&self, index: RangeTo<Column>) -> &[T] {
222        &self.inner[..(index.end.0)]
223    }
224}
225
226impl<T> IndexMut<RangeTo<Column>> for Row<T> {
227    #[inline]
228    fn index_mut(&mut self, index: RangeTo<Column>) -> &mut [T] {
229        self.occ = max(self.occ, *index.end);
230        &mut self.inner[..(index.end.0)]
231    }
232}
233
234impl<T> Index<RangeFrom<Column>> for Row<T> {
235    type Output = [T];
236
237    #[inline]
238    fn index(&self, index: RangeFrom<Column>) -> &[T] {
239        &self.inner[(index.start.0)..]
240    }
241}
242
243impl<T> IndexMut<RangeFrom<Column>> for Row<T> {
244    #[inline]
245    fn index_mut(&mut self, index: RangeFrom<Column>) -> &mut [T] {
246        self.occ = self.len();
247        &mut self.inner[(index.start.0)..]
248    }
249}
250
251impl<T> Index<RangeFull> for Row<T> {
252    type Output = [T];
253
254    #[inline]
255    fn index(&self, _: RangeFull) -> &[T] {
256        &self.inner[..]
257    }
258}
259
260impl<T> IndexMut<RangeFull> for Row<T> {
261    #[inline]
262    fn index_mut(&mut self, _: RangeFull) -> &mut [T] {
263        self.occ = self.len();
264        &mut self.inner[..]
265    }
266}
267
268impl<T> Index<RangeToInclusive<Column>> for Row<T> {
269    type Output = [T];
270
271    #[inline]
272    fn index(&self, index: RangeToInclusive<Column>) -> &[T] {
273        &self.inner[..=(index.end.0)]
274    }
275}
276
277impl<T> IndexMut<RangeToInclusive<Column>> for Row<T> {
278    #[inline]
279    fn index_mut(&mut self, index: RangeToInclusive<Column>) -> &mut [T] {
280        self.occ = max(self.occ, *index.end);
281        &mut self.inner[..=(index.end.0)]
282    }
283}