1#[derive(Copy, Clone, PartialEq, Eq)]
4pub(crate) struct Seq(u32);
5
6static_assertions::assert_not_impl_any!(Seq: PartialOrd, Ord, From<u32>, std::ops::Deref);
12
13impl Seq {
14 #[inline]
15 pub fn new(x: u32) -> Self {
16 Self(x)
17 }
18}
19
20impl std::fmt::Debug for Seq {
21 #[inline]
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 self.0.fmt(f)
24 }
25}
26
27impl std::fmt::Display for Seq {
28 #[inline]
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 self.0.fmt(f)
31 }
32}
33
34impl From<Seq> for u32 {
35 #[inline]
36 fn from(x: Seq) -> Self {
37 x.0
38 }
39}
40
41impl std::ops::Add<u32> for Seq {
42 type Output = Self;
43
44 fn add(self, offset: u32) -> Self::Output {
45 Self::new(self.0.wrapping_add(offset))
46 }
47}
48
49impl std::ops::Sub<u32> for Seq {
50 type Output = Self;
51
52 fn sub(self, offset: u32) -> Self::Output {
53 Self::new(self.0.wrapping_sub(offset))
54 }
55}
56
57impl std::ops::Sub for Seq {
58 type Output = u32;
59
60 fn sub(self, other: Self) -> Self::Output {
61 self.0.wrapping_sub(other.0)
62 }
63}
64
65impl std::ops::AddAssign<u32> for Seq {
66 fn add_assign(&mut self, offset: u32) {
67 self.0 = self.0.wrapping_add(offset);
68 }
69}
70
71impl std::ops::SubAssign<u32> for Seq {
72 fn sub_assign(&mut self, offset: u32) {
73 self.0 = self.0.wrapping_sub(offset);
74 }
75}
76
77#[derive(Copy, Clone, PartialEq, Eq)]
80pub(crate) struct SeqRange {
81 pub start: Seq,
83 pub end: Seq,
85}
86
87impl std::fmt::Debug for SeqRange {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 self.start.fmt(f)?;
90 write!(f, "..")?;
91 self.end.fmt(f)?;
92 Ok(())
93 }
94}
95
96impl SeqRange {
97 #[inline]
98 pub fn new(start: Seq, end: Seq) -> Self {
99 Self { start, end }
100 }
101
102 #[inline]
103 pub fn len(&self) -> u32 {
104 self.end - self.start
105 }
106
107 #[inline]
108 pub fn is_empty(&self) -> bool {
109 self.len() == 0
110 }
111
112 #[inline]
114 pub fn contains(&self, seq: Seq) -> bool {
115 SeqRange::new(self.start, seq).len() < self.len()
116 }
117
118 pub fn intersection(&self, other: &Self) -> Option<SeqRange> {
123 let a = self;
124 let b = other;
125
126 match (a.is_empty(), b.is_empty()) {
128 (true, true) => return (a == b).then_some(*a),
130 (true, false) => return b.contains(a.start).then_some(*a),
132 (false, true) => return a.contains(b.start).then_some(*b),
134 (false, false) => {}
136 }
137
138 let a_0_in_b = b.contains(a.start);
140 let a_1_in_b = b.contains(a.end - 1);
141
142 match (a_0_in_b, a_1_in_b) {
143 (true, false) => Some(Self::new(a.start, b.end)),
145 (false, true) => Some(Self::new(b.start, a.end)),
147 (true, true) => {
148 if a.start - b.start < a.end - b.start {
149 Some(*a)
151 } else {
152 None
155 }
156 }
157 (false, false) => {
158 let b_0_in_a = a.contains(b.start);
160 let b_1_in_a = a.contains(b.end - 1);
161
162 if b_0_in_a && b_1_in_a {
163 Some(*b)
165 } else {
166 None
168 }
169 }
170 }
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 fn range(start: u32, end: u32) -> SeqRange {
180 SeqRange::new(Seq::new(start), Seq::new(end))
181 }
182
183 fn seq(val: u32) -> Seq {
185 Seq::new(val)
186 }
187
188 #[test]
189 fn test_range_contains() {
190 fn test_range(
194 range: SeqRange,
195 val: Seq,
196 contained: bool,
197 offset_range: std::ops::Range<i32>,
198 ) {
199 for i in offset_range {
200 let i = i as u32;
202
203 let range = SeqRange::new(range.start + i, range.end + i);
204 let val = val + i;
205
206 assert_eq!(range.contains(val), contained);
207
208 if !range.is_empty() {
209 let reverse_range = SeqRange::new(range.end, range.start);
210 assert_eq!(reverse_range.contains(val), !contained);
211 }
212 }
213 }
214
215 test_range(range(0, 0), seq(0), false, -10..10);
216 test_range(range(0, 1), seq(0), true, -10..10);
217 test_range(range(0, 1), seq(1), false, -10..10);
218 test_range(range(0, 2), seq(0), true, -10..10);
219 test_range(range(0, 2), seq(1), true, -10..10);
220 test_range(range(0, 2), seq(2), false, -10..10);
221 }
222
223 #[test]
224 fn test_range_intersection() {
225 fn test_pair(
229 a: SeqRange,
230 b: SeqRange,
231 expected: impl Into<Option<SeqRange>>,
232 offset_range: std::ops::Range<i32>,
233 ) {
234 let expected = expected.into();
235
236 for i in offset_range {
237 let i = i as u32;
239
240 let a = SeqRange::new(a.start + i, a.end + i);
242 let b = SeqRange::new(b.start + i, b.end + i);
243 let expected = expected.map(|x| SeqRange::new(x.start + i, x.end + i));
244
245 assert_eq!(a.intersection(&b), expected);
247 assert_eq!(b.intersection(&a), expected);
248 }
249 }
250
251 test_pair(range(0, 0), range(0, 0), range(0, 0), -10..10);
252 test_pair(range(0, 0), range(1, 1), None, -10..10);
253 test_pair(range(0, 0), range(0, 1), range(0, 0), -10..10);
254 test_pair(range(1, 1), range(0, 1), None, -10..10);
255 test_pair(range(0, 1), range(1, 2), None, -10..10);
256 test_pair(range(0, 2), range(1, 2), range(1, 2), -10..10);
257 test_pair(range(0, 2), range(0, 1), range(0, 1), -10..10);
258 test_pair(range(10, 12), range(10, 12), range(10, 12), -100..100);
259 test_pair(range(10, 12), range(12, 10), None, -100..100);
260
261 test_pair(range(10, 20), range(12, 16), range(12, 16), -100..100);
263 test_pair(range(10, 20), range(16, 12), None, -100..100);
264 }
265}