diff --git a/CHANGELOG.md b/CHANGELOG.md index 532800e..3e7e49e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG +**v0.4.2:** +- Fix u64 overflow + **v0.4.1:** - Derive `Clone` trait [[PR #6](https://github.com/sqids/sqids-rust/pull/6)] - Cargo update diff --git a/Cargo.toml b/Cargo.toml index b46fa52..b469efd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ description = "Generate short unique ids from numbers." repository = "https://github.com/sqids/sqids-rust" documentation = "https://docs.rs/sqids" homepage = "https://sqids.org/rust" -version = "0.4.1" +version = "0.4.2" license = "MIT" edition = "2021" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index e2a7d0d..f16f0bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -251,7 +251,9 @@ impl Sqids { let alphabet_without_separator: Vec = alphabet.iter().copied().skip(1).collect(); - ret.push(self.to_number(chunks[0], &alphabet_without_separator)); + if let Some(value) = self.to_number(chunks[0], &alphabet_without_separator) { + ret.push(value) + } if chunks.len() > 1 { alphabet = Self::shuffle(&alphabet); @@ -332,15 +334,19 @@ impl Sqids { id.into_iter().collect() } - fn to_number(&self, id: &str, alphabet: &[char]) -> u64 { + fn to_number(&self, id: &str, alphabet: &[char]) -> Option { let mut result = 0; for c in id.chars() { let idx = alphabet.iter().position(|&x| x == c).unwrap(); - result = result * alphabet.len() as u64 + idx as u64; + result = result * alphabet.len() as u128 + idx as u128; } - result + if result <= u64::MAX.into() { + Some(result.try_into().unwrap()) + } else { + None + } } fn shuffle(alphabet: &[char]) -> Vec { diff --git a/tests/decoding.rs b/tests/decoding.rs new file mode 100644 index 0000000..ce3d1b7 --- /dev/null +++ b/tests/decoding.rs @@ -0,0 +1,15 @@ +use sqids::*; + +#[test] +fn decode_number_maximum_value() { + let sqids = Sqids::default(); + let numbers = sqids.decode("ABARpJzdz9"); + assert_eq!(numbers, [9_007_199_254_740_991]); // 2 ^ 53 +} + +#[test] +fn decode_number_overflows() { + let sqids = Sqids::default(); + let numbers = sqids.decode("0J4AEXRN106Z0"); + assert_eq!(numbers, Vec::::new()); +}