1use crate::bucket::BucketIApi;
2use crate::common::page::tree::leaf::BUCKET_LEAF_FLAG;
3use crate::cursor::{CursorIApi, InnerCursor};
4use crate::tx::TxIApi;
5use crate::{BucketApi, BucketImpl, BucketRwImpl, TxImpl, TxRef, TxRwImpl, TxRwRef};
6use itertools::rev;
7use std::marker::PhantomData;
8
9#[derive(Clone)]
10struct KvIter<'tx: 'p, 'p> {
11 next: InnerCursor<'tx>,
12 next_started: bool,
13 back: InnerCursor<'tx>,
14 back_started: bool,
15 p: PhantomData<&'p u8>,
16}
17
18impl<'tx: 'p, 'p> KvIter<'tx, 'p> {
19 pub(crate) fn new(c: InnerCursor<'tx>) -> KvIter<'tx, 'p> {
20 KvIter {
21 next: c.clone(),
22 next_started: false,
23 back: c,
24 back_started: false,
25 p: PhantomData,
26 }
27 }
28}
29
30impl<'tx: 'p, 'p> Iterator for KvIter<'tx, 'p> {
31 type Item = (&'p [u8], &'p [u8], u32);
32
33 fn next(&mut self) -> Option<Self::Item> {
34 if self.next_started && self.back_started && self.next == self.back {
35 return None;
36 }
37 if self.next_started {
38 self.next.i_next()
39 } else {
40 self.next_started = true;
41 self.next.i_first()
42 }
43 }
44}
45
46impl<'tx: 'p, 'p> DoubleEndedIterator for KvIter<'tx, 'p> {
47 fn next_back(&mut self) -> Option<Self::Item> {
48 if self.next_started && self.back_started && self.next == self.back {
49 return None;
50 }
51 if self.back_started {
52 self.back.i_prev()
53 } else {
54 self.back_started = true;
55 self.back.api_last();
56 self.back.key_value()
57 }
58 }
59}
60
61#[derive(Clone)]
62pub struct EntryIter<'tx: 'p, 'p> {
63 i: KvIter<'tx, 'p>,
64}
65
66impl<'tx: 'p, 'p> EntryIter<'tx, 'p> {
67 pub(crate) fn new(c: InnerCursor<'tx>) -> EntryIter<'tx, 'p> {
68 EntryIter { i: KvIter::new(c) }
69 }
70}
71
72impl<'tx: 'p, 'p> Iterator for EntryIter<'tx, 'p> {
73 type Item = (&'p [u8], &'p [u8]);
74
75 fn next(&mut self) -> Option<Self::Item> {
76 while let Some((k, v, flags)) = self.i.next() {
77 if flags & BUCKET_LEAF_FLAG == 0 {
78 return Some((k, v));
79 }
80 }
81 None
82 }
83}
84
85impl<'tx: 'p, 'p> DoubleEndedIterator for EntryIter<'tx, 'p> {
86 fn next_back(&mut self) -> Option<Self::Item> {
87 while let Some((k, v, flags)) = self.i.next_back() {
88 if flags & BUCKET_LEAF_FLAG == 0 {
89 return Some((k, v));
90 }
91 }
92 None
93 }
94}
95
96pub struct BucketIter<'tx: 'p, 'p> {
97 i: KvIter<'tx, 'p>,
98}
99
100impl<'tx: 'p, 'p> BucketIter<'tx, 'p> {
101 pub(crate) fn new(c: InnerCursor<'tx>) -> BucketIter<'tx, 'p> {
102 BucketIter { i: KvIter::new(c) }
103 }
104}
105
106impl<'tx: 'p, 'p> Iterator for BucketIter<'tx, 'p> {
107 type Item = (&'p [u8], BucketImpl<'tx, 'p>);
108
109 fn next(&mut self) -> Option<Self::Item> {
110 while let Some((k, _, flags)) = self.i.next() {
111 if flags & BUCKET_LEAF_FLAG != 0 {
112 let bucket = BucketImpl::from(self.i.next.bucket.api_bucket(k).unwrap());
113 return Some((k, bucket));
114 }
115 }
116 None
117 }
118}
119
120impl<'tx: 'p, 'p> DoubleEndedIterator for BucketIter<'tx, 'p> {
121 fn next_back(&mut self) -> Option<Self::Item> {
122 while let Some((k, _, flags)) = self.i.next_back() {
123 if flags & BUCKET_LEAF_FLAG != 0 {
124 let bucket = BucketImpl::from(self.i.back.bucket.api_bucket(k).unwrap());
125 return Some((k, bucket));
126 }
127 }
128 None
129 }
130}
131
132impl<'tx: 'a, 'a> IntoIterator for &'a TxImpl<'tx> {
133 type Item = (&'a [u8], BucketImpl<'tx, 'a>);
134 type IntoIter = BucketIter<'tx, 'a>;
135
136 fn into_iter(self) -> Self::IntoIter {
137 BucketIter::new(self.tx.api_cursor())
138 }
139}
140
141impl<'tx: 'a, 'a> IntoIterator for &'a TxRwImpl<'tx> {
142 type Item = (&'a [u8], BucketImpl<'tx, 'a>);
143 type IntoIter = BucketIter<'tx, 'a>;
144
145 fn into_iter(self) -> Self::IntoIter {
146 BucketIter::new(self.tx.api_cursor())
147 }
148}
149
150impl<'tx: 'a, 'a> IntoIterator for &'a TxRef<'tx> {
151 type Item = (&'a [u8], BucketImpl<'tx, 'a>);
152 type IntoIter = BucketIter<'tx, 'a>;
153
154 fn into_iter(self) -> Self::IntoIter {
155 BucketIter::new(self.tx.api_cursor())
156 }
157}
158
159impl<'tx: 'a, 'a> IntoIterator for &'a TxRwRef<'tx> {
160 type Item = (&'a [u8], BucketImpl<'tx, 'a>);
161 type IntoIter = BucketIter<'tx, 'a>;
162
163 fn into_iter(self) -> Self::IntoIter {
164 BucketIter::new(self.tx.api_cursor())
165 }
166}
167
168pub struct BucketIterMut<'tx: 'p, 'p> {
169 i: KvIter<'tx, 'p>,
170}
171
172impl<'tx: 'p, 'p> BucketIterMut<'tx, 'p> {
173 pub(crate) fn new(c: InnerCursor<'tx>) -> BucketIterMut<'tx, 'p> {
174 BucketIterMut { i: KvIter::new(c) }
175 }
176}
177
178impl<'tx: 'p, 'p> Iterator for BucketIterMut<'tx, 'p> {
179 type Item = (&'p [u8], BucketRwImpl<'tx, 'p>);
180
181 fn next(&mut self) -> Option<Self::Item> {
182 while let Some((k, _, flags)) = self.i.next() {
183 if flags & BUCKET_LEAF_FLAG != 0 {
184 let bucket = BucketRwImpl::from(self.i.next.bucket.api_bucket(k).unwrap());
185 return Some((k, bucket));
186 }
187 }
188 None
189 }
190}
191
192impl<'tx: 'p, 'p> DoubleEndedIterator for BucketIterMut<'tx, 'p> {
193 fn next_back(&mut self) -> Option<Self::Item> {
194 while let Some((k, _, flags)) = self.i.next_back() {
195 if flags & BUCKET_LEAF_FLAG != 0 {
196 let bucket = BucketRwImpl::from(self.i.back.bucket.api_bucket(k).unwrap());
197 return Some((k, bucket));
198 }
199 }
200 None
201 }
202}
203
204impl<'tx: 'a, 'a> IntoIterator for &'a mut TxRwImpl<'tx> {
205 type Item = (&'a [u8], BucketRwImpl<'tx, 'a>);
206 type IntoIter = BucketIterMut<'tx, 'a>;
207
208 fn into_iter(self) -> Self::IntoIter {
209 BucketIterMut::new(self.tx.api_cursor())
210 }
211}
212
213impl<'tx: 'a, 'a> IntoIterator for &'a mut TxRwRef<'tx> {
214 type Item = (&'a [u8], BucketRwImpl<'tx, 'a>);
215 type IntoIter = BucketIterMut<'tx, 'a>;
216
217 fn into_iter(self) -> Self::IntoIter {
218 BucketIterMut::new(self.tx.api_cursor())
219 }
220}
221
222pub enum ValueBucket<'tx: 'p, 'p> {
223 Value(&'p [u8]),
224 Bucket(BucketImpl<'tx, 'p>),
225}
226
227pub struct ValueBucketIter<'tx: 'p, 'p> {
228 i: KvIter<'tx, 'p>,
229}
230
231impl<'tx: 'p, 'p> ValueBucketIter<'tx, 'p> {
232 pub(crate) fn new(c: InnerCursor<'tx>) -> ValueBucketIter<'tx, 'p> {
233 ValueBucketIter { i: KvIter::new(c) }
234 }
235}
236
237impl<'tx: 'p, 'p> Iterator for ValueBucketIter<'tx, 'p> {
238 type Item = (&'p [u8], ValueBucket<'tx, 'p>);
239
240 fn next(&mut self) -> Option<Self::Item> {
241 if let Some((k, v, flags)) = self.i.next() {
242 return if flags & BUCKET_LEAF_FLAG == 0 {
243 Some((k, ValueBucket::Value(v)))
244 } else {
245 let bucket = BucketImpl::from(self.i.next.bucket.api_bucket(k).unwrap());
246 Some((k, ValueBucket::Bucket(bucket)))
247 };
248 }
249 None
250 }
251}
252
253impl<'tx: 'p, 'p> DoubleEndedIterator for ValueBucketIter<'tx, 'p> {
254 fn next_back(&mut self) -> Option<Self::Item> {
255 if let Some((k, v, flags)) = self.i.next_back() {
256 return if flags & BUCKET_LEAF_FLAG == 0 {
257 Some((k, ValueBucket::Value(v)))
258 } else {
259 let bucket = BucketImpl::from(self.i.back.bucket.api_bucket(k).unwrap());
260 Some((k, ValueBucket::Bucket(bucket)))
261 };
262 }
263 None
264 }
265}
266
267#[derive(Debug)]
268pub enum ValueBucketSeq<'p> {
269 Value(&'p [u8]),
270 BucketSeq(u64),
271}
272
273impl<'p> ValueBucketSeq<'p> {
274 pub fn len(&self) -> usize {
275 match self {
276 ValueBucketSeq::Value(v) => v.len(),
277 ValueBucketSeq::BucketSeq(_) => 0,
278 }
279 }
280}
281
282pub struct DbWalker<'tx: 'p, 'p> {
283 root_buckets: BucketIter<'tx, 'p>,
284 path: Vec<&'p [u8]>,
285 cursors: Vec<ValueBucketIter<'tx, 'p>>,
286 bucket_seq: bool,
287 p: PhantomData<&'p u8>,
288}
289
290impl<'tx: 'p, 'p> DbWalker<'tx, 'p> {
291 pub(crate) fn new(root_cursor: InnerCursor<'tx>) -> DbWalker<'tx, 'p> {
292 DbWalker {
293 root_buckets: BucketIter::new(root_cursor),
294 path: Vec::new(),
295 cursors: Vec::new(),
296 bucket_seq: false,
297 p: PhantomData,
298 }
299 }
300
301 pub fn path(&self) -> &[&'p [u8]] {
302 if self.bucket_seq {
303 self.path.split_last().unwrap().1
304 } else {
305 &self.path
306 }
307 }
308}
309
310impl<'tx: 'p, 'p> Iterator for DbWalker<'tx, 'p> {
311 type Item = (&'p [u8], ValueBucketSeq<'p>);
312
313 fn next(&mut self) -> Option<Self::Item> {
314 self.bucket_seq = false;
315 loop {
316 if self.cursors.is_empty() {
317 return if let Some((k, b)) = self.root_buckets.next() {
318 let seq = b.sequence();
319 self.bucket_seq = true;
320 self.path.push(k);
321 let i = ValueBucketIter::new(b.b.i_cursor());
322 self.cursors.push(i);
323 Some((k, ValueBucketSeq::BucketSeq(seq)))
324 } else {
325 None
326 };
327 }
328 if let Some((k, vb)) = self.cursors.last_mut().and_then(|i| i.next()) {
329 return match vb {
330 ValueBucket::Value(v) => Some((k, ValueBucketSeq::Value(v))),
331 ValueBucket::Bucket(b) => {
332 let seq = b.sequence();
333 self.bucket_seq = true;
334 self.path.push(k);
335 let i = ValueBucketIter::new(b.b.i_cursor());
336 self.cursors.push(i);
337 Some((k, ValueBucketSeq::BucketSeq(seq)))
338 }
339 };
340 } else {
341 self.path.pop();
342 self.cursors.pop();
343 }
344 }
345 }
346}
347
348#[cfg(test)]
349mod test {
350 use crate::iter::DbWalker;
351 use crate::test_support::TestDb;
352 use crate::tx::TxIApi;
353 use crate::{BucketApi, BucketRwApi, DbRwAPI, TxRwRefApi};
354
355 #[test]
356 fn test_tx_for_each_no_error() -> crate::Result<()> {
357 let mut db = TestDb::new()?;
358 db.update(|mut tx| {
359 let mut b = tx.create_bucket("widgets")?;
360 b.put("foo", "bar")?;
361
362 for (k, mut b) in tx.iter_mut_buckets() {
363 let mut wb = b.create_bucket("woojits")?;
364 wb.put("fooz", "ball")?;
365 for (k, wb) in b.iter_buckets() {
366 println!("{:?}", k);
367 for (k, v) in wb.iter_entries() {
368 println!("{:?}", k);
369 }
370 }
371 }
372 Ok(())
373 })?;
374 Ok(())
375 }
376
377 #[test]
378 fn test_tx_walk_no_error() -> crate::Result<()> {
379 let mut db = TestDb::new()?;
380 db.update(|mut tx| {
381 let mut b = tx.create_bucket("widgets")?;
382 b.put("foo1", "bar")?;
383 b.put("foo2", "bar")?;
384 let mut wb = b.create_bucket("woojits")?;
385 wb.set_sequence(1)?;
386 wb.put("fooz1", "ball")?;
387 wb.put("fooz2", "ball")?;
388 let mut hb = wb.create_bucket("hoojits")?;
389 hb.set_sequence(2)?;
390 hb.put("fooz1", "bill")?;
391 hb.put("fooz2", "bill")?;
392 let mut wb = b.create_bucket("wajits")?;
393 wb.set_sequence(3)?;
394 wb.put("fooz1", "balls")?;
395 wb.put("fooz2", "balls")?;
396 let mut pb = tx.create_bucket_path(&["one", "two", "three", "four"])?;
397 pb.set_sequence(4)?;
398 pb.put("five", "six")?;
399 Ok(())
400 })?;
401 let tx = db.begin_tx()?;
402 let mut w = DbWalker::new(tx.tx.api_cursor());
403 while let Some(i) = w.next() {
404 let path = w.path();
405 println!("{:?}: {:?}", path, i);
406 }
407 drop(w);
408 let c = DbWalker::new(tx.tx.api_cursor()).count();
409 println!("{:?}", c);
410 Ok(())
411 }
412}