From c8aa39223a65cd4e0ed087b46b7c1cd70b898a0b Mon Sep 17 00:00:00 2001 From: toBinio Date: Mon, 31 Jul 2023 14:39:20 +0200 Subject: [PATCH 1/6] fix typo in Names doc --- src/names.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/names.rs b/src/names.rs index ba19aa52..1b4a4000 100644 --- a/src/names.rs +++ b/src/names.rs @@ -1,6 +1,6 @@ /// An iterator over all possible permutations of hyphens (`-`) and underscores (`_`) of a crate name. /// -/// For instance, the name `parking_lot` is turned into the sequence `parking_lot` and `parking_lot`, while +/// For instance, the name `parking_lot` is turned into the sequence `parking_lot` and `parking-lot`, while /// `serde-yaml` is turned into `serde-yaml` and `serde_yaml`. #[derive(Clone)] pub struct Names { From 254d21e0a10c49cc2dc16b25569743f8d209ef80 Mon Sep 17 00:00:00 2001 From: toBinio Date: Mon, 31 Jul 2023 15:49:32 +0200 Subject: [PATCH 2/6] use max_count for count() --- src/names.rs | 7 +++++++ tests/names/mod.rs | 20 +++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/names.rs b/src/names.rs index 1b4a4000..5df2a0f6 100644 --- a/src/names.rs +++ b/src/names.rs @@ -78,4 +78,11 @@ impl Iterator for Names { } } } + + fn count(self) -> usize + where + Self: Sized, + { + self.max_count as usize + } } diff --git a/tests/names/mod.rs b/tests/names/mod.rs index 5ba90be4..7f2c350d 100644 --- a/tests/names/mod.rs +++ b/tests/names/mod.rs @@ -1,13 +1,17 @@ use crates_index::Names; +fn data_count(names: Names) -> usize { + names.collect::>().len() +} + #[test] fn empty_string() { - assert_eq!(Names::new("").unwrap().count(), 1); + assert_eq!(data_count(Names::new("").unwrap()), 1); } #[test] fn name_without_separators_yields_name() { - assert_eq!(Names::new("serde").unwrap().count(), 1); + assert_eq!(data_count(Names::new("serde").unwrap()), 1); } #[test] @@ -18,12 +22,18 @@ fn permutation_count() { assert_eq!(Names::new("a_b_c-d").unwrap().count(), 8); } +#[test] +fn permutation_data_count() { + assert_eq!(data_count(Names::new("a-b").unwrap()), 2); + assert_eq!(data_count(Names::new("a-b_c").unwrap()), 4); + assert_eq!(data_count(Names::new("a_b_c").unwrap()), 4); + assert_eq!(data_count(Names::new("a_b_c-d").unwrap()), 8); +} + #[test] fn max_permutation_count_causes_error() { assert_eq!( - Names::new("a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p") - .expect("15 separators are fine") - .count(), + data_count(Names::new("a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p").expect("15 separators are fine")), 32768 ); assert!( From b63ec378b7b6e248225848b0632b41882311e6f9 Mon Sep 17 00:00:00 2001 From: toBinio Date: Mon, 31 Jul 2023 15:50:11 +0200 Subject: [PATCH 3/6] update test to capture edge case --- tests/names/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/names/mod.rs b/tests/names/mod.rs index 7f2c350d..7a6b75f6 100644 --- a/tests/names/mod.rs +++ b/tests/names/mod.rs @@ -38,7 +38,7 @@ fn max_permutation_count_causes_error() { ); assert!( Names::new("a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r").is_none(), - "17 are not fine anymore" + "16 are not fine anymore" ); } From 6b66356d9c1c463495c5f841a67e5c62152ebc97 Mon Sep 17 00:00:00 2001 From: toBinio Date: Mon, 31 Jul 2023 16:27:20 +0200 Subject: [PATCH 4/6] first return all-hyphens & all_underscores --- src/names.rs | 5 ++++- tests/names/mod.rs | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/names.rs b/src/names.rs index 5df2a0f6..10111d2e 100644 --- a/src/names.rs +++ b/src/names.rs @@ -60,8 +60,11 @@ impl Iterator for Names { return None; } + //map the count so the first value is the last one (all "-"), the second one is the first one (all "_")... + let used_count = *count as isize - 1 + self.max_count as isize; + for (sep_index, char_index) in self.separator_indexes[..self.separator_count].iter().enumerate() { - let char = if *count & (1 << sep_index) == 0 { b'-' } else { b'_' }; + let char = if used_count & (1 << sep_index) == 0 { b'_' } else { b'-' }; // SAFETY: We validated that `char_index` is a valid UTF-8 codepoint #[allow(unsafe_code)] unsafe { diff --git a/tests/names/mod.rs b/tests/names/mod.rs index 7a6b75f6..0de7aef1 100644 --- a/tests/names/mod.rs +++ b/tests/names/mod.rs @@ -46,19 +46,25 @@ fn max_permutation_count_causes_error() { fn permutations() { for (name, expected) in [ ("parking_lot", &["parking_lot", "parking-lot"] as &[_]), // the input name is always the first one returned. + ( + "a-b_c-d", // input name -> all-hyphens -> all_underscores -> rest + &[ + "a-b_c-d", "a-b-c-d", "a_b_c_d", "a-b_c_d", "a_b-c_d", "a-b-c_d", "a_b_c-d", "a_b-c-d", + ], + ), ("a_b", &["a_b", "a-b"]), ("a-b", &["a-b", "a_b"]), - ("a-b-c", &["a-b-c", "a_b-c", "a-b_c", "a_b_c"]), + ("a-b-c", &["a-b-c", "a_b_c", "a-b_c", "a_b-c"]), ( "a-b-c-d", &[ - "a-b-c-d", "a_b-c-d", "a-b_c-d", "a_b_c-d", "a-b-c_d", "a_b-c_d", "a-b_c_d", "a_b_c_d", + "a-b-c-d", "a_b_c_d", "a-b_c_d", "a_b-c_d", "a-b-c_d", "a_b_c-d", "a-b_c-d", "a_b-c-d", ], ), ( "a_b_c_d", &[ - "a_b_c_d", "a-b-c-d", "a_b-c-d", "a-b_c-d", "a_b_c-d", "a-b-c_d", "a_b-c_d", "a-b_c_d", + "a_b_c_d", "a-b-c-d", "a-b_c_d", "a_b-c_d", "a-b-c_d", "a_b_c-d", "a-b_c-d", "a_b-c-d", ], ), ] { From a20138dbfc94fe2a9fa28b0560cd47d53dec8899 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 31 Jul 2023 21:36:30 +0200 Subject: [PATCH 5/6] minor refactor --- src/names.rs | 1 - tests/names/mod.rs | 40 +++++++++++++++++++--------------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/names.rs b/src/names.rs index 10111d2e..790f2aae 100644 --- a/src/names.rs +++ b/src/names.rs @@ -62,7 +62,6 @@ impl Iterator for Names { //map the count so the first value is the last one (all "-"), the second one is the first one (all "_")... let used_count = *count as isize - 1 + self.max_count as isize; - for (sep_index, char_index) in self.separator_indexes[..self.separator_count].iter().enumerate() { let char = if used_count & (1 << sep_index) == 0 { b'_' } else { b'-' }; // SAFETY: We validated that `char_index` is a valid UTF-8 codepoint diff --git a/tests/names/mod.rs b/tests/names/mod.rs index 0de7aef1..6187d340 100644 --- a/tests/names/mod.rs +++ b/tests/names/mod.rs @@ -1,39 +1,27 @@ use crates_index::Names; -fn data_count(names: Names) -> usize { - names.collect::>().len() -} - #[test] -fn empty_string() { - assert_eq!(data_count(Names::new("").unwrap()), 1); +fn empty_string_is_nothing_special() { + assert_eq!(assert_count(Names::new("").unwrap()), 1); } #[test] fn name_without_separators_yields_name() { - assert_eq!(data_count(Names::new("serde").unwrap()), 1); -} - -#[test] -fn permutation_count() { - assert_eq!(Names::new("a-b").unwrap().count(), 2); - assert_eq!(Names::new("a-b_c").unwrap().count(), 4); - assert_eq!(Names::new("a_b_c").unwrap().count(), 4); - assert_eq!(Names::new("a_b_c-d").unwrap().count(), 8); + assert_eq!(assert_count(Names::new("serde").unwrap()), 1); } #[test] -fn permutation_data_count() { - assert_eq!(data_count(Names::new("a-b").unwrap()), 2); - assert_eq!(data_count(Names::new("a-b_c").unwrap()), 4); - assert_eq!(data_count(Names::new("a_b_c").unwrap()), 4); - assert_eq!(data_count(Names::new("a_b_c-d").unwrap()), 8); +fn permutation_counts() { + assert_eq!(assert_count(Names::new("a-b").unwrap()), 2); + assert_eq!(assert_count(Names::new("a-b_c").unwrap()), 4); + assert_eq!(assert_count(Names::new("a_b_c").unwrap()), 4); + assert_eq!(assert_count(Names::new("a_b_c-d").unwrap()), 8); } #[test] fn max_permutation_count_causes_error() { assert_eq!( - data_count(Names::new("a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p").expect("15 separators are fine")), + assert_count(Names::new("a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p").expect("15 separators are fine")), 32768 ); assert!( @@ -72,3 +60,13 @@ fn permutations() { assert_eq!(&names, expected); } } + +fn assert_count(names: Names) -> usize { + let expected = names.clone().collect::>().len(); + assert_eq!( + names.count(), + expected, + "the computed count should match the actual one" + ); + expected +} From 6ab652e52c10ae29bbcc69ae822fb2f03e54550d Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Mon, 31 Jul 2023 21:40:00 +0200 Subject: [PATCH 6/6] improve docs for `Names` --- src/names.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/names.rs b/src/names.rs index 790f2aae..76ac0ad2 100644 --- a/src/names.rs +++ b/src/names.rs @@ -1,7 +1,11 @@ /// An iterator over all possible permutations of hyphens (`-`) and underscores (`_`) of a crate name. /// +/// The sequence yields the input name first, then an all-hyphens variant of it followed by an +/// all-underscores variant to maximize the chance of finding a match. Then follow all remaining permutations. +/// /// For instance, the name `parking_lot` is turned into the sequence `parking_lot` and `parking-lot`, while /// `serde-yaml` is turned into `serde-yaml` and `serde_yaml`. +/// Finally, `a-b_c` is returned as `a-b_c`, `a-b-c`, `a_b_c`, `a_b-c`. #[derive(Clone)] pub struct Names { count: Option,