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

Reply via email to