rustc_index/
idx.rs

1use std::fmt::Debug;
2use std::hash::Hash;
3use std::ops;
4use std::slice::SliceIndex;
5
6/// Represents some newtyped `usize` wrapper.
7///
8/// Purpose: avoid mixing indexes for different bitvector domains.
9pub 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
49/// Helper trait for indexing operations with a custom index type.
50pub 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}