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

CoW CountTree #5

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 34 additions & 50 deletions src/count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ use Node;
use NodeMut;
use BinaryTree;
use WalkAction;
use cow::ArcCow;
use iter::Iter as GenIter;
use iter::IntoIter as GenIntoIter;
use unbox::Unbox;

pub type NodePtr<T> = Box<CountNode<T>>;
pub type NodePtr<T> = ArcCow<CountNode<T>>;

macro_rules! index_walker {
($index:ident, $node:ident, $up_count:ident, $stop:block) => {
Expand Down Expand Up @@ -78,9 +80,10 @@ macro_rules! index_walker {
/// assert_eq!(ct.remove(32), 32);
/// # }
/// ```
pub struct CountTree<T>(Option<NodePtr<T>>);
#[derive(Clone)]
pub struct CountTree<T: Clone>(Option<NodePtr<T>>);

impl<T> CountTree<T> {
impl<T: Clone> CountTree<T> {
fn root_must(&mut self) -> &mut CountNode<T> {
&mut **self.0.as_mut().unwrap()
}
Expand Down Expand Up @@ -157,7 +160,7 @@ impl<T> CountTree<T> {
if index == 0 {
self.push_front(value);
} else if index < len {
let new_node = Box::new(CountNode::new(value));
let new_node = ArcCow::new(CountNode::new(value));
let mut up_count = 0;
let root = self.root_must();
root.walk_reshape(|node| index_walker!(index, node, up_count, {}),
Expand All @@ -175,7 +178,7 @@ impl<T> CountTree<T> {

/// Prepends an element at the beginning.
pub fn push_front(&mut self, value: T) {
let new_node = Box::new(CountNode::new(value));
let new_node = ArcCow::new(CountNode::new(value));
if self.is_empty() {
self.0 = Some(new_node);
} else {
Expand All @@ -189,7 +192,7 @@ impl<T> CountTree<T> {

/// Appends an element at the end.
pub fn push_back(&mut self, value: T) {
let new_node = Box::new(CountNode::new(value));
let new_node = ArcCow::new(CountNode::new(value));
if self.is_empty() {
self.0 = Some(new_node);
} else {
Expand Down Expand Up @@ -220,6 +223,7 @@ impl<T> CountTree<T> {
*ret = node.try_remove(|node, _| node.rebalance());
},
|node, _| node.rebalance())
.map(|p| p.unbox())
.unwrap()
.into_value()
} else if index + 1 == len {
Expand All @@ -234,7 +238,7 @@ impl<T> CountTree<T> {
if self.is_empty() {
None
} else if self.len() == 1 {
Some(self.0.take().unwrap().into_value())
Some(self.0.take().map(|p| p.unbox()).unwrap().into_value())
} else {
let root = self.root_must();
Some(root.walk_extract(|_| WalkAction::Left,
Expand All @@ -245,6 +249,7 @@ impl<T> CountTree<T> {
}
},
|node, _| node.rebalance())
.map(|p| p.unbox())
.unwrap()
.into_value())
}
Expand All @@ -256,7 +261,7 @@ impl<T> CountTree<T> {
if self.is_empty() {
None
} else if self.len() == 1 {
Some(self.0.take().unwrap().into_value())
Some(self.0.take().map(|p| p.unbox()).unwrap().into_value())
} else {
let root = self.root_must();
Some(root.walk_extract(|_| WalkAction::Right,
Expand All @@ -267,6 +272,7 @@ impl<T> CountTree<T> {
}
},
|node, _| node.rebalance())
.map(|p| p.unbox())
.unwrap()
.into_value())
}
Expand All @@ -276,15 +282,15 @@ impl<T> CountTree<T> {
// TODO { O(n) } truncate, append, split_off, retain
}

impl<T> BinaryTree for CountTree<T> {
impl<T: Clone> BinaryTree for CountTree<T> {
type Node = CountNode<T>;

fn root(&self) -> Option<&Self::Node> {
self.0.as_ref().map(|nodeptr| &**nodeptr)
}
}

impl<T> Debug for CountTree<T>
impl<T: Clone> Debug for CountTree<T>
where T: Debug
{
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
Expand All @@ -302,7 +308,7 @@ impl<T> Debug for CountTree<T>
}
}

impl<T> Drop for CountTree<T> {
impl<T: Clone> Drop for CountTree<T> {
fn drop(&mut self) {
self.clear();
}
Expand Down Expand Up @@ -331,7 +337,7 @@ fn exp_floor_log(v: u32) -> u32 {
}
}

impl<T> FromIterator<T> for CountTree<T> {
impl<T: Clone> FromIterator<T> for CountTree<T> {
/// Time complexity: &Theta;(n + log<sup>2</sup>(n))
fn from_iter<I>(iterable: I) -> Self
where I: IntoIterator<Item = T>
Expand All @@ -340,10 +346,10 @@ impl<T> FromIterator<T> for CountTree<T> {

let mut iter = iterable.into_iter();
if let Some(item) = iter.next() {
let mut node = Box::new(CountNode::new(item));
let mut node = ArcCow::new(CountNode::new(item));
let mut count = 1;
for item in iter {
let mut new_node = Box::new(CountNode::new(item));
let mut new_node = ArcCow::new(CountNode::new(item));
new_node.insert_left(Some(node));
node = new_node;
count += 1;
Expand Down Expand Up @@ -385,7 +391,7 @@ impl<T> FromIterator<T> for CountTree<T> {
}
}

impl<'a, T> IntoIterator for &'a CountTree<T> {
impl<'a, T: Clone> IntoIterator for &'a CountTree<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;

Expand Down Expand Up @@ -419,7 +425,7 @@ impl<'a, T> Iterator for Iter<'a, T> {

impl<'a, T> ExactSizeIterator for Iter<'a, T> {}

impl<T> IntoIterator for CountTree<T> {
impl<T: Clone> IntoIterator for CountTree<T> {
type Item = T;
type IntoIter = IntoIter<T>;

Expand All @@ -434,12 +440,12 @@ impl<T> IntoIterator for CountTree<T> {
}
}

pub struct IntoIter<T> {
pub struct IntoIter<T: Clone> {
inner: GenIntoIter<CountNode<T>>,
remaining: usize,
}

impl<T> Iterator for IntoIter<T> {
impl<T: Clone> Iterator for IntoIter<T> {
type Item = T;

fn next(&mut self) -> Option<T> {
Expand All @@ -454,14 +460,15 @@ impl<T> Iterator for IntoIter<T> {
}
}

impl<T> ExactSizeIterator for IntoIter<T> {}
impl<T: Clone> ExactSizeIterator for IntoIter<T> {}

/// Node of a `CountTree`.
///
/// The only way of getting your hands on a `CountNode` is through
/// [`CountTree::root()`](struct.CountTree.html#method.root) method which
/// returns a shared reference to its root. Thus `NodeMut` methods are not
/// accessible to users.
#[derive(Clone)]
pub struct CountNode<T> {
val: T,
left: Option<NodePtr<T>>,
Expand All @@ -470,7 +477,7 @@ pub struct CountNode<T> {
height: u16,
}

impl<T> CountNode<T> {
impl<T: Clone> CountNode<T> {
fn new(val: T) -> CountNode<T> {
CountNode {
val: val,
Expand Down Expand Up @@ -546,7 +553,7 @@ impl<T> Node for CountNode<T> {
}
}

impl<T> NodeMut for CountNode<T> {
impl<T: Clone> NodeMut for CountNode<T> {
type NodePtr = NodePtr<T>;

fn detach_left(&mut self) -> Option<Self::NodePtr> {
Expand Down Expand Up @@ -633,30 +640,6 @@ impl Arbitrary for CountTree<usize> {
}
}

#[cfg(feature="quickcheck")]
impl<T> Clone for CountTree<T>
where T: Clone
{
fn clone(&self) -> Self {
CountTree(self.0.clone())
}
}

#[cfg(feature="quickcheck")]
impl<T> Clone for CountNode<T>
where T: Clone
{
fn clone(&self) -> Self {
CountNode {
val: self.val.clone(),
left: self.left.clone(),
right: self.right.clone(),
count: self.count,
height: self.height,
}
}
}

#[cfg(feature="quickcheck")]
pub mod quickcheck {
use super::CountTree;
Expand Down Expand Up @@ -727,14 +710,15 @@ mod tests {
use NodeMut;
use super::CountNode;
use super::CountTree;
use cow::ArcCow;
use test::compute_level;
use test::Level;

fn test_nodes() -> Box<CountNode<u32>> {
let mut cn = Box::new(CountNode::new(7));
cn.insert_before(Box::new(CountNode::new(8)), |_, _| ());
cn.insert_before(Box::new(CountNode::new(12)), |_, _| ());
cn.insert_right(Some(Box::new(CountNode::new(5))));
fn test_nodes() -> ArcCow<CountNode<u32>> {
let mut cn = ArcCow::new(CountNode::new(7));
cn.insert_before(ArcCow::new(CountNode::new(8)), |_, _| ());
cn.insert_before(ArcCow::new(CountNode::new(12)), |_, _| ());
cn.insert_right(Some(ArcCow::new(CountNode::new(5))));
cn
}

Expand Down
31 changes: 31 additions & 0 deletions src/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
//! Thin wrappers around the standard library ref-counted pointers that clones
//! on `DerefMut` if reference count is greater than 1.

use std::fmt;
use std::ops::Deref;
use std::ops::DerefMut;
use std::rc::Rc;
use std::sync::Arc;

use unbox::Unbox;

pub struct RcCow<T>(pub Rc<T>);

impl<T: Clone> RcCow<T> {
Expand Down Expand Up @@ -36,6 +39,20 @@ impl<T: Clone> DerefMut for RcCow<T> {
}
}

impl<T: Clone> Unbox for RcCow<T> {
type Target = T;

fn unbox(self) -> T {
self.0.unbox()
}
}

impl<T: fmt::Debug> fmt::Debug for RcCow<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}

pub struct ArcCow<T>(pub Arc<T>);

impl<T: Clone> ArcCow<T> {
Expand Down Expand Up @@ -63,3 +80,17 @@ impl<T: Clone> DerefMut for ArcCow<T> {
Arc::make_mut(&mut self.0)
}
}

impl<T: Clone> Unbox for ArcCow<T> {
type Target = T;

fn unbox(self) -> T {
self.0.unbox()
}
}

impl<T: fmt::Debug> fmt::Debug for ArcCow<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}