Skip to content

Commit

Permalink
Clean up iteration
Browse files Browse the repository at this point in the history
  • Loading branch information
JayKickliter committed Nov 2, 2023
1 parent 2184795 commit 2960403
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 63 deletions.
66 changes: 23 additions & 43 deletions src/disktree/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use crate::{
use byteorder::ReadBytesExt;
use std::io::{Read, Seek, SeekFrom};

pub trait Reader<R> {
pub trait Deserializer<R> {
/// This can be the serialized type or a result, depending on
/// fallability.
type T;
fn read(&self, rdr: Result<(Cell, &mut R)>) -> Self::T;
}

impl<R, T, F> Reader<R> for F
impl<R, T, F> Deserializer<R> for F
where
R: Read,
F: Fn(Result<(Cell, &mut R)>) -> T,
Expand Down Expand Up @@ -69,11 +69,11 @@ where
let node_tag = self.rdr.read_u8()?;
let base_pos = self.rdr.stream_position()?;
assert!(node_tag == 0 || node_tag > 0b1000_0000);
if node_tag == 0 {
Ok(Node::Leaf(base_pos))
let node = if node_tag == 0 {
Node::Leaf(base_pos)
} else {
let mut buf = self.node_buf();
for digit in (0..8).rev() {
for digit in (0..7).rev() {
if node_tag & (1 << digit) != 0 {
let bit_cnt = (((node_tag as u16) << (8 - digit)) & 0xFF).count_ones();
let child_dptr_pos = base_pos + (bit_cnt as u64 * dptr::DPTR_SZ as u64);
Expand All @@ -82,8 +82,9 @@ where
buf.push((digit, child_dptr));
}
}
Ok(Node::Parent(buf))
}
Node::Parent(buf)
};
Ok(node)
}

fn node_buf(&mut self) -> Vec<(u8, u64)> {
Expand All @@ -97,6 +98,14 @@ where
self.recycle_bin.push(buf);
}

// We've encountered an IO error. We're still going to return
// `Some` with the contents of the user's deserializer, but let's
// make sure we never yeild another value by clearing stack.
fn stop_yeilding(&mut self) {
self.stack.clear();
self.curr = None;
}

pub(crate) fn new(rdr: &'a mut R, f: F) -> Result<Iter<'a, R, F>> {
let mut cell_stack = CellStack::new();
let mut stack = Vec::new();
Expand All @@ -121,34 +130,32 @@ where
impl<'a, R, F> Iterator for Iter<'a, R, F>
where
R: Read + Seek,
F: Reader<R>,
F: Deserializer<R>,
{
type Item = <F as Reader<R>>::T;
type Item = <F as Deserializer<R>>::T;

fn next(&mut self) -> Option<Self::Item> {
while self.curr.is_none() {
println!("a");
if let Some(mut dptrs) = self.stack.pop() {
println!("b");
self.cell_stack.pop();
if let Some((digit, dptr)) = dptrs.pop() {
println!("c");
self.cell_stack.push(digit);
self.curr = Some((digit, dptr));
self.stack.push(dptrs);
} else {
println!("d");
self.recycle_buf(dptrs);
}
} else {
println!("e");
break;
}
}
while let Some((digit, dptr)) = self.curr {
self.cell_stack.swap(digit);
println!("f: {}", self.cell_stack.cell().unwrap().res());
match self.read_node(dptr) {
Err(e) => {
self.stop_yeilding();
return Some(self.f.read(Err(e)));
}
Ok(Node::Parent(mut children)) => {
if let Some((digit, dptr)) = children.pop() {
self.cell_stack.push(digit);
Expand All @@ -161,43 +168,16 @@ where
Ok(Node::Leaf(dptr)) => {
self.curr = None;
if let Err(e) = self.seek_to(dptr) {
self.stack.clear();
self.curr = None;
self.stop_yeilding();
return Some(self.f.read(Err(e)));
}
return Some(self.f.read(Ok((
*self.cell_stack.cell().expect("corrupted cell-stack"),
self.rdr,
))));
}
Err(e) => return Some(self.f.read(Err(e))),
};
}
None
// while let Some((digit, curr)) = self.curr {
// self.cell_stack.swap(digit as u8);
// match curr {
// Node::Parent(children) => {
// let mut iter = make_node_stack_iter(children.as_ref());
// self.curr = iter.next();
// // This branch is not 100% necessary, but I prefer
// // pushing an actual digit instead of 0 and
// // relying on the swap the further up to replace
// // it with the correct value.
// if let Some((digit, _)) = self.curr {
// self.cell_stack.push(digit as u8)
// }
// self.stack.push(iter);
// }
// Node::Leaf(value) => {
// self.curr = None;
// return Some((
// *self.cell_stack.cell().expect("corrupted cell-stack"),
// value,
// ));
// }
// }
// }
// None
}
}
30 changes: 13 additions & 17 deletions src/disktree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,17 @@ mod tests {
.unwrap();
let mut monaco_disktree = DiskTree::from_reader(file).unwrap();

for (tree_cell, tree_val) in monaco.iter() {
let (disk_cell, rdr) = monaco_disktree.seek_to_cell(tree_cell).unwrap().unwrap();
assert_eq!(tree_cell, disk_cell);
let disk_val: Cell = bincode::deserialize_from(rdr).unwrap();
assert_eq!(*tree_val, disk_val);
}

// Error type for user-defined deserializer.
#[derive(Debug)]
enum RdrErr {
Bincode(bincode::Error),
Disktree(crate::error::Error),
}

// User-defined deserializer.
fn deserialzer(
res: crate::error::Result<(Cell, &mut impl std::io::Read)>,
// Our function for deserializing `Cell` values from the
// disktree.
fn deserialze_cell<R: std::io::Read>(
res: crate::error::Result<(Cell, &mut R)>,
) -> Result<(Cell, Cell), RdrErr> {
match res {
Ok((cell, rdr)) => match bincode::deserialize_from(rdr) {
Expand All @@ -117,12 +111,14 @@ mod tests {
}

// Create the iterator with the user-defined deserialzer.
let iter = monaco_disktree.iter(deserialzer).unwrap();

for item_res in iter {
let (cell, value) = item_res.unwrap();
println!("{cell:?} → {value:?}");
assert_eq!(cell, value);
}
let disktree_iter = monaco_disktree.iter(deserialze_cell).unwrap();
let disktree_collection: Vec<_> = disktree_iter.collect::<Result<Vec<_>, _>>().unwrap();
let hextree_collection: Vec<_> = monaco.iter().map(|(k, v)| (k, *v)).collect();

assert_eq!(
hextree_collection,
disktree_collection,
"iterating a disktree should yeild identically ordered elements as the hextree tree it was derived from"
);
}
}
9 changes: 6 additions & 3 deletions src/disktree/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
digits::Digits,
disktree::{
dptr::{self, DPTR_NULL, DPTR_SZ},
iter::{Iter, Reader},
iter::{Deserializer, Iter},
},
error::{Error, Result},
Cell,
Expand Down Expand Up @@ -83,9 +83,12 @@ impl<R: Read + Seek> DiskTree<R> {
///
/// However, insteading of returning the concrete value, the
/// iterator retuns a reader pre-seeked to the node's value.
pub fn iter<'a, F>(&'a mut self, f: F) -> Result<impl Iterator<Item = <F as Reader<R>>::T> + 'a>
pub fn iter<'a, F>(
&'a mut self,
f: F,
) -> Result<impl Iterator<Item = <F as Deserializer<R>>::T> + 'a>
where
F: Reader<R> + 'a,
F: Deserializer<R> + 'a,
{
Iter::new(&mut self.0, f)
}
Expand Down

0 comments on commit 2960403

Please sign in to comment.