1 | use 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 |
11 | pub 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 | |
18 | impl<K> TiRangeBounds<K> for ops::Range<K> |
19 | where |
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 | |
29 | impl<K> TiRangeBounds<K> for ops::RangeFrom<K> |
30 | where |
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 | |
40 | impl<K> TiRangeBounds<K> for ops::RangeFull |
41 | where |
42 | usize: From<K>, |
43 | { |
44 | type Range = Self; |
45 | #[inline ] |
46 | fn into_range(self) -> Self::Range { |
47 | Self |
48 | } |
49 | } |
50 | |
51 | impl<K> TiRangeBounds<K> for ops::RangeInclusive<K> |
52 | where |
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 | |
63 | impl<K> TiRangeBounds<K> for ops::RangeTo<K> |
64 | where |
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 | |
74 | impl<K> TiRangeBounds<K> for ops::RangeToInclusive<K> |
75 | where |
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 | |
85 | impl<K> TiRangeBounds<K> for (ops::Bound<K>, ops::Bound<K>) |
86 | where |
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 ] |
97 | fn map_bound<K>(bound: ops::Bound<K>) -> ops::Bound<usize> |
98 | where |
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 | |