b_tree/
range.rs

1use std::borrow::Borrow;
2use std::cmp::Ordering;
3use std::fmt;
4use std::ops::{Bound, Range as Bounds};
5
6use collate::{Collate, Overlap, OverlapsRange, OverlapsValue};
7use smallvec::smallvec;
8
9use super::{Collator, Key};
10
11/// A range used to select a slice of a `BTree`
12#[derive(Clone, Eq, PartialEq)]
13pub struct Range<V> {
14    prefix: Key<V>,
15    start: Bound<V>,
16    end: Bound<V>,
17}
18
19impl<V> Default for Range<V> {
20    fn default() -> Self {
21        Self {
22            prefix: smallvec![],
23            start: Bound::Unbounded,
24            end: Bound::Unbounded,
25        }
26    }
27}
28
29impl<V> Range<V> {
30    /// Construct a new [`Range`] with the given `prefix`.
31    pub fn with_bounds<K: Into<Key<V>>>(prefix: K, bounds: (Bound<V>, Bound<V>)) -> Self {
32        let prefix = prefix.into();
33        let (start, end) = bounds;
34        Self { prefix, start, end }
35    }
36
37    /// Construct a new [`Range`] with the given `prefix`.
38    pub fn with_range<K: Into<Key<V>>>(prefix: K, range: Bounds<V>) -> Self {
39        let Bounds { start, end } = range;
40        Self::with_bounds(prefix, (Bound::Included(start), Bound::Excluded(end)))
41    }
42
43    /// Construct a new [`Range`] with only the given `prefix`.
44    pub fn from_prefix<K: Into<Key<V>>>(prefix: K) -> Self {
45        Self {
46            prefix: prefix.into(),
47            start: Bound::Unbounded,
48            end: Bound::Unbounded,
49        }
50    }
51
52    /// Construct an owned [`Range`] by borrowing this [`Range`].
53    pub fn as_ref(&self) -> Range<&V> {
54        Range {
55            prefix: self.prefix.iter().collect(),
56            start: self.start.as_ref(),
57            end: self.end.as_ref(),
58        }
59    }
60
61    /// Destructure this [`Range`] into a prefix and [`Bound`]s.
62    pub fn into_inner(self) -> (Key<V>, (Bound<V>, Bound<V>)) {
63        (self.prefix, (self.start, self.end))
64    }
65
66    /// Return `false` if this [`Range`] has only a prefix.
67    pub fn has_bounds(&self) -> bool {
68        match (&self.start, &self.end) {
69            (Bound::Unbounded, Bound::Unbounded) => false,
70            _ => true,
71        }
72    }
73
74    /// Return `true` if this [`Range`] is empty.
75    pub fn is_default(&self) -> bool {
76        if self.prefix.is_empty() {
77            match (&self.start, &self.end) {
78                (Bound::Unbounded, Bound::Unbounded) => true,
79                _ => false,
80            }
81        } else {
82            false
83        }
84    }
85
86    /// Return the number of columns specified by this [`Range`].
87    pub fn len(&self) -> usize {
88        if self.has_bounds() {
89            self.prefix.len() + 1
90        } else {
91            self.prefix.len()
92        }
93    }
94
95    /// Construct a new [`Range`] by prepending the given `prefix` to this one.
96    pub fn prepend<I: IntoIterator<Item = V>>(self, prefix: I) -> Self {
97        Self {
98            prefix: prefix.into_iter().chain(self.prefix).collect(),
99            start: self.start,
100            end: self.end,
101        }
102    }
103}
104
105impl<BV, C> OverlapsValue<Vec<C::Value>, Collator<C>> for Range<BV>
106where
107    BV: Borrow<C::Value>,
108    C: Collate,
109    C::Value: fmt::Debug,
110{
111    fn overlaps_value(&self, key: &Vec<C::Value>, collator: &Collator<C>) -> Overlap {
112        match collator.cmp_slices(&self.prefix, key) {
113            Ordering::Less => Overlap::Less,
114            Ordering::Greater => Overlap::Greater,
115            Ordering::Equal if self.prefix.len() >= key.len() => Overlap::Narrow,
116            Ordering::Equal => {
117                let value = &key[self.prefix.len()];
118
119                let start = match &self.start {
120                    Bound::Unbounded => Ordering::Less,
121                    Bound::Included(start) => collator.value.cmp(start.borrow(), value),
122                    Bound::Excluded(start) => match collator.value.cmp(start.borrow(), value) {
123                        Ordering::Less => Ordering::Less,
124                        Ordering::Greater | Ordering::Equal => Ordering::Greater,
125                    },
126                };
127
128                let end = match &self.end {
129                    Bound::Unbounded => Ordering::Greater,
130                    Bound::Included(end) => collator.value.cmp(end.borrow(), value),
131                    Bound::Excluded(end) => match collator.value.cmp(end.borrow(), value) {
132                        Ordering::Greater => Ordering::Greater,
133                        Ordering::Less | Ordering::Equal => Ordering::Less,
134                    },
135                };
136
137                match (start, end) {
138                    (start, Ordering::Less) => {
139                        debug_assert!(start != Ordering::Greater);
140                        Overlap::Less
141                    }
142                    (Ordering::Greater, end) => {
143                        debug_assert_eq!(end, Ordering::Greater);
144                        Overlap::Greater
145                    }
146                    (Ordering::Equal, Ordering::Equal) if key.len() == self.prefix.len() + 1 => {
147                        // in this case, the range prefix of length n is exactly equal to key[0..n]
148                        // and the trailing range is exactly equal to key[n]
149                        Overlap::Equal
150                    }
151                    _ => Overlap::Wide,
152                }
153            }
154        }
155    }
156}
157
158impl<C: Collate> OverlapsRange<Range<C::Value>, Collator<C>> for Range<C::Value> {
159    fn overlaps(&self, other: &Range<C::Value>, collator: &Collator<C>) -> Overlap {
160        #[inline]
161        fn cmp_start<C>(collator: &C, bound: &Bound<C::Value>, value: &C::Value) -> Ordering
162        where
163            C: Collate,
164        {
165            match bound {
166                Bound::Unbounded => Ordering::Less,
167                Bound::Included(start) => collator.cmp(start, value),
168                Bound::Excluded(start) => match collator.cmp(start, value) {
169                    Ordering::Less | Ordering::Equal => Ordering::Less,
170                    Ordering::Greater => Ordering::Greater,
171                },
172            }
173        }
174
175        #[inline]
176        fn cmp_end<C>(collator: &C, bound: &Bound<C::Value>, value: &C::Value) -> Ordering
177        where
178            C: Collate,
179        {
180            match bound {
181                Bound::Unbounded => Ordering::Less,
182                Bound::Included(end) => collator.cmp(end, value),
183                Bound::Excluded(end) => match collator.cmp(end, value) {
184                    Ordering::Less => Ordering::Less,
185                    Ordering::Greater | Ordering::Equal => Ordering::Greater,
186                },
187            }
188        }
189
190        match collator.cmp_slices(&self.prefix, &other.prefix) {
191            Ordering::Less => return Overlap::Less,
192            Ordering::Greater => return Overlap::Greater,
193            Ordering::Equal => match self.prefix.len().cmp(&other.prefix.len()) {
194                Ordering::Less => {
195                    let value = &other.prefix[self.prefix.len()];
196
197                    match (
198                        cmp_start(&collator.value, &self.start, value),
199                        cmp_end(&collator.value, &self.end, value),
200                    ) {
201                        (Ordering::Greater, _) => Overlap::Greater,
202                        (_, Ordering::Less) => Overlap::Less,
203
204                        (Ordering::Equal, Ordering::Greater) => Overlap::WideGreater,
205                        (Ordering::Less, Ordering::Equal) => Overlap::WideLess,
206
207                        (Ordering::Less, Ordering::Greater) => Overlap::Wide,
208                        (Ordering::Equal, Ordering::Equal) => Overlap::Wide,
209                    }
210                }
211                Ordering::Equal => {
212                    (&self.start, &self.end).overlaps(&(&other.start, &other.end), &collator.value)
213                }
214                Ordering::Greater => {
215                    let value = &self.prefix[other.prefix.len()];
216
217                    match (
218                        cmp_start(&collator.value, &other.start, value),
219                        cmp_end(&collator.value, &other.end, value),
220                    ) {
221                        (Ordering::Greater, _) => Overlap::Less,
222                        (_, Ordering::Less) => Overlap::Greater,
223                        _ => Overlap::Narrow,
224                    }
225                }
226            },
227        }
228    }
229}
230
231impl<V> From<Key<V>> for Range<V> {
232    fn from(prefix: Key<V>) -> Self {
233        Self {
234            prefix,
235            start: Bound::Unbounded,
236            end: Bound::Unbounded,
237        }
238    }
239}
240
241impl<V, K: Into<Key<V>>> From<(K, Bounds<V>)> for Range<V> {
242    fn from(tuple: (K, Bounds<V>)) -> Self {
243        let (prefix, suffix) = tuple;
244        let Bounds { start, end } = suffix;
245
246        Self {
247            prefix: prefix.into(),
248            start: Bound::Included(start),
249            end: Bound::Excluded(end),
250        }
251    }
252}
253
254impl<K: fmt::Debug> fmt::Debug for Range<K> {
255    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256        write!(f, "range ")?;
257
258        match (&self.start, &self.end) {
259            (Bound::Excluded(l), Bound::Unbounded) => write!(f, "[{:?},)", l),
260            (Bound::Excluded(l), Bound::Excluded(r)) => write!(f, "[{:?}, {:?}]", l, r),
261            (Bound::Excluded(l), Bound::Included(r)) => write!(f, "[{:?}, {:?})", l, r),
262            (Bound::Included(l), Bound::Unbounded) => write!(f, "({:?},)", l),
263            (Bound::Included(l), Bound::Excluded(r)) => write!(f, "({:?}, {:?}]", l, r),
264            (Bound::Included(l), Bound::Included(r)) => write!(f, "({:?}, {:?})", l, r),
265            (Bound::Unbounded, Bound::Unbounded) => write!(f, "()"),
266            (Bound::Unbounded, Bound::Excluded(r)) => write!(f, "(,{:?}]", r),
267            (Bound::Unbounded, Bound::Included(r)) => write!(f, "(,{:?})", r),
268        }?;
269
270        write!(f, " with prefix {:?}", self.prefix)
271    }
272}