Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add api get index of child and to insert child at given index. #15

Closed
wants to merge 8 commits into from
45 changes: 45 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,15 @@ impl<'a, T: 'a> NodeRef<'a, T> {
.map(|(_, id)| unsafe { self.tree.get_unchecked(id) })
}

/// Returns the index of the given child or None if child doesn't exist.
/// This function may take up to linear time in worst case scenarios.
pub fn index_of_child(&self, child: &NodeRef<T>) -> Option<usize> {
self.children()
.enumerate()
.find(|(_, each)| each == child)
.map(|(i, _)| i)
}

/// Returns true if this node has siblings.
pub fn has_siblings(&self) -> bool {
self.node.prev_sibling.is_some() || self.node.next_sibling.is_some()
Expand Down Expand Up @@ -365,6 +374,17 @@ impl<'a, T: 'a> NodeMut<'a, T> {
self.prepend_id(id)
}

/// Insert a new child into this node at given index.
/// This function may take up to linear time in worst case scenarios.
///
/// # Panics
///
/// Panics if `index` is not valid.
pub fn insert(&mut self, value: T, index: usize) -> NodeMut<T> {
let id = self.tree.orphan(value).id;
self.insert_id(id, index)
}

/// Appends a subtree, return the root of the merged subtree.
pub fn append_subtree(&mut self, subtree: Tree<T>) -> NodeMut<T> {
let root_id = self.tree.extend_tree(subtree).id;
Expand Down Expand Up @@ -465,6 +485,31 @@ impl<'a, T: 'a> NodeMut<'a, T> {
unsafe { self.tree.get_unchecked_mut(new_child_id) }
}

/// Insert a child into this node at given index.
/// This function may take up to linear time in worst case scenarios.
///
/// # Panics
///
/// Panics if `new_child_id` or `index` are not valid.
pub fn insert_id(&mut self, new_child_id: NodeId, index: usize) -> NodeMut<T> {
if index == 0 {
return self.prepend_id(new_child_id);
}

let mut pre_sibling: NodeMut<T> = unsafe {
self.tree
.get_unchecked(self.id)
.children()
.nth(index - 1) // worst case O(n)
.map(|node| node.id)
.map(|id| self.tree.get_unchecked_mut(id))
.unwrap_or_else(|| panic!("No child found at index {}", index - 1))
};

pre_sibling.insert_id_after(new_child_id);
unsafe { self.tree.get_unchecked_mut(new_child_id) }
}

/// Prepends a child to this node.
///
/// # Panics
Expand Down
41 changes: 41 additions & 0 deletions tests/node_mut.rs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,47 @@ fn prepend_3() {
assert_eq!(None, d.next_sibling());
}

#[test]
fn insert() {
let mut tree = tree!('a');
tree.root_mut().insert('c', 0);
tree.root_mut().insert('b', 0);
tree.root_mut().insert('d', 2);

let root = tree.root();
let b = root.first_child().unwrap();
let c = b.next_sibling().unwrap();
let d = root.last_child().unwrap();

assert_eq!(&'b', b.value());
assert_eq!(&'c', c.value());
assert_eq!(&'d', d.value());
assert_eq!(Some(root), b.parent());
assert_eq!(Some(root), c.parent());
assert_eq!(Some(root), d.parent());
assert_eq!(None, b.prev_sibling());
assert_eq!(Some(c), b.next_sibling());
assert_eq!(Some(b), c.prev_sibling());
assert_eq!(Some(d), c.next_sibling());
assert_eq!(Some(c), d.prev_sibling());
assert_eq!(None, d.next_sibling());
}

#[test]
#[should_panic]
fn insert_should_panic_1() {
let mut tree = tree!('a');
tree.root_mut().insert('b', 1);
}

#[test]
#[should_panic]
fn insert_should_panic_2() {
let mut tree = tree!('a');
tree.root_mut().insert('b', 0);
tree.root_mut().insert('c', 2);
}

#[test]
fn insert_before_first() {
let mut tree = tree!('a' => { 'c' });
Expand Down
12 changes: 12 additions & 0 deletions tests/node_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ fn last_child() {
assert_eq!(&'c', tree.root().last_child().unwrap().value());
}

#[test]
fn index_of_child() {
let tree = tree!('a' => { 'b', 'c' });
let root = tree.root();
let b = root.first_child().unwrap();
let c = root.last_child().unwrap();

assert_eq!(0, root.index_of_child(&b).unwrap());
assert_eq!(1, root.index_of_child(&c).unwrap());
assert!(root.index_of_child(&root).is_none());
}

#[test]
fn has_siblings() {
let tree = tree!('a' => { 'b', 'c' });
Expand Down
Loading