1use std::num::ParseIntError;
3use std::ops::BitAnd;
4
5use serde::Serialize;
6
7use crate::UtilesCoreError;
8use crate::UtilesCoreError::InvalidZoom;
9use crate::constants::MAX_ZOOM;
10use crate::errors::UtilesCoreResult;
11
12#[must_use]
14pub fn zoom_max_xy(zoom: u8) -> u32 {
15 2_u32.pow(u32::from(zoom)) - 1
16}
17
18#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Serialize)]
38pub struct ZoomSet(u32);
39
40#[must_use]
58pub fn zset2zvec(zset: u32) -> Vec<u8> {
59 if zset & (1 << 31) != 0 {
61 zset2zvec(zset.reverse_bits() >> 1)
62 } else {
63 (0u8..31).filter(|&i| (zset & (1u32 << i)) != 0).collect()
64 }
65}
66
67#[must_use]
77pub fn zvec2zset(zvec: &[u8]) -> u32 {
78 zvec.iter().fold(0, |acc, &z| acc | (1 << z))
79}
80
81#[must_use]
84pub fn zset2zvec_rev(zset: u32) -> Vec<u8> {
85 zset2zvec(zset.reverse_bits() >> 1)
86}
87
88#[must_use]
90pub fn zvec2zset_rev(zvec: &[u8]) -> u32 {
91 zvec.iter().fold(0, |acc, &z| acc | (1 << (31 - z)))
92}
93
94impl ZoomSet {
96 #[must_use]
98 pub const fn new(zset: u32) -> Self {
99 Self(zset)
100 }
101
102 #[must_use]
104 pub fn from_zooms(zooms: &[u8]) -> Self {
105 Self(zvec2zset(zooms))
106 }
107
108 #[must_use]
110 pub fn to_zooms(&self) -> Vec<u8> {
111 zset2zvec(self.0)
112 }
113
114 #[must_use]
115 pub const fn all() -> Self {
116 Self(0b0111_1111_1111_1111_1111_1111_1111_1111)
117 }
118
119 #[must_use]
120 pub fn zoom_ranges(&self) -> Vec<ZoomRange> {
121 let mut ranges: Vec<ZoomRange> = vec![];
122 let mut min: u8 = 0;
123 let mut max: u8 = 0;
124 let mut i: u8 = 0;
125 while i < MAX_ZOOM {
126 if self.0 & (1 << i) != 0 {
127 if min == 0 {
128 min = i;
129 }
130 max = i;
131 } else if min != 0 {
132 ranges.push(ZoomRange::new(min, max));
133 min = 0;
134 max = 0;
135 }
136 i += 1;
137 }
138 if min != 0 {
139 ranges.push(ZoomRange::new(min, max));
140 }
141 ranges
142 }
143}
144
145impl From<u8> for ZoomSet {
146 fn from(zoom: u8) -> Self {
147 Self(1 << zoom)
148 }
149}
150
151impl From<u32> for ZoomSet {
152 fn from(zset: u32) -> Self {
153 Self(zset)
154 }
155}
156
157impl From<ZoomSet> for Vec<u8> {
158 fn from(zset: ZoomSet) -> Self {
159 zset2zvec(zset.0)
160 }
161}
162
163impl TryFrom<Vec<u8>> for ZoomSet {
164 type Error = UtilesCoreError;
165
166 fn try_from(zvec: Vec<u8>) -> Result<Self, Self::Error> {
167 let result = zvec.iter().try_fold(0u32, |acc, &z| {
168 if z > MAX_ZOOM {
169 Err(InvalidZoom(z.to_string()))
170 } else {
171 Ok(acc | (1 << z))
172 }
173 })?;
174 Ok(Self::new(result)) }
176}
177
178impl BitAnd for ZoomSet {
179 type Output = Self;
180
181 fn bitand(self, rhs: Self) -> Self::Output {
182 Self(self.0 & rhs.0)
183 }
184}
185
186impl BitAnd<u32> for ZoomSet {
187 type Output = Self;
188
189 fn bitand(self, rhs: u32) -> Self::Output {
190 Self(self.0 & rhs)
191 }
192}
193
194impl BitAnd<ZoomSet> for u32 {
195 type Output = ZoomSet;
196
197 fn bitand(self, rhs: ZoomSet) -> Self::Output {
198 ZoomSet(self & rhs.0)
199 }
200}
201
202impl BitAnd<u8> for ZoomSet {
203 type Output = Self;
204
205 fn bitand(self, rhs: u8) -> Self::Output {
206 Self(self.0 & (1 << (31 - rhs)))
207 }
208}
209
210type ZoomsSetInt = u32;
211
212#[derive(Debug, Clone, Eq, PartialEq)]
214pub struct ZoomRange {
215 pub min: u8,
217 pub max: u8,
219}
220
221impl Default for ZoomRange {
223 fn default() -> Self {
224 Self {
225 min: 0,
226 max: MAX_ZOOM,
227 }
228 }
229}
230
231impl ZoomRange {
232 #[must_use]
234 pub const fn new(min: u8, max: u8) -> Self {
235 Self { min, max }
236 }
237
238 #[must_use]
240 pub const fn from_max(max: u8) -> Self {
241 Self { min: 0, max }
242 }
243
244 #[must_use]
246 pub const fn from_min(min: u8) -> Self {
247 Self { min, max: 30 }
248 }
249}
250
251impl IntoIterator for ZoomRange {
252 type Item = u8;
253 type IntoIter = std::ops::RangeInclusive<u8>;
254
255 fn into_iter(self) -> Self::IntoIter {
256 self.min..=self.max
257 }
258}
259
260impl From<ZoomRange> for ZoomSet {
270 fn from(zoom_range: ZoomRange) -> Self {
271 Self(zoom_range.into_iter().fold(0, |acc, z| acc | (1 << z)))
272 }
273}
274
275pub fn parse_zooms(zstr: &str) -> UtilesCoreResult<Vec<u8>> {
289 let mut zvec: Vec<u8> = vec![];
290 for z in zstr.split(',') {
291 if z.contains('-') {
292 let zrange: Result<Vec<u8>, ParseIntError> =
293 z.split('-').map(str::parse).collect::<Result<Vec<_>, _>>();
294
295 let zrange = match zrange {
296 Ok(zrange) => match zrange.len() {
297 1 => vec![zrange[0]],
298 2 => (zrange[0]..=zrange[1]).collect(),
299 _ => vec![],
300 },
301 Err(_) => return Err(InvalidZoom(z.to_string())),
302 };
303 zvec.extend(zrange);
304 } else {
305 match z.parse::<u8>() {
306 Ok(num) => zvec.push(num),
307 Err(_) => return Err(InvalidZoom(z.to_string())),
308 }
309 }
310 }
311 for z in &zvec {
313 if *z > 32 {
314 return Err(InvalidZoom((*z).to_string()));
315 }
316 }
317 zvec.sort_unstable();
319 zvec.dedup();
320 Ok(zvec)
321}
322
323pub enum ZoomOrZooms {
325 Zoom(u8),
327
328 Zooms(Vec<u8>),
330}
331
332impl From<u8> for ZoomOrZooms {
333 fn from(zoom: u8) -> Self {
334 Self::Zoom(zoom)
335 }
336}
337
338impl From<Vec<u8>> for ZoomOrZooms {
339 fn from(zooms: Vec<u8>) -> Self {
340 Self::Zooms(zooms)
341 }
342}
343
344impl From<ZoomOrZooms> for ZoomsSetInt {
345 fn from(zoom_or_zooms: ZoomOrZooms) -> Self {
346 match zoom_or_zooms {
347 ZoomOrZooms::Zoom(zoom) => 1 << (31 - zoom),
348 ZoomOrZooms::Zooms(zooms) => zvec2zset_rev(&zooms),
349 }
350 }
351}
352
353#[cfg(test)]
354mod tests {
355 use super::*;
356
357 #[test]
358 fn zset2zvec_none() {
359 let zset: u32 = 0b0000_0000_0000_0000_0000_0000_0000_0000;
360 let zvec: Vec<u8> = vec![];
361 assert_eq!(zset2zvec(zset), zvec);
362 assert_eq!(zset2zvec_rev(zset), zvec);
363 assert_eq!(zset, 0);
364 }
365
366 #[test]
367 fn zset2zvec_0_1_2() {
368 let zset_fwd: u32 = 0b0000_0000_0000_0000_0000_0000_0000_0111;
369 let zset_rev: u32 = 0b1111_0000_0000_0000_0000_0000_0000_0000;
370 let zvec: Vec<u8> = vec![0, 1, 2];
371 assert_eq!(zset2zvec(zset_fwd), zvec);
372 assert_eq!(zset_fwd, 7);
373 assert_eq!(zset2zvec_rev(zset_rev), zvec);
374 }
375
376 #[test]
377 fn zset2zvec_all() {
378 let zset_int_fwd: u32 = 0b0111_1111_1111_1111_1111_1111_1111_1111;
379 let zset_int_rev: u32 = 0b1111_1111_1111_1111_1111_1111_1111_1111;
380 let zvec: Vec<u8> = vec![
381 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
382 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
383 ];
384 assert_eq!(zset2zvec(zset_int_fwd), zvec);
385 assert_eq!(zset2zvec_rev(zset_int_rev), zvec);
386 }
387
388 #[test]
389 fn zvec2zset_none() {
390 let zset_int: u32 = 0b0000_0000_0000_0000_0000_0000_0000_0000;
391 assert!(zset2zvec(zset_int).is_empty());
392 assert!(zset2zvec_rev(zset_int).is_empty());
393 }
394
395 #[test]
396 fn zvec2zset_0_1_2() {
397 let zset_int: u32 = 0b1110_0000_0000_0000_0000_0000_0000_0000;
398 let zvec: Vec<u8> = vec![0, 1, 2];
399
400 assert_eq!(zvec2zset_rev(&zvec), zset_int);
401 }
402
403 #[test]
404 fn zvec2zset_0_1_2_3_4_5_6_7() {
405 let zset_int: u32 = 0b1111_1111_0000_0000_0000_0000_0000_0000;
406 let zvec: Vec<u8> = vec![0, 1, 2, 3, 4, 5, 6, 7];
407 let zset_from_zvec = zvec2zset_rev(&zvec);
408 assert_eq!(zset_from_zvec, zset_int);
409 }
410
411 #[test]
412 fn zoom_set_into_zoom_vec() {
413 let zset_int_fwd: u32 = 0b0000_0000_0000_0000_0000_0000_1111_1111;
414 let zet_fwd_vec: Vec<u8> = ZoomSet::from(zset_int_fwd).into();
415 assert_eq!(zet_fwd_vec, vec![0, 1, 2, 3, 4, 5, 6, 7]);
416 let zset_int_rev: u32 = 0b1111_1111_1000_0000_0000_0000_0000_0000;
417 let zset: ZoomSet = zset_int_rev.into();
418 let zvec = Vec::from(zset);
419 assert_eq!(zvec, vec![0, 1, 2, 3, 4, 5, 6, 7]);
420 }
421}