sled/
fastcmp.rs

1use std::cmp::Ordering;
2
3#[cfg(any(unix, windows))]
4#[allow(unsafe_code)]
5pub(crate) fn fastcmp(l: &[u8], r: &[u8]) -> Ordering {
6    let len = std::cmp::min(l.len(), r.len());
7    let cmp = unsafe { libc::memcmp(l.as_ptr() as _, r.as_ptr() as _, len) };
8    match cmp {
9        a if a > 0 => Ordering::Greater,
10        a if a < 0 => Ordering::Less,
11        _ => l.len().cmp(&r.len()),
12    }
13}
14
15#[cfg(not(any(unix, windows)))]
16#[allow(unsafe_code)]
17pub(crate) fn fastcmp(l: &[u8], r: &[u8]) -> Ordering {
18    l.cmp(r)
19}
20
21#[cfg(test)]
22mod qc {
23    use super::fastcmp;
24
25    fn prop_cmp_matches(l: &[u8], r: &[u8]) -> bool {
26        assert_eq!(fastcmp(l, r), l.cmp(r));
27        assert_eq!(fastcmp(r, l), r.cmp(l));
28        assert_eq!(fastcmp(l, l), l.cmp(l));
29        assert_eq!(fastcmp(r, r), r.cmp(r));
30        true
31    }
32
33    #[test]
34    fn test_fastcmp() {
35        let cases: [&[u8]; 8] = [
36            &[],
37            &[0],
38            &[1],
39            &[1],
40            &[255],
41            &[1, 2, 3],
42            &[1, 2, 3, 0],
43            &[1, 2, 3, 55],
44        ];
45        for pair in cases.windows(2) {
46            prop_cmp_matches(pair[0], pair[1]);
47        }
48    }
49
50    quickcheck::quickcheck! {
51        #[cfg_attr(miri, ignore)]
52        fn qc_fastcmp(l: Vec<u8>, r: Vec<u8>) -> bool {
53            prop_cmp_matches(&l, &r)
54        }
55    }
56}