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: K, end: K) = 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: K) => ops::Bound::Included(index.into()),
103 ops::Bound::Excluded(index: K) => ops::Bound::Excluded(index.into()),
104 ops::Bound::Unbounded => ops::Bound::Unbounded,
105 }
106}
107