From b789ffb3fcbaf42451dbb86514237307cf4c716d Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Thu, 22 Jun 2023 18:38:02 +0900 Subject: [PATCH] id_prefix: inline IdIndex::resolve_prefix_range() I'll rewrite resolve_prefix_range() to branch depending on the prefix length, and the easiest way to do that is passing iterator to continuation function instead of returning iterator as an either (or boxed) type. --- lib/src/id_prefix.rs | 62 ++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/lib/src/id_prefix.rs b/lib/src/id_prefix.rs index 0c53f9c6f..a4ca0170f 100644 --- a/lib/src/id_prefix.rs +++ b/lib/src/id_prefix.rs @@ -193,28 +193,47 @@ where pub fn resolve_prefix_with<'a, B, U>( &'a self, prefix: &HexPrefix, - mut value_mapper: impl FnMut(&'a V) -> U, + value_mapper: impl FnMut(&'a V) -> U, ) -> PrefixResolution<(&'a K, B)> where B: FromIterator, { - if prefix.min_prefix_bytes().is_empty() { + fn collect<'a, B, K, V, U>( + range: impl Iterator, + mut value_mapper: impl FnMut(&'a V) -> U, + ) -> PrefixResolution<(&'a K, B)> + where + B: FromIterator, + K: Eq + 'a, + V: 'a, + { + let mut range = range.peekable(); + if let Some((first_key, _)) = range.peek().copied() { + let maybe_values: Option = range + .map(|(k, v)| (k == first_key).then(|| value_mapper(v))) + .collect(); + if let Some(values) = maybe_values { + PrefixResolution::SingleMatch((first_key, values)) + } else { + PrefixResolution::AmbiguousMatch + } + } else { + PrefixResolution::NoMatch + } + } + + let min_bytes = prefix.min_prefix_bytes(); + if min_bytes.is_empty() { // We consider an empty prefix ambiguous even if the index has a single entry. return PrefixResolution::AmbiguousMatch; } - let mut range = self.resolve_prefix_range(prefix).peekable(); - if let Some((first_key, _)) = range.peek().copied() { - let maybe_values: Option = range - .map(|(k, v)| (k == first_key).then(|| value_mapper(v))) - .collect(); - if let Some(values) = maybe_values { - PrefixResolution::SingleMatch((first_key, values)) - } else { - PrefixResolution::AmbiguousMatch - } - } else { - PrefixResolution::NoMatch - } + + let pos = self.0.partition_point(|(k, _)| k.as_bytes() < min_bytes); + let range = self.0[pos..] + .iter() + .take_while(|(k, _)| prefix.matches(k)) + .map(|(k, v)| (k, v)); + collect(range, value_mapper) } /// Looks up unambiguous key with the given prefix. @@ -223,19 +242,6 @@ where .map(|(key, ())| key) } - /// Iterates over entries with the given prefix. - pub fn resolve_prefix_range<'a: 'b, 'b>( - &'a self, - prefix: &'b HexPrefix, - ) -> impl Iterator + 'b { - let min_bytes = prefix.min_prefix_bytes(); - let pos = self.0.partition_point(|(k, _)| k.as_bytes() < min_bytes); - self.0[pos..] - .iter() - .take_while(|(k, _)| prefix.matches(k)) - .map(|(k, v)| (k, v)) - } - /// Looks up entry for the key. Returns accessor to neighbors. pub fn lookup_exact<'i, 'q>(&'i self, key: &'q K) -> Option> { let lookup = self.lookup_some(key);