rustc_index/
idx.rs
1use std::fmt::Debug;
2use std::hash::Hash;
3use std::ops;
4use std::slice::SliceIndex;
5
6pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash {
10 fn new(idx: usize) -> Self;
11
12 fn index(self) -> usize;
13
14 #[inline]
15 fn increment_by(&mut self, amount: usize) {
16 *self = self.plus(amount);
17 }
18
19 #[inline]
20 #[must_use = "Use `increment_by` if you wanted to update the index in-place"]
21 fn plus(self, amount: usize) -> Self {
22 Self::new(self.index() + amount)
23 }
24}
25
26impl Idx for usize {
27 #[inline]
28 fn new(idx: usize) -> Self {
29 idx
30 }
31 #[inline]
32 fn index(self) -> usize {
33 self
34 }
35}
36
37impl Idx for u32 {
38 #[inline]
39 fn new(idx: usize) -> Self {
40 assert!(idx <= u32::MAX as usize);
41 idx as u32
42 }
43 #[inline]
44 fn index(self) -> usize {
45 self as usize
46 }
47}
48
49pub trait IntoSliceIdx<I, T: ?Sized> {
51 type Output: SliceIndex<T>;
52 fn into_slice_idx(self) -> Self::Output;
53}
54
55impl<I: Idx, T> IntoSliceIdx<I, [T]> for I {
56 type Output = usize;
57 #[inline]
58 fn into_slice_idx(self) -> Self::Output {
59 self.index()
60 }
61}
62
63impl<I, T> IntoSliceIdx<I, [T]> for ops::RangeFull {
64 type Output = ops::RangeFull;
65 #[inline]
66 fn into_slice_idx(self) -> Self::Output {
67 self
68 }
69}
70
71impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::Range<I> {
72 type Output = ops::Range<usize>;
73 #[inline]
74 fn into_slice_idx(self) -> Self::Output {
75 ops::Range { start: self.start.index(), end: self.end.index() }
76 }
77}
78
79impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeFrom<I> {
80 type Output = ops::RangeFrom<usize>;
81 #[inline]
82 fn into_slice_idx(self) -> Self::Output {
83 ops::RangeFrom { start: self.start.index() }
84 }
85}
86
87impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeTo<I> {
88 type Output = ops::RangeTo<usize>;
89 #[inline]
90 fn into_slice_idx(self) -> Self::Output {
91 ..self.end.index()
92 }
93}
94
95impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeInclusive<I> {
96 type Output = ops::RangeInclusive<usize>;
97 #[inline]
98 fn into_slice_idx(self) -> Self::Output {
99 ops::RangeInclusive::new(self.start().index(), self.end().index())
100 }
101}
102
103impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeToInclusive<I> {
104 type Output = ops::RangeToInclusive<usize>;
105 #[inline]
106 fn into_slice_idx(self) -> Self::Output {
107 ..=self.end.index()
108 }
109}
110
111#[cfg(feature = "nightly")]
112impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::Range<I> {
113 type Output = core::range::Range<usize>;
114 #[inline]
115 fn into_slice_idx(self) -> Self::Output {
116 core::range::Range { start: self.start.index(), end: self.end.index() }
117 }
118}
119
120#[cfg(feature = "nightly")]
121impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeFrom<I> {
122 type Output = core::range::RangeFrom<usize>;
123 #[inline]
124 fn into_slice_idx(self) -> Self::Output {
125 core::range::RangeFrom { start: self.start.index() }
126 }
127}
128
129#[cfg(feature = "nightly")]
130impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeInclusive<I> {
131 type Output = core::range::RangeInclusive<usize>;
132 #[inline]
133 fn into_slice_idx(self) -> Self::Output {
134 core::range::RangeInclusive { start: self.start.index(), end: self.end.index() }
135 }
136}