1use crate::{DescendError, IntoKeys, KeyError, Keys, Schema, Seeded, Short, Track, Transcode};
2
3#[derive(Clone, Debug, PartialEq, Eq)]
5pub struct ExactSize<T> {
6 iter: T,
7 count: usize,
8}
9
10impl<T: Iterator> Iterator for ExactSize<T> {
11 type Item = T::Item;
12
13 fn next(&mut self) -> Option<Self::Item> {
14 if let Some(v) = self.iter.next() {
15 self.count -= 1; Some(v)
17 } else {
18 debug_assert!(self.count == 0);
19 None
20 }
21 }
22
23 fn size_hint(&self) -> (usize, Option<usize>) {
24 (self.count, Some(self.count))
25 }
26}
27
28impl<T: Iterator> ExactSizeIterator for ExactSize<T> {}
31
32impl<T: Iterator> core::iter::FusedIterator for ExactSize<T> {}
34
35#[derive(Clone, Debug, PartialEq)]
48pub struct NodeIter<N: Seeded, const D: usize> {
49 schema: &'static Schema,
53 state: [usize; D],
54 root: usize,
55 depth: usize,
56 seed: N::Seed,
57}
58
59impl<N: Seeded, const D: usize> NodeIter<N, D> {
60 pub const fn new(
65 schema: &'static Schema,
66 state: [usize; D],
67 root: usize,
68 seed: N::Seed,
69 ) -> Self {
70 assert!(root <= D);
71 Self {
72 schema,
73 state,
74 root,
75 depth: D + 1,
77 seed,
78 }
79 }
80
81 pub fn with_root(
85 schema: &'static Schema,
86 root: impl IntoKeys,
87 seed: N::Seed,
88 ) -> Result<Self, DescendError<()>> {
89 let mut state = [0; D];
90 let mut root = root.into_keys().track();
91 let mut tr = Short::new(state.as_mut());
92 tr.transcode(schema, &mut root)?;
93 Ok(Self::new(schema, state, root.depth(), seed))
94 }
95
96 pub const fn exact_size(self) -> ExactSize<Self> {
104 let shape = self.schema.shape();
105 if D < shape.max_depth {
106 panic!("insufficient depth for exact size iteration");
107 }
108 let mut i = 0;
109 while i < D {
110 if self.state[i] != 0 {
111 panic!("exact size requires a fresh root iterator");
112 }
113 i += 1;
114 }
115 if self.root != 0 || self.depth != D + 1 {
116 panic!("exact size requires a fresh root iterator");
117 }
118 ExactSize {
119 iter: self,
120 count: shape.count.get(),
121 }
122 }
123
124 pub const fn schema(&self) -> &'static Schema {
126 self.schema
127 }
128
129 pub fn state(&self) -> Option<&[usize]> {
131 self.state.get(..self.depth)
132 }
133
134 pub const fn root(&self) -> usize {
136 self.root
137 }
138}
139
140impl<N: Transcode + Seeded, const D: usize> Iterator for NodeIter<N, D> {
141 type Item = Result<N, N::Error>;
142
143 fn next(&mut self) -> Option<Self::Item> {
144 loop {
145 debug_assert!(self.depth >= self.root);
146 debug_assert!(self.depth <= self.state.len() + 1);
147 if self.depth == self.root {
148 return None;
149 }
150 if self.depth <= self.state.len() {
151 self.state[self.depth - 1] += 1;
152 }
153 let mut item = Track::new(N::from_seed(&self.seed));
154 let ret = item.transcode(self.schema, &self.state[..]);
155 let (item, depth) = item.into_inner();
156 match ret {
157 Err(DescendError::Key(KeyError::NotFound)) => {
158 self.state[depth] = 0;
159 self.depth = depth.max(self.root);
160 }
161 Err(DescendError::Key(KeyError::TooLong)) | Ok(()) => {
162 self.depth = depth;
163 return Some(Ok(item));
164 }
165 Err(DescendError::Key(KeyError::TooShort)) => {
166 self.depth = depth;
167 }
168 Err(DescendError::Inner(e)) => {
169 self.depth = depth;
170 return Some(Err(e));
171 }
172 }
173 }
174 }
175}
176
177impl<N: Transcode + Seeded, const D: usize> core::iter::FusedIterator for NodeIter<N, D> {}