typed_index_collections/
range.rs

1use core::ops;
2
3/// A helper trait used to convert typed index ranges to `usize` ranges.
4/// The trait is implemented for Rust's built-in range types with
5/// `K where usize: `[`From<K>`] used as bound endpoints.
6///
7/// See [`core::ops::RangeBounds`] for more details.
8///
9/// [`From<K>`]: https://doc.rust-lang.org/std/convert/trait.From.html
10/// [`core::ops::RangeBounds`]: https://doc.rust-lang.org/core/ops/trait.RangeBounds.html
11pub trait TiRangeBounds<K> {
12    /// Appropriate usize range
13    type Range: ops::RangeBounds<usize>;
14    /// Converts the `TiRangeBounds` into an appropriate usize range.
15    fn into_range(self) -> Self::Range;
16}
17
18impl<K> TiRangeBounds<K> for ops::Range<K>
19where
20    usize: From<K>,
21{
22    type Range = ops::Range<usize>;
23    #[inline]
24    fn into_range(self) -> Self::Range {
25        self.start.into()..self.end.into()
26    }
27}
28
29impl<K> TiRangeBounds<K> for ops::RangeFrom<K>
30where
31    usize: From<K>,
32{
33    type Range = ops::RangeFrom<usize>;
34    #[inline]
35    fn into_range(self) -> Self::Range {
36        self.start.into()..
37    }
38}
39
40impl<K> TiRangeBounds<K> for ops::RangeFull
41where
42    usize: From<K>,
43{
44    type Range = Self;
45    #[inline]
46    fn into_range(self) -> Self::Range {
47        Self
48    }
49}
50
51impl<K> TiRangeBounds<K> for ops::RangeInclusive<K>
52where
53    usize: From<K>,
54{
55    type Range = ops::RangeInclusive<usize>;
56    #[inline]
57    fn into_range(self) -> Self::Range {
58        let (start, end) = self.into_inner();
59        start.into()..=end.into()
60    }
61}
62
63impl<K> TiRangeBounds<K> for ops::RangeTo<K>
64where
65    usize: From<K>,
66{
67    type Range = ops::RangeTo<usize>;
68    #[inline]
69    fn into_range(self) -> Self::Range {
70        ..self.end.into()
71    }
72}
73
74impl<K> TiRangeBounds<K> for ops::RangeToInclusive<K>
75where
76    usize: From<K>,
77{
78    type Range = ops::RangeToInclusive<usize>;
79    #[inline]
80    fn into_range(self) -> Self::Range {
81        ..=self.end.into()
82    }
83}
84
85impl<K> TiRangeBounds<K> for (ops::Bound<K>, ops::Bound<K>)
86where
87    usize: From<K>,
88{
89    type Range = (ops::Bound<usize>, ops::Bound<usize>);
90    #[inline]
91    fn into_range(self) -> Self::Range {
92        (map_bound(self.0), map_bound(self.1))
93    }
94}
95
96#[inline]
97fn map_bound<K>(bound: ops::Bound<K>) -> ops::Bound<usize>
98where
99    usize: From<K>,
100{
101    match bound {
102        ops::Bound::Included(index) => ops::Bound::Included(index.into()),
103        ops::Bound::Excluded(index) => ops::Bound::Excluded(index.into()),
104        ops::Bound::Unbounded => ops::Bound::Unbounded,
105    }
106}