1pub struct PolylineIter<'a> {
41 polyline: &'a [u8],
42 scale: f64,
43 lat: i32,
45 lon: i32,
47}
48
49impl<'a> PolylineIter<'a> {
50 #[inline(always)]
53 pub fn new(precision: u8, polyline: &'a str) -> Self {
54 assert!(precision <= 7, "i32 can hold up to 180 * 10^7");
55 PolylineIter {
56 polyline: polyline.as_bytes(),
57 lat: 0,
58 lon: 0,
59 scale: 10.0_f64.powi(precision as i32),
60 }
61 }
62
63 #[inline(always)]
64 fn varint_decode(&mut self) -> Option<u32> {
65 let mut result = 0;
66 for i in 0..self.polyline.len().min(7) {
67 let chunk = (self.polyline[i] as i32) - 63;
69 result |= (chunk & 0x1f) << (i * 5); if chunk & 0x20 == 0 {
71 self.polyline = &self.polyline[i + 1..];
72 return Some(result as u32);
73 }
74 }
75 None
76 }
77
78 pub fn len(&self) -> usize {
80 self.polyline
81 .iter()
82 .filter(|&&byte| (byte as i8 - 63) & 0x20 == 0)
83 .count()
84 / 2 }
86
87 pub fn is_empty(&self) -> bool {
89 self.polyline
90 .iter()
91 .filter(|&&byte| (byte as i8 - 63) & 0x20 == 0)
92 .nth(1)
93 .is_none()
94 }
95}
96
97impl Iterator for PolylineIter<'_> {
98 type Item = (f64, f64);
99
100 fn next(&mut self) -> Option<Self::Item> {
101 let lat_change = self.varint_decode()?;
102 let lon_change = self.varint_decode()?;
103 self.lat += zigzag_decode(lat_change);
104 self.lon += zigzag_decode(lon_change);
105 let lat = self.lat as f64 / self.scale;
106 let lon = self.lon as f64 / self.scale;
107 Some((lat, lon))
108 }
109
110 fn size_hint(&self) -> (usize, Option<usize>) {
111 let len = self.polyline.len();
114 (len / 12, Some(len / 2))
115 }
116
117 fn count(self) -> usize {
118 self.len()
119 }
120}
121
122#[inline(always)]
151pub fn decode(precision: u8, polyline: &str) -> PolylineIter<'_> {
152 PolylineIter::new(precision, polyline)
153}
154
155pub fn encode(precision: u8, points: impl IntoIterator<Item = (f64, f64)>) -> String {
178 assert!(precision <= 7, "i32 can hold up to 180 * 10^7");
179
180 let scale = 10.0_f64.powi(precision as i32);
181 let mut result = String::with_capacity(16);
182
183 let mut prev = (0.0, 0.0);
184 for point in points {
185 let lat_change = ((point.0 - prev.0) * scale).round() as i32;
186 let lon_change = ((point.1 - prev.1) * scale).round() as i32;
187
188 varint_encode(zigzag_encode(lat_change), &mut result);
189 varint_encode(zigzag_encode(lon_change), &mut result);
190
191 prev = point;
192 }
193 result
194}
195
196fn zigzag_decode(i: u32) -> i32 {
198 (i >> 1) as i32 ^ -((i & 1) as i32)
199}
200
201fn zigzag_encode(value: i32) -> u32 {
204 (value << 1) as u32 ^ (value >> 31) as u32
205}
206
207fn varint_encode(mut value: u32, buffer: &mut String) {
210 while value >= 0x20 {
211 let byte = char::from_u32(((value & 0x1F) | 0x20) + 63).unwrap();
212 buffer.push(byte);
213 value >>= 5;
214 }
215 let byte = char::from_u32(value + 63).unwrap();
216 buffer.push(byte);
217}
218
219#[cfg(test)]
220mod tests {
221 use super::*;
222 use pretty_assertions::assert_eq;
223
224 fn check_polyline(polyline: &str) -> bool {
226 let bytes = polyline.as_bytes();
227 let mut stop_bytes = 0;
228 for &byte in bytes {
229 if (byte as u32) < 63 || (byte as u32) > 127 {
230 return false;
231 }
232 if (byte - 63) & 0x20 == 0 {
233 stop_bytes += 1;
234 }
235 }
236 stop_bytes % 2 == 0 && bytes.last().map(|b| b & 0x20 == 0).unwrap_or(true)
238 }
239
240 #[test]
241 fn zigzag() {
242 assert_eq!(zigzag_decode(0), 0);
243 assert_eq!(zigzag_decode(1), -1);
244 assert_eq!(zigzag_decode(2), 1);
245 assert_eq!(zigzag_decode(3), -2);
246 assert_eq!(zigzag_decode(4), 2);
247 assert_eq!(zigzag_decode(5), -3);
248 assert_eq!(zigzag_decode(6), 3);
249 assert_eq!(zigzag_decode(7), -4);
250 assert_eq!(zigzag_decode(8), 4);
251 assert_eq!(zigzag_decode(9), -5);
252 assert_eq!(zigzag_decode(10), 5);
253 assert_eq!(zigzag_decode(11), -6);
254 assert_eq!(zigzag_decode(12), 6);
255 assert_eq!(zigzag_decode(13), -7);
256 assert_eq!(zigzag_decode(14), 7);
257 assert_eq!(zigzag_decode(15), -8);
258
259 assert_eq!(zigzag_encode(0), 0);
260 assert_eq!(zigzag_encode(-1), 1);
261 assert_eq!(zigzag_encode(1), 2);
262 assert_eq!(zigzag_encode(-2), 3);
263 assert_eq!(zigzag_encode(2), 4);
264 assert_eq!(zigzag_encode(-3), 5);
265 assert_eq!(zigzag_encode(3), 6);
266 assert_eq!(zigzag_encode(-4), 7);
267 assert_eq!(zigzag_encode(4), 8);
268 assert_eq!(zigzag_encode(-5), 9);
269 assert_eq!(zigzag_encode(5), 10);
270 assert_eq!(zigzag_encode(-6), 11);
271 assert_eq!(zigzag_encode(6), 12);
272 assert_eq!(zigzag_encode(-7), 13);
273 assert_eq!(zigzag_encode(7), 14);
274 assert_eq!(zigzag_encode(-8), 15);
275 }
276
277 #[test]
278 fn empty_polyline() {
279 assert_eq!(decode(5, "").next(), None);
280 assert_eq!(encode(5, []), "");
281
282 assert_eq!(decode(6, "").next(), None);
283 assert_eq!(encode(6, []), "");
284 }
285
286 #[test]
287 fn single_point() {
288 assert_eq!(encode(5, [(0.0, 0.0)]), "??");
289 assert_eq!(decode(5, "??").collect::<Vec<_>>(), [(0.0, 0.0)]);
290 assert_eq!(encode(6, [(0.0, 0.0)]), "??");
291 assert_eq!(decode(6, "??").collect::<Vec<_>>(), [(0.0, 0.0)]);
292
293 let point = (55.71218211778275, 13.21561509233427);
294 assert_eq!(encode(5, [point]), "ch`sIsdtoA");
295 assert_eq!(
296 decode(5, "ch`sIsdtoA").collect::<Vec<_>>(),
297 [(55.71218, 13.21562)]
298 );
299 assert_eq!(encode(6, [point]), "kzkgiB}vreX");
300 assert_eq!(
301 decode(6, "kzkgiB}vreX").collect::<Vec<_>>(),
302 [(55.712182, 13.215615)]
303 );
304 assert_eq!(encode(7, [point]), "yp_se`@mnda{F");
305 assert_eq!(
306 decode(7, "yp_se`@mnda{F").collect::<Vec<_>>(),
307 [(55.7121821, 13.2156151)]
308 );
309
310 let point = (37.82070486887192, -122.47866012130189);
311 assert_eq!(encode(5, [point]), "kzyeFrrpjV");
312 assert_eq!(
313 decode(5, "kzyeFrrpjV").collect::<Vec<_>>(),
314 [(37.82070, -122.47866)]
315 );
316 assert_eq!(encode(6, [point]), "aqkcgAfcorhF");
317 assert_eq!(
318 decode(6, "aqkcgAfcorhF").collect::<Vec<_>>(),
319 [(37.820705, -122.478660)]
320 );
321
322 let point = (-54.906532713928094, -65.99208264367125);
323 assert_eq!(encode(5, [point]), "x|bnInaxqK");
324 assert_eq!(
325 decode(5, "x|bnInaxqK").collect::<Vec<_>>(),
326 [(-54.90653, -65.99208)]
327 );
328 assert_eq!(encode(6, [point]), "hifvgBdxyz|B");
329 assert_eq!(
330 decode(6, "hifvgBdxyz|B").collect::<Vec<_>>(),
331 [(-54.906533, -65.992083)]
332 );
333
334 let point = (-37.88209074375984, 144.79631245265494);
335 assert_eq!(encode(5, [point]), "`zefF}owrZ");
336 assert_eq!(
337 decode(5, "`zefF}owrZ").collect::<Vec<_>>(),
338 [(-37.88209, 144.79631)]
339 );
340 assert_eq!(encode(6, [point]), "tmcggAohtdsG");
341 assert_eq!(
342 decode(6, "tmcggAohtdsG").collect::<Vec<_>>(),
343 [(-37.882091, 144.796312)]
344 );
345 }
346
347 #[test]
348 fn multiple_points() {
349 let polyline = "angrIk~inAgwDybH_|D_{KeoEwtLozFo`Gre@tcA";
350 assert!(check_polyline(polyline));
351 assert_eq!(decode(5, polyline).count(), 6);
352
353 let mut iter = decode(5, polyline);
354 assert_eq!(iter.next(), Some((55.58513, 12.99958)));
355 assert_eq!(iter.next(), Some((55.61461, 13.04627)));
356 assert_eq!(iter.next(), Some((55.64485, 13.11219)));
357 assert_eq!(iter.next(), Some((55.67816, 13.18223)));
358 assert_eq!(iter.next(), Some((55.71840, 13.22343)));
359 assert_eq!(iter.next(), Some((55.71222, 13.21244)));
360 assert_eq!(iter.next(), None);
361
362 let mut iter = decode(6, polyline);
364 assert_eq!(iter.next(), Some((5.558513, 1.299958)));
365 assert_eq!(iter.next(), Some((5.561461, 1.304627)));
366 assert_eq!(iter.next(), Some((5.564485, 1.311219)));
367 assert_eq!(iter.next(), Some((5.567816, 1.318223)));
368 assert_eq!(iter.next(), Some((5.571840, 1.322343)));
369 assert_eq!(iter.next(), Some((5.571222, 1.321244)));
370 assert_eq!(iter.next(), None);
371
372 let polyline = "gzkgiBgwreX{@sI~HcBwBoi@sXvBsIcBgJSwGg@wGg@cG{@{JoAwGSkC{@ce@gOwj@oKsb@cBoFz@gEjC?~RRb[f@v[Sz@kHnAoA_l@SsIR?";
374 assert_eq!(encode(6, decode(6, polyline)), polyline);
375
376 assert_eq!(
378 encode(5, decode(6, polyline)),
379 "ch`sIsdtoAEa@^IKgCqAJa@Ic@A[C[CYEe@G[AMEyBs@kCg@qBIWDSL?~@@xABzAAD]FGoCAa@@?"
380 );
381
382 assert_eq!(
383 encode(
384 6,
385 decode(7, polyline).map(|(lat, lon)| (lat * 10.0, lon * 10.0))
387 ),
388 polyline
389 );
390 }
391
392 #[test]
393 #[should_panic]
394 fn decode_bad_precision() {
395 decode(8, "");
396 }
397
398 #[test]
399 #[should_panic]
400 fn encode_bad_precision() {
401 encode(8, []);
402 }
403
404 #[test]
405 fn broken_string() {
406 assert_eq!(decode(5, "?").next(), None);
408 assert_eq!(decode(5, "?").is_empty(), true);
409 assert_eq!(decode(5, "?").len(), 0);
410
411 let polyline = "_p~iF~ps|U_ulLnnqC_mqNvxq";
413 assert!(!check_polyline(polyline)); let mut iter = decode(5, polyline);
415 assert_eq!(iter.len(), 2);
416 assert_eq!(iter.is_empty(), false);
417 assert_eq!(iter.next(), Some((38.5, -120.2)));
418 assert_eq!(iter.len(), 1);
419 assert_eq!(iter.is_empty(), false);
420 assert_eq!(iter.next(), Some((40.7, -120.95)));
421 assert_eq!(iter.len(), 0);
422 assert_eq!(iter.is_empty(), true);
423 assert_eq!(iter.next(), None);
424
425 let mut iter = decode(6, polyline);
426 assert_eq!(iter.len(), 2);
427 assert_eq!(iter.is_empty(), false);
428 assert_eq!(iter.next(), Some((3.85, -12.02)));
429 assert_eq!(iter.len(), 1);
430 assert_eq!(iter.is_empty(), false);
431 assert_eq!(iter.next(), Some((4.07, -12.095)));
432 assert_eq!(iter.len(), 0);
433 assert_eq!(iter.is_empty(), true);
434 assert_eq!(iter.next(), None);
435 assert_eq!(iter.len(), 0);
436 assert_eq!(iter.is_empty(), true);
437
438 assert_eq!(iter.next(), None); assert_eq!(iter.is_empty(), true);
440 }
441
442 #[test]
443 fn invalid_symbols() {
444 let polyline = "!!!!";
446 assert!(!check_polyline(polyline));
447 let mut iter = decode(5, polyline);
448 assert_eq!(iter.next(), None);
449
450 let polyline = "_p~iF~ps|U_ulLnnqC!_mqNvxq";
452 assert!(!check_polyline(polyline)); let mut iter = decode(5, polyline);
454 assert_eq!(iter.next(), Some((38.5, -120.2)));
455 assert_eq!(iter.next(), Some((40.7, -120.95)));
456 assert_eq!(iter.next(), None);
457 }
458
459 #[test]
460 fn size_hint() {
461 let iter = decode(5, "_p~iF~ps|U_ulLnnqC_mqNvxq`@");
462 assert!(iter.size_hint().0 <= 3);
464 assert!(iter.size_hint().1.unwrap() >= 3);
465 assert_eq!(iter.count(), 3);
466 }
467}