1#[derive(Debug, Clone, Eq, Hash)]
4pub enum Path {
5 Opt(u64, usize),
6 Vec(Vec<usize>),
7}
8
9impl Default for Path {
10 fn default() -> Self {
11 Self::Opt(0, 0)
12 }
13}
14
15impl PartialEq for Path {
16 fn eq(&self, other: &Self) -> bool {
17 self.iter().eq(other.iter())
18 }
19}
20
21impl From<Vec<usize>> for Path {
22 fn from(v: Vec<usize>) -> Path {
23 let mut out = Path::default();
24 for v in v.into_iter() {
25 out.push(v);
26 }
27 out
28 }
29}
30
31impl Into<Vec<usize>> for Path {
32 fn into(self: Self) -> Vec<usize> {
33 self.iter().collect()
34 }
35}
36
37impl Path {
38 pub fn with_next(u: usize) -> Self {
39 let mut out = Self::default();
40 out.push(u);
41 out
42 }
43
44 pub fn push(&mut self, u: usize) {
45 match self {
46 Self::Opt(v, cnt) => match stuffed_val_push(*v, u) {
47 Ok(new_v) => {
48 *v = new_v;
49 *cnt += 1;
50 }
51 Err(()) => {
52 let mut new_v: Vec<usize> = self.iter().collect();
53 new_v.push(u);
54 *self = Self::Vec(new_v);
55 }
56 },
57 Self::Vec(v) => v.push(u),
58 }
59 }
60
61 pub fn iter<'a>(&'a self) -> PathIter<'a> {
62 PathIter {
63 path: self,
64 offset: 0,
65 }
66 }
67}
68
69pub struct PathIter<'a> {
71 path: &'a Path,
72 offset: usize,
73}
74
75impl Iterator for PathIter<'_> {
76 type Item = usize;
77
78 fn next(&mut self) -> Option<Self::Item> {
79 match self.path {
80 Path::Opt(v, cnt) => {
81 if self.offset >= *cnt {
82 None
83 } else {
84 self.offset += 1;
85 let possible = v >> ((cnt - self.offset) * 4);
86 if possible == 0 {
87 None
88 } else if (possible & 0b11) == 0b11 {
89 todo!("support longer formats")
90 } else {
91 Some(((possible >> 1) & 0b11) as usize)
92 }
93 }
94 }
95 Path::Vec(v) => {
96 if self.offset >= v.len() {
97 None
98 } else {
99 self.offset += 1;
100 Some(v[self.offset - 1])
101 }
102 }
103 }
104 }
105}
106
107#[inline(always)]
108fn stuffed_val_full(v: &u64) -> bool {
109 (v >> 60) != 0
110}
111
112#[inline(always)]
113fn stuffed_val_push(v: u64, n: usize) -> Result<u64, ()> {
114 if stuffed_val_full(&v) {
115 return Err(());
116 }
117 if n > 3 {
118 return Err(());
119 }
120
121 Ok((v << 4) | (n << 1) as u64 | if n == 0 { 1 } else { 0 })
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn opt() {
130 let mut path = Path::default();
131 assert_eq!(path.iter().collect::<Vec<_>>(), vec![]);
132
133 path.push(2);
134 assert_eq!(path.iter().collect::<Vec<_>>(), vec![2]);
135 path.push(0);
136 assert_eq!(path.iter().collect::<Vec<_>>(), vec![2, 0]);
137 path.push(1);
138 assert_eq!(path.iter().collect::<Vec<_>>(), vec![2, 0, 1]);
139 assert!(!matches!(path, Path::Vec(_)));
140 }
141
142 #[test]
143 fn vec() {
144 let mut path = Path::default();
145 assert_eq!(path.iter().collect::<Vec<_>>(), vec![]);
146
147 path.push(4);
148 assert!(matches!(path, Path::Vec(_)));
149 assert_eq!(path.iter().collect::<Vec<_>>(), vec![4]);
150 path.push(1);
151 assert_eq!(path.iter().collect::<Vec<_>>(), vec![4, 1]);
152 path.push(0);
153 assert_eq!(path.iter().collect::<Vec<_>>(), vec![4, 1, 0]);
154 }
155
156 #[test]
157 fn vec_promote() {
158 let mut path = Path::default();
159 assert_eq!(path.iter().collect::<Vec<_>>(), vec![]);
160
161 path.push(0);
162 assert_eq!(path.iter().collect::<Vec<_>>(), vec![0]);
163 path.push(3);
164 assert_eq!(path.iter().collect::<Vec<_>>(), vec![0, 3]);
165 path.push(0);
166 assert_eq!(path.iter().collect::<Vec<_>>(), vec![0, 3, 0]);
167 assert!(!matches!(path, Path::Vec(_)));
168 path.push(88);
169 assert!(matches!(path, Path::Vec(_)));
170 assert_eq!(path.iter().collect::<Vec<_>>(), vec![0, 3, 0, 88]);
171 path.push(1);
172 assert_eq!(path.iter().collect::<Vec<_>>(), vec![0, 3, 0, 88, 1]);
173 }
174}