1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use core::borrow::Borrow;
use rend::LittleEndian;
use rkyv::{Archive, Deserialize, Serialize};
use crate::annotations::{Annotation, Combine};
use crate::walk::{Discriminant, Step, Walkable, Walker};
use crate::Compound;
#[derive(
PartialEq, Debug, Clone, Default, Copy, Archive, Serialize, Deserialize,
)]
#[archive(as = "Self")]
pub struct Cardinality(pub(crate) LittleEndian<u64>);
impl From<Cardinality> for u64 {
fn from(c: Cardinality) -> Self {
c.0.into()
}
}
impl<'a> From<&'a Cardinality> for u64 {
fn from(c: &'a Cardinality) -> Self {
c.0.into()
}
}
impl<L> Annotation<L> for Cardinality {
fn from_leaf(_: &L) -> Self {
Cardinality(1.into())
}
}
impl<A> Combine<A> for Cardinality
where
A: Borrow<Self>,
{
fn combine(&mut self, other: &A) {
self.0 += other.borrow().0
}
}
#[derive(Debug)]
pub struct Nth(pub u64);
impl<C, A, S> Walker<C, A, S> for Nth
where
C: Compound<A, S>,
A: Borrow<Cardinality>,
{
fn walk(&mut self, walk: impl Walkable<C, A, S>) -> Step {
for i in 0.. {
match walk.probe(i) {
Discriminant::Leaf(_) => {
if self.0 == 0 {
return Step::Found(i);
} else {
self.0 -= 1;
}
}
Discriminant::Annotation(a) => {
let card: &Cardinality = (*a).borrow();
if card.0 <= self.0 {
self.0 -= u64::from(card.0);
} else {
return Step::Found(i);
}
}
Discriminant::Empty => (),
Discriminant::End => return Step::Abort,
};
}
unreachable!()
}
}