1use std::fmt;
2use std::cmp::Ordering;
3use std::hash::{Hasher, Hash};
4
5use crate::cell::Cell;
6
7#[derive(Clone, Copy, Eq)]
8pub struct Reference {
9 pub start_cell : Cell,
10 pub end_cell : Option<Cell>
11}
12
13impl PartialOrd for Reference {
14 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
15 Some(self.cmp(other))
16 }
17}
18
19impl Hash for Reference {
20 fn hash<H: Hasher>(&self, state: &mut H) {
21 self.start_cell.hash(state);
22 self.end_cell.hash(state);
23 }
24}
25
26impl Ord for Reference {
27 fn cmp(&self, other: &Self) -> Ordering {
29 self.start_cell.cmp(&other.start_cell)
30 }
31}
32
33impl PartialEq for Reference {
34 fn eq(&self, other: &Self) -> bool {
35 (self.start_cell == other.start_cell)
36 & (self.end_cell == other.end_cell)
37 }
38}
39
40impl From<Cell> for Reference {
41 fn from(a : Cell) -> Reference {
42 Reference {
43 start_cell : a,
44 end_cell : None
45 }
46 }
47}
48
49impl From<(Cell, Option<Cell>)> for Reference {
50 fn from((a, b) : (Cell, Option<Cell>)) -> Reference {
51 Reference {
52 start_cell : a,
53 end_cell : b
54 }
55 }
56}
57
58impl From<(usize, usize)> for Reference {
59 fn from((a, b) : (usize, usize)) -> Reference {
60 Reference {
61 start_cell : Cell::from((a, b)),
62 end_cell : None
63 }
64 }
65}
66
67impl From<(usize, usize, usize, usize)> for Reference {
68 fn from((a, b, c, d) : (usize, usize, usize, usize)) -> Reference {
69 Reference {
70 start_cell : Cell::from((a, b)),
71 end_cell : Some(Cell::from((c, d)))
72 }
73 }
74}
75
76impl From<String> for Reference {
77 fn from(a1 : String) -> Reference {
78 if !a1.contains(':') {
79 let cell = Cell::from(a1);
81 Reference::from(cell)
82 } else {
83 let mut cells_split = a1.split(':').map(|x| x.to_owned()).collect::<Vec<String>>();
85 let c1: String = cells_split.remove(0);
86 let c2: String = cells_split.remove(0);
87 Reference::from((Cell::from(c1), Some(Cell::from(c2))))
88 }
89 }
90}
91
92impl From<&str> for Reference {
93 fn from(s : &str) -> Reference {
94 Reference::from(s.to_owned())
95 }
96}
97
98impl fmt::Display for Reference {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 if self.is_multi_cell() {
101 write!(
103 f,
104 "{}:{}",
105 self.start_cell,
106 self.end_cell.as_ref().unwrap()
107 )
108 } else {
109 write!(f, "{}", self.start_cell)
110 }
111 }
112}
113
114impl fmt::Debug for Reference {
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116 write!(f, "{}", self)
117 }
118}
119
120impl Reference {
121 pub fn row(&self) -> usize {
122 self.start_cell.row.index
123 }
124
125 pub fn column(&self) -> usize {
126 self.start_cell.column.index
127 }
128
129 pub fn is_single_cell(&self) -> bool {
130 self.end_cell.is_none() && !self.start_cell.is_hrange() && !self.start_cell.is_vrange()
131 }
132
133 pub fn is_multi_cell(&self) -> bool {
134 self.end_cell.is_some() || self.start_cell.is_hrange() || self.start_cell.is_vrange()
135 }
136
137 pub fn is_hrange(&self) -> bool {
138 self.start_cell.is_hrange()
139 }
140
141 pub fn is_vrange(&self) -> bool {
142 self.start_cell.is_vrange()
143 }
144
145 pub fn num_rows(&self) -> usize {
146 if self.is_multi_cell() {
147 if self.start_cell.is_vrange() {
148 usize::MAX
149 } else {
150 self.end_cell.as_ref().unwrap().row.index - self.start_cell.row.index + 1
151 }
152 } else {
153 1
154 }
155 }
156
157 pub fn num_cols(&self) -> usize {
158 if self.is_multi_cell() {
159 if self.start_cell.is_hrange() {
160 usize::MAX
161 } else {
162 self.end_cell.as_ref().unwrap().column.index - self.start_cell.column.index + 1
163 }
164 } else {
165 1
166 }
167 }
168
169 pub fn get_dimensions(&self) -> (usize, usize, usize, usize) {
170 (
171 self.row(),
172 self.column(),
173 self.num_rows(),
174 self.num_cols(),
175 )
176 }
177
178 pub fn get_cells_from_dim(start_row: usize, start_column: usize, num_rows: usize, num_cols: usize) -> Vec<(usize, usize)> {
179 let mut output: Vec<(usize, usize)> = vec![];
180 for row in start_row..(start_row + num_rows) {
181 for column in start_column..(start_column + num_cols) {
182 output.push((row, column));
183 }
184 }
185 output
186 }
187
188 pub fn get_cells(&self) -> Vec<(usize, usize)> {
189 let (start_row, start_column, num_rows, num_cols) = self.get_dimensions();
190 Self::get_cells_from_dim(start_row, start_column, num_rows, num_cols)
191 }
192
193 pub fn offset(&mut self, offset: (i32, i32)) {
194 if !self.start_cell.row.anchor && !self.start_cell.is_vrange() {
195 self.start_cell.row.index = (self.row() as i32 + offset.0) as usize;
196 }
197
198 if !self.start_cell.column.anchor && !self.start_cell.is_hrange() {
199 self.start_cell.column.index = (self.column() as i32 + offset.1) as usize;
200 }
201
202 if self.end_cell.is_some() {
203 if !self.end_cell.as_ref().unwrap().row.anchor && !self.end_cell.as_ref().unwrap().is_vrange() {
204 self.end_cell = Some(Cell::from(((self.end_cell.as_ref().unwrap().row.index as i32 + offset.0) as usize, self.end_cell.as_ref().unwrap().column.index)))
205 }
206
207 if !self.end_cell.as_ref().unwrap().column.anchor && !self.end_cell.as_ref().unwrap().is_hrange() {
208 self.end_cell = Some(Cell::from((self.end_cell.as_ref().unwrap().row.index, (self.end_cell.as_ref().unwrap().column.index as i32 + offset.1) as usize)))
209 }
210 }
211 }
212}
213