1use crate::{
2 grid::config::Offset,
3 grid::records::{ExactRecords, Records, Resizable},
4 settings::TableOption,
5};
6
7#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
11pub struct Reverse {
12 columns: bool,
13 start: usize,
14 limit: Offset,
15}
16
17impl Reverse {
18 pub const fn columns(start: usize) -> Self {
20 Self::new(true, start, Offset::End(0))
21 }
22
23 pub const fn rows(start: usize) -> Self {
25 Self::new(false, start, Offset::End(0))
26 }
27
28 pub const fn limit(self, limit: Offset) -> Self {
30 Self::new(self.columns, self.start, limit)
31 }
32
33 const fn new(columns: bool, start: usize, limit: Offset) -> Self {
34 Self {
35 columns,
36 start,
37 limit,
38 }
39 }
40}
41
42impl<R, D, C> TableOption<R, C, D> for Reverse
43where
44 R: Resizable + Records + ExactRecords,
45{
46 fn change(self, records: &mut R, _: &mut C, _: &mut D) {
47 let count_rows = records.count_rows();
48 let count_columns = records.count_columns();
49
50 let start = self.start;
51
52 if self.columns {
53 let end = match self.limit {
54 Offset::Start(limit) => start + limit,
55 Offset::End(limit) => count_columns - limit,
56 };
57
58 if start >= end || end > count_columns {
59 return;
60 }
61
62 reverse_columns(records, start, end);
63 } else {
64 let end = match self.limit {
65 Offset::Start(limit) => start + limit,
66 Offset::End(limit) => count_rows - limit,
67 };
68
69 if start >= end || end > count_rows {
70 return;
71 }
72
73 reverse_rows(records, start, end);
74 }
75 }
76}
77
78fn reverse_rows<R>(data: &mut R, start: usize, end: usize)
79where
80 R: Resizable + ExactRecords,
81{
82 let count_rows = end - start;
83 if count_rows < 2 {
84 return;
85 }
86
87 let mut i = start;
88 let mut j = end - 1;
89
90 while i < j {
91 data.swap_row(i, j);
92 i += 1;
93 j -= 1;
94 }
95}
96
97fn reverse_columns<R>(data: &mut R, start: usize, end: usize)
98where
99 R: Resizable + Records,
100{
101 let count_columns = end - start;
102 if count_columns < 2 {
103 return;
104 }
105
106 let mut i = start;
107 let mut j = end - 1;
108
109 while i < j {
110 data.swap_column(i, j);
111 i += 1;
112 j -= 1;
113 }
114}
115
116#[cfg(test)]
117#[cfg(feature = "std")]
118mod tests {
119 use crate::grid::records::{vec_records::VecRecords, Records};
120
121 use super::{reverse_columns, reverse_rows};
122
123 #[test]
124 fn test_reverse_rows() {
125 assert_eq!(
126 rev_rows(vec![vec![0, 1, 2], vec![3, 4, 5], vec![6, 7, 8]]),
127 vec![vec![6, 7, 8], vec![3, 4, 5], vec![0, 1, 2]]
128 )
129 }
130
131 #[test]
132 fn test_reverse_columns() {
133 assert_eq!(
134 rev_cols(vec![vec![0, 1, 2], vec![3, 4, 5], vec![6, 7, 8]]),
135 vec![vec![2, 1, 0], vec![5, 4, 3], vec![8, 7, 6]]
136 )
137 }
138
139 fn rev_rows(mut data: Vec<Vec<usize>>) -> Vec<Vec<usize>> {
140 let end = data.len();
141 reverse_rows(&mut data, 0, end);
142 data
143 }
144
145 fn rev_cols(data: Vec<Vec<usize>>) -> Vec<Vec<usize>> {
146 let mut records = VecRecords::new(data);
147 let end = records.count_columns();
148 reverse_columns(&mut records, 0, end);
149
150 records.into()
151 }
152}