1use super::{PMDirectory, PMTileType};
2use crate::{parsers::Buffer, util::CompressionFormat};
3use s2json::Face;
4
5#[derive(Debug, Clone, Default, PartialEq)]
7pub struct S2PMEntries {
8 pub face_0: PMDirectory,
10 pub face_1: PMDirectory,
12 pub face_2: PMDirectory,
14 pub face_3: PMDirectory,
16 pub face_4: PMDirectory,
18 pub face_5: PMDirectory,
20}
21impl S2PMEntries {
22 pub fn get(&self, face: Face) -> &PMDirectory {
24 match face {
25 Face::Face0 => &self.face_0,
26 Face::Face1 => &self.face_1,
27 Face::Face2 => &self.face_2,
28 Face::Face3 => &self.face_3,
29 Face::Face4 => &self.face_4,
30 Face::Face5 => &self.face_5,
31 }
32 }
33
34 pub fn get_mut(&mut self, face: Face) -> &mut PMDirectory {
36 match face {
37 Face::Face0 => &mut self.face_0,
38 Face::Face1 => &mut self.face_1,
39 Face::Face2 => &mut self.face_2,
40 Face::Face3 => &mut self.face_3,
41 Face::Face4 => &mut self.face_4,
42 Face::Face5 => &mut self.face_5,
43 }
44 }
45
46 pub fn set_dir(&mut self, face: Face, dir: PMDirectory) {
48 match face {
49 Face::Face0 => self.face_0 = dir,
50 Face::Face1 => self.face_1 = dir,
51 Face::Face2 => self.face_2 = dir,
52 Face::Face3 => self.face_3 = dir,
53 Face::Face4 => self.face_4 = dir,
54 Face::Face5 => self.face_5 = dir,
55 }
56 }
57}
58
59pub const S2_PM_HEADER_SIZE_BYTES: usize = 262;
61pub const S2_PM_ROOT_SIZE: usize = 98_304;
63
64#[derive(Debug, Copy, Clone, Default, PartialEq)]
66pub struct S2PMHeader {
67 pub is_s2: bool,
69 pub version: u8,
71 pub root_directory_offset: u64,
73 pub root_directory_length: u64,
75 pub metadata_offset: u64,
77 pub metadata_length: u64,
79 pub leaf_directory_offset: u64,
81 pub leaf_directory_length: u64,
83 pub data_offset: u64,
85 pub data_length: u64,
87 pub n_addressed_tiles: u64,
89 pub n_tile_entries: u64,
91 pub n_tile_contents: u64,
93 pub clustered: bool,
95 pub internal_compression: CompressionFormat,
98 pub tile_compression: CompressionFormat,
100 pub tile_type: PMTileType,
102 pub min_zoom: u8,
104 pub max_zoom: u8,
106 pub min_longitude: f32,
108 pub min_latitude: f32,
110 pub max_longitude: f32,
112 pub max_latitude: f32,
114 pub center_zoom: u8,
116 pub center_longitude: f32,
118 pub center_latitude: f32,
120 pub root_directory_offset1: u64,
122 pub root_directory_length1: u64,
124 pub root_directory_offset2: u64,
126 pub root_directory_length2: u64,
128 pub root_directory_offset3: u64,
130 pub root_directory_length3: u64,
132 pub root_directory_offset4: u64,
134 pub root_directory_length4: u64,
136 pub root_directory_offset5: u64,
138 pub root_directory_length5: u64,
140 pub leaf_directory_offset1: u64,
142 pub leaf_directory_length1: u64,
144 pub leaf_directory_offset2: u64,
146 pub leaf_directory_length2: u64,
148 pub leaf_directory_offset3: u64,
150 pub leaf_directory_length3: u64,
152 pub leaf_directory_offset4: u64,
154 pub leaf_directory_length4: u64,
156 pub leaf_directory_offset5: u64,
158 pub leaf_directory_length5: u64,
160}
161impl S2PMHeader {
162 pub fn from_bytes(buffer: &mut Buffer) -> Self {
164 let ess = buffer.get_u8_at(0);
165 let two = buffer.get_u8_at(1);
166 let is_s2 = ess == 83 && two == 50;
167 Self {
168 is_s2,
169 version: buffer.get_u8_at(7),
170 root_directory_offset: buffer.get_u64_at(8),
171 root_directory_length: buffer.get_u64_at(16),
172 metadata_offset: buffer.get_u64_at(24),
173 metadata_length: buffer.get_u64_at(32),
174 leaf_directory_offset: buffer.get_u64_at(40),
175 leaf_directory_length: buffer.get_u64_at(48),
176 data_offset: buffer.get_u64_at(56),
177 data_length: buffer.get_u64_at(64),
178 n_addressed_tiles: buffer.get_u64_at(72),
179 n_tile_entries: buffer.get_u64_at(80),
180 n_tile_contents: buffer.get_u64_at(88),
181 clustered: buffer.get_u8_at(96) == 1,
182 internal_compression: CompressionFormat::from(buffer.get_u8_at(97)),
183 tile_compression: CompressionFormat::from(buffer.get_u8_at(98)),
184 tile_type: PMTileType::from(buffer.get_u8_at(99)),
185 min_zoom: buffer.get_u8_at(100),
186 max_zoom: buffer.get_u8_at(101),
187 min_longitude: if is_s2 { 0.0 } else { (buffer.get_i32_at(102) as f32) / 10_000_000.0 },
188 min_latitude: if is_s2 { 0.0 } else { (buffer.get_i32_at(106) as f32) / 10_000_000.0 },
189 max_longitude: if is_s2 { 0.0 } else { (buffer.get_i32_at(110) as f32) / 10_000_000.0 },
190 max_latitude: if is_s2 { 0.0 } else { (buffer.get_i32_at(114) as f32) / 10_000_000.0 },
191 center_zoom: if is_s2 { 0 } else { buffer.get_u8_at(118) },
192 center_longitude: if is_s2 {
193 0.0
194 } else {
195 (buffer.get_i32_at(119) as f32) / 10_000_000.0
196 },
197 center_latitude: if is_s2 {
198 0.0
199 } else {
200 (buffer.get_i32_at(123) as f32) / 10_000_000.0
201 },
202 root_directory_offset1: if is_s2 { buffer.get_u64_at(102) } else { 0 },
203 root_directory_length1: if is_s2 { buffer.get_u64_at(110) } else { 0 },
204 root_directory_length2: if is_s2 { buffer.get_u64_at(118) } else { 0 },
205 root_directory_offset2: if is_s2 { buffer.get_u64_at(126) } else { 0 },
206 root_directory_offset3: if is_s2 { buffer.get_u64_at(134) } else { 0 },
207 root_directory_length3: if is_s2 { buffer.get_u64_at(142) } else { 0 },
208 root_directory_offset4: if is_s2 { buffer.get_u64_at(150) } else { 0 },
209 root_directory_length4: if is_s2 { buffer.get_u64_at(158) } else { 0 },
210 root_directory_offset5: if is_s2 { buffer.get_u64_at(166) } else { 0 },
211 root_directory_length5: if is_s2 { buffer.get_u64_at(174) } else { 0 },
212 leaf_directory_offset1: if is_s2 { buffer.get_u64_at(182) } else { 0 },
213 leaf_directory_length1: if is_s2 { buffer.get_u64_at(190) } else { 0 },
214 leaf_directory_offset2: if is_s2 { buffer.get_u64_at(198) } else { 0 },
215 leaf_directory_length2: if is_s2 { buffer.get_u64_at(206) } else { 0 },
216 leaf_directory_offset3: if is_s2 { buffer.get_u64_at(214) } else { 0 },
217 leaf_directory_length3: if is_s2 { buffer.get_u64_at(222) } else { 0 },
218 leaf_directory_offset4: if is_s2 { buffer.get_u64_at(230) } else { 0 },
219 leaf_directory_length4: if is_s2 { buffer.get_u64_at(238) } else { 0 },
220 leaf_directory_offset5: if is_s2 { buffer.get_u64_at(246) } else { 0 },
221 leaf_directory_length5: if is_s2 { buffer.get_u64_at(254) } else { 0 },
222 }
223 }
224
225 pub fn to_bytes(&self) -> Buffer {
227 let mut buffer = Buffer::default();
228
229 buffer.set_u8(b'S');
231 buffer.set_u8(b'2');
232 buffer.set_u8_at(7, 1);
234
235 buffer.set_u64_at(8, self.root_directory_offset);
237 buffer.set_u64_at(16, self.root_directory_length);
238
239 buffer.set_u64_at(24, self.metadata_offset);
241 buffer.set_u64_at(32, self.metadata_length);
242
243 buffer.set_u64_at(40, self.leaf_directory_offset);
245 buffer.set_u64_at(48, self.leaf_directory_length);
246
247 buffer.set_u64_at(56, self.data_offset);
249 buffer.set_u64_at(64, self.data_length);
250
251 buffer.set_u64_at(72, self.n_addressed_tiles);
253 buffer.set_u64_at(80, self.n_tile_entries);
254 buffer.set_u64_at(88, self.n_tile_contents);
255
256 buffer.set_u8_at(96, if self.clustered { 1 } else { 0 });
258 buffer.set_u8_at(97, self.internal_compression.into());
259 buffer.set_u8_at(98, self.tile_compression.into());
260 buffer.set_u8_at(99, self.tile_type.into());
261 buffer.set_u8_at(100, self.min_zoom);
262 buffer.set_u8_at(101, self.max_zoom);
263
264 buffer.set_u64_at(102, self.root_directory_offset1);
266 buffer.set_u64_at(110, self.root_directory_length1);
267 buffer.set_u64_at(118, self.root_directory_length2);
268 buffer.set_u64_at(126, self.root_directory_offset2);
269 buffer.set_u64_at(134, self.root_directory_offset3);
270 buffer.set_u64_at(142, self.root_directory_length3);
271 buffer.set_u64_at(150, self.root_directory_offset4);
272 buffer.set_u64_at(158, self.root_directory_length4);
273 buffer.set_u64_at(166, self.root_directory_offset5);
274 buffer.set_u64_at(174, self.root_directory_length5);
275
276 buffer.set_u64_at(182, self.leaf_directory_offset1);
278 buffer.set_u64_at(190, self.leaf_directory_length1);
279 buffer.set_u64_at(198, self.leaf_directory_offset2);
280 buffer.set_u64_at(206, self.leaf_directory_length2);
281 buffer.set_u64_at(214, self.leaf_directory_offset3);
282 buffer.set_u64_at(222, self.leaf_directory_length3);
283 buffer.set_u64_at(230, self.leaf_directory_offset4);
284 buffer.set_u64_at(238, self.leaf_directory_length4);
285 buffer.set_u64_at(246, self.leaf_directory_offset5);
286 buffer.set_u64_at(254, self.leaf_directory_length5);
287
288 buffer
289 }
290
291 pub fn get_root_offset(&self, face: Face) -> u64 {
293 match face {
294 Face::Face0 => self.root_directory_offset,
295 Face::Face1 => self.root_directory_offset1,
296 Face::Face2 => self.root_directory_offset2,
297 Face::Face3 => self.root_directory_offset3,
298 Face::Face4 => self.root_directory_offset4,
299 Face::Face5 => self.root_directory_offset5,
300 }
301 }
302
303 pub fn get_root_length(&self, face: Face) -> u64 {
305 match face {
306 Face::Face0 => self.root_directory_length,
307 Face::Face1 => self.root_directory_length1,
308 Face::Face2 => self.root_directory_length2,
309 Face::Face3 => self.root_directory_length3,
310 Face::Face4 => self.root_directory_length4,
311 Face::Face5 => self.root_directory_length5,
312 }
313 }
314}