Skip to content

Commit

Permalink
Merge pull request #37 from rust-scraper/prevent-self-id-in-bare-modi…
Browse files Browse the repository at this point in the history
…fiers

Prevent usage of self ID in modifiers working on bare ID
  • Loading branch information
cfvescovo authored Nov 30, 2024
2 parents 78c6bd8 + 4e030f7 commit 8127d31
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 10 deletions.
54 changes: 44 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
///
/// Panics if `new_child_id` is not valid.
pub fn append_id(&mut self, new_child_id: NodeId) -> NodeMut<T> {
assert_ne!(
self.id(),
new_child_id,
"Cannot append node as a child to itself"
);

let last_child_id = self.node().children.map(|(_, id)| id);
{
let mut new_child = self.tree.get_mut(new_child_id).unwrap();
Expand All @@ -565,11 +571,10 @@ impl<'a, T: 'a> NodeMut<'a, T> {
}

{
if let Some((first_child_id, _)) = self.node().children {
self.node().children = Some((first_child_id, new_child_id));
} else {
self.node().children = Some((new_child_id, new_child_id));
}
self.node().children = match self.node().children {
Some((first_child_id, _)) => Some((first_child_id, new_child_id)),
None => Some((new_child_id, new_child_id)),
};
}

unsafe { self.tree.get_unchecked_mut(new_child_id) }
Expand All @@ -581,6 +586,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
///
/// Panics if `new_child_id` is not valid.
pub fn prepend_id(&mut self, new_child_id: NodeId) -> NodeMut<T> {
assert_ne!(
self.id(),
new_child_id,
"Cannot prepend node as a child to itself"
);

let first_child_id = self.node().children.map(|(id, _)| id);
{
let mut new_child = self.tree.get_mut(new_child_id).unwrap();
Expand All @@ -596,11 +607,10 @@ impl<'a, T: 'a> NodeMut<'a, T> {
}

{
if let Some((_, last_child_id)) = self.node().children {
self.node().children = Some((new_child_id, last_child_id));
} else {
self.node().children = Some((new_child_id, new_child_id));
}
self.node().children = match self.node().children {
Some((_, last_child_id)) => Some((new_child_id, last_child_id)),
None => Some((new_child_id, new_child_id)),
};
}

unsafe { self.tree.get_unchecked_mut(new_child_id) }
Expand All @@ -613,6 +623,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
/// - Panics if `new_sibling_id` is not valid.
/// - Panics if this node is an orphan.
pub fn insert_id_before(&mut self, new_sibling_id: NodeId) -> NodeMut<T> {
assert_ne!(
self.id(),
new_sibling_id,
"Cannot insert node as a sibling of itself"
);

let parent_id = self.node().parent.unwrap();
let prev_sibling_id = self.node().prev_sibling;

Expand Down Expand Up @@ -650,6 +666,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
/// - Panics if `new_sibling_id` is not valid.
/// - Panics if this node is an orphan.
pub fn insert_id_after(&mut self, new_sibling_id: NodeId) -> NodeMut<T> {
assert_ne!(
self.id(),
new_sibling_id,
"Cannot insert node as a sibling of itself"
);

let parent_id = self.node().parent.unwrap();
let next_sibling_id = self.node().next_sibling;

Expand Down Expand Up @@ -686,6 +708,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
///
/// Panics if `from_id` is not valid.
pub fn reparent_from_id_append(&mut self, from_id: NodeId) {
assert_ne!(
self.id(),
from_id,
"Cannot reparent node's children to itself"
);

let new_child_ids = {
let mut from = self.tree.get_mut(from_id).unwrap();
match from.node().children.take() {
Expand Down Expand Up @@ -719,6 +747,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
///
/// Panics if `from_id` is not valid.
pub fn reparent_from_id_prepend(&mut self, from_id: NodeId) {
assert_ne!(
self.id(),
from_id,
"Cannot reparent node's children to itself"
);

let new_child_ids = {
let mut from = self.tree.get_mut(from_id).unwrap();
match from.node().children.take() {
Expand Down
28 changes: 28 additions & 0 deletions tests/node_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,34 @@ fn detach() {
assert!(c.next_sibling().is_none());
}

#[test]
#[should_panic(expected = "Cannot append node as a child to itself")]
fn append_id_itself() {
let mut tree = tree! {
'a' => {
'b' => { 'c', 'd' },
'e' => { 'f', 'g' },
}
};
let mut a = tree.root_mut();
let mut e = a.last_child().unwrap();
e.append_id(e.id());
}

#[test]
#[should_panic(expected = "Cannot prepend node as a child to itself")]
fn prepend_id_itself() {
let mut tree = tree! {
'a' => {
'b' => { 'c', 'd' },
'e' => { 'f', 'g' },
}
};
let mut a = tree.root_mut();
let mut e = a.last_child().unwrap();
e.prepend_id(e.id());
}

#[test]
fn reparent_from_id_append() {
let mut tree = tree! {
Expand Down

0 comments on commit 8127d31

Please sign in to comment.