maplibre/legacy/util/
mod.rs

1use std::{
2    hash::{DefaultHasher, Hash, Hasher},
3    ops::Range,
4};
5
6pub mod constants;
7pub mod geo;
8pub mod i18n;
9pub mod math;
10
11/// maplibre/maplibre-native#4add9ea original name: hash_combine
12pub fn hash_combine<T: Hash>(seed: &mut u64, v: &T) {
13    let mut hasher = DefaultHasher::new(); // TODO previously used std::hash https://en.cppreference.com/w/cpp/utility/hash
14    v.hash(&mut hasher);
15    *seed ^= hasher
16        .finish()
17        .overflowing_add(0x9e3779b9)
18        .0
19        .overflowing_add(*seed << 6)
20        .0
21        .overflowing_add(*seed >> 2)
22        .0;
23}
24
25/// maplibre/maplibre-native#4add9ea original name: hash
26pub fn hash<T: Hash>(args: &[T]) -> u64 {
27    let mut seed = 0;
28
29    for arg in args {
30        hash_combine(&mut seed, arg);
31    }
32    seed
33}
34
35/// maplibre/maplibre-native#4add9ea original name: split_in_half
36fn split_in_half(range: &Range<usize>) -> (Range<usize>, Range<usize>) {
37    let mid = (range.end - range.start) / 2 + range.start;
38
39    ((range.start..mid), (mid..range.end))
40}
41
42/// maplibre/maplibre-native#4add9ea original name: lower_bound
43pub fn lower_bound<T: PartialOrd>(v: &[T], elt: &T) -> usize {
44    let mut range = 0..v.len();
45    while !range.is_empty() {
46        let (a, b) = split_in_half(&range);
47        if v[b.start] < *elt {
48            range = b.start + 1..b.end;
49        } else {
50            range = a;
51        }
52    }
53    range.start
54}
55
56#[cfg(test)]
57mod tests {
58    use crate::legacy::util::lower_bound;
59
60    #[test]
61    /// maplibre/maplibre-native#4add9ea original name: lower_bound_test
62    fn lower_bound_test() {
63        let mut input = [10, 20, 30, 30, 20, 10, 10, 20];
64
65        input.sort();
66
67        assert_eq!(lower_bound(&input, &20), 3);
68        assert_eq!(lower_bound(&input, &15), 3);
69        assert_eq!(lower_bound(&input, &5), 0);
70    }
71}