From 46ae59244d24116e2ebc01f1565b5250405114b6 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 7 May 2024 11:45:26 -0700 Subject: [PATCH 1/2] scale once Co-authored-by: mattiZed --- src/lib.rs | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7dd3746..ade7a80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,20 +46,18 @@ where } } -fn encode(current: f64, previous: f64, factor: i32, output: &mut String) -> Result<(), String> { - let current = scale(current, factor); - let previous = scale(previous, factor); - let mut coordinate = (current - previous) << 1; - if (current - previous) < 0 { - coordinate = !coordinate; +fn encode(delta: i64, output: &mut String) -> Result<(), String> { + let mut value = delta << 1; + if value < 0 { + value = !value; } - while coordinate >= 0x20 { - let from_char = char::from_u32(((0x20 | (coordinate & 0x1f)) + 63) as u32) + while value >= 0x20 { + let from_char = char::from_u32(((0x20 | (value & 0x1f)) + 63) as u32) .ok_or("Couldn't convert character")?; output.push(from_char); - coordinate >>= 5; + value >>= 5; } - let from_char = char::from_u32((coordinate + 63) as u32).ok_or("Couldn't convert character")?; + let from_char = char::from_u32((value + 63) as u32).ok_or("Couldn't convert character")?; output.push(from_char); Ok(()) } @@ -83,16 +81,21 @@ where let factor: i32 = base.pow(precision); let mut output = String::new(); - let mut b = Coord { x: 0.0, y: 0.0 }; + let mut previous = Coord { x: 0, y: 0 }; - for (i, a) in coordinates.into_iter().enumerate() { - check(a.y, (MIN_LATITUDE, MAX_LATITUDE)) + for (i, next) in coordinates.into_iter().enumerate() { + check(next.y, (MIN_LATITUDE, MAX_LATITUDE)) .map_err(|e| format!("Latitude error at position {0}: {1}", i, e))?; - check(a.x, (MIN_LONGITUDE, MAX_LONGITUDE)) + check(next.x, (MIN_LONGITUDE, MAX_LONGITUDE)) .map_err(|e| format!("Longitude error at position {0}: {1}", i, e))?; - encode(a.y, b.y, factor, &mut output)?; - encode(a.x, b.x, factor, &mut output)?; - b = a; + + let scaled_next = Coord { + x: scale(next.x, factor), + y: scale(next.y, factor), + }; + encode(scaled_next.y - previous.y, &mut output)?; + encode(scaled_next.x - previous.x, &mut output)?; + previous = scaled_next; } Ok(output) } From 3efa13116a61b11c7d77750136f2a4425df9008d Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Tue, 7 May 2024 13:05:17 -0700 Subject: [PATCH 2/2] inline error checking --- src/lib.rs | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ade7a80..e04b4f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ //! It is thus advisable to pay careful attention to the order of the coordinates you use for encoding and decoding. use geo_types::{Coord, LineString}; -use std::{char, cmp}; +use std::char; const MIN_LONGITUDE: f64 = -180.0; const MAX_LONGITUDE: f64 = 180.0; @@ -35,17 +35,6 @@ fn scale(n: f64, factor: i32) -> i64 { scaled.round() as i64 } -// Bounds checking for input values -fn check(to_check: T, bounds: (T, T)) -> Result -where - T: cmp::PartialOrd + Copy, -{ - match to_check { - to_check if bounds.0 <= to_check && to_check <= bounds.1 => Ok(to_check), - _ => Err(to_check), - } -} - fn encode(delta: i64, output: &mut String) -> Result<(), String> { let mut value = delta << 1; if value < 0 { @@ -84,10 +73,18 @@ where let mut previous = Coord { x: 0, y: 0 }; for (i, next) in coordinates.into_iter().enumerate() { - check(next.y, (MIN_LATITUDE, MAX_LATITUDE)) - .map_err(|e| format!("Latitude error at position {0}: {1}", i, e))?; - check(next.x, (MIN_LONGITUDE, MAX_LONGITUDE)) - .map_err(|e| format!("Longitude error at position {0}: {1}", i, e))?; + if !(MIN_LATITUDE..MAX_LATITUDE).contains(&next.y) { + return Err(format!( + "Invalid latitude: {lat} at position {i}", + lat = next.y + )); + } + if !(MIN_LONGITUDE..MAX_LONGITUDE).contains(&next.x) { + return Err(format!( + "Invalid longitude: {lon} at position {i}", + lon = next.x + )); + } let scaled_next = Coord { x: scale(next.x, factor),