Coverage Report

Created: 2025-02-21 07:11

/rust/registry/src/index.crates.io-6f17d22bba15001f/roaring-0.10.10/src/bitmap/util.rs
Line
Count
Source (jump to first uncovered line)
1
use core::ops::{Bound, RangeBounds, RangeInclusive};
2
3
/// Returns the container key and the index
4
/// in this container for a given integer.
5
#[inline]
6
0
pub fn split(value: u32) -> (u16, u16) {
7
0
    ((value >> 16) as u16, value as u16)
8
0
}
Unexecuted instantiation: roaring::bitmap::util::split
Unexecuted instantiation: roaring::bitmap::util::split
9
10
/// Returns the original integer from the container
11
/// key and the index of it in the container.
12
#[inline]
13
0
pub fn join(high: u16, low: u16) -> u32 {
14
0
    (u32::from(high) << 16) + u32::from(low)
15
0
}
16
17
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
18
pub enum ConvertRangeError {
19
    Empty,
20
    StartGreaterThanEnd,
21
    StartAndEndEqualExcluded,
22
}
23
24
/// Convert a `RangeBounds<u32>` object to `RangeInclusive<u32>`,
25
0
pub fn convert_range_to_inclusive<R>(range: R) -> Result<RangeInclusive<u32>, ConvertRangeError>
26
0
where
27
0
    R: RangeBounds<u32>,
28
0
{
29
0
    let start_bound = range.start_bound().cloned();
30
0
    let end_bound = range.end_bound().cloned();
31
0
    match (start_bound, end_bound) {
32
0
        (Bound::Excluded(s), Bound::Excluded(e)) if s == e => {
33
0
            Err(ConvertRangeError::StartAndEndEqualExcluded)
34
        }
35
0
        (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e))
36
0
            if s > e =>
37
        {
38
0
            Err(ConvertRangeError::StartGreaterThanEnd)
39
        }
40
        _ => {
41
0
            let start = match start_bound {
42
0
                Bound::Included(s) => s,
43
0
                Bound::Excluded(s) => s.checked_add(1).ok_or(ConvertRangeError::Empty)?,
44
0
                Bound::Unbounded => 0,
45
            };
46
47
0
            let end = match end_bound {
48
0
                Bound::Included(e) => e,
49
0
                Bound::Excluded(e) => e.checked_sub(1).ok_or(ConvertRangeError::Empty)?,
50
0
                Bound::Unbounded => u32::MAX,
51
            };
52
53
0
            if start > end {
54
                // This handles e.g. `x..x`: we've ruled out `start > end` overall, so a value must
55
                // have been changed via exclusion.
56
0
                Err(ConvertRangeError::Empty)
57
            } else {
58
0
                Ok(start..=end)
59
            }
60
        }
61
    }
62
0
}
63
64
#[cfg(test)]
65
mod test {
66
    use super::{convert_range_to_inclusive, join, split, ConvertRangeError};
67
    use core::ops::Bound;
68
69
    #[test]
70
    fn test_split_u32() {
71
        assert_eq!((0x0000u16, 0x0000u16), split(0x0000_0000u32));
72
        assert_eq!((0x0000u16, 0x0001u16), split(0x0000_0001u32));
73
        assert_eq!((0x0000u16, 0xFFFEu16), split(0x0000_FFFEu32));
74
        assert_eq!((0x0000u16, 0xFFFFu16), split(0x0000_FFFFu32));
75
        assert_eq!((0x0001u16, 0x0000u16), split(0x0001_0000u32));
76
        assert_eq!((0x0001u16, 0x0001u16), split(0x0001_0001u32));
77
        assert_eq!((0xFFFFu16, 0xFFFEu16), split(0xFFFF_FFFEu32));
78
        assert_eq!((0xFFFFu16, 0xFFFFu16), split(0xFFFF_FFFFu32));
79
    }
80
81
    #[test]
82
    fn test_join_u32() {
83
        assert_eq!(0x0000_0000u32, join(0x0000u16, 0x0000u16));
84
        assert_eq!(0x0000_0001u32, join(0x0000u16, 0x0001u16));
85
        assert_eq!(0x0000_FFFEu32, join(0x0000u16, 0xFFFEu16));
86
        assert_eq!(0x0000_FFFFu32, join(0x0000u16, 0xFFFFu16));
87
        assert_eq!(0x0001_0000u32, join(0x0001u16, 0x0000u16));
88
        assert_eq!(0x0001_0001u32, join(0x0001u16, 0x0001u16));
89
        assert_eq!(0xFFFF_FFFEu32, join(0xFFFFu16, 0xFFFEu16));
90
        assert_eq!(0xFFFF_FFFFu32, join(0xFFFFu16, 0xFFFFu16));
91
    }
92
93
    #[test]
94
    #[allow(clippy::reversed_empty_ranges)]
95
    fn test_convert_range_to_inclusive() {
96
        assert_eq!(Ok(1..=5), convert_range_to_inclusive(1..6));
97
        assert_eq!(Ok(1..=u32::MAX), convert_range_to_inclusive(1..));
98
        assert_eq!(Ok(0..=u32::MAX), convert_range_to_inclusive(..));
99
        assert_eq!(Ok(16..=16), convert_range_to_inclusive(16..=16));
100
        assert_eq!(
101
            Ok(11..=19),
102
            convert_range_to_inclusive((Bound::Excluded(10), Bound::Excluded(20)))
103
        );
104
105
        assert_eq!(Err(ConvertRangeError::Empty), convert_range_to_inclusive(0..0));
106
        assert_eq!(Err(ConvertRangeError::Empty), convert_range_to_inclusive(5..5));
107
        assert_eq!(Err(ConvertRangeError::StartGreaterThanEnd), convert_range_to_inclusive(1..0));
108
        assert_eq!(Err(ConvertRangeError::StartGreaterThanEnd), convert_range_to_inclusive(10..5));
109
        assert_eq!(
110
            Err(ConvertRangeError::Empty),
111
            convert_range_to_inclusive((Bound::Excluded(u32::MAX), Bound::Included(u32::MAX)))
112
        );
113
        assert_eq!(
114
            Err(ConvertRangeError::StartAndEndEqualExcluded),
115
            convert_range_to_inclusive((Bound::Excluded(u32::MAX), Bound::Excluded(u32::MAX)))
116
        );
117
        assert_eq!(
118
            Err(ConvertRangeError::Empty),
119
            convert_range_to_inclusive((Bound::Excluded(0), Bound::Included(0)))
120
        );
121
    }
122
}