From f421b6883f44f8f024b71d2975b0372d4be7b416 Mon Sep 17 00:00:00 2001 From: jake <77554505+brxken128@users.noreply.github.com> Date: Mon, 11 Sep 2023 12:35:09 +0100 Subject: [PATCH] Fix builds and make `String` -> `PlusCode` validation more generic (Google support) (#1326) fix builds and make string -> pc matching more generic, so it works with google's format too --- .../src/image/geographic/pluscodes.rs | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/crates/media-metadata/src/image/geographic/pluscodes.rs b/crates/media-metadata/src/image/geographic/pluscodes.rs index 9147d6624..1988b2f26 100644 --- a/crates/media-metadata/src/image/geographic/pluscodes.rs +++ b/crates/media-metadata/src/image/geographic/pluscodes.rs @@ -47,11 +47,12 @@ impl PlusCodeState { impl PlusCode { #[inline] #[must_use] + #[allow(clippy::tuple_array_conversions)] pub fn new(lat: f64, long: f64) -> Self { let mut output = Self::encode_coordinates(Self::normalize_lat(lat)) .into_iter() .zip(Self::encode_coordinates(Self::normalize_long(long))) - .flat_map(<[char; 2]>::from) + .flat_map(|(x, y)| [x, y]) .collect::(); output.insert(8, '+'); @@ -98,15 +99,21 @@ impl PlusCode { impl TryFrom for PlusCode { type Error = Error; - fn try_from(mut value: String) -> Result { - value.retain(|c| !c.is_whitespace()); + fn try_from(value: String) -> Result { + let mut pc_value = value.clone(); + pc_value.retain(|c| !c.is_whitespace()); - if value.len() > 11 - || value.len() < 2 - || (value.len() < 8 && !value.contains('+')) - || PLUSCODE_DIGITS - .iter() - .any(|x| value.chars().any(|y| y != '+' && x != &y)) + if pc_value.len() > 11 { + pc_value.truncate(11); + } + + if pc_value.len() < 2 + || (pc_value.len() < 8 && pc_value.chars().nth(7) != Some('+')) + // this covers Google's shorter format + || (pc_value.len() == 7 && pc_value.chars().nth(4) != Some('+')) + || PLUSCODE_DIGITS + .iter() + .any(|x| pc_value.chars().any(|y| y != '+' && x != &y)) { return Err(Error::Conversion); } @@ -114,3 +121,20 @@ impl TryFrom for PlusCode { Ok(Self(value)) } } + +#[cfg(test)] +mod tests { + use super::PlusCode; + + #[test] + fn pluscode_maximum_precision() { + let x = String::from("8FW4V74V+X8"); + PlusCode::try_from(x).unwrap(); + } + + #[test] + fn pluscode_google() { + let x = String::from("WR2C+2C Bibra Lake"); + PlusCode::try_from(x).unwrap(); + } +}