diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bd45895..409c628 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -28,15 +28,13 @@ jobs: - name: Lint run: | rustfmt +nightly **/*.rs - cargo clippy --all -- -D warnings -A clippy::redundant_async_block + cargo clippy --all -- -D warnings - name: Install cargo check tools run: | - cargo install --locked cargo-deny || true cargo install --locked cargo-outdated || true cargo install --locked cargo-udeps || true - name: Check run: | - cargo deny check cargo outdated --exit-code 1 cargo udeps rm -rf ~/.cargo/advisory-db diff --git a/src/lib.rs b/src/lib.rs index 05003d1..8971353 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ use derive_more::Display; use std::collections::HashSet; -use std::result::Result; +use std::result; #[derive(Display, Debug)] pub enum Error { @@ -8,13 +8,15 @@ pub enum Error { AlphabetLength, #[display(fmt = "Alphabet must contain unique characters")] AlphabetUniqueCharacters, + #[display(fmt = "Minimum length has to be between {min} and {max}")] + MinLength { min: usize, max: usize }, #[display(fmt = "Encoding supports numbers between {min} and {max}")] EncodingRange { min: u64, max: u64 }, #[display(fmt = "Ran out of range checking against the blocklist")] BlocklistOutOfRange, } -pub type SqidsResult = Result; +pub type Result = result::Result; #[derive(Debug)] pub struct Options { @@ -41,7 +43,7 @@ pub struct Sqids { } impl Sqids { - pub fn new(options: Option) -> SqidsResult { + pub fn new(options: Option) -> Result { let options = options.unwrap_or_default(); let alphabet: Vec = options.alphabet.chars().collect(); @@ -73,11 +75,20 @@ impl Sqids { blocklist: filtered_blocklist, }; + if options.min_length < sqids.min_value() as usize + || options.min_length > options.alphabet.len() + { + return Err(Error::MinLength { + min: sqids.min_value() as usize, + max: options.alphabet.len(), + }); + } + sqids.alphabet = sqids.shuffle(&sqids.alphabet); Ok(sqids) } - pub fn encode(&self, numbers: &[u64]) -> SqidsResult { + pub fn encode(&self, numbers: &[u64]) -> Result { if numbers.is_empty() { return Ok(String::new()); } @@ -165,12 +176,12 @@ impl Sqids { u64::MAX } - fn encode_numbers(&self, numbers: &[u64], partitioned: bool) -> SqidsResult { + fn encode_numbers(&self, numbers: &[u64], partitioned: bool) -> Result { let offset = numbers .iter() .enumerate() .fold(numbers.len(), |a, (i, &v)| { - (v as usize % self.alphabet.len()) + i + a + self.alphabet[v as usize % self.alphabet.len()] as usize + i + a }) % self.alphabet.len(); diff --git a/tests/encoding.rs b/tests/encoding.rs index a26172c..1a7cf1f 100644 --- a/tests/encoding.rs +++ b/tests/encoding.rs @@ -1,12 +1,11 @@ -// use sqids::*; +use sqids::*; #[test] fn simple() { - assert_eq!(1, 1); - // let id = "8QRLaD".to_string(); - // let numbers = vec![1, 2, 3]; + let id = "8QRLaD".to_string(); + let numbers = vec![1, 2, 3]; - // let sqids = Sqids::new(None).unwrap(); - // assert_eq!(sqids.encode(&numbers).unwrap(), id); - // assert_eq!(sqids.decode(&id), numbers); + let sqids = Sqids::new(None).unwrap(); + assert_eq!(sqids.encode(&numbers).unwrap(), id); + assert_eq!(sqids.decode(&id), numbers); }