1use std::{fmt, iter::Iterator};
2
3#[derive(Debug, PartialEq, Eq, Clone)]
19pub enum LeafOrNode<T> {
25 Leaf(T),
26 PackedNodes,
28 Node(usize),
30}
31
32#[derive(PartialEq, Eq, Clone)]
33pub struct Asterism<T>(Vec<LeafOrNode<T>>);
34#[derive(PartialEq, Eq)]
35pub struct AsterismSlice<'a, T>(&'a [LeafOrNode<T>]);
36
37impl<'a, T> Copy for AsterismSlice<'a, T> {}
39impl<'a, T> Clone for AsterismSlice<'a, T> {
40 fn clone(&self) -> AsterismSlice<'a, T> { *self }
41}
42
43pub trait AsterMarchable<'a, T: 'a>: Sized + Clone + Copy {
45 fn as_slice(self) -> AsterismSlice<'a, T>;
46
47 fn inner(self) -> &'a [LeafOrNode<T>];
50
51 fn march(self) -> std::vec::IntoIter<AsterismSlice<'a, T>> {
53 let mut subs = vec![];
54 if self.inner().len() == 0 {
55 return subs.into_iter();
56 }
57
58 let depth_1: bool = match self.inner()[0] {
60 LeafOrNode::PackedNodes => true,
61 _ => false,
62 };
63 let mut i = if depth_1 { 1 } else { 0 }; while i < self.inner().len() {
66 let span = match self.inner()[i] {
67 LeafOrNode::Leaf(_) => {
68 if !depth_1 {
69 icp!("Unexpected Leaf")
70 }
71 1
72 }
73 LeafOrNode::PackedNodes => icp!("Unexpected PackedNodes"),
74 LeafOrNode::Node(span) => {
75 if depth_1 {
76 icp!("Unexpected Node")
77 }
78 i += 1;
79 span
80 }
81 };
82 subs.push(AsterismSlice(&self.inner()[i..i + span]));
83
84 i += span;
85 }
86
87 subs.into_iter()
88 }
89
90 fn collect(self) -> Vec<AsterismSlice<'a, T>> {
91 let mut res = vec![];
92 for sub in self.march() {
93 res.push(sub);
94 }
95 res
96 }
97
98 fn is_leaf(self) -> bool {
99 let inner = self.as_slice().0;
100 if inner.len() == 0 {
101 return false;
102 }
103 match inner[0] {
104 LeafOrNode::Leaf(_) => true,
105 _ => false,
106 }
107 }
108
109 fn as_leaf(self) -> &'a T {
110 let inner = self.as_slice().0;
111 if inner.len() != 1 {
112 icp!("not a leaf, length is {}", inner.len())
113 }
114 match inner[0] {
115 LeafOrNode::Leaf(ref l) => l,
116 _ => icp!("malformed Asterism"),
117 }
118 }
119
120 fn as_depth_1(self) -> Box<dyn Iterator<Item = &'a T> + 'a> {
121 if self.as_slice().0.len() == 0 {
122 return Box::new(std::iter::empty());
127 }
128 match self.as_slice().0[0] {
129 LeafOrNode::PackedNodes => {}
130 _ => icp!("Not depth-1"),
131 }
132 Box::new(self.as_slice().0[1..].iter().map(|lon| match lon {
133 LeafOrNode::Leaf(ref l) => l,
134 _ => icp!("Not depth-1"),
135 }))
136 }
137}
138
139impl<'a, T> AsterMarchable<'a, T> for AsterismSlice<'a, T> {
140 fn as_slice(self) -> AsterismSlice<'a, T> { self }
141 fn inner(self) -> &'a [LeafOrNode<T>] { self.0 }
142}
143
144impl<'a, T> AsterMarchable<'a, T> for &'a Asterism<T> {
145 fn as_slice(self) -> AsterismSlice<'a, T> { AsterismSlice(&self.0[..]) }
146 fn inner(self) -> &'a [LeafOrNode<T>] { &self.0[..] }
147}
148
149impl<T> Asterism<T> {
150 pub fn join(subs: Vec<Asterism<T>>) -> Asterism<T> {
151 let mut res = vec![];
152 if subs.len() == 0 {
153 return Asterism(vec![LeafOrNode::Node(0)]);
154 }
155 if subs[0].0.len() != 0 {
156 match subs[0].0[0] {
157 LeafOrNode::Leaf(_) => {
158 let mut res = vec![LeafOrNode::PackedNodes];
159 for mut leaf_asterism in subs {
160 if !leaf_asterism.is_leaf() {
161 icp!("Not a valid leaf");
162 }
163 res.push(leaf_asterism.0.remove(0));
164 }
165 return Asterism(res);
166 }
167 _ => {}
168 }
169 }
170
171 for mut aster in subs {
172 res.push(LeafOrNode::Node(aster.0.len()));
173 res.append(&mut aster.0);
174 }
175 Asterism(res)
176 }
177
178 pub fn from_leaf(leaf: T) -> Asterism<T> { Asterism(vec![LeafOrNode::Leaf(leaf)]) }
179
180 pub fn from_depth_1(leaves: Vec<T>) -> Asterism<T> {
181 let mut res = vec![LeafOrNode::PackedNodes];
182 for leaf in leaves {
183 res.push(LeafOrNode::Leaf(leaf))
184 }
185
186 Asterism(res)
187 }
188}
189
190impl<'a, T: Clone> AsterismSlice<'a, T> {
191 pub fn to_asterism(self) -> Asterism<T> { Asterism(self.0.to_vec()) }
192}
193
194impl<T: fmt::Debug> fmt::Debug for AsterismSlice<'_, T> {
195 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196 if self.is_leaf() {
197 write!(f, "{:?}", self.as_leaf())
198 } else {
199 write!(f, "[")?;
200 let mut first = true;
201 for ref sub in self.march() {
202 if !first {
203 write!(f, " ")?;
204 }
205 write!(f, "{:?}", sub)?;
206 first = false;
207 }
208 write!(f, "]")
209 }
210 }
211}
212
213impl<T: fmt::Debug> fmt::Debug for Asterism<T> {
214 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_slice().fmt(f) }
215}
216
217impl<T: fmt::Display> fmt::Display for AsterismSlice<'_, T> {
218 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
219 if self.is_leaf() {
220 write!(f, "{}", self.as_leaf())
221 } else {
222 write!(f, "[")?;
223 let mut first = true;
224 for ref sub in self.march() {
225 if !first {
226 write!(f, " ")?;
227 }
228 write!(f, "{}", sub)?;
229 first = false;
230 }
231 write!(f, "]")
232 }
233 }
234}
235
236impl<T: fmt::Display> fmt::Display for Asterism<T> {
237 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_slice().fmt(f) }
238}
239
240impl<T: fmt::Debug> Asterism<T> {
241 fn show(&self) {
243 for elt in &self.0 {
244 match elt {
245 LeafOrNode::Node(n) => print!("N{} ", n),
246 LeafOrNode::PackedNodes => print!("PN "),
247 LeafOrNode::Leaf(l) => print!("L{:?} ", l),
248 }
249 }
250 }
251}
252
253#[test]
254fn asterism_basics() {
255 let abc = Asterism::from_depth_1(vec!["a", "b", "c"]);
256
257 assert_eq!(abc.as_slice().as_depth_1().collect::<Vec<_>>(), vec![&"a", &"b", &"c"]);
258
259 let (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) =
260 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
261
262 let a_through_i = Asterism::join(vec![
263 Asterism::from_depth_1(vec![a, b]),
264 Asterism::from_depth_1(vec![c]),
265 Asterism::from_depth_1(vec![d, e]),
266 Asterism::from_depth_1(vec![f, g]),
267 Asterism::from_depth_1(vec![h, i]),
268 ]);
269
270 let a_through_m = Asterism::join(vec![
271 a_through_i,
272 Asterism::join(vec![]), Asterism::join(vec![Asterism::from_depth_1(vec![j, k, l, m])]),
274 ]);
275
276 let a_through_o = Asterism::join(vec![
277 a_through_m,
278 Asterism::join(vec![Asterism::join(vec![
279 Asterism::from_depth_1(vec![n]),
280 Asterism::from_depth_1(vec![o]),
281 ])]),
282 ]);
283
284 assert_eq!(
285 format!("{}", a_through_o),
286 "[[[[0 1] [2] [3 4] [5 6] [7 8]] [[]] [[9 10 11 12]]] [[[13] [14]]]]"
287 );
288
289 let mut expected_d1 = 0;
290 let mut expected_m = 0;
291 for m in a_through_o.march() {
292 for mm in m.march() {
293 for mmm in mm.march() {
294 for mmmm in mmm.as_depth_1() {
295 assert_eq!(*mmmm, expected_d1);
296 expected_d1 += 1;
297 }
298 for mmmm in mmm.march() {
299 assert_eq!(*mmmm.as_leaf(), expected_m);
300 expected_m += 1;
301 }
302 }
303 }
304 }
305 assert_eq!(15, expected_d1);
306 assert_eq!(15, expected_m);
307
308 let d1 = Asterism::from_depth_1(vec![vec![1, 3], vec![2, 3]]);
309
310 for v in d1.as_depth_1() {
311 assert_eq!(v.len(), 2)
312 }
313}