1use std::cmp::Ordering::{Equal, Greater, Less};
2
3use crate::{fastcmp, IVec};
4
5pub(crate) fn binary_search_lub(key: &[u8], s: &[IVec]) -> Option<usize> {
6 match binary_search(key, s) {
7 Ok(i) => Some(i),
8 Err(i) if i == 0 => None,
9 Err(i) => Some(i - 1),
10 }
11}
12
13pub fn binary_search(key: &[u8], s: &[IVec]) -> Result<usize, usize> {
14 let mut size = s.len();
15 if size == 0 || *key < *s[0] {
16 return Err(0);
17 }
18 let mut base = 0_usize;
19 while size > 1 {
20 let half = size / 2;
21 let mid = base + half;
22 #[allow(unsafe_code)]
26 let l = unsafe { s.get_unchecked(mid).as_ref() };
27 let cmp = fastcmp(l, key);
28 base = if cmp == Greater { base } else { mid };
29 size -= half;
30 }
31 #[allow(unsafe_code)]
33 let l = unsafe { s.get_unchecked(base).as_ref() };
34 let cmp = fastcmp(l, key);
35 if cmp == Equal {
36 Ok(base)
37 } else {
38 Err(base + (cmp == Less) as usize)
39 }
40}
41
42#[test]
43fn test_binary_search_lub() {
44 let s = vec![
45 vec![4].into(),
46 vec![5].into(),
47 vec![5].into(),
48 vec![6].into(),
49 vec![9].into(),
50 ];
51 assert_eq!(binary_search_lub(&[3], &*s), None);
52 assert_eq!(binary_search_lub(&[4], &*s), Some(0));
53 assert_eq!(binary_search_lub(&[5], &*s), Some(2));
54 assert_eq!(binary_search_lub(&[6], &*s), Some(3));
55 assert_eq!(binary_search_lub(&[7], &*s), Some(3));
56 assert_eq!(binary_search_lub(&[8], &*s), Some(3));
57 assert_eq!(binary_search_lub(&[9], &*s), Some(4));
58 assert_eq!(binary_search_lub(&[10], &*s), Some(4));
59
60 let mut s = s;
61 s.clear();
62 assert_eq!(binary_search_lub(&[8], &*s), None);
63}