1#[cfg(test)]
2#[macro_use] extern crate assert_matches;
3
4use std::fmt;
5use std::fmt::Formatter;
6use std::string::ToString;
7use std::slice::{Iter, IterMut};
8
9#[derive(Default, Debug, Clone)]
10pub struct DynamicGrid <T>{
12 data: Vec<T>,
13 line_start_index: Vec<usize>
14}
15
16impl <T> DynamicGrid<T> where T: Clone{
17
18 pub fn new () -> Self{
20 DynamicGrid{ data: vec![], line_start_index: vec![] }
21 }
22
23 pub fn init (row: usize, col: usize, value: T) -> Self{
30 let mut v = vec![0, row];
31 let mut index_row = 0;
32 v.iter_mut().for_each(| value| {
33 *value = index_row;
34 index_row += col;
35 });
36
37 DynamicGrid{
38 data: vec![value; row * col],
39 line_start_index: v
40 }
41 }
42
43 pub fn from_vec(vec: Vec<Vec<T>>) -> Self{
47 let mut g = DynamicGrid::new();
48 let mut start_index = 0;
49 for row in vec.iter() {
50 g.line_start_index.push(start_index);
51 for item in row.iter(){
52 g.data.push(item.clone());
53 start_index+=1;
54 }
55 }
56 g
57 }
58
59 pub fn rows(&self) -> usize {
61 self.line_start_index.len()
62 }
63
64 pub fn row_size(&self, index_row: usize) -> Option<usize> {
68 if index_row < self.rows() {
69 Some(self.row_size_unchecked(index_row))
70 } else {
71 None
72 }
73 }
74
75 pub fn row_size_unchecked(&self, index_row: usize) -> usize{
79 let end = if index_row < self.rows() - 1 {self.line_start_index[index_row + 1]}
80 else {self.data.len()};
81 end - self.line_start_index[index_row]
82 }
83
84 pub fn push(&mut self, value: T) -> (usize, usize){
87 self.data.push(value);
88 (self.rows() - 1, self.row_size_unchecked(self.rows() - 1) - 1 )
89
90 }
91
92 pub fn push_at_row(&mut self, index_row: usize, value: T) -> Option<(usize, usize)> {
97 if index_row < self.rows() {
98 let position = (index_row, self.row_size_unchecked(index_row));
99 self.insert(position.0, position.1, value);
100 return Some(position)
101 }
102 return None
103 }
104
105 pub fn insert(&mut self, index_row: usize, index_col:usize, value: T){
114 if index_row < self.rows(){
115 if index_col <= self.row_size_unchecked(index_row){
116 self.data.insert(self.line_start_index[index_row] + index_col, value);
117 if index_row < self.rows() - 1 {self.line_start_index[index_row + 1] += 1}
118 }else {
119 panic!("Out of bounds. Col index must be less than {:?}, your index is {:?}", self.row_size_unchecked(index_row) - 1, index_col)
120
121 }
122 } else {
123 panic!("Out of bounds. Row index must be less than {:?}, your index is {:?}", self.rows() - 1, index_row)
124 }
125 }
126
127 pub fn swap(&mut self, first_position: (usize, usize), second_position: (usize, usize)) {
134 if first_position.0 < self.rows() && second_position.0 < self.rows() {
135 if first_position.1 < self.row_size_unchecked(first_position.0)
136 && second_position.1 < self.row_size_unchecked(second_position.0){
137 let first_index = self.line_start_index[first_position.0] + first_position.1;
138 let second_index = self.line_start_index[second_position.0] + second_position.1;
139
140 self.data.swap(first_index, second_index);
141 } else {
142 panic!("Out of bounds");
143 }
144 } else {
145 panic!("Out of bounds");
146 }
147 }
148
149
150 pub fn push_new_row(&mut self, value: T) -> (usize, usize){
152 self.line_start_index.push(self.data.len());
153 self.push(value);
154 (self.rows() - 1, self.row_size_unchecked(self.rows() - 1) - 1 )
155 }
156
157 pub fn remove(&mut self){
159 if self.data.len() > 0 {
160 self.data.remove(self.data.len() -1 );
161 if *self.line_start_index.last().unwrap() >= self.data.len(){
162 self.remove_row(self.rows() - 1 )
163 }
164 }
165 }
166
167 pub fn remove_row(&mut self, index_row: usize) {
169 if !self.data.is_empty() && index_row < self.rows(){
170 let start = self.line_start_index[index_row];
171 let end = start + self.row_size_unchecked(index_row);
172
173 self.data = self.data.iter()
174 .enumerate()
175 .filter(|(i, _)| !(start..end).contains(i))
176 .map(|(_, v)| v.clone())
177 .collect();
178
179 self.line_start_index.remove(index_row);
180 }
181 }
182
183 pub unsafe fn get_unchecked(&self, index_row: usize, index_col: usize) -> &T{
189 self.data.get_unchecked(self.line_start_index[index_row] + index_col)
190 }
191
192 pub unsafe fn get_unchecked_mut(&mut self, index_row: usize, index_col: usize) -> &mut T{
198 self.data.get_unchecked_mut(self.line_start_index[index_row] + index_col)
199 }
200
201 pub fn get (&self, index_row: usize, index_col: usize) -> Option<&T>{
209 if index_row < self.rows() {
210 if index_col < self.row_size_unchecked(index_row) {
211 unsafe{ Some(self.get_unchecked(index_row, index_col))}
212 } else {
213 None
214 }
215 }else {
216 None
217 }
218 }
219
220 pub fn get_mut (&mut self, index_row: usize, index_col: usize) -> Option<&mut T>{
228 if index_row < self.rows() {
229 if index_col < self.row_size_unchecked(index_row) {
230 unsafe{ Some(self.get_unchecked_mut(index_row, index_col))}
231 } else {
232 None
233 }
234 }else {
235 None
236 }
237 }
238
239 pub fn iter(&self) -> Iter<T> {
241 self.data.iter()
242 }
243
244 pub fn iter_mut(&mut self) -> IterMut<T> {
246 self.data.iter_mut()
247 }
248
249 pub fn iter_row(&self, index_row: usize) -> Iter<T> {
254 if index_row < self.rows() {
255 let cols = self.row_size_unchecked(index_row);
256 let start = self.line_start_index[index_row];
257 return self.data[start..(start + cols)].iter()
258 } else {
259 panic!("Out of bounds. Row index must be less than {:?}, your index is {:?}", self.rows() - 1, index_row)
260 }
261 }
262
263 pub fn iter_row_mut(&mut self, index_row: usize) -> IterMut<T> {
268 if index_row < self.rows() {
269 let cols = self.row_size_unchecked(index_row);
270 let start = self.line_start_index[index_row];
271 return self.data[start..(start + cols)].iter_mut()
272 } else {
273 panic!("Out of bounds. Row index must be less than {:?}, your index is {:?}", self.rows() - 1, index_row)
274 }
275 }
276
277
278}
279
280impl <T> fmt::Display for DynamicGrid<T> where T: Clone + ToString{
281 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
282 let mut s = String::new();
283
284 for row in 0..self.rows(){
285 for data in self.iter_row(row) {
286 s.push_str(data.to_string().as_str());
287 s.push_str(",")
288 }
289 s.push_str("\n");
290 }
291
292 write!(f, "{}", s)
293 }
294}
295
296#[cfg(test)]
297mod tests {
298
299 use crate::DynamicGrid;
300
301 fn init() -> DynamicGrid<usize>{
306 let g =
322 DynamicGrid::from_vec(
323 vec![
324 vec![10, 5, 4],
325 vec![3, 9],
326 vec![1],
327 vec![7, 6, 2, 8]
328 ]);
329
330 g
331 }
332
333 #[test]
334 fn test_new() {
335 let g: DynamicGrid<i32> = DynamicGrid::new();
336
337 assert_matches!(g.rows(), 0);
338 assert_matches!(g.row_size(0), None);
339 assert_matches!(g.row_size(10), None);
340 }
341
342 #[test]
343 fn test_init() {
344 let g = init();
345 assert_matches!(g.rows(), 4);
346 assert_matches!(g.row_size(0), Some(3));
347 assert_matches!(g.row_size(1), Some(2));
348 assert_matches!(g.row_size(2), Some(1));
349 assert_matches!(g.row_size(3), Some(4));
350 assert_matches!(g.row_size(10), None);
351 }
352
353 #[test]
354 fn test_push() {
355 let mut g = init();
356
357 let position = g.push(4);
358 assert_matches!(position, (3, 4));
359 assert_matches!(g.row_size(0), Some(3));
360 assert_matches!(g.row_size(3), Some(5));
361 }
362
363 #[test]
364 fn test_push_new_row(){
365 let mut g = init();
366 let position = g.push_new_row(4);
367 assert_matches!(position, (4, 0));
368 assert_matches!(g.row_size(0), Some(3));
369 assert_matches!(g.row_size(4), Some(1));
370 }
371
372 #[test]
373 fn test_push_at_row() {
374 let mut g = init();
375
376 let position = g.push_at_row(2, 4);
377 println!("{}", g);
378 assert_matches!(position, Some((2, 1)));
379 assert_matches!(g.get(2, 1), Some(4));
380 assert_matches!(g.row_size(0), Some(3));
381 assert_matches!(g.row_size(2), Some(2));
382
383 }
384
385 #[test]
386 fn test_swap() {
387 let mut g = init();
388
389 g.swap((0, 1), (3, 2));
390
391 assert_matches!(g.get(0, 1), Some(2));
392 assert_matches!(g.get(3, 2), Some(5));
393
394 }
395
396 #[test]
397 fn test_remove() {
398 let mut g = init();
399 g.remove();
400 assert_matches!(g.row_size(3), Some(3))
401 }
402
403 #[test]
404 fn test_remove_row() {
405 let mut g = init();
406 g.remove_row(0);
407 assert_matches!(g.rows(), 3);
408 }
409
410 #[test]
411 fn test_get() {
412 let mut g = init();
413 assert_matches!(g.get(0,0), Some(10));
414 assert_matches!(g.get(10,0), None);
415 assert_matches!(g.get(1, 1), Some(9));
416 assert_matches!(g.get(3, 3), Some(8));
417 assert_matches!(g.get(3, 4), None);
418
419
420 g.push(11);
421 assert_matches!(g.get(3, 4), Some(11));
422 }
423
424 #[test]
425 fn test_get_mut() {
426 let mut g = init();
427 assert_matches!(g.get_mut(0,0), Some(10));
428 assert_matches!(g.get_mut(10,0), None);
429 assert_matches!(g.get_mut(1, 1), Some(9));
430
431 g.push(3);
432 assert_matches!(g.get_mut(3, 4), Some(3));
433
434 *g.get_mut(3, 4).unwrap() = 5;
435 assert_matches!(g.get(3, 4), Some(5));
436 }
437
438 #[test]
439 fn test_iterator() {
440 let g = init();
441 let mut iter = g.iter();
442 assert_matches!(iter.next(), Some(10));
443 assert_matches!(iter.next(), Some(5));
444 assert_matches!(iter.next(), Some(4));
445 assert_matches!(iter.next(), Some(3));
446 assert_matches!(iter.next(), Some(9));
447 assert_matches!(iter.next(), Some(1));
448 assert_matches!(iter.next(), Some(7));
449 assert_matches!(iter.next(), Some(6));
450 assert_matches!(iter.next(), Some(2));
451 assert_matches!(iter.next(), Some(8));
452 assert_matches!(iter.next(), None);
453 }
454
455 #[test]
456 fn test_row_iterator() {
457 let g = init();
458 let mut iter = g.iter_row(1);
459 assert_matches!(iter.next(), Some(3));
460 assert_matches!(iter.next(), Some(9));
461 assert_matches!(iter.next(), None);
462
463 let mut iter = g.iter_row(2);
464 assert_matches!(iter.next(), Some(1));
465 assert_matches!(iter.next(), None);
466
467 let mut iter = g.iter_row(3);
468 assert_matches!(iter.next(), Some(7));
469 assert_matches!(iter.next(), Some(6));
470 assert_matches!(iter.next(), Some(2));
471 assert_matches!(iter.next(), Some(8));
472 assert_matches!(iter.next(), None);
473
474 }
475
476 #[test]
477 #[should_panic]
478 fn test_row_iterator_should_panic() {
479 let g = init();
480 let mut _iter = g.iter_row(10);
481
482 }
487}