From 039a9a4cc7463e6c18aed3c78c622b8bbb38b51d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Sun, 6 Jan 2019 11:11:55 +0100 Subject: [PATCH 1/7] feat: Pre-compute matches query index groups --- src/rank/criterion/exact.rs | 7 +- src/rank/criterion/number_of_words.rs | 8 +-- src/rank/criterion/sum_of_typos.rs | 11 ++-- src/rank/criterion/sum_of_words_attribute.rs | 10 ++- src/rank/criterion/sum_of_words_position.rs | 12 ++-- src/rank/criterion/words_proximity.rs | 8 +-- src/rank/mod.rs | 69 ++++++++++++++++++-- src/rank/query_builder.rs | 2 +- 8 files changed, 86 insertions(+), 41 deletions(-) diff --git a/src/rank/criterion/exact.rs b/src/rank/criterion/exact.rs index 041a6ae67..6d33a6f38 100644 --- a/src/rank/criterion/exact.rs +++ b/src/rank/criterion/exact.rs @@ -2,9 +2,8 @@ use std::cmp::Ordering; use std::ops::Deref; use rocksdb::DB; -use group_by::GroupBy; -use crate::rank::{match_query_index, Document}; +use crate::rank::{Document, Matches}; use crate::rank::criterion::Criterion; use crate::database::DatabaseView; use crate::Match; @@ -15,8 +14,8 @@ fn contains_exact(matches: &[Match]) -> bool { } #[inline] -fn number_exact_matches(matches: &[Match]) -> usize { - GroupBy::new(matches, match_query_index).map(contains_exact).count() +fn number_exact_matches(matches: &Matches) -> usize { + matches.query_index_groups().map(contains_exact).count() } #[derive(Debug, Clone, Copy)] diff --git a/src/rank/criterion/number_of_words.rs b/src/rank/criterion/number_of_words.rs index 855d997ba..23cf36a2c 100644 --- a/src/rank/criterion/number_of_words.rs +++ b/src/rank/criterion/number_of_words.rs @@ -2,16 +2,14 @@ use std::cmp::Ordering; use std::ops::Deref; use rocksdb::DB; -use group_by::GroupBy; -use crate::rank::{match_query_index, Document}; +use crate::rank::{Document, Matches}; use crate::rank::criterion::Criterion; use crate::database::DatabaseView; -use crate::Match; #[inline] -fn number_of_query_words(matches: &[Match]) -> usize { - GroupBy::new(matches, match_query_index).count() +fn number_of_query_words(matches: &Matches) -> usize { + matches.query_index_groups().count() } #[derive(Debug, Clone, Copy)] diff --git a/src/rank/criterion/sum_of_typos.rs b/src/rank/criterion/sum_of_typos.rs index 409c37cb4..18a199113 100644 --- a/src/rank/criterion/sum_of_typos.rs +++ b/src/rank/criterion/sum_of_typos.rs @@ -3,21 +3,18 @@ use std::ops::Deref; use rocksdb::DB; -use group_by::GroupBy; - -use crate::rank::{match_query_index, Document}; +use crate::rank::{Document, Matches}; use crate::rank::criterion::Criterion; use crate::database::DatabaseView; -use crate::Match; #[inline] -fn sum_matches_typos(matches: &[Match]) -> i8 { +fn sum_matches_typos(matches: &Matches) -> i8 { let mut sum_typos = 0; let mut number_words = 0; // note that GroupBy will never return an empty group // so we can do this assumption safely - for group in GroupBy::new(matches, match_query_index) { + for group in matches.query_index_groups() { sum_typos += unsafe { group.get_unchecked(0).distance } as i8; number_words += 1; } @@ -44,7 +41,7 @@ where D: Deref mod tests { use super::*; - use crate::{DocumentId, Attribute, WordArea}; + use crate::{Match, DocumentId, Attribute, WordArea}; // typing: "Geox CEO" // diff --git a/src/rank/criterion/sum_of_words_attribute.rs b/src/rank/criterion/sum_of_words_attribute.rs index 718ae7447..cfcaaec68 100644 --- a/src/rank/criterion/sum_of_words_attribute.rs +++ b/src/rank/criterion/sum_of_words_attribute.rs @@ -2,19 +2,17 @@ use std::cmp::Ordering; use std::ops::Deref; use rocksdb::DB; -use group_by::GroupBy; +use crate::rank::{Document, Matches}; use crate::database::DatabaseView; -use crate::rank::{match_query_index, Document}; use crate::rank::criterion::Criterion; -use crate::Match; #[inline] -fn sum_matches_attributes(matches: &[Match]) -> u16 { +fn sum_matches_attributes(matches: &Matches) -> u16 { // note that GroupBy will never return an empty group // so we can do this assumption safely - GroupBy::new(matches, match_query_index).map(|group| unsafe { - group.get_unchecked(0).attribute.attribute() + matches.query_index_groups().map(|group| { + unsafe { group.get_unchecked(0).attribute.attribute() } }).sum() } diff --git a/src/rank/criterion/sum_of_words_position.rs b/src/rank/criterion/sum_of_words_position.rs index d0ebaa74f..e1d650534 100644 --- a/src/rank/criterion/sum_of_words_position.rs +++ b/src/rank/criterion/sum_of_words_position.rs @@ -2,19 +2,17 @@ use std::cmp::Ordering; use std::ops::Deref; use rocksdb::DB; -use group_by::GroupBy; -use crate::database::DatabaseView; -use crate::rank::{match_query_index, Document}; +use crate::rank::{Document, Matches}; use crate::rank::criterion::Criterion; -use crate::Match; +use crate::database::DatabaseView; #[inline] -fn sum_matches_attribute_index(matches: &[Match]) -> u32 { +fn sum_matches_attribute_index(matches: &Matches) -> u32 { // note that GroupBy will never return an empty group // so we can do this assumption safely - GroupBy::new(matches, match_query_index).map(|group| unsafe { - group.get_unchecked(0).attribute.word_index() + matches.query_index_groups().map(|group| { + unsafe { group.get_unchecked(0).attribute.word_index() } }).sum() } diff --git a/src/rank/criterion/words_proximity.rs b/src/rank/criterion/words_proximity.rs index fc80dfaec..41f4b49b8 100644 --- a/src/rank/criterion/words_proximity.rs +++ b/src/rank/criterion/words_proximity.rs @@ -2,9 +2,8 @@ use std::cmp::{self, Ordering}; use std::ops::Deref; use rocksdb::DB; -use group_by::GroupBy; -use crate::rank::{match_query_index, Document}; +use crate::rank::{Document, Matches}; use crate::rank::criterion::Criterion; use crate::database::DatabaseView; use crate::Match; @@ -34,9 +33,9 @@ fn min_proximity(lhs: &[Match], rhs: &[Match]) -> u32 { min_prox } -fn matches_proximity(matches: &[Match]) -> u32 { +fn matches_proximity(matches: &Matches) -> u32 { let mut proximity = 0; - let mut iter = GroupBy::new(matches, match_query_index); + let mut iter = matches.query_index_groups(); // iterate over groups by windows of size 2 let mut last = iter.next(); @@ -91,6 +90,7 @@ mod tests { // soup -> of = 8 // + of -> the = 1 // + the -> day = 8 (not 1) + let matches = Matches::from_unsorted_matches(matches.to_vec()); assert_eq!(matches_proximity(matches), 17); } diff --git a/src/rank/mod.rs b/src/rank/mod.rs index 4d1b6b1ea..0d3f538d0 100644 --- a/src/rank/mod.rs +++ b/src/rank/mod.rs @@ -2,6 +2,11 @@ pub mod criterion; mod query_builder; mod distinct_map; +use std::slice::Windows; + +use sdset::SetBuf; +use group_by::GroupBy; + use crate::{Match, DocumentId}; pub use self::query_builder::{FilterFunc, QueryBuilder, DistinctQueryBuilder}; @@ -14,20 +19,70 @@ fn match_query_index(a: &Match, b: &Match) -> bool { #[derive(Debug, Clone)] pub struct Document { pub id: DocumentId, - pub matches: Vec, + pub matches: Matches, } impl Document { pub fn new(doc: DocumentId, match_: Match) -> Self { - unsafe { Self::from_sorted_matches(doc, vec![match_]) } + let matches = SetBuf::new_unchecked(vec![match_]); + Self::from_matches(doc, matches) } - pub fn from_matches(doc: DocumentId, mut matches: Vec) -> Self { - matches.sort_unstable(); - unsafe { Self::from_sorted_matches(doc, matches) } - } + pub fn from_matches(id: DocumentId, matches: SetBuf) -> Self { + let mut last = 0; + let mut slices = vec![0]; + for group in GroupBy::new(&matches, match_query_index) { + let index = last + group.len(); + slices.push(index); + last = index; + } - pub unsafe fn from_sorted_matches(id: DocumentId, matches: Vec) -> Self { + let matches = Matches { matches, slices }; Self { id, matches } } + + pub fn from_unsorted_matches(doc: DocumentId, mut matches: Vec) -> Self { + matches.sort_unstable(); + let matches = SetBuf::new_unchecked(matches); + Self::from_matches(doc, matches) + } } + +#[derive(Debug, Clone)] +pub struct Matches { + matches: SetBuf, + slices: Vec, +} + +impl Matches { + pub fn query_index_groups(&self) -> QueryIndexGroups { + QueryIndexGroups { + matches: &self.matches, + windows: self.slices.windows(2), + } + } +} + +pub struct QueryIndexGroups<'a, 'b> { + matches: &'a [Match], + windows: Windows<'b, usize>, +} + +impl<'a, 'b> Iterator for QueryIndexGroups<'a, 'b> { + type Item = &'a [Match]; + + fn next(&mut self) -> Option { + self.windows.next().map(|range| { + match *range { + [left, right] => &self.matches[left..right], + _ => unreachable!() + } + }) + } +} + +// impl ExactSizeIterator for QueryIndexGroups<'_, '_> { +// fn len(&self) -> usize { +// self.windows.len() // FIXME (+1) ? +// } +// } diff --git a/src/rank/query_builder.rs b/src/rank/query_builder.rs index 4df983f8a..9a17e0473 100644 --- a/src/rank/query_builder.rs +++ b/src/rank/query_builder.rs @@ -116,7 +116,7 @@ where D: Deref, } } - matches.into_iter().map(|(id, matches)| Document::from_matches(id, matches)).collect() + matches.into_iter().map(|(id, m)| Document::from_unsorted_matches(id, m)).collect() } } From d21406a93908b2b3ed8cd57b2182996b43cf7806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Sun, 6 Jan 2019 11:23:21 +0100 Subject: [PATCH 2/7] feat: Allow Matches to be constructed --- src/rank/criterion/sum_of_typos.rs | 30 ++++--------------- src/rank/criterion/words_proximity.rs | 9 ++++-- src/rank/mod.rs | 42 +++++++++++++++++---------- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/rank/criterion/sum_of_typos.rs b/src/rank/criterion/sum_of_typos.rs index 18a199113..400650ad2 100644 --- a/src/rank/criterion/sum_of_typos.rs +++ b/src/rank/criterion/sum_of_typos.rs @@ -66,10 +66,7 @@ mod tests { word_area: WordArea::new_faillible(0, 6) }, ]; - Document { - id: DocumentId(0), - matches: matches, - } + Document::from_unsorted_matches(DocumentId(0), matches) }; let doc1 = { @@ -89,10 +86,7 @@ mod tests { word_area: WordArea::new_faillible(0, 6) }, ]; - Document { - id: DocumentId(1), - matches: matches, - } + Document::from_unsorted_matches(DocumentId(1), matches) }; let lhs = sum_matches_typos(&doc0.matches); @@ -123,10 +117,7 @@ mod tests { word_area: WordArea::new_faillible(0, 6) }, ]; - Document { - id: DocumentId(0), - matches: matches, - } + Document::from_unsorted_matches(DocumentId(0), matches) }; let doc1 = { @@ -139,10 +130,7 @@ mod tests { word_area: WordArea::new_faillible(0, 6) }, ]; - Document { - id: DocumentId(1), - matches: matches, - } + Document::from_unsorted_matches(DocumentId(1), matches) }; let lhs = sum_matches_typos(&doc0.matches); @@ -173,10 +161,7 @@ mod tests { word_area: WordArea::new_faillible(0, 6) }, ]; - Document { - id: DocumentId(0), - matches: matches, - } + Document::from_unsorted_matches(DocumentId(0), matches) }; let doc1 = { @@ -189,10 +174,7 @@ mod tests { word_area: WordArea::new_faillible(0, 6) }, ]; - Document { - id: DocumentId(1), - matches: matches, - } + Document::from_unsorted_matches(DocumentId(1), matches) }; let lhs = sum_matches_typos(&doc0.matches); diff --git a/src/rank/criterion/words_proximity.rs b/src/rank/criterion/words_proximity.rs index 41f4b49b8..7fe3102d3 100644 --- a/src/rank/criterion/words_proximity.rs +++ b/src/rank/criterion/words_proximity.rs @@ -90,8 +90,8 @@ mod tests { // soup -> of = 8 // + of -> the = 1 // + the -> day = 8 (not 1) - let matches = Matches::from_unsorted_matches(matches.to_vec()); - assert_eq!(matches_proximity(matches), 17); + let matches = Matches::from_unsorted(matches.to_vec()); + assert_eq!(matches_proximity(&matches), 17); } #[test] @@ -118,7 +118,8 @@ mod tests { // soup -> of = 1 // + of -> the = 1 // + the -> day = 1 - assert_eq!(matches_proximity(matches), 3); + let matches = Matches::from_unsorted(matches.to_vec()); + assert_eq!(matches_proximity(&matches), 3); } } @@ -152,6 +153,8 @@ mod bench { matches.push(match_); } + let matches = Matches::from_unsorted(matches.to_vec()); + bench.iter(|| { let proximity = matches_proximity(&matches); test::black_box(move || proximity) diff --git a/src/rank/mod.rs b/src/rank/mod.rs index 0d3f538d0..ad91830bf 100644 --- a/src/rank/mod.rs +++ b/src/rank/mod.rs @@ -23,28 +23,19 @@ pub struct Document { } impl Document { - pub fn new(doc: DocumentId, match_: Match) -> Self { + pub fn new(id: DocumentId, match_: Match) -> Self { let matches = SetBuf::new_unchecked(vec![match_]); - Self::from_matches(doc, matches) + Self::from_matches(id, matches) } pub fn from_matches(id: DocumentId, matches: SetBuf) -> Self { - let mut last = 0; - let mut slices = vec![0]; - for group in GroupBy::new(&matches, match_query_index) { - let index = last + group.len(); - slices.push(index); - last = index; - } - - let matches = Matches { matches, slices }; + let matches = Matches::new(matches); Self { id, matches } } - pub fn from_unsorted_matches(doc: DocumentId, mut matches: Vec) -> Self { - matches.sort_unstable(); - let matches = SetBuf::new_unchecked(matches); - Self::from_matches(doc, matches) + pub fn from_unsorted_matches(id: DocumentId, matches: Vec) -> Self { + let matches = Matches::from_unsorted(matches); + Self { id, matches } } } @@ -55,6 +46,25 @@ pub struct Matches { } impl Matches { + pub fn new(matches: SetBuf) -> Matches { + let mut last = 0; + let mut slices = vec![0]; + + for group in GroupBy::new(&matches, match_query_index) { + let index = last + group.len(); + slices.push(index); + last = index; + } + + Matches { matches, slices } + } + + pub fn from_unsorted(mut matches: Vec) -> Matches { + matches.sort_unstable(); + let matches = SetBuf::new_unchecked(matches); + Matches::new(matches) + } + pub fn query_index_groups(&self) -> QueryIndexGroups { QueryIndexGroups { matches: &self.matches, @@ -75,7 +85,7 @@ impl<'a, 'b> Iterator for QueryIndexGroups<'a, 'b> { self.windows.next().map(|range| { match *range { [left, right] => &self.matches[left..right], - _ => unreachable!() + _ => unreachable!(), } }) } From ef7ba96d4a3f2107c386aa33860e707b812ab732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Sun, 6 Jan 2019 11:23:42 +0100 Subject: [PATCH 3/7] feat: Introducing the Matches as_matches method --- examples/query-database.rs | 4 ++-- src/rank/mod.rs | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/query-database.rs b/examples/query-database.rs index ce64870a9..edd311f16 100644 --- a/examples/query-database.rs +++ b/examples/query-database.rs @@ -115,7 +115,7 @@ fn main() -> Result<(), Box> { }; print!("{}: ", name); - let areas = create_highlight_areas(&text, &doc.matches, attr); + let areas = create_highlight_areas(&text, doc.matches.as_matches(), attr); display_highlights(&text, &areas)?; println!(); } @@ -124,7 +124,7 @@ fn main() -> Result<(), Box> { } let mut matching_attributes = HashSet::new(); - for _match in doc.matches { + for _match in doc.matches.as_matches() { let attr = SchemaAttr::new(_match.attribute.attribute()); let name = schema.attribute_name(attr); matching_attributes.insert(name); diff --git a/src/rank/mod.rs b/src/rank/mod.rs index ad91830bf..5416ca882 100644 --- a/src/rank/mod.rs +++ b/src/rank/mod.rs @@ -71,6 +71,10 @@ impl Matches { windows: self.slices.windows(2), } } + + pub fn as_matches(&self) -> &[Match] { + &self.matches + } } pub struct QueryIndexGroups<'a, 'b> { From c594597a01422087a66e78bdfddd32d5abc99ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Sun, 6 Jan 2019 11:29:43 +0100 Subject: [PATCH 4/7] feat: Introduce multiple Iterator impl for Matches --- src/rank/mod.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/src/rank/mod.rs b/src/rank/mod.rs index 5416ca882..2023cb266 100644 --- a/src/rank/mod.rs +++ b/src/rank/mod.rs @@ -2,6 +2,7 @@ pub mod criterion; mod query_builder; mod distinct_map; +use std::iter::FusedIterator; use std::slice::Windows; use sdset::SetBuf; @@ -82,9 +83,10 @@ pub struct QueryIndexGroups<'a, 'b> { windows: Windows<'b, usize>, } -impl<'a, 'b> Iterator for QueryIndexGroups<'a, 'b> { +impl<'a> Iterator for QueryIndexGroups<'a, '_> { type Item = &'a [Match]; + #[inline] fn next(&mut self) -> Option { self.windows.next().map(|range| { match *range { @@ -93,10 +95,56 @@ impl<'a, 'b> Iterator for QueryIndexGroups<'a, 'b> { } }) } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.windows.size_hint() + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + self.windows.nth(n).map(|range| { + match *range { + [left, right] => &self.matches[left..right], + _ => unreachable!(), + } + }) + } + + #[inline] + fn last(self) -> Option { + let (matches, windows) = (self.matches, self.windows); + windows.last().map(|range| { + match *range { + [left, right] => &matches[left..right], + _ => unreachable!(), + } + }) + } } -// impl ExactSizeIterator for QueryIndexGroups<'_, '_> { -// fn len(&self) -> usize { -// self.windows.len() // FIXME (+1) ? -// } -// } +impl ExactSizeIterator for QueryIndexGroups<'_, '_> { + #[inline] + fn len(&self) -> usize { + self.windows.len() + } +} + +impl FusedIterator for QueryIndexGroups<'_, '_> { } + +impl DoubleEndedIterator for QueryIndexGroups<'_, '_> { + #[inline] + fn next_back(&mut self) -> Option { + self.windows.next_back().map(|range| { + match *range { + [left, right] => &self.matches[left..right], + _ => unreachable!(), + } + }) + } +} From 0d07af3caf432f6a4c62125f5765c191881f637a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Sun, 6 Jan 2019 11:41:47 +0100 Subject: [PATCH 5/7] fix: Filter and count the exact matching words --- src/rank/criterion/exact.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rank/criterion/exact.rs b/src/rank/criterion/exact.rs index 6d33a6f38..759bd951e 100644 --- a/src/rank/criterion/exact.rs +++ b/src/rank/criterion/exact.rs @@ -9,13 +9,13 @@ use crate::database::DatabaseView; use crate::Match; #[inline] -fn contains_exact(matches: &[Match]) -> bool { +fn contains_exact(matches: &&[Match]) -> bool { matches.iter().any(|m| m.is_exact) } #[inline] fn number_exact_matches(matches: &Matches) -> usize { - matches.query_index_groups().map(contains_exact).count() + matches.query_index_groups().filter(contains_exact).count() } #[derive(Debug, Clone, Copy)] From d899b8660382ea5a4c211761d28ea31e885a46ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Sun, 6 Jan 2019 12:33:27 +0100 Subject: [PATCH 6/7] feat: Prefer using ranges and not using unreachable! --- src/rank/mod.rs | 54 ++++++++++++++++----------------------- src/rank/query_builder.rs | 2 +- 2 files changed, 23 insertions(+), 33 deletions(-) diff --git a/src/rank/mod.rs b/src/rank/mod.rs index 2023cb266..91392cbee 100644 --- a/src/rank/mod.rs +++ b/src/rank/mod.rs @@ -3,7 +3,8 @@ mod query_builder; mod distinct_map; use std::iter::FusedIterator; -use std::slice::Windows; +use std::slice::Iter; +use std::ops::Range; use sdset::SetBuf; use group_by::GroupBy; @@ -43,18 +44,19 @@ impl Document { #[derive(Debug, Clone)] pub struct Matches { matches: SetBuf, - slices: Vec, + slices: Vec>, } impl Matches { pub fn new(matches: SetBuf) -> Matches { - let mut last = 0; - let mut slices = vec![0]; + let mut last_end = 0; + let mut slices = Vec::new(); for group in GroupBy::new(&matches, match_query_index) { - let index = last + group.len(); - slices.push(index); - last = index; + let start = last_end; + let end = last_end + group.len(); + slices.push(Range { start, end }); + last_end = end; } Matches { matches, slices } @@ -69,7 +71,7 @@ impl Matches { pub fn query_index_groups(&self) -> QueryIndexGroups { QueryIndexGroups { matches: &self.matches, - windows: self.slices.windows(2), + slices: self.slices.iter(), } } @@ -80,7 +82,7 @@ impl Matches { pub struct QueryIndexGroups<'a, 'b> { matches: &'a [Match], - windows: Windows<'b, usize>, + slices: Iter<'b, Range>, } impl<'a> Iterator for QueryIndexGroups<'a, '_> { @@ -88,17 +90,14 @@ impl<'a> Iterator for QueryIndexGroups<'a, '_> { #[inline] fn next(&mut self) -> Option { - self.windows.next().map(|range| { - match *range { - [left, right] => &self.matches[left..right], - _ => unreachable!(), - } + self.slices.next().cloned().map(|range| { + unsafe { self.matches.get_unchecked(range) } }) } #[inline] fn size_hint(&self) -> (usize, Option) { - self.windows.size_hint() + self.slices.size_hint() } #[inline] @@ -108,22 +107,16 @@ impl<'a> Iterator for QueryIndexGroups<'a, '_> { #[inline] fn nth(&mut self, n: usize) -> Option { - self.windows.nth(n).map(|range| { - match *range { - [left, right] => &self.matches[left..right], - _ => unreachable!(), - } + self.slices.nth(n).cloned().map(|range| { + unsafe { self.matches.get_unchecked(range) } }) } #[inline] fn last(self) -> Option { - let (matches, windows) = (self.matches, self.windows); - windows.last().map(|range| { - match *range { - [left, right] => &matches[left..right], - _ => unreachable!(), - } + let (matches, slices) = (self.matches, self.slices); + slices.last().cloned().map(|range| { + unsafe { matches.get_unchecked(range) } }) } } @@ -131,7 +124,7 @@ impl<'a> Iterator for QueryIndexGroups<'a, '_> { impl ExactSizeIterator for QueryIndexGroups<'_, '_> { #[inline] fn len(&self) -> usize { - self.windows.len() + self.slices.len() } } @@ -140,11 +133,8 @@ impl FusedIterator for QueryIndexGroups<'_, '_> { } impl DoubleEndedIterator for QueryIndexGroups<'_, '_> { #[inline] fn next_back(&mut self) -> Option { - self.windows.next_back().map(|range| { - match *range { - [left, right] => &self.matches[left..right], - _ => unreachable!(), - } + self.slices.next_back().cloned().map(|range| { + unsafe { self.matches.get_unchecked(range) } }) } } diff --git a/src/rank/query_builder.rs b/src/rank/query_builder.rs index 9a17e0473..3ec49d83d 100644 --- a/src/rank/query_builder.rs +++ b/src/rank/query_builder.rs @@ -116,7 +116,7 @@ where D: Deref, } } - matches.into_iter().map(|(id, m)| Document::from_unsorted_matches(id, m)).collect() + matches.into_iter().map(|(i, m)| Document::from_unsorted_matches(i, m)).collect() } } From c74caa0f82ece8abb9179b3cf1416f6ac5e76bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Sun, 6 Jan 2019 13:18:04 +0100 Subject: [PATCH 7/7] feat: Sum usizes instead of little u16/u32 --- src/rank/criterion/sum_of_words_attribute.rs | 4 ++-- src/rank/criterion/sum_of_words_position.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rank/criterion/sum_of_words_attribute.rs b/src/rank/criterion/sum_of_words_attribute.rs index cfcaaec68..aea21c35f 100644 --- a/src/rank/criterion/sum_of_words_attribute.rs +++ b/src/rank/criterion/sum_of_words_attribute.rs @@ -8,11 +8,11 @@ use crate::database::DatabaseView; use crate::rank::criterion::Criterion; #[inline] -fn sum_matches_attributes(matches: &Matches) -> u16 { +fn sum_matches_attributes(matches: &Matches) -> usize { // note that GroupBy will never return an empty group // so we can do this assumption safely matches.query_index_groups().map(|group| { - unsafe { group.get_unchecked(0).attribute.attribute() } + unsafe { group.get_unchecked(0).attribute.attribute() as usize } }).sum() } diff --git a/src/rank/criterion/sum_of_words_position.rs b/src/rank/criterion/sum_of_words_position.rs index e1d650534..0b27184ba 100644 --- a/src/rank/criterion/sum_of_words_position.rs +++ b/src/rank/criterion/sum_of_words_position.rs @@ -8,11 +8,11 @@ use crate::rank::criterion::Criterion; use crate::database::DatabaseView; #[inline] -fn sum_matches_attribute_index(matches: &Matches) -> u32 { +fn sum_matches_attribute_index(matches: &Matches) -> usize { // note that GroupBy will never return an empty group // so we can do this assumption safely matches.query_index_groups().map(|group| { - unsafe { group.get_unchecked(0).attribute.word_index() } + unsafe { group.get_unchecked(0).attribute.word_index() as usize } }).sum() }