1use serde::{Deserialize, Serialize};
2use std::hash::{Hash, Hasher};
3
4pub trait ToGridPointND<T>
5where
6 T: Clone,
7{
8 fn to_nd(&self) -> GridPointND<T>;
9}
10
11#[derive(Clone, Debug, Serialize, Deserialize)]
12pub struct GridPoint1D<T> {
13 pub x: T,
14}
15
16#[derive(Clone, Debug, Serialize, Deserialize)]
17pub struct GridPoint2D<T> {
18 pub x: T,
19 pub y: T,
20}
21
22#[derive(Clone, Debug, Serialize, Deserialize)]
23pub struct GridPoint3D<T> {
24 pub x: T,
25 pub y: T,
26 pub z: T,
27}
28
29#[derive(Clone, Debug)]
30pub struct GridPointND<T> {
31 indices: Vec<T>,
32}
33
34impl<T> ToGridPointND<T> for GridPoint1D<T>
35where
36 T: Clone,
37{
38 fn to_nd(&self) -> GridPointND<T> {
39 GridPointND::new(vec![self.x.clone()].iter())
40 }
41}
42
43impl<T> ToGridPointND<T> for GridPoint2D<T>
44where
45 T: Clone,
46{
47 fn to_nd(&self) -> GridPointND<T> {
48 GridPointND::new(vec![self.x.clone(), self.y.clone()].iter())
49 }
50}
51
52impl<T> ToGridPointND<T> for GridPoint3D<T>
53where
54 T: Clone,
55{
56 fn to_nd(&self) -> GridPointND<T> {
57 GridPointND::new(vec![self.x.clone(), self.y.clone(), self.z.clone()].iter())
58 }
59}
60
61impl<T> GridPointND<T> {
62 pub fn new<'a, 'b, I>(indices: I) -> Self
63 where
64 'a: 'b,
65 T: 'a + Clone,
66 I: Iterator<Item = &'b T>,
67 {
68 Self {
69 indices: indices.map(|ele| ele.clone()).collect(),
70 }
71 }
72
73 pub fn indices<'a>(&'a self) -> std::slice::Iter<'a, T> {
74 self.indices.iter()
75 }
76
77 pub fn to_1d(&self) -> Option<GridPoint1D<T>>
78 where
79 T: Clone,
80 {
81 let mut iter = self.indices();
82 let x = iter.next();
83 if x.is_none() {
84 return None;
85 }
86 match iter.next() {
87 Some(_) => None,
88 None => Some(GridPoint1D {
89 x: x.unwrap().clone(),
90 }),
91 }
92 }
93
94 pub fn to_2d(&self) -> Option<GridPoint2D<T>>
95 where
96 T: Clone,
97 {
98 let mut iter = self.indices();
99 let x = iter.next();
100 if x.is_none() {
101 return None;
102 }
103 let y = iter.next();
104 if y.is_none() {
105 return None;
106 }
107 match iter.next() {
108 Some(_) => None,
109 None => Some(GridPoint2D {
110 x: x.unwrap().clone(),
111 y: y.unwrap().clone(),
112 }),
113 }
114 }
115
116 pub fn to_3d(&self) -> Option<GridPoint3D<T>>
117 where
118 T: Clone,
119 {
120 let mut iter = self.indices();
121 let x = iter.next();
122 if x.is_none() {
123 return None;
124 }
125 let y = iter.next();
126 if y.is_none() {
127 return None;
128 }
129 let z = iter.next();
130 if z.is_none() {
131 return None;
132 }
133 match iter.next() {
134 Some(_) => None,
135 None => Some(GridPoint3D {
136 x: x.unwrap().clone(),
137 y: y.unwrap().clone(),
138 z: z.unwrap().clone(),
139 }),
140 }
141 }
142}
143
144impl<T> PartialEq for GridPoint1D<T>
145where
146 T: PartialEq,
147{
148 fn eq(&self, other: &Self) -> bool {
149 self.x == other.x
150 }
151}
152
153impl<T> PartialEq for GridPoint2D<T>
154where
155 T: PartialEq,
156{
157 fn eq(&self, other: &Self) -> bool {
158 self.x == other.x && self.y == other.y
159 }
160}
161
162impl<T> PartialEq for GridPoint3D<T>
163where
164 T: PartialEq,
165{
166 fn eq(&self, other: &Self) -> bool {
167 self.x == other.x && self.y == other.y && self.z == other.z
168 }
169}
170
171impl<T> PartialEq for GridPointND<T>
172where
173 T: PartialEq,
174{
175 fn eq(&self, other: &Self) -> bool {
176 let mut not_eq_res = self.indices().zip(other.indices()).filter(|(a, b)| a != b);
177 match not_eq_res.next() {
178 Some(_) => false,
179 None => true,
180 }
181 }
182}
183
184impl<T> Eq for GridPoint1D<T> where T: PartialEq {}
185impl<T> Eq for GridPoint2D<T> where T: PartialEq {}
186impl<T> Eq for GridPoint3D<T> where T: PartialEq {}
187impl<T> Eq for GridPointND<T> where T: PartialEq {}
188
189impl<T> Hash for GridPoint1D<T>
190where
191 T: Hash,
192{
193 fn hash<H: Hasher>(&self, state: &mut H) {
194 self.x.hash(state);
195 }
196}
197
198impl<T> Hash for GridPoint2D<T>
199where
200 T: Hash,
201{
202 fn hash<H: Hasher>(&self, state: &mut H) {
203 self.x.hash(state);
204 self.y.hash(state);
205 }
206}
207
208impl<T> Hash for GridPoint3D<T>
209where
210 T: Hash,
211{
212 fn hash<H: Hasher>(&self, state: &mut H) {
213 self.x.hash(state);
214 self.y.hash(state);
215 self.z.hash(state);
216 }
217}
218
219impl<T> Hash for GridPointND<T>
220where
221 T: Hash,
222{
223 fn hash<H: Hasher>(&self, state: &mut H) {
224 for idx in self.indices() {
225 idx.hash(state)
226 }
227 }
228}
229
230impl<T> GridPoint3D<T> {
231 pub fn new(x: T, y: T, z: T) -> Self {
232 Self { x, y, z }
233 }
234}
235
236impl<T> GridPoint2D<T> {
237 pub fn new(x: T, y: T) -> Self {
238 Self { x, y }
239 }
240}
241
242impl<T> GridPoint1D<T> {
243 pub fn new(x: T) -> Self {
244 Self { x }
245 }
246}