From 6fa660d9a85cb4b6dfa48fead02e51e173881953 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Sun, 11 Feb 2024 22:35:44 +0900 Subject: [PATCH] index: extract inner binary search function The callback returns Ordering instead of &[u8] due to lifetime difficulty. --- lib/src/default_index/readonly.rs | 40 +++++++++++++++++++------------ 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/lib/src/default_index/readonly.rs b/lib/src/default_index/readonly.rs index acb4632a8..cfe2daaed 100644 --- a/lib/src/default_index/readonly.rs +++ b/lib/src/default_index/readonly.rs @@ -373,21 +373,10 @@ impl ReadonlyIndexSegment { /// Otherwise, returns `Err` containing the position where the id could be /// inserted. fn commit_id_byte_prefix_to_lookup_pos(&self, prefix: &[u8]) -> Result { - let mut low = 0; - let mut high = self.num_local_commits; - while low < high { - let mid = (low + high) / 2; - let entry = self.commit_lookup_entry(mid); - let cmp = entry.commit_id_bytes().cmp(prefix); - // According to Rust std lib, this produces cmov instructions. - // https://github.com/rust-lang/rust/blob/1.76.0/library/core/src/slice/mod.rs#L2845-L2855 - low = if cmp == Ordering::Less { mid + 1 } else { low }; - high = if cmp == Ordering::Greater { mid } else { high }; - if cmp == Ordering::Equal { - return Ok(mid); - } - } - Err(low) + binary_search_pos_by(self.num_local_commits, |pos| { + let entry = self.commit_lookup_entry(pos); + entry.commit_id_bytes().cmp(prefix) + }) } } @@ -571,3 +560,24 @@ impl ReadonlyIndex for DefaultReadonlyIndex { Box::new(DefaultMutableIndex::incremental(self.0.clone())) } } + +/// Binary searches u32 position with the given comparison function. +/// +/// If matched exactly, returns `Ok` with the position. Otherwise, returns `Err` +/// containing the position where the element could be inserted. +fn binary_search_pos_by(size: u32, mut f: impl FnMut(u32) -> Ordering) -> Result { + let mut low = 0; + let mut high = size; + while low < high { + let mid = (low + high) / 2; + let cmp = f(mid); + // According to Rust std lib, this produces cmov instructions. + // https://github.com/rust-lang/rust/blob/1.76.0/library/core/src/slice/mod.rs#L2845-L2855 + low = if cmp == Ordering::Less { mid + 1 } else { low }; + high = if cmp == Ordering::Greater { mid } else { high }; + if cmp == Ordering::Equal { + return Ok(mid); + } + } + Err(low) +}