1#[macro_export]
2macro_rules! define_index {
3 ($ix:ident) => {
4 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
5 #[cfg_attr(
6 feature = "enable-serde",
7 derive(::serde::Serialize, ::serde::Deserialize)
8 )]
9 pub struct $ix(pub u32);
10 impl $ix {
11 #[inline(always)]
12 pub fn new(i: usize) -> Self {
13 Self(i as u32)
14 }
15 #[inline(always)]
16 pub fn index(self) -> usize {
17 debug_assert!(self.is_valid());
18 self.0 as usize
19 }
20 #[inline(always)]
21 pub fn invalid() -> Self {
22 Self(u32::MAX)
23 }
24 #[inline(always)]
25 pub fn is_invalid(self) -> bool {
26 self == Self::invalid()
27 }
28 #[inline(always)]
29 pub fn is_valid(self) -> bool {
30 self != Self::invalid()
31 }
32 #[inline(always)]
33 pub fn next(self) -> $ix {
34 debug_assert!(self.is_valid());
35 Self(self.0 + 1)
36 }
37 #[inline(always)]
38 pub fn prev(self) -> $ix {
39 debug_assert!(self.is_valid());
40 Self(self.0 - 1)
41 }
42
43 #[inline(always)]
44 pub fn raw_u32(self) -> u32 {
45 self.0
46 }
47 }
48
49 impl crate::index::ContainerIndex for $ix {}
50 };
51}
52
53pub trait ContainerIndex: Clone + Copy + std::fmt::Debug + PartialEq + Eq {}
54
55pub trait ContainerComparator {
56 type Ix: ContainerIndex;
57 fn compare(&self, a: Self::Ix, b: Self::Ix) -> std::cmp::Ordering;
58}
59
60define_index!(Inst);
61define_index!(Block);
62
63#[derive(Clone, Copy, Debug)]
64pub struct InstRange(Inst, Inst, bool);
65
66impl InstRange {
67 #[inline(always)]
68 pub fn forward(from: Inst, to: Inst) -> Self {
69 debug_assert!(from.index() <= to.index());
70 InstRange(from, to, true)
71 }
72
73 #[inline(always)]
74 pub fn backward(from: Inst, to: Inst) -> Self {
75 debug_assert!(from.index() >= to.index());
76 InstRange(to, from, false)
77 }
78
79 #[inline(always)]
80 pub fn first(self) -> Inst {
81 debug_assert!(self.len() > 0);
82 if self.is_forward() {
83 self.0
84 } else {
85 self.1.prev()
86 }
87 }
88
89 #[inline(always)]
90 pub fn last(self) -> Inst {
91 debug_assert!(self.len() > 0);
92 if self.is_forward() {
93 self.1.prev()
94 } else {
95 self.0
96 }
97 }
98
99 #[inline(always)]
100 pub fn rest(self) -> InstRange {
101 debug_assert!(self.len() > 0);
102 if self.is_forward() {
103 InstRange::forward(self.0.next(), self.1)
104 } else {
105 InstRange::backward(self.1.prev(), self.0)
106 }
107 }
108
109 #[inline(always)]
110 pub fn len(self) -> usize {
111 self.1.index() - self.0.index()
112 }
113
114 #[inline(always)]
115 pub fn is_forward(self) -> bool {
116 self.2
117 }
118
119 #[inline(always)]
120 pub fn rev(self) -> Self {
121 Self(self.0, self.1, !self.2)
122 }
123
124 #[inline(always)]
125 pub fn iter(self) -> InstRangeIter {
126 InstRangeIter(self)
127 }
128}
129
130#[derive(Clone, Copy, Debug)]
131pub struct InstRangeIter(InstRange);
132
133impl Iterator for InstRangeIter {
134 type Item = Inst;
135 #[inline(always)]
136 fn next(&mut self) -> Option<Inst> {
137 if self.0.len() == 0 {
138 None
139 } else {
140 let ret = self.0.first();
141 self.0 = self.0.rest();
142 Some(ret)
143 }
144 }
145}
146
147#[cfg(test)]
148mod test {
149 use super::*;
150
151 #[test]
152 fn test_inst_range() {
153 let range = InstRange::forward(Inst::new(0), Inst::new(0));
154 debug_assert_eq!(range.len(), 0);
155
156 let range = InstRange::forward(Inst::new(0), Inst::new(5));
157 debug_assert_eq!(range.first().index(), 0);
158 debug_assert_eq!(range.last().index(), 4);
159 debug_assert_eq!(range.len(), 5);
160 debug_assert_eq!(
161 range.iter().collect::<Vec<_>>(),
162 vec![
163 Inst::new(0),
164 Inst::new(1),
165 Inst::new(2),
166 Inst::new(3),
167 Inst::new(4)
168 ]
169 );
170 let range = range.rev();
171 debug_assert_eq!(range.first().index(), 4);
172 debug_assert_eq!(range.last().index(), 0);
173 debug_assert_eq!(range.len(), 5);
174 debug_assert_eq!(
175 range.iter().collect::<Vec<_>>(),
176 vec![
177 Inst::new(4),
178 Inst::new(3),
179 Inst::new(2),
180 Inst::new(1),
181 Inst::new(0)
182 ]
183 );
184 }
185}