kasane_logic/spatial_id/flex_id/
mod.rs1pub mod constructor;
2pub mod convert;
3pub mod impls;
4pub mod ops;
5
6use crate::{MAX_ZOOM_LEVEL, Side, TemporalId};
7
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[cfg_attr(feature = "openapi", derive(utoipa::ToSchema))]
10#[derive(Clone, PartialEq, Debug, Eq, PartialOrd, Ord, Hash)]
11pub struct FlexId {
13 f_zoomlevel: u8,
14 f_index: i32,
15 x_zoomlevel: u8,
16 x_index: u32,
17 y_zoomlevel: u8,
18 y_index: u32,
19 temporal_id: TemporalId,
20}
21
22impl FlexId {
23 pub const UPPER_MAX: FlexId = FlexId {
24 f_zoomlevel: 0,
25 f_index: 0,
26 x_zoomlevel: 0,
27 x_index: 0,
28 y_zoomlevel: 0,
29 y_index: 0,
30 temporal_id: TemporalId::WHOLE,
31 };
32
33 pub const LOWER_MAX: FlexId = FlexId {
34 f_zoomlevel: 0,
35 f_index: -1,
36 x_zoomlevel: 0,
37 x_index: 0,
38 y_zoomlevel: 0,
39 y_index: 0,
40 temporal_id: TemporalId::WHOLE,
41 };
42
43 pub fn f_zoomlevel(&self) -> u8 {
44 self.f_zoomlevel
45 }
46 pub fn x_zoomlevel(&self) -> u8 {
47 self.x_zoomlevel
48 }
49 pub fn y_zoomlevel(&self) -> u8 {
50 self.y_zoomlevel
51 }
52 pub fn f_index(&self) -> i32 {
53 self.f_index
54 }
55 pub fn x_index(&self) -> u32 {
56 self.x_index
57 }
58 pub fn y_index(&self) -> u32 {
59 self.y_index
60 }
61
62 pub fn f_split(&self, side: Side) -> Option<FlexId> {
64 if self.f_zoomlevel() == MAX_ZOOM_LEVEL as u8 {
65 return None;
66 } else {
67 #[cfg(feature = "temporal_id")]
68 return Some(unsafe {
69 FlexId::new_with_temporal_unchecked(
70 self.f_zoomlevel() + 1,
71 self.f_index() * 2 + side as i32,
72 self.x_zoomlevel(),
73 self.x_index(),
74 self.y_zoomlevel(),
75 self.y_index(),
76 self.temporal_id.clone(),
77 )
78 });
79
80 #[cfg(not(feature = "temporal_id"))]
81 return Some(unsafe {
82 FlexId::new_unchecked(
83 self.f_zoomlevel() + 1,
84 self.f_index() * 2 + side as i32,
85 self.x_zoomlevel(),
86 self.x_index(),
87 self.y_zoomlevel(),
88 self.y_index(),
89 )
90 });
91 }
92 }
93
94 pub fn x_split(&self, side: Side) -> Option<FlexId> {
96 if self.x_zoomlevel() == MAX_ZOOM_LEVEL as u8 {
97 return None;
98 } else {
99 #[cfg(feature = "temporal_id")]
100 return Some(unsafe {
101 FlexId::new_with_temporal_unchecked(
102 self.f_zoomlevel(),
103 self.f_index(),
104 self.x_zoomlevel() + 1,
105 self.x_index() * 2 + side as u32,
106 self.y_zoomlevel(),
107 self.y_index(),
108 self.temporal().clone(),
109 )
110 });
111
112 #[cfg(not(feature = "temporal_id"))]
113 return Some(unsafe {
114 FlexId::new_unchecked(
115 self.f_zoomlevel(),
116 self.f_index(),
117 self.x_zoomlevel() + 1,
118 self.x_index() * 2 + side as u32,
119 self.y_zoomlevel(),
120 self.y_index(),
121 )
122 });
123 }
124 }
125
126 pub fn y_split(&self, side: Side) -> Option<FlexId> {
128 if self.y_zoomlevel() == MAX_ZOOM_LEVEL as u8 {
129 return None;
130 } else {
131 #[cfg(feature = "temporal_id")]
132 return Some(unsafe {
133 FlexId::new_with_temporal_unchecked(
134 self.f_zoomlevel(),
135 self.f_index(),
136 self.x_zoomlevel(),
137 self.x_index(),
138 self.y_zoomlevel() + 1,
139 self.y_index() * 2 + side as u32,
140 self.temporal_id.clone(),
141 )
142 });
143
144 #[cfg(not(feature = "temporal_id"))]
145 return Some(unsafe {
146 FlexId::new_unchecked(
147 self.f_zoomlevel(),
148 self.f_index(),
149 self.x_zoomlevel(),
150 self.x_index(),
151 self.y_zoomlevel() + 1,
152 self.y_index() * 2 + side as u32,
153 )
154 });
155 }
156 }
157}