Skip to content

Commit

Permalink
Bump version to 0.2.0 in Cargo.toml. Not a release.
Browse files Browse the repository at this point in the history
1. [feature] `Forest` can be borrowed from `Node`, via `Node::<T>::forest()` and `Node::<T>::forest_mut()`
2. [feature] access to node's parent via `linked::fully::Node::<T>::parent()`
3. [refactoring] refine some doc tests to cover more branches
  • Loading branch information
oooutlk committed Sep 3, 2018
1 parent 4db51f5 commit e519fab
Show file tree
Hide file tree
Showing 10 changed files with 277 additions and 81 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "trees"
version = "0.1.6"
version = "0.2.0"
authors = ["oooutlk <oooutlk@outlook.com>"]
license = "MIT/Apache-2.0"
keywords = [ "tree", "forest", "node", "simple", "linked" ]
Expand Down
55 changes: 37 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
//!
//! General purpose tree library.
//!
//! The current version provides the tree implemented in classic child-sibling nodes.
//! More kinds of trees may be added in the future.
//!
//! [`signly_linked`]: signly_linked/index.html
//! The current version provides two implementions of heap-allocated, child-sibling linked trees.
//! The default implementation is [`linked::fully`](linked/fully/index.html),
//! which stores previous/next sibling and parent/child pointers in one node, with size information tracked.
//! The alternative is [`linked::singly`](linked/singly/index.html),
//! which stores only next sibling and last child pointers in one node, without size information tracked.
//! More kinds of trees will be added in the future.
//!
//! This crate can be used with or without libstd.
//!
Expand Down Expand Up @@ -60,23 +62,20 @@
//! 3. `Tree` traversal, using `Node::iter()` recursively
//!
//! ```rust
//! use std::string::{String,ToString};
//! use trees::{tr,Node};
//! use std::fmt::Display;
//!
//! let tree = tr(0)
//! /( tr(1) /tr(2)/tr(3) )
//! /( tr(4) /tr(5)/tr(6) );
//!
//! fn tree_to_string<T:ToString>( node: &Node<T> ) -> String {
//! fn tree_to_string<T:Display>( node: &Node<T> ) -> String {
//! if node.is_leaf() {
//! node.data.to_string()
//! } else {
//! node.data.to_string()
//! + &"( "
//! + &node.iter()
//! .fold( String::new(),
//! |s,c| s + &tree_to_string(c) + &" " )
//! + &")"
//! format!( "{}( {})", node.data,
//! node.iter().fold( String::new(),
//! |s,c| s + &tree_to_string(c) + &" " ))
//! }
//! }
//!
Expand Down Expand Up @@ -110,18 +109,25 @@
//! ### Concepts
//!
//! 1. `Tree` is composed of a root `Node` and an optional `Forest` as its children. A tree can NOT be empty.
//! ```rust,no_run
//! ```rust
//! use trees::{tr,Tree,Forest};
//!
//! let mut tree: Tree<i32> = tr(0);
//!
//! let forest: Forest<i32> = -tr(1)-tr(2)-tr(3);
//! tree.append( forest );
//! let forest = tree.abandon();
//! assert_eq!( tree, tr(0) /tr(1) /tr(2) /tr(3) );
//!
//! { let _forest: &Forest<i32> = tree.forest(); }
//! { let _forest: &mut Forest<i32> = tree.forest_mut(); }
//! { let _forest: Forest<i32> = tree.abandon(); }
//!
//! assert_eq!( tree, tr(0) );
//! ```
//!
//! 2. `Forest` is composed of `Node`s as its children. A forest can be empty.
//! ```rust,no_run
//! use trees::{tr,fr,Tree,Forest};
//! use trees::{tr,fr,Forest};
//!
//! let mut forest: Forest<i32> = fr(); // an empty forest
//! forest.push_back( tr(1) ); // forest has one tree
Expand Down Expand Up @@ -183,17 +189,28 @@
//!
//! 2. `Clone` for `Tree` and `Forest` makes deep copy which clones all its decendant nodes. To do copy for just one node, simplely `let cloned = trees::tr( node.data.clone() );`.
//!
//! 3. No bookkeeping of size information.
//! 3. `linked::fully::Node` will track count of children nodes, and count of all descendant nodes and itself, while `linked::singly::node` does not track any size information.
//!
//! ### Panics
//!
//! No panics unless `Clone` is involved:
//! * `Node::<T>::to_owned()`
//! * `Tree::<T>::clone()`
//! * `Forest::<T>::clone()`
//! * all of the operator overloading functions the operands of which contain at least one referenced type.
//! * `Forest::<T>::clone()`
//! * all of the operator overloading functions the operands of which contain at least one referenced type.
//!
//! Panics if and only if `T::clone()` panics.
//!
//! ### Safety
//!
//! Collections of pointer-based tree implementation require many `unsafe`s to do raw pointer dereferences.
//! Currently this crate contains **150 `unsafe`** lines in its source code.
//!
//! A node's value is composed of its **`data`** field and the **structure** of its descendant nodes.
//! So adding/removing/modifying a child of a node are regarded as modifying its value.
//! And the only possible way to obtain mutable references on a child node is via its parent's mutable reference.
//! Rust borrow checker guarantees memory safety in safe code, and the author of this crate is responsible for memory safety
//! inside `Node`s methods which take `&mut self` and contain `unsafe` blocks.

#![cfg_attr( feature = "no_std", no_std )]
#![cfg_attr( feature = "no_std", feature( alloc ))]
Expand Down Expand Up @@ -230,3 +247,5 @@ mod rust {

pub mod linked;
pub use linked::{tr,fr,Tree,Forest,Node,Iter,IterMut,Subnode,OntoIter,Visit,TreeWalk,ForestWalk};

//pub mod potted;
59 changes: 39 additions & 20 deletions src/linked/fully/forest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,12 @@ impl<T> Forest<T> {
/// # Examples
///
/// ```
/// use trees::linked::fully::tr;
/// let mut forest = -tr(1)-tr(2);
/// forest.push_front( tr(3) );
/// assert_eq!( forest.to_string(), "( 3 1 2 )" );
/// use trees::linked::fully::{tr,fr};
/// let mut forest = fr();
/// forest.push_front( tr(1) );
/// assert_eq!( forest.to_string(), "( 1 )" );
/// forest.push_front( tr(2) );
/// assert_eq!( forest.to_string(), "( 2 1 )" );
/// ```
#[inline] pub fn push_front( &mut self, mut tree: Tree<T> ) {
let tree_root = tree.root_mut().plink();
Expand All @@ -152,10 +154,12 @@ impl<T> Forest<T> {
/// # Examples
///
/// ```
/// use trees::linked::fully::tr;
/// let mut forest = -tr(1)-tr(2);
/// forest.push_back( tr(3) );
/// assert_eq!( forest.to_string(), "( 1 2 3 )" );
/// use trees::linked::fully::{tr,fr};
/// let mut forest = fr();
/// forest.push_back( tr(1) );
/// assert_eq!( forest.to_string(), "( 1 )" );
/// forest.push_back( tr(2) );
/// assert_eq!( forest.to_string(), "( 1 2 )" );
/// ```
#[inline] pub fn push_back( &mut self, mut tree: Tree<T> ) {
let tree_root = tree.root_mut().plink();
Expand All @@ -180,6 +184,8 @@ impl<T> Forest<T> {
/// let mut forest = -tr(1)-tr(2);
/// assert_eq!( forest.pop_front(), Some( tr(1) ));
/// assert_eq!( forest.to_string(), "( 2 )" );
/// assert_eq!( forest.pop_front(), Some( tr(2) ));
/// assert_eq!( forest.to_string(), "()" );
/// ```
#[inline] pub fn pop_front( &mut self ) -> Option<Tree<T>> {
if self.is_empty() {
Expand Down Expand Up @@ -209,6 +215,8 @@ impl<T> Forest<T> {
/// let mut forest = -tr(1)-tr(2);
/// assert_eq!( forest.pop_back(), Some( tr(2) ));
/// assert_eq!( forest.to_string(), "( 1 )" );
/// assert_eq!( forest.pop_back(), Some( tr(1) ));
/// assert_eq!( forest.to_string(), "()" );
/// ```
#[inline] pub fn pop_back( &mut self ) -> Option<Tree<T>> {
if self.is_empty() {
Expand Down Expand Up @@ -236,11 +244,12 @@ impl<T> Forest<T> {
/// # Examples
///
/// ```
/// use trees::linked::fully::tr;
/// let mut forest1 = -tr(0)-tr(1);
/// let mut forest2 = -tr(2)-tr(3);
/// forest1.prepend( forest2 );
/// assert_eq!( forest1.to_string(), "( 2 3 0 1 )" );
/// use trees::linked::fully::{tr,fr};
/// let mut forest = fr();
/// forest.prepend( -tr(0)-tr(1) );
/// assert_eq!( forest.to_string(), "( 0 1 )" );
/// forest.prepend( -tr(2)-tr(3) );
/// assert_eq!( forest.to_string(), "( 2 3 0 1 )" );
/// ```
#[inline] pub fn prepend( &mut self, mut forest: Forest<T> ) {
if !forest.is_empty() {
Expand All @@ -261,11 +270,12 @@ impl<T> Forest<T> {
/// # Examples
///
/// ```
/// use trees::linked::fully::tr;
/// let mut forest1 = -tr(0)-tr(1);
/// let mut forest2 = -tr(2)-tr(3);
/// forest1.append( forest2 );
/// assert_eq!( forest1.to_string(), "( 0 1 2 3 )" );
/// use trees::linked::fully::{tr,fr};
/// let mut forest = fr();
/// forest.append( -tr(0)-tr(1) );
/// assert_eq!( forest.to_string(), "( 0 1 )" );
/// forest.append( -tr(2)-tr(3) );
/// assert_eq!( forest.to_string(), "( 0 1 2 3 )" );
/// ```
#[inline] pub fn append( &mut self, mut forest: Forest<T> ) {
if !forest.is_empty() {
Expand All @@ -285,12 +295,17 @@ impl<T> Forest<T> {
/// # Examples
///
/// ```
/// use trees::linked::fully::tr;
/// use trees::linked::fully::{tr,fr};
///
/// let forest = fr::<i32>();
/// assert_eq!( forest.iter().next(), None );
///
/// let forest = -tr(1)-tr(2);
/// let mut iter = forest.iter();
/// assert_eq!( iter.next(), Some( tr(1).root() ));
/// assert_eq!( iter.next(), Some( tr(2).root() ));
/// assert_eq!( iter.next(), None );
/// assert_eq!( iter.next(), None );
/// ```
#[inline] pub fn iter<'a>( &self ) -> Iter<'a,T> {
if self.is_empty() {
Expand All @@ -305,7 +320,11 @@ impl<T> Forest<T> {
/// # Examples
///
/// ```
/// use trees::linked::fully::tr;
/// use trees::linked::fully::{tr,fr};
///
/// let mut forest = fr::<i32>();
/// assert_eq!( forest.iter_mut().next(), None );
///
/// let mut forest = -tr(1)-tr(2);
/// for child in forest.iter_mut() { child.data *= 10; }
/// assert_eq!( forest.to_string(), "( 10 20 )" );
Expand Down
4 changes: 2 additions & 2 deletions src/linked/fully/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ impl<'a, T> FusedIterator for Iter<'a, T> {}
/// This `struct` is created by [`Node::iter_mut`] and [`Forest::iter_mut`].
/// See its document for more.
///
/// [`Node::iter`]: struct.Node.html#method.iter_mut
/// [`Forest::iter`]: struct.Forest.html#method.iter_mut
/// [`Node::iter_mut`]: struct.Node.html#method.iter_mut
/// [`Forest::iter_mut`]: struct.Forest.html#method.iter_mut
pub struct IterMut<'a, T:'a> {
head : *mut Link,
tail : *mut Link,
Expand Down
18 changes: 17 additions & 1 deletion src/linked/fully/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! `Tree`/`Forest` implemented in last-child/next-sibling `Node`s, allocated on heap
//! `Tree`/`Forest` implemented in last-child/next-sibling `Node`s, allocated on heap, with size information tracked.

pub mod tree;
pub use self::tree::Tree;
Expand Down Expand Up @@ -143,4 +143,20 @@ mod tests {
forest.extend( tr(3)-tr(4) );
assert_eq!( forest, tr(1)-tr(2)-tr(3)-tr(4) );
}

#[test]
fn borrow_forest() {
let mut tree = tr(0) /tr(1) /tr(2);
{
let forest: &Forest<_> = tree.borrow();
assert_eq!( forest.to_string(), "( 1 2 )" );
}
{
let forest: &mut Forest<_> = tree.borrow_mut();
for node in forest.iter_mut() {
node.data *= 10;
}
}
assert_eq!( tree.to_string(), "0( 10 20 )" );
}
}
Loading

0 comments on commit e519fab

Please sign in to comment.