diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..062f970 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,47 @@ +name: Tests + +on: + pull_request: + push: + branches: + - "master" + +jobs: + format: + name: Format code + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - run: cargo fmt -- --check + + clippy: + name: Clippy check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + - run: cargo clippy --all-targets --all-features -- --deny warnings + + test: + name: Test code + runs-on: ubuntu-latest + strategy: + matrix: + rust_version: [stable, beta, nightly] + fail-fast: false + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{matrix.rust_version}} + - uses: Swatinem/rust-cache@v2 + with: + key: ${{matrix.rust_version}} + - run: cargo update + - run: cargo test --all-features diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8c91a74..0000000 --- a/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: rust -rust: - - stable - - beta - - nightly -matrix: - allow_failures: - - rust: nightly diff --git a/src/iter.rs b/src/iter.rs index 446ba4d..7a0e554 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -1,12 +1,12 @@ -use std::{slice, vec}; use std::ops::Range; +use std::{slice, vec}; -use {Tree, NodeId, Node, NodeRef}; +use {Node, NodeId, NodeRef, Tree}; /// Iterator that moves out of a tree in insert order. #[derive(Debug)] pub struct IntoIter(vec::IntoIter>); -impl ExactSizeIterator for IntoIter { } +impl ExactSizeIterator for IntoIter {} impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { @@ -30,7 +30,7 @@ impl<'a, T: 'a> Clone for Values<'a, T> { Values(self.0.clone()) } } -impl<'a, T: 'a> ExactSizeIterator for Values<'a, T> { } +impl<'a, T: 'a> ExactSizeIterator for Values<'a, T> {} impl<'a, T: 'a> Iterator for Values<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { @@ -49,7 +49,7 @@ impl<'a, T: 'a> DoubleEndedIterator for Values<'a, T> { /// Mutable iterator over values in insert order. #[derive(Debug)] pub struct ValuesMut<'a, T: 'a>(slice::IterMut<'a, Node>); -impl<'a, T: 'a> ExactSizeIterator for ValuesMut<'a, T> { } +impl<'a, T: 'a> ExactSizeIterator for ValuesMut<'a, T> {} impl<'a, T: 'a> Iterator for ValuesMut<'a, T> { type Item = &'a mut T; fn next(&mut self) -> Option { @@ -73,14 +73,19 @@ pub struct Nodes<'a, T: 'a> { } impl<'a, T: 'a> Clone for Nodes<'a, T> { fn clone(&self) -> Self { - Self { tree: self.tree, iter: self.iter.clone() } + Self { + tree: self.tree, + iter: self.iter.clone(), + } } } -impl<'a, T: 'a> ExactSizeIterator for Nodes<'a, T> { } +impl<'a, T: 'a> ExactSizeIterator for Nodes<'a, T> {} impl<'a, T: 'a> Iterator for Nodes<'a, T> { type Item = NodeRef<'a, T>; fn next(&mut self) -> Option { - self.iter.next().map(|i| unsafe { self.tree.get_unchecked(NodeId::from_index(i)) }) + self.iter + .next() + .map(|i| unsafe { self.tree.get_unchecked(NodeId::from_index(i)) }) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() @@ -88,7 +93,9 @@ impl<'a, T: 'a> Iterator for Nodes<'a, T> { } impl<'a, T: 'a> DoubleEndedIterator for Nodes<'a, T> { fn next_back(&mut self) -> Option { - self.iter.next_back().map(|i| unsafe { self.tree.get_unchecked(NodeId::from_index(i)) }) + self.iter + .next_back() + .map(|i| unsafe { self.tree.get_unchecked(NodeId::from_index(i)) }) } } @@ -113,7 +120,10 @@ impl Tree { /// Returns an iterator over nodes in insert order. pub fn nodes(&self) -> Nodes { - Nodes { tree: self, iter: 0..self.vec.len() } + Nodes { + tree: self, + iter: 0..self.vec.len(), + } } } @@ -165,7 +175,10 @@ pub struct Children<'a, T: 'a> { } impl<'a, T: 'a> Clone for Children<'a, T> { fn clone(&self) -> Self { - Self { front: self.front.clone(), back: self.back.clone() } + Self { + front: self.front, + back: self.back, + } } } impl<'a, T: 'a> Iterator for Children<'a, T> { @@ -204,17 +217,17 @@ pub enum Edge<'a, T: 'a> { /// Close. Close(NodeRef<'a, T>), } -impl<'a, T: 'a> Copy for Edge<'a, T> { } +impl<'a, T: 'a> Copy for Edge<'a, T> {} impl<'a, T: 'a> Clone for Edge<'a, T> { - fn clone(&self) -> Self { *self } + fn clone(&self) -> Self { + *self + } } -impl<'a, T: 'a> Eq for Edge<'a, T> { } +impl<'a, T: 'a> Eq for Edge<'a, T> {} impl<'a, T: 'a> PartialEq for Edge<'a, T> { fn eq(&self, other: &Self) -> bool { match (*self, *other) { - (Edge::Open(a), Edge::Open(b)) | (Edge::Close(a), Edge::Close(b)) => { - a == b - }, + (Edge::Open(a), Edge::Open(b)) | (Edge::Close(a), Edge::Close(b)) => a == b, _ => false, } } @@ -228,7 +241,10 @@ pub struct Traverse<'a, T: 'a> { } impl<'a, T: 'a> Clone for Traverse<'a, T> { fn clone(&self) -> Self { - Self { root: self.root, edge: self.edge } + Self { + root: self.root, + edge: self.edge, + } } } impl<'a, T: 'a> Iterator for Traverse<'a, T> { @@ -237,23 +253,23 @@ impl<'a, T: 'a> Iterator for Traverse<'a, T> { match self.edge { None => { self.edge = Some(Edge::Open(self.root)); - }, + } Some(Edge::Open(node)) => { if let Some(first_child) = node.first_child() { self.edge = Some(Edge::Open(first_child)); } else { self.edge = Some(Edge::Close(node)); } - }, + } Some(Edge::Close(node)) => { if node == self.root { - self.edge = None; + self.edge = None; } else if let Some(next_sibling) = node.next_sibling() { self.edge = Some(Edge::Open(next_sibling)); } else { self.edge = node.parent().map(Edge::Close); } - }, + } } self.edge } diff --git a/src/lib.rs b/src/lib.rs index 1a6585c..c2e7781 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,7 @@ #![warn( missing_docs, missing_debug_implementations, - missing_copy_implementations, + missing_copy_implementations )] use std::fmt::{self, Debug, Formatter}; @@ -117,24 +117,28 @@ pub struct NodeMut<'a, T: 'a> { // Trait implementations regardless of T. -impl<'a, T: 'a> Copy for NodeRef<'a, T> { } +impl<'a, T: 'a> Copy for NodeRef<'a, T> {} impl<'a, T: 'a> Clone for NodeRef<'a, T> { - fn clone(&self) -> Self { *self } + fn clone(&self) -> Self { + *self + } } -impl<'a, T: 'a> Eq for NodeRef<'a, T> { } +impl<'a, T: 'a> Eq for NodeRef<'a, T> {} impl<'a, T: 'a> PartialEq for NodeRef<'a, T> { fn eq(&self, other: &Self) -> bool { self.id == other.id - && self.tree as *const _ == other.tree as *const _ - && self.node as *const _ == other.node as *const _ + && std::ptr::eq(self.tree, other.tree) + && std::ptr::eq(self.node, other.node) } } impl Tree { /// Creates a tree with a root node. pub fn new(root: T) -> Self { - Tree { vec: vec![Node::new(root)] } + Tree { + vec: vec![Node::new(root)], + } } /// Creates a tree with a root node and the specified capacity. @@ -146,7 +150,11 @@ impl Tree { /// Returns a reference to the specified node. pub fn get(&self, id: NodeId) -> Option> { - self.vec.get(id.to_index()).map(|node| NodeRef { id, node, tree: self }) + self.vec.get(id.to_index()).map(|node| NodeRef { + id, + node, + tree: self, + }) } /// Returns a mutator of the specified node. @@ -164,11 +172,19 @@ impl Tree { } /// Returns a reference to the specified node. + /// # Safety + /// The caller must ensure that `id` is a valid node ID. pub unsafe fn get_unchecked(&self, id: NodeId) -> NodeRef { - NodeRef { id, node: self.node(id), tree: self } + NodeRef { + id, + node: self.node(id), + tree: self, + } } /// Returns a mutator of the specified node. + /// # Safety + /// The caller must ensure that `id` is a valid node ID. pub unsafe fn get_unchecked_mut(&mut self, id: NodeId) -> NodeMut { NodeMut { id, tree: self } } @@ -209,27 +225,37 @@ impl<'a, T: 'a> NodeRef<'a, T> { /// Returns the parent of this node. pub fn parent(&self) -> Option { - self.node.parent.map(|id| unsafe { self.tree.get_unchecked(id) }) + self.node + .parent + .map(|id| unsafe { self.tree.get_unchecked(id) }) } /// Returns the previous sibling of this node. pub fn prev_sibling(&self) -> Option { - self.node.prev_sibling.map(|id| unsafe { self.tree.get_unchecked(id) }) + self.node + .prev_sibling + .map(|id| unsafe { self.tree.get_unchecked(id) }) } /// Returns the next sibling of this node. pub fn next_sibling(&self) -> Option { - self.node.next_sibling.map(|id| unsafe { self.tree.get_unchecked(id) }) + self.node + .next_sibling + .map(|id| unsafe { self.tree.get_unchecked(id) }) } /// Returns the first child of this node. pub fn first_child(&self) -> Option { - self.node.children.map(|(id, _)| unsafe { self.tree.get_unchecked(id) }) + self.node + .children + .map(|(id, _)| unsafe { self.tree.get_unchecked(id) }) } /// Returns the last child of this node. pub fn last_child(&self) -> Option { - self.node.children.map(|(_, id)| unsafe { self.tree.get_unchecked(id) }) + self.node + .children + .map(|(_, id)| unsafe { self.tree.get_unchecked(id) }) } /// Returns true if this node has siblings. @@ -351,10 +377,14 @@ impl<'a, T: 'a> NodeMut<'a, T> { } if let Some(id) = prev_sibling_id { - unsafe { self.tree.node_mut(id).next_sibling = next_sibling_id; } + unsafe { + self.tree.node_mut(id).next_sibling = next_sibling_id; + } } if let Some(id) = next_sibling_id { - unsafe { self.tree.node_mut(id).prev_sibling = prev_sibling_id; } + unsafe { + self.tree.node_mut(id).prev_sibling = prev_sibling_id; + } } let parent = unsafe { self.tree.node_mut(parent_id) }; @@ -383,7 +413,9 @@ impl<'a, T: 'a> NodeMut<'a, T> { } if let Some(id) = last_child_id { - unsafe { self.tree.node_mut(id).next_sibling = Some(new_child_id); } + unsafe { + self.tree.node_mut(id).next_sibling = Some(new_child_id); + } } { @@ -412,7 +444,9 @@ impl<'a, T: 'a> NodeMut<'a, T> { } if let Some(id) = first_child_id { - unsafe { self.tree.node_mut(id).prev_sibling = Some(new_child_id); } + unsafe { + self.tree.node_mut(id).prev_sibling = Some(new_child_id); + } } { @@ -444,7 +478,9 @@ impl<'a, T: 'a> NodeMut<'a, T> { } if let Some(id) = prev_sibling_id { - unsafe { self.tree.node_mut(id).next_sibling = Some(new_sibling_id); } + unsafe { + self.tree.node_mut(id).next_sibling = Some(new_sibling_id); + } } self.node().prev_sibling = Some(new_sibling_id); @@ -478,7 +514,9 @@ impl<'a, T: 'a> NodeMut<'a, T> { } if let Some(id) = next_sibling_id { - unsafe { self.tree.node_mut(id).prev_sibling = Some(new_sibling_id); } + unsafe { + self.tree.node_mut(id).prev_sibling = Some(new_sibling_id); + } } self.node().next_sibling = Some(new_sibling_id); @@ -655,21 +693,21 @@ impl Debug for Tree { match edge { Edge::Open(node) if node.has_children() => { write!(f, " {:?} => {{", node.value())?; - }, + } Edge::Open(node) if node.next_sibling().is_some() => { write!(f, " {:?},", node.value())?; - }, + } Edge::Open(node) => { write!(f, " {:?}", node.value())?; - }, + } Edge::Close(node) if node.has_children() => { if node.next_sibling().is_some() { write!(f, " }},")?; } else { write!(f, " }}")?; } - }, - _ => {}, + } + _ => {} } } write!(f, " }}") diff --git a/tests/iter.rs b/tests/iter.rs index f2d320a..302ecf2 100644 --- a/tests/iter.rs +++ b/tests/iter.rs @@ -47,10 +47,14 @@ fn nodes() { #[test] fn ancestors() { let tree = tree!('a' => { 'b' => { 'c' => { 'd' } } }); - let d = tree.root() - .last_child().unwrap() - .last_child().unwrap() - .last_child().unwrap(); + let d = tree + .root() + .last_child() + .unwrap() + .last_child() + .unwrap() + .last_child() + .unwrap(); assert_eq!( vec![&'c', &'b', &'a'], d.ancestors().map(|n| n.value()).collect::>() @@ -90,7 +94,10 @@ fn children() { let tree = tree!('a' => { 'b', 'c', 'd' }); assert_eq!( vec![&'b', &'c', &'d'], - tree.root().children().map(|n| n.value()).collect::>() + tree.root() + .children() + .map(|n| n.value()) + .collect::>() ); } @@ -99,7 +106,11 @@ fn children_rev() { let tree = tree!('a' => { 'b', 'c', 'd' }); assert_eq!( vec![&'d', &'c', &'b'], - tree.root().children().rev().map(|n| n.value()).collect::>() + tree.root() + .children() + .rev() + .map(|n| n.value()) + .collect::>() ); } @@ -108,7 +119,10 @@ fn first_children() { let tree = tree!('a' => { 'b' => { 'd', 'e' }, 'c' }); assert_eq!( vec![&'b', &'d'], - tree.root().first_children().map(|n| n.value()).collect::>() + tree.root() + .first_children() + .map(|n| n.value()) + .collect::>() ); } @@ -117,7 +131,10 @@ fn last_children() { let tree = tree!('a' => { 'b', 'c' => { 'd', 'e' } }); assert_eq!( vec![&'c', &'e'], - tree.root().last_children().map(|n| n.value()).collect::>() + tree.root() + .last_children() + .map(|n| n.value()) + .collect::>() ); } @@ -133,12 +150,14 @@ fn traverse() { let tree = tree!('a' => { 'b' => { 'd', 'e' }, 'c' }); - let traversal = tree.root().traverse().map(|edge| { - match edge { + let traversal = tree + .root() + .traverse() + .map(|edge| match edge { Edge::Open(node) => Value::Open(node.value()), Edge::Close(node) => Value::Close(node.value()), - } - }).collect::>(); + }) + .collect::>(); assert_eq!( &[ @@ -161,16 +180,11 @@ fn traverse() { fn descendants() { let tree = tree!('a' => { 'b' => { 'd', 'e' }, 'c' }); - let descendants = tree.root().descendants().map(|n| n.value()).collect::>(); + let descendants = tree + .root() + .descendants() + .map(|n| n.value()) + .collect::>(); - assert_eq!( - &[ - &'a', - &'b', - &'d', - &'e', - &'c', - ], - &descendants[..] - ); + assert_eq!(&[&'a', &'b', &'d', &'e', &'c',], &descendants[..]); } diff --git a/tests/node_mut.rs b/tests/node_mut.rs index 091b579..d9b00af 100644 --- a/tests/node_mut.rs +++ b/tests/node_mut.rs @@ -66,15 +66,15 @@ fn last_child() { #[test] fn has_siblings() { let mut tree = tree!('a' => { 'b', 'c' }); - assert_eq!(true, tree.root_mut().first_child().unwrap().has_siblings()); - assert_eq!(false, tree.root_mut().has_siblings()); + assert!(tree.root_mut().first_child().unwrap().has_siblings()); + assert!(!tree.root_mut().has_siblings()); } #[test] fn has_children() { let mut tree = tree!('a' => { 'b', 'c' }); - assert_eq!(true, tree.root_mut().has_children()); - assert_eq!(false, tree.root_mut().first_child().unwrap().has_children()); + assert!(tree.root_mut().has_children()); + assert!(!tree.root_mut().first_child().unwrap().has_children()); } #[test] @@ -299,7 +299,10 @@ fn reparent_from_id_append() { } }; let e_id = tree.root().last_child().unwrap().id(); - tree.root_mut().first_child().unwrap().reparent_from_id_append(e_id); + tree.root_mut() + .first_child() + .unwrap() + .reparent_from_id_append(e_id); let b = tree.root().first_child().unwrap(); let e = tree.root().last_child().unwrap(); @@ -307,7 +310,7 @@ fn reparent_from_id_append() { let g = b.last_child().unwrap(); let f = g.prev_sibling().unwrap(); - assert_eq!(false, e.has_children()); + assert!(!e.has_children()); assert_eq!(&'f', f.value()); assert_eq!(&'g', g.value()); assert_eq!(Some(f), d.next_sibling()); @@ -323,7 +326,10 @@ fn reparent_from_id_prepend() { } }; let e_id = tree.root().last_child().unwrap().id(); - tree.root_mut().first_child().unwrap().reparent_from_id_prepend(e_id); + tree.root_mut() + .first_child() + .unwrap() + .reparent_from_id_prepend(e_id); let b = tree.root().first_child().unwrap(); let e = tree.root().last_child().unwrap(); @@ -331,7 +337,7 @@ fn reparent_from_id_prepend() { let d = c.next_sibling().unwrap(); let f = b.last_child().unwrap().prev_sibling().unwrap(); - assert_eq!(false, e.has_children()); + assert!(!e.has_children()); assert_eq!(&'c', c.value()); assert_eq!(&'d', d.value()); assert_eq!(Some(f), d.next_sibling()); diff --git a/tests/node_ref.rs b/tests/node_ref.rs index ad05b7a..c46cb65 100644 --- a/tests/node_ref.rs +++ b/tests/node_ref.rs @@ -43,22 +43,22 @@ fn last_child() { #[test] fn has_siblings() { let tree = tree!('a' => { 'b', 'c' }); - assert_eq!(false, tree.root().has_siblings()); - assert_eq!(true, tree.root().first_child().unwrap().has_siblings()); + assert!(!tree.root().has_siblings()); + assert!(tree.root().first_child().unwrap().has_siblings()); } #[test] fn has_children() { let tree = tree!('a' => { 'b', 'c' }); - assert_eq!(true, tree.root().has_children()); - assert_eq!(false, tree.root().first_child().unwrap().has_children()); + assert!(tree.root().has_children()); + assert!(!tree.root().first_child().unwrap().has_children()); } #[test] fn clone() { let tree = tree!('a'); let one = tree.root(); - let two = one.clone(); + let two = one; assert_eq!(one, two); }