Here is the heart of the code, maybe it will be clearer why I had to use
unsafe (or, maybe, how I could avoid it):
/// A path is just an array of atoms.
#[deriving(Eq, TotalEq, Ord, TotalOrd, Clone, IterBytes)]
pub struct Path {
/// The array of atoms the path consists of.
pub atoms: ~[Atom],
}
/// An entry contained in the tree map.
#[deriving(Eq, TotalEq, Ord, TotalOrd)]
pub struct TreeMapEntry<T> {
/// The full path of the entry.
path: Path,
/// The value of the entry.
value: T,
}
/// A tree map holds values of some arbitrary type, indexed by a path.
pub struct TreeMap<T> {
/// The entry of this node, if any.
priv entry: Option<TreeMapEntry<T>>,
/// The sub-trees under this node, if any.
priv sub_trees: HashMap<Atom, ~TreeMap<T>>
}
/// Iterate and mutate on a single level of the tree map.
struct LevelMutIterator<'self, T> {
/// The root node to return the value of (as the 1st result).
root: Option<&'self mut TreeMapEntry<T>>,
/// The iterator at the current level of the tree.
iterator: HashMapMutIterator<'self, Atom, ~TreeMap<T>>,
}
/// Iterate and mutate on a tree map in an arbitrary order.
pub struct TreeMapMutIterator<'self, T> {
/// The iterators of all levels we have reached so far.
priv levels: ~[LevelMutIterator<'self, T>]
}
/// Iterate and mutate on a tree map in an arbitrary order.
impl<'self, T> Iterator<(&'self Path, &'self mut T)> for
TreeMapMutIterator<'self, T> {
/// Move to the next value contained in the tree map.
fn next(&mut self) -> Option<(&'self Path, &'self mut T)> {
if self.levels.len() == 0 {
None
} else {
unsafe {
let last: *mut LevelMutIterator<'self, T> = &mut
self.levels[self.levels.len() - 1];
match (*last).root {
Some(ref mut entry) => {
let path = &entry.path;
let value = &mut entry.value;
// TRICKY: This makes the entry inaccessible, which
is
// why we took the returned path and value above.
(*last).root = None;
Some((path, value))
}
None => {
match self.levels[self.levels.len() -
1].iterator.next() {
Some((_atom, treemap)) => {
self.levels.push(treemap.level_mut_iter());
}
None => {
self.levels.pop();
}
}
self.next()
}
}
}
}
}
}
I tried for around a day to make this work without the unsafe, to no avail.
The trick is I want to take the value out of the option (leaving None
behind), and return the value. I'm probably missing some solution which may
be obvious to a non-newbie to Rust...?
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev