1use std::{
4 fmt::{self, Formatter},
5 ops::{Index, IndexMut},
6};
7
8use super::{cell_info::CellInfo, Records, RecordsMut, Resizable};
9use crate::{width::WidthFunc, Position};
10
11#[derive(Debug, Default, Clone)]
13pub struct VecRecords<T> {
14 records: Vec<Vec<T>>,
15 size: (usize, usize),
16}
17
18impl<'a> VecRecords<CellInfo<'a>> {
19 pub fn new<R, C, T, W>(records: R, size: (usize, usize), width_ctrl: W) -> Self
21 where
22 R: IntoIterator<Item = C> + 'a,
23 C: IntoIterator<Item = T> + 'a,
24 T: AsRef<str> + 'a,
25 W: WidthFunc,
26 {
27 let records = create_records(records, width_ctrl, size);
28 Self { records, size }
29 }
30}
31
32impl<T> VecRecords<T> {
33 pub fn with_hint(records: Vec<Vec<T>>, count_columns: usize) -> Self {
37 let count_rows = records.len();
38 let size = (count_rows, count_columns);
39
40 Self { records, size }
41 }
42
43 pub fn size(&self) -> (usize, usize) {
45 self.size
46 }
47
48 pub fn count_rows(&self) -> usize {
50 self.size.0
51 }
52
53 pub fn count_columns(&self) -> usize {
55 self.size.1
56 }
57
58 pub fn truncate(&mut self, len: usize) {
60 if self.size.1 > len {
61 self.size.1 = len;
62 for row in &mut self.records {
63 row.truncate(len);
64 }
65 }
66 }
67}
68
69impl<T> VecRecords<T>
70where
71 T: Clone,
72{
73 pub fn push(&mut self, cell: T) {
77 for row in &mut self.records {
78 row.push(cell.clone());
79 }
80
81 self.size.1 += 1;
82 }
83}
84
85impl<T> From<Vec<Vec<T>>> for VecRecords<T> {
86 fn from(records: Vec<Vec<T>>) -> Self {
87 let count_rows = records.len();
88 let count_cols = records.get(0).map_or(0, Vec::len);
89 let size = (count_rows, count_cols);
90
91 Self { records, size }
92 }
93}
94
95impl<T> VecRecords<T>
96where
97 T: Clone,
98{
99 pub fn duplicate_row(&mut self, row: usize) {
101 if row >= self.size.0 {
102 return;
103 }
104
105 let row = self.records[row].clone();
106 self.records.push(row);
107 self.size.0 += 1;
108 }
109}
110
111impl<T> Records for VecRecords<T>
112where
113 T: Cell,
114{
115 fn count_rows(&self) -> usize {
116 self.size.0
117 }
118
119 fn count_columns(&self) -> usize {
120 self.size.1
121 }
122
123 fn get_text(&self, (row, col): Position) -> &str {
124 self.records[row][col].as_ref()
125 }
126
127 fn get_line(&self, (row, col): Position, i: usize) -> &str {
128 self.records[row][col].get_line(i)
129 }
130
131 fn get_width<W>(&self, (row, col): Position, width_ctrl: W) -> usize
132 where
133 W: WidthFunc,
134 {
135 self.records[row][col].width(width_ctrl)
136 }
137
138 fn get_line_width<W>(&self, (row, col): Position, i: usize, width_ctrl: W) -> usize
139 where
140 W: WidthFunc,
141 {
142 self.records[row][col].line_width(i, width_ctrl)
143 }
144
145 fn count_lines(&self, (row, col): Position) -> usize {
146 self.records[row][col].count_lines()
147 }
148
149 fn fmt_text_prefix(
150 &self,
151 f: &mut std::fmt::Formatter<'_>,
152 (row, col): Position,
153 ) -> std::fmt::Result {
154 self.records[row][col].fmt_prefix(f)
155 }
156
157 fn fmt_text_suffix(
158 &self,
159 f: &mut std::fmt::Formatter<'_>,
160 (row, col): Position,
161 ) -> std::fmt::Result {
162 self.records[row][col].fmt_suffix(f)
163 }
164}
165
166impl<T, Q> RecordsMut<Q> for VecRecords<T>
167where
168 T: CellMut<Q>,
169{
170 fn set<W>(&mut self, (row, col): Position, text: Q, width_ctrl: W)
171 where
172 W: WidthFunc,
173 {
174 self.records[row][col].set(text, width_ctrl);
175 }
176
177 fn update<W>(&mut self, (row, col): Position, width_ctrl: W)
178 where
179 W: WidthFunc,
180 {
181 self.records[row][col].update(width_ctrl);
182 }
183}
184
185impl<T> Resizable for VecRecords<T>
186where
187 T: Default + Clone,
188{
189 fn swap(&mut self, lhs: Position, rhs: Position) {
190 if lhs.0 >= self.size.0
191 || lhs.1 >= self.size.1
192 || rhs.0 >= self.size.0
193 || rhs.1 >= self.size.1
194 {
195 return;
196 }
197
198 if lhs == rhs {
199 return;
200 }
201
202 let t = std::mem::take(&mut self.records[lhs.0][lhs.1]);
203 let t = std::mem::replace(&mut self.records[rhs.0][rhs.1], t);
204 let _ = std::mem::replace(&mut self.records[lhs.0][lhs.1], t);
205 }
206
207 fn swap_row(&mut self, lhs: usize, rhs: usize) {
208 if lhs >= self.size.0 || rhs >= self.size.0 {
209 return;
210 }
211
212 let t = std::mem::take(&mut self.records[lhs]);
213 let t = std::mem::replace(&mut self.records[rhs], t);
214 let _ = std::mem::replace(&mut self.records[lhs], t);
215 }
216
217 fn swap_column(&mut self, lhs: usize, rhs: usize) {
218 if lhs >= self.size.1 || rhs >= self.size.1 {
219 return;
220 }
221
222 for row in &mut self.records {
223 row.swap(lhs, rhs);
224 }
225 }
226
227 fn push_row(&mut self) {
228 self.size.0 += 1;
229 self.records.push(vec![T::default(); self.size.1]);
230 }
231
232 fn push_column(&mut self) {
233 self.size.1 += 1;
234 for row in &mut self.records {
235 row.push(T::default());
236 }
237 }
238
239 fn remove_row(&mut self, row: usize) {
240 if row >= self.records.len() {
241 return;
242 }
243
244 self.records.remove(row);
245 self.size.0 -= 1;
246 }
247
248 fn remove_column(&mut self, column: usize) {
249 if column >= self.size.1 {
250 return;
251 }
252
253 for row in &mut self.records {
254 row.remove(column);
255 }
256 self.size.1 -= 1;
257 }
258
259 fn insert_row(&mut self, row: usize) {
260 self.records.insert(row, vec![T::default(); self.size.1]);
261 }
262}
263
264impl<T> Index<Position> for VecRecords<T> {
265 type Output = T;
266
267 fn index(&self, (row, col): Position) -> &Self::Output {
268 &self.records[row][col]
269 }
270}
271
272impl<T> IndexMut<Position> for VecRecords<T> {
273 fn index_mut(&mut self, (row, col): Position) -> &mut Self::Output {
274 &mut self.records[row][col]
275 }
276}
277
278fn create_records<'a, I, T, S, W>(
279 data: I,
280 width_ctrl: W,
281 (hint_count_rows, hint_count_cols): (usize, usize),
282) -> Vec<Vec<CellInfo<'a>>>
283where
284 I: IntoIterator<Item = T>,
285 T: IntoIterator<Item = S>,
286 S: AsRef<str> + 'a,
287 W: WidthFunc,
288{
289 let mut cells = vec![vec![CellInfo::default(); hint_count_cols]; hint_count_rows];
290 let mut count_rows = hint_count_rows;
291
292 for (row, rows) in data.into_iter().enumerate() {
293 if row >= count_rows {
294 cells.push(vec![CellInfo::default(); hint_count_cols]);
295 count_rows += 1;
296 }
297
298 for (col, text) in rows.into_iter().enumerate().take(hint_count_cols) {
299 let text = text.as_ref();
300 if text.is_empty() {
301 continue;
302 }
303
304 cells[row][col] = CellInfo::new(text.to_owned(), &width_ctrl);
305 }
306 }
307
308 cells
309}
310
311pub trait Cell: AsRef<str> {
313 fn get_line(&self, i: usize) -> &str;
315
316 fn count_lines(&self) -> usize;
318
319 fn width<W>(&self, width_ctrl: W) -> usize
321 where
322 W: WidthFunc;
323
324 fn line_width<W>(&self, i: usize, width_ctrl: W) -> usize
326 where
327 W: WidthFunc;
328
329 fn fmt_prefix(&self, _: &mut Formatter<'_>) -> fmt::Result {
333 Ok(())
334 }
335
336 fn fmt_suffix(&self, _: &mut Formatter<'_>) -> fmt::Result {
340 Ok(())
341 }
342}
343
344pub trait CellMut<T> {
346 fn set<W>(&mut self, text: T, width_ctrl: W)
348 where
349 W: WidthFunc;
350
351 fn update<W>(&mut self, width_ctrl: W)
355 where
356 W: WidthFunc;
357}