1#[cfg(feature = "doc")]
2use crate::scope;
3use {
4 crate::{
5 container::Container,
6 proof::{Id, NonEmpty, ProofAdd, Unknown},
7 traits::{Idx, TrustedContainer},
8 },
9 core::{
10 cmp, fmt,
11 hash::{self, Hash},
12 marker::PhantomData,
13 ops,
14 },
15};
16
17pub struct Index<'id, I: Idx = u32, Emptiness = NonEmpty> {
26 #[allow(unused)]
27 id: Id<'id>,
28 idx: I,
29 phantom: PhantomData<Emptiness>,
30}
31
32impl<'id, I: Idx> Index<'id, I, Unknown> {
33 pub(crate) unsafe fn new(idx: I) -> Self {
34 Index::new_any(idx)
35 }
36}
37
38impl<'id, I: Idx> Index<'id, I, NonEmpty> {
39 pub(crate) unsafe fn new_nonempty(idx: I) -> Self {
40 Index::new_any(idx)
41 }
42}
43
44impl<'id, I: Idx, Emptiness> Index<'id, I, Emptiness> {
45 pub(crate) unsafe fn new_any(idx: I) -> Self {
46 Index {
47 id: Id::default(),
48 idx,
49 phantom: PhantomData,
50 }
51 }
52}
53
54impl<'id, I: Idx, Emptiness> Index<'id, I, Emptiness> {
55 pub fn untrusted(&self) -> I {
57 self.idx
58 }
59
60 pub fn erased(&self) -> Index<'id, I, Unknown> {
62 unsafe { Index::new(self.idx) }
63 }
64}
65
66impl<'id, I: Idx> Index<'id, I, NonEmpty> {
67 #[doc(hidden)]
68 pub fn observe_proof(&self) {}
69}
70
71impl<'id, I: Idx, Emptiness> fmt::Debug for Index<'id, I, Emptiness> {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 f.debug_tuple("Index<'id>").field(&self.idx).finish()
74 }
75}
76
77impl<'id, I: Idx, Emptiness> Copy for Index<'id, I, Emptiness> {}
78impl<'id, I: Idx, Emptiness> Clone for Index<'id, I, Emptiness> {
79 fn clone(&self) -> Self {
80 *self
81 }
82}
83
84impl<'id, I: Idx, Emptiness> Ord for Index<'id, I, Emptiness> {
85 fn cmp(&self, other: &Self) -> cmp::Ordering {
86 self.idx.cmp(&other.idx)
87 }
88}
89
90impl<'id, I: Idx, P, Q> PartialOrd<Index<'id, I, Q>> for Index<'id, I, P> {
91 fn partial_cmp(&self, other: &Index<'id, I, Q>) -> Option<cmp::Ordering> {
92 self.idx.partial_cmp(&other.idx)
93 }
94}
95
96impl<'id, I: Idx, Emptiness> Eq for Index<'id, I, Emptiness> {}
97impl<'id, I: Idx, P, Q> PartialEq<Index<'id, I, Q>> for Index<'id, I, P> {
98 fn eq(&self, other: &Index<'id, I, Q>) -> bool {
99 self.idx.eq(&other.idx)
100 }
101}
102
103impl<'id, I: Idx, Emptiness> Hash for Index<'id, I, Emptiness> {
104 fn hash<H: hash::Hasher>(&self, state: &mut H) {
105 self.idx.hash(state);
106 }
107}
108
109pub struct Range<'id, I: Idx = u32, Emptiness = Unknown> {
117 start: Index<'id, I, Unknown>,
118 end: Index<'id, I, Unknown>,
119 phantom: PhantomData<Emptiness>,
120}
121
122impl<'id, I: Idx> Range<'id, I, Unknown> {
123 pub(crate) unsafe fn new(start: I, end: I) -> Self {
124 Range::new_any(start, end)
125 }
126}
127
128impl<'id, I: Idx> Range<'id, I, NonEmpty> {
129 pub(crate) unsafe fn new_nonempty(start: I, end: I) -> Self {
130 Range::new_any(start, end)
131 }
132}
133
134impl<'id, I: Idx, Emptiness> Range<'id, I, Emptiness> {
135 pub(crate) unsafe fn new_any(start: I, end: I) -> Self {
136 Range {
137 start: Index::new(start),
138 end: Index::new(end),
139 phantom: PhantomData,
140 }
141 }
142}
143
144impl<'id, I: Idx> Range<'id, I, Unknown> {
145 pub fn from<P, Q>(start: Index<'id, I, P>, end: Index<'id, I, Q>) -> Self {
147 unsafe { Range::new(start.untrusted(), end.untrusted()) }
148 }
149}
150
151impl<'id, I: Idx, Emptiness> Range<'id, I, Emptiness> {
152 pub fn untrusted(&self) -> ops::Range<I> {
154 self.start.idx..self.end.idx
155 }
156
157 pub fn erased(&self) -> Range<'id, I, Unknown> {
159 unsafe { Range::new(self.start.idx, self.end.idx) }
160 }
161
162 pub fn len(&self) -> I {
164 if self.is_empty() {
165 I::zero()
166 } else {
167 self.end.idx.sub(self.start.idx.as_usize())
168 }
169 }
170
171 pub fn is_empty(&self) -> bool {
173 self.start.idx >= self.end.idx
174 }
175
176 pub fn nonempty(&self) -> Option<Range<'id, I, NonEmpty>> {
178 if self.is_empty() {
179 None
180 } else {
181 unsafe { Some(Range::new_nonempty(self.start.idx, self.end.idx)) }
182 }
183 }
184
185 pub fn start(&self) -> Index<'id, I, Emptiness> {
187 unsafe { Index::new_any(self.start.idx) }
188 }
189
190 pub fn end(&self) -> Index<'id, I, Unknown> {
192 self.end
193 }
194
195 pub fn split_at<E>(&self, index: Index<'id, I, E>) -> Option<(Range<'id, I>, Range<'id, I>)> {
197 if index >= self.start && index <= self.end {
198 unsafe {
199 Some((
200 Range::new(self.start.idx, index.idx),
201 Range::new(index.idx, self.end.idx),
202 ))
203 }
204 } else {
205 None
206 }
207 }
208
209 pub fn contains_in<Array: TrustedContainer>(
211 &self,
212 index: I,
213 container: &Container<'id, Array>,
214 ) -> Option<Index<'id, I, NonEmpty>> {
215 if index >= self.start().untrusted() && index < self.end().untrusted() {
216 container.vet(index).ok()
217 } else {
218 None
219 }
220 }
221
222 pub fn contains<P>(&self, index: Index<'id, I, P>) -> Option<Index<'id, I, NonEmpty>> {
224 if index >= self.start() && index < self.end() {
225 unsafe { Some(Index::new_nonempty(index.untrusted())) }
226 } else {
227 None
228 }
229 }
230
231 pub fn join<Q>(
234 &self,
235 other: Range<'id, I, Q>,
236 ) -> Option<Range<'id, I, <(Emptiness, Q) as ProofAdd>::Sum>>
237 where
238 (Emptiness, Q): ProofAdd,
239 {
240 if self.end == other.start {
241 unsafe { Some(Range::new_any(self.start.idx, other.end.idx)) }
242 } else {
243 None
244 }
245 }
246
247 pub fn join_cover<Q>(
249 &self,
250 other: Range<'id, I, Q>,
251 ) -> Range<'id, I, <(Emptiness, Q) as ProofAdd>::Sum>
252 where
253 (Emptiness, Q): ProofAdd,
254 {
255 let start = cmp::min(self.start, other.start);
256 let end = cmp::max(self.end, other.end);
257 unsafe { Range::new_any(start.idx, end.idx) }
258 }
259
260 pub fn frontiers(&self) -> (Range<'id, I, Unknown>, Range<'id, I, Unknown>) {
262 (
263 Range::from(self.start(), self.start()),
264 Range::from(self.end(), self.end()),
265 )
266 }
267}
268
269impl<'id, I: Idx> Range<'id, I, NonEmpty> {
270 #[doc(hidden)]
271 pub fn observe_proof(&self) {}
272
273 pub fn advance_in<Array: TrustedContainer>(
277 &mut self,
278 container: &Container<'id, Array>,
279 ) -> bool {
280 if let Some(next) = container.advance(self.start()) {
281 if next < self.end() {
282 *self = unsafe { Range::new_nonempty(next.untrusted(), self.end().untrusted()) };
283 true
284 } else {
285 false
286 }
287 } else {
288 false
289 }
290 }
291}
292
293impl<'id, I: Idx, Emptiness> From<ops::Range<Index<'id, I, Emptiness>>> for Range<'id, I, Unknown> {
298 fn from(r: ops::Range<Index<'id, I, Emptiness>>) -> Self {
299 Range::from(r.start, r.end)
300 }
301}
302
303impl<'id, I: Idx, Emptiness> fmt::Debug for Range<'id, I, Emptiness> {
304 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305 f.debug_tuple("Range<'id>")
306 .field(&self.start.idx)
307 .field(&self.end.idx)
308 .finish()
309 }
310}
311
312impl<'id, I: Idx, Emptiness> Copy for Range<'id, I, Emptiness> {}
313impl<'id, I: Idx, Emptiness> Clone for Range<'id, I, Emptiness> {
314 fn clone(&self) -> Self {
315 *self
316 }
317}
318
319impl<'id, I: Idx, Emptiness> Eq for Range<'id, I, Emptiness> {}
320impl<'id, I: Idx, P, Q> PartialEq<Range<'id, I, Q>> for Range<'id, I, P> {
321 fn eq(&self, other: &Range<'id, I, Q>) -> bool {
322 self.start.eq(&other.start) && self.end.eq(&other.end)
323 }
324}
325
326impl<'id, I: Idx, Emptiness> Hash for Range<'id, I, Emptiness> {
327 fn hash<H: hash::Hasher>(&self, state: &mut H) {
328 self.start.hash(state);
329 self.end.hash(state);
330 }
331}
332
333#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
335pub enum IndexError {
336 OutOfBounds,
338 Invalid,
340}