<commit_before>mod interval;
mod adjacent_bound;

pub use adjacent_bound::AdjacentBound;

use interval::Interval;
use std::borrow::Borrow;
use std::ops::Range;
use std::collections::VecDeque;
use std::iter::FromIterator;

#[derive(Debug)]
struct DietNode<T> {
    interval: Interval<T>,
    left: Option<Box<DietNode<T>>>,
    right: Option<Box<DietNode<T>>>,
}

#[derive(Debug)]
pub struct Diet<T> {
    root: Option<Box<DietNode<T>>>,
}

#[derive(Debug)]
struct DietNodeIterator<T> {
    pending: VecDeque<T>
}

trait DietNodeRelationshipOps {
    type Bound : AdjacentBound;

    fn max_parent_mut(&mut self) -> &mut Self;

    fn min_parent_mut(&mut self) -> &mut Self;

    fn traverse_to_node_containing(&self, value: &Self::Bound) -> &Self;

    fn traverse_to_node_containing_mut(&mut self, value: &Self::Bound) -> &mut Self;

    fn insert(&mut self, value: Self::Bound) -> bool;

    fn remove(&mut self, value: &Self::Bound) -> bool;
}

impl<T : AdjacentBound> DietNodeRelationshipOps for Option<Box<DietNode<T>>> {
    type Bound = T;

    fn max_parent_mut(&mut self) -> &mut Self {
        let mut parent = self;

        loop {
            let move_next = parent.as_ref().map_or(false, |c|c.right.is_some());
            if move_next {
                parent = &mut {parent}.as_mut().unwrap().right
            } else {
                return parent;
            }
        }
    }

    fn min_parent_mut(&mut self) ->  &mut Self {
        let mut parent = self;

        loop {
            let move_next = parent.as_ref().map_or(false, |c|c.left.is_some());
            if move_next {
                parent = &mut {parent}.as_mut().unwrap().left
            } else {
                return parent;
            }
        }
    }

    fn traverse_to_node_containing(&self, value: &Self::Bound) -> &Self {
        let mut current = self;

        while let Some(ref node) = *current {
            if node.interval.contains(value) {
                break;
            }

            if value < node.interval.inclusive_start() {
                current = &node.left
            } else {
                debug_assert!(value >= node.interval.exclusive_end());
                current = &node.right
            }
        }

        current
    }

    fn traverse_to_node_containing_mut(&mut self, value: &Self::Bound) -> &mut Self {
        let mut current = self;

        loop {
            let local_current = current;
            if let Some(node) = local_current.take() {
                if node.interval.contains(value) {
                    *local_current = Some(node);
                    return local_current;
                }

                if node.is_adjacent(value) {
                    *local_current = Some(node);
                    return local_current;
                }

                if value < node.interval.inclusive_start() {
                    *local_current = Some(node);
                    current = &mut local_current.as_mut().unwrap().left
                } else {
                    debug_assert!(value >= node.interval.exclusive_end());
                    *local_current = Some(node);
                    current = &mut local_current.as_mut().unwrap().right
                }
            } else {
                return local_current;
            }
        }
    }

    fn insert(&mut self, value: Self::Bound) -> bool {
        let mut current = self;
        loop {
            let local_current = current;
            if let Some(ref mut node) = *local_current {
                if value.comes_before(node.interval.inclusive_start()) {

                    node.interval.set_inclusive_start(value);
                    node.join_left();

                    return true;

                } else if &value == node.interval.exclusive_end() {

                    node.interval.set_exclusive_end(value.increment());
                    node.join_right();

                    return true;

                } if &value < node.interval.inclusive_start() {
                    current = &mut node.left;
                } else if &value > node.interval.exclusive_end() {
                    current = &mut node.right;
                }  else {
                    debug_assert!(node.interval.contains(&value), "the value should already be contained within the interval");
                    return false;
                }
            } else {
                let new_exclusive_end = value.increment();

                *local_current = Some(Box::new(DietNode {
                    interval: Interval::from(value..new_exclusive_end),
                    left: None,
                    right: None
                }));

                return true;
            }
        }
    }

    fn remove(&mut self, value: &Self::Bound) -> bool {
        let containing_node = self.traverse_to_node_containing_mut(value);

        let mut delete_node = false;

        let removed = if let Some(ref mut node) = *containing_node {
            if value == node.interval.inclusive_start() {
                if value.comes_before(node.interval.exclusive_end()) {
                    // The entire node needs to be removed but any children should be moved up
                    match (node.left.take(), node.right.take()) {
                        (None, None) => {
                            delete_node = true
                        }
                        (Some(child), None) | (None, Some(child)) => {
                            *node = child;
                        }
                        (mut left @ Some(_), right @ Some(_)) => {
                            let max = *(left.max_parent_mut().take().unwrap());

                            node.interval = max.interval;
                            node.left = left;
                            node.right = right;
                        }
                    }
                } else {
                    node.interval.inclusive_start_mut().increment_ref();
                }
            } else if value.comes_before(node.interval.exclusive_end()) {
                node.interval.exclusive_end_mut().decrement_ref();
            } else {
                node.split_on_value(value);
            };
            true
        } else {
            false
        };

        if delete_node {
            *containing_node = None;
        }

        removed
    }
}

impl<'a, T> Iterator for DietNodeIterator<&'a DietNode<T>> {
    type Item = &'a DietNode<T>;

    fn next(&mut self) -> Option<&'a DietNode<T>> {
        self.pending.pop_front()
            .map(|current| {
                let children = [&current.left, &current.right];
                for child in children.into_iter().flat_map(|x| x.as_ref()) {
                    self.pending.push_back(child);

                }
                current
            })
    }
}

impl<T> DietNode<T> {
    fn min_inclusive_start(&self) -> &T {
        let mut current = self;

        loop {
            if let Some(child) = current.left.as_ref() {
                current = child;
            } else {
                return current.interval.inclusive_start();
            }
        }
    }

    fn max_exclusive_end(&self) -> &T {
        let mut current = self;

        loop {
            if let Some(child) = current.right.as_ref() {
                current = child;
            } else {
                return current.interval.exclusive_end();
            }
        }
    }

    pub fn nodes(&self) -> DietNodeIterator<&DietNode<T>> {
        let mut pending = VecDeque::new();
        pending.push_back(self);

        DietNodeIterator {
            pending: pending
        }
    }

    pub fn len(&self) -> usize {
        self.nodes().count()
    }

    pub fn is_adjacent<Q: ?Sized>(&self, value: &Q) -> bool where T : Borrow<Q>, Q : AdjacentBound {
        value.comes_before(self.interval.inclusive_start().borrow()) ||
                    value == self.interval.exclusive_end().borrow()
    }
}

impl<T: AdjacentBound> DietNode<T> {

    pub fn split_on_value(&mut self, value: &T) {
        debug_assert!(self.interval.contains(value), "the value should be contained within the interval");

        let old_exclusive_end = self.interval.set_exclusive_end(value.decrement());

        let new_right_interval = Interval::from(value.increment()..old_exclusive_end);

        let right = self.right.take();
        self.right = Some(Box::new(DietNode {
            interval: new_right_interval,
            left: None,
            right: right
        }));
    }

    fn join_left(&mut self) {
        let max_parent_mut = self.left.max_parent_mut();

        if let Some(max) = max_parent_mut.take() {

            debug_assert!(max.right.is_none(), "the maximum node should have no right children");

            if max.interval.exclusive_end() == self.interval.inclusive_start() {
                // Deref the box so we can take the field values
                let max = *max;

                // If the maximum should be joined with self then the thing which used to point at max should now point at max's left node
                *max_parent_mut = max.left;
                self.interval.set_inclusive_start(max.interval.take_inclusive_start());
            } else {
                *max_parent_mut = Some(max);
            }
        }

    }

    fn join_right(&mut self) {
        let min_parent_mut = self.right.min_parent_mut();

        if let Some(min) = min_parent_mut.take() {

            debug_assert!(min.left.is_none(), "the minimum node should have no left children");

            if min.interval.inclusive_start() == self.interval.exclusive_end() {
                // Deref the box so we can take the field values
                let min = *min;

                // If the minimum should be joined with self then the thing which used to point at max should now point at min's right node
                *min_parent_mut = min.right;
                self.interval.set_exclusive_end(min.interval.take_exclusive_end());
            } else {
                *min_parent_mut = Some(min);
            }
        }
    }
}

impl<T> Diet<T> {
    pub fn len(&self) -> usize {
        self.root.as_ref().map_or(0, |n| n.len())
    }
}

impl<T: AdjacentBound> Diet<T> {

    pub fn insert(&mut self, value: T) -> bool {
        self.root.insert(value)
    }

    pub fn remove(&mut self, value: &T) -> bool {
        self.root.remove(value)
    }

    pub fn contains(&self, value: &T) -> bool {
        self.root.traverse_to_node_containing(value).is_some()
    }
}

// TODO LH Implement iterators which traverse the intervals in the tree

impl<T> Default for Diet<T>{
    fn default() -> Self {
        Self {
            root: None
        }
    }
}

impl<A : AdjacentBound> FromIterator<A> for Diet<A> {
    fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = A> {
        let mut diet = Diet::default();

        for value in iter {
            diet.insert(value);
        }

        diet
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn contains_returns_false_for_default(){
        let diet = Diet::<u32>::default();

        assert!(!diet.contains(&5));
    }

    #[test]
    fn contains_returns_true_for_existing_value(){
        let mut diet = Diet::from_iter([3, 1, 5].iter().cloned());

        assert!(diet.contains(&5));
    }

    #[test]
    fn len_returns_zero_for_default() {
        let diet = Diet::<u32>::default();

        assert_eq!(diet.len(), 0);
    }

    #[test]
    fn insert_returns_true_for_new_value() {
        let mut diet = Diet::default();

        assert!(diet.insert(1));
    }

    #[test]
    fn insert_returns_false_for_existing_value() {
        let mut diet = Diet::default();

        diet.insert(1);
        assert!(!diet.insert(1));
    }

    #[test]
    fn insert_extends_existing_ranges() {
        let mut diet = Diet::from_iter([1, 5].iter().cloned());

        diet.insert(2);
        diet.insert(4);

        assert_eq!(diet.len(), 2);
    }

    #[test]
    fn insert_combines_ranges() {
        let mut diet = Diet::from_iter([3, 1, 5, 8].iter().cloned());

        diet.insert(2);
        diet.insert(4);
        diet.insert(6);
        diet.insert(7);

        assert_eq!(diet.len(), 1);
    }

    #[test]
    fn remove_returns_false_for_default(){
        let mut diet = Diet::<u32>::default();

        assert!(!diet.remove(&5));
    }

    #[test]
    fn remove_returns_false_for_non_existant_value(){
        let mut diet = Diet::from_iter([1, 2, 3, 6].iter().cloned());

        assert!(!diet.remove(&10));
    }

    #[test]
    fn remove_removes_values(){
        let mut diet = Diet::from_iter([5, 6, 1, 2, 8, 9].iter().cloned());

        assert!(diet.remove(&5));
        assert!(diet.remove(&6));

        assert_eq!(diet.len(), 2);
    }

     #[test]
    fn test_delete_split_left() {
        let mut d = Diet::default();
        d.insert(8);
        d.insert(9);
        d.insert(10);

        d.insert(2);
        d.insert(4);
        d.insert(6);
        d.insert(14);
        d.insert(12);
        d.insert(16);

        d.remove(&8);
        d.remove(&9);
        d.remove(&10);

        assert!(d.contains(&2));
        assert!(d.contains(&4));
        assert!(d.contains(&6));
        assert!(d.contains(&14));
        assert!(d.contains(&12));
        assert!(d.contains(&16));
    }

    #[test]
    fn test_delete_simple() {
        let mut d = Diet::default();
        d.remove(&5);
        d.insert(5);
        assert!(d.contains(&5));
        d.remove(&5);
        assert!(!d.contains(&5));
    }

    #[test]
    fn test_delete_branch() {
        let mut d = Diet::default();
        d.insert(5);
        d.insert(3);
        d.insert(7);

        d.remove(&3);
        assert!(!d.contains(&3));
        assert!(d.contains(&5));
        assert!(d.contains(&7));

        d.remove(&7);
        assert!(d.contains(&5));
    }

    #[test]
    fn test_delete_replace_merge() {
        let mut d = Diet::default();
        d.insert(5);
        d.insert(3);

        d.remove(&5);
        assert!(!d.contains(&5));
        assert!(d.contains(&3));

        d.insert(7);
        d.remove(&3);
        assert!(!d.contains(&3));
        assert!(d.contains(&7));
    }

    #[test]
    fn test_delete_lower_upper() {
        let mut d = Diet::default();
        d.insert(5);
        d.insert(6);
        d.insert(7);

        d.remove(&5);
        assert!(d.contains(&6));
        assert!(d.contains(&7));

        d.remove(&7);
        assert!(d.contains(&6));
    }

}
<commit_msg>join_(left/right) now only take the max/min value when it is adjacent<commit_after>mod interval;
mod adjacent_bound;

pub use adjacent_bound::AdjacentBound;

use interval::Interval;
use std::borrow::Borrow;
use std::ops::Range;
use std::collections::VecDeque;
use std::iter::FromIterator;

#[derive(Debug)]
struct DietNode<T> {
    interval: Interval<T>,
    left: Option<Box<DietNode<T>>>,
    right: Option<Box<DietNode<T>>>,
}

#[derive(Debug)]
pub struct Diet<T> {
    root: Option<Box<DietNode<T>>>,
}

#[derive(Debug)]
struct DietNodeIterator<T> {
    pending: VecDeque<T>
}

trait DietNodeRelationshipOps {
    type Bound : AdjacentBound;

    fn max_parent_mut(&mut self) -> &mut Self;

    fn min_parent_mut(&mut self) -> &mut Self;

    fn traverse_to_node_containing(&self, value: &Self::Bound) -> &Self;

    fn traverse_to_node_containing_mut(&mut self, value: &Self::Bound) -> &mut Self;

    fn insert(&mut self, value: Self::Bound) -> bool;

    fn remove(&mut self, value: &Self::Bound) -> bool;
}

impl<T : AdjacentBound> DietNodeRelationshipOps for Option<Box<DietNode<T>>> {
    type Bound = T;

    fn max_parent_mut(&mut self) -> &mut Self {
        let mut parent = self;

        loop {
            let move_next = parent.as_ref().map_or(false, |c|c.right.is_some());
            if move_next {
                parent = &mut {parent}.as_mut().unwrap().right
            } else {
                return parent;
            }
        }
    }

    fn min_parent_mut(&mut self) ->  &mut Self {
        let mut parent = self;

        loop {
            let move_next = parent.as_ref().map_or(false, |c|c.left.is_some());
            if move_next {
                parent = &mut {parent}.as_mut().unwrap().left
            } else {
                return parent;
            }
        }
    }

    fn traverse_to_node_containing(&self, value: &Self::Bound) -> &Self {
        let mut current = self;

        while let Some(ref node) = *current {
            if node.interval.contains(value) {
                break;
            }

            if value < node.interval.inclusive_start() {
                current = &node.left
            } else {
                debug_assert!(value >= node.interval.exclusive_end());
                current = &node.right
            }
        }

        current
    }

    fn traverse_to_node_containing_mut(&mut self, value: &Self::Bound) -> &mut Self {
        let mut current = self;

        loop {
            let local_current = current;
            if let Some(node) = local_current.take() {
                if node.interval.contains(value) {
                    *local_current = Some(node);
                    return local_current;
                }

                if node.is_adjacent(value) {
                    *local_current = Some(node);
                    return local_current;
                }

                if value < node.interval.inclusive_start() {
                    *local_current = Some(node);
                    current = &mut local_current.as_mut().unwrap().left
                } else {
                    debug_assert!(value >= node.interval.exclusive_end());
                    *local_current = Some(node);
                    current = &mut local_current.as_mut().unwrap().right
                }
            } else {
                return local_current;
            }
        }
    }

    fn insert(&mut self, value: Self::Bound) -> bool {
        let mut current = self;
        loop {
            let local_current = current;
            if let Some(ref mut node) = *local_current {
                if value.comes_before(node.interval.inclusive_start()) {

                    node.interval.set_inclusive_start(value);
                    node.join_left();

                    return true;

                } else if &value == node.interval.exclusive_end() {

                    node.interval.set_exclusive_end(value.increment());
                    node.join_right();

                    return true;

                } if &value < node.interval.inclusive_start() {
                    current = &mut node.left;
                } else if &value > node.interval.exclusive_end() {
                    current = &mut node.right;
                }  else {
                    debug_assert!(node.interval.contains(&value), "the value should already be contained within the interval");
                    return false;
                }
            } else {
                let new_exclusive_end = value.increment();

                *local_current = Some(Box::new(DietNode {
                    interval: Interval::from(value..new_exclusive_end),
                    left: None,
                    right: None
                }));

                return true;
            }
        }
    }

    fn remove(&mut self, value: &Self::Bound) -> bool {
        let containing_node = self.traverse_to_node_containing_mut(value);

        let mut delete_node = false;

        let removed = if let Some(ref mut node) = *containing_node {
            if value == node.interval.inclusive_start() {
                if value.comes_before(node.interval.exclusive_end()) {
                    // The entire node needs to be removed but any children should be moved up
                    match (node.left.take(), node.right.take()) {
                        (None, None) => {
                            delete_node = true
                        }
                        (Some(child), None) | (None, Some(child)) => {
                            *node = child;
                        }
                        (mut left @ Some(_), right @ Some(_)) => {
                            let max = *(left.max_parent_mut().take().unwrap());

                            node.interval = max.interval;
                            node.left = left;
                            node.right = right;
                        }
                    }
                } else {
                    node.interval.inclusive_start_mut().increment_ref();
                }
            } else if value.comes_before(node.interval.exclusive_end()) {
                node.interval.exclusive_end_mut().decrement_ref();
            } else {
                node.split_on_value(value);
            };
            true
        } else {
            false
        };

        if delete_node {
            *containing_node = None;
        }

        removed
    }
}

impl<'a, T> Iterator for DietNodeIterator<&'a DietNode<T>> {
    type Item = &'a DietNode<T>;

    fn next(&mut self) -> Option<&'a DietNode<T>> {
        self.pending.pop_front()
            .map(|current| {
                let children = [&current.left, &current.right];
                for child in children.into_iter().flat_map(|x| x.as_ref()) {
                    self.pending.push_back(child);

                }
                current
            })
    }
}

impl<T> DietNode<T> {
    fn min_inclusive_start(&self) -> &T {
        let mut current = self;

        loop {
            if let Some(child) = current.left.as_ref() {
                current = child;
            } else {
                return current.interval.inclusive_start();
            }
        }
    }

    fn max_exclusive_end(&self) -> &T {
        let mut current = self;

        loop {
            if let Some(child) = current.right.as_ref() {
                current = child;
            } else {
                return current.interval.exclusive_end();
            }
        }
    }

    pub fn nodes(&self) -> DietNodeIterator<&DietNode<T>> {
        let mut pending = VecDeque::new();
        pending.push_back(self);

        DietNodeIterator {
            pending: pending
        }
    }

    pub fn len(&self) -> usize {
        self.nodes().count()
    }

    pub fn is_adjacent<Q: ?Sized>(&self, value: &Q) -> bool where T : Borrow<Q>, Q : AdjacentBound {
        value.comes_before(self.interval.inclusive_start().borrow()) ||
                    value == self.interval.exclusive_end().borrow()
    }
}

impl<T: AdjacentBound> DietNode<T> {

    pub fn split_on_value(&mut self, value: &T) {
        debug_assert!(self.interval.contains(value), "the value should be contained within the interval");

        let old_exclusive_end = self.interval.set_exclusive_end(value.decrement());

        let new_right_interval = Interval::from(value.increment()..old_exclusive_end);

        let right = self.right.take();
        self.right = Some(Box::new(DietNode {
            interval: new_right_interval,
            left: None,
            right: right
        }));
    }

    fn join_left(&mut self) {
        let max_parent_mut = self.left.max_parent_mut();

        let interval = &mut self.interval;

        let should_merge = max_parent_mut.as_ref().map_or(false, |c| c.interval.exclusive_end() == interval.inclusive_start());

        if should_merge {
            let max = *max_parent_mut.take().unwrap();
            *max_parent_mut = max.left;
            interval.set_inclusive_start(max.interval.take_inclusive_start());
        }
    }

    fn join_right(&mut self) {
        let min_parent_mut = self.right.min_parent_mut();

        let interval = &mut self.interval;

        let should_merge = min_parent_mut.as_ref().map_or(false, |c| c.interval.inclusive_start() == interval.exclusive_end());

        if should_merge {
            let min = *min_parent_mut.take().unwrap();
            *min_parent_mut = min.right;
            interval.set_exclusive_end(min.interval.take_exclusive_end());
        }
    }
}

impl<T> Diet<T> {
    pub fn len(&self) -> usize {
        self.root.as_ref().map_or(0, |n| n.len())
    }
}

impl<T: AdjacentBound> Diet<T> {

    pub fn insert(&mut self, value: T) -> bool {
        self.root.insert(value)
    }

    pub fn remove(&mut self, value: &T) -> bool {
        self.root.remove(value)
    }

    pub fn contains(&self, value: &T) -> bool {
        self.root.traverse_to_node_containing(value).is_some()
    }
}

// TODO LH Implement iterators which traverse the intervals in the tree

impl<T> Default for Diet<T>{
    fn default() -> Self {
        Self {
            root: None
        }
    }
}

impl<A : AdjacentBound> FromIterator<A> for Diet<A> {
    fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = A> {
        let mut diet = Diet::default();

        for value in iter {
            diet.insert(value);
        }

        diet
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn contains_returns_false_for_default(){
        let diet = Diet::<u32>::default();

        assert!(!diet.contains(&5));
    }

    #[test]
    fn contains_returns_true_for_existing_value(){
        let mut diet = Diet::from_iter([3, 1, 5].iter().cloned());

        assert!(diet.contains(&5));
    }

    #[test]
    fn len_returns_zero_for_default() {
        let diet = Diet::<u32>::default();

        assert_eq!(diet.len(), 0);
    }

    #[test]
    fn insert_returns_true_for_new_value() {
        let mut diet = Diet::default();

        assert!(diet.insert(1));
    }

    #[test]
    fn insert_returns_false_for_existing_value() {
        let mut diet = Diet::default();

        diet.insert(1);
        assert!(!diet.insert(1));
    }

    #[test]
    fn insert_extends_existing_ranges() {
        let mut diet = Diet::from_iter([1, 5].iter().cloned());

        diet.insert(2);
        diet.insert(4);

        assert_eq!(diet.len(), 2);
    }

    #[test]
    fn insert_combines_ranges() {
        let mut diet = Diet::from_iter([3, 1, 5, 8].iter().cloned());

        diet.insert(2);
        diet.insert(4);
        diet.insert(6);
        diet.insert(7);

        assert_eq!(diet.len(), 1);
    }

    #[test]
    fn remove_returns_false_for_default(){
        let mut diet = Diet::<u32>::default();

        assert!(!diet.remove(&5));
    }

    #[test]
    fn remove_returns_false_for_non_existant_value(){
        let mut diet = Diet::from_iter([1, 2, 3, 6].iter().cloned());

        assert!(!diet.remove(&10));
    }

    #[test]
    fn remove_removes_values(){
        let mut diet = Diet::from_iter([5, 6, 1, 2, 8, 9].iter().cloned());

        assert!(diet.remove(&5));
        assert!(diet.remove(&6));

        assert_eq!(diet.len(), 2);
    }

     #[test]
    fn test_delete_split_left() {
        let mut d = Diet::default();
        d.insert(8);
        d.insert(9);
        d.insert(10);

        d.insert(2);
        d.insert(4);
        d.insert(6);
        d.insert(14);
        d.insert(12);
        d.insert(16);

        d.remove(&8);
        d.remove(&9);
        d.remove(&10);

        assert!(d.contains(&2));
        assert!(d.contains(&4));
        assert!(d.contains(&6));
        assert!(d.contains(&14));
        assert!(d.contains(&12));
        assert!(d.contains(&16));
    }

    #[test]
    fn test_delete_simple() {
        let mut d = Diet::default();
        d.remove(&5);
        d.insert(5);
        assert!(d.contains(&5));
        d.remove(&5);
        assert!(!d.contains(&5));
    }

    #[test]
    fn test_delete_branch() {
        let mut d = Diet::default();
        d.insert(5);
        d.insert(3);
        d.insert(7);

        d.remove(&3);
        assert!(!d.contains(&3));
        assert!(d.contains(&5));
        assert!(d.contains(&7));

        d.remove(&7);
        assert!(d.contains(&5));
    }

    #[test]
    fn test_delete_replace_merge() {
        let mut d = Diet::default();
        d.insert(5);
        d.insert(3);

        d.remove(&5);
        assert!(!d.contains(&5));
        assert!(d.contains(&3));

        d.insert(7);
        d.remove(&3);
        assert!(!d.contains(&3));
        assert!(d.contains(&7));
    }

    #[test]
    fn test_delete_lower_upper() {
        let mut d = Diet::default();
        d.insert(5);
        d.insert(6);
        d.insert(7);

        d.remove(&5);
        assert!(d.contains(&6));
        assert!(d.contains(&7));

        d.remove(&7);
        assert!(d.contains(&6));
    }

}
<|endoftext|>


<commit_before>extern crate libc;

use std::ffi::CString;
use std::mem::transmute;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const libc::c_void, length: libc::size_t, name: *const libc::c_char);
}

pub fn any(data: *const libc::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(transmute(data), 4, name_cstr.as_ptr());
  }
}

pub fn u32(data: *const u32, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(transmute(data), 4, name_cstr.as_ptr());
  }
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::ffi::CString;
use std::mem::transmute;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const libc::c_void, length: libc::size_t, name: *const libc::c_char);
}

pub fn any(data: *const libc::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length as libc::size_t, name_cstr.as_ptr());
  }
}

pub fn i32(data: *const i32, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(transmute(data), 4, name_cstr.as_ptr());
  }
}

pub fn u32(data: *const u32, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(transmute(data), 4, name_cstr.as_ptr());
  }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate nix;

use std::io;
use std::io::{Write, Read, Error, ErrorKind};
use nix::errno::Errno;
use nix::Error::Sys;
use nix::sys::termios;
use nix::sys::termios::{BRKINT, ICRNL, INPCK, ISTRIP, IXON, OPOST, CS8, ECHO, ICANON, IEXTEN, ISIG, VMIN, VTIME};

static MAX_LINE: u32 = 4096;
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb","cons25","emacs"];

const    NULL     : u8   = 0;     // NULL
const    CTRL_A    : u8   = 1;     // C-a
const    CTRL_B    : u8   = 2;     // C-b
const    CTRL_C    : u8   = 3;     // C-c
const    CTRL_D    : u8   = 4;     // C-d
const    CTRL_E    : u8   = 5;     // C-e
const    CTRL_F    : u8   = 6;     // C-f
const    CTRL_H    : u8   = 8;     // C-h
const    TAB      : u8   = 9;     // Tab
const    CTRL_K    : u8   = 11;    // C-k
const    CTRL_L    : u8   = 12;    // C-l
const    ENTER    : u8   = 13;    // Enter
const    CTRL_N    : u8   = 14;    // C-n
const    CTRL_P    : u8   = 16;    // C-p
const    CTRL_T    : u8   = 20;    // C-t
const    CTRL_U    : u8   = 21;    // C-u
const    CTRL_W    : u8   = 23;    // C-w
const    ESC      : u8   = 27;    // Esc
const    BACKSPACE: u8   = 127;   // Backspace

fn is_a_tty() -> bool {
    let isatty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
    isatty
}

fn is_unsupported_term() -> bool {
    let term = std::env::var("TERM").ok().unwrap();
    let mut unsupported = false;
    for iter in &UNSUPPORTED_TERM {
        unsupported = term == *iter
    }
    unsupported
}

fn enable_raw_mode() -> Result<termios::Termios, nix::Error> {
    if !is_a_tty() {
        Err(Sys(Errno::ENOTTY))
    } else {
        let original_term = try!(termios::tcgetattr(libc::STDIN_FILENO));
        let mut raw = original_term;
        raw.c_iflag = raw.c_iflag   & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        raw.c_oflag = raw.c_oflag   & !(OPOST);
        raw.c_cflag = raw.c_cflag   | (CS8);
        raw.c_lflag = raw.c_lflag   & !(ECHO | ICANON | IEXTEN | ISIG);
        raw.c_cc[VMIN] = 1;
        raw.c_cc[VTIME] = 0;
        try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &raw));
        Ok(original_term)
    }
}

fn disable_raw_mode(original_termios: termios::Termios) -> Result<(), nix::Error> {
    try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &original_termios));
    Ok(())
}

fn readline_edit() -> Result<String, io::Error> {
    let mut buffer = Vec::new();
    let mut input: [u8; 1] = [0];
    loop {
        let numread = io::stdin().read(&mut input).unwrap();
        match input[0] {
            CTRL_A => print!("Pressed C-a"),
            CTRL_B => print!("Pressed C-b"),
            CTRL_C => print!("Pressed C-c"),
            CTRL_D => print!("Pressed C-d"),
            CTRL_E => print!("Pressed C-e"),
            CTRL_F => print!("Pressed C-f"),
            CTRL_H => print!("Pressed C-h"),
            CTRL_K => print!("Pressed C-k"),
            CTRL_L => print!("Pressed C-l"),
            CTRL_N => print!("Pressed C-n"),
            CTRL_P => print!("Pressed C-p"),
            CTRL_T => print!("Pressed C-t"),
            CTRL_U => print!("Pressed C-u"),
            CTRL_W => print!("Pressed C-w"),
            ESC    => print!("Pressed esc") ,
            ENTER  => break,
            _      => { print!("{}", input[0]); io::stdout().flush(); }
        }
        buffer.push(input[0]);
    }
    Ok(String::from_utf8(buffer).unwrap())
}

fn readline_raw() -> Result<String, io::Error> {
    if is_a_tty() {
        let original_termios = match enable_raw_mode() {
            Err(Sys(Errno::ENOTTY)) => return Err(Error::new(ErrorKind::Other, "Not a TTY")),
            Err(Sys(Errno::EBADF))  => return Err(Error::new(ErrorKind::Other, "Not a file descriptor")),
            Err(..)                 => return Err(Error::new(ErrorKind::Other, "Unknown Error")),
            Ok(term)                => term
        };

        let user_input = readline_edit();

        match disable_raw_mode(original_termios) {
            Err(..) => return Err(Error::new(ErrorKind::Other, "Failed to revert to original termios")),
            Ok(..)  => ()
        }

        user_input
    } else {

        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(e) => Err(e),
        }
    }
}

pub fn readline(prompt: &'static str) -> Result<String, io::Error> {
    // Write prompt and flush it to stdout
    let mut stdout = io::stdout();
    try!(stdout.write(prompt.as_bytes()));
    try!(stdout.flush());

    if is_unsupported_term() {
        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(e) => Err(e),
        }
    } else {
        readline_raw()
    }
}
<commit_msg>Fixed spacing<commit_after>extern crate libc;
extern crate nix;

use std::io;
use std::io::{Write, Read, Error, ErrorKind};
use nix::errno::Errno;
use nix::Error::Sys;
use nix::sys::termios;
use nix::sys::termios::{BRKINT, ICRNL, INPCK, ISTRIP, IXON, OPOST, CS8, ECHO, ICANON, IEXTEN, ISIG, VMIN, VTIME};

static MAX_LINE: u32 = 4096;
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb","cons25","emacs"];

const    NULL     : u8   = 0;     // NULL
const    CTRL_A   : u8   = 1;     // C-a
const    CTRL_B   : u8   = 2;     // C-b
const    CTRL_C   : u8   = 3;     // C-c
const    CTRL_D   : u8   = 4;     // C-d
const    CTRL_E   : u8   = 5;     // C-e
const    CTRL_F   : u8   = 6;     // C-f
const    CTRL_H   : u8   = 8;     // C-h
const    TAB      : u8   = 9;     // Tab
const    CTRL_K   : u8   = 11;    // C-k
const    CTRL_L   : u8   = 12;    // C-l
const    ENTER    : u8   = 13;    // Enter
const    CTRL_N   : u8   = 14;    // C-n
const    CTRL_P   : u8   = 16;    // C-p
const    CTRL_T   : u8   = 20;    // C-t
const    CTRL_U   : u8   = 21;    // C-u
const    CTRL_W   : u8   = 23;    // C-w
const    ESC      : u8   = 27;    // Esc
const    BACKSPACE: u8   = 127;   // Backspace

fn is_a_tty() -> bool {
    let isatty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
    isatty
}

fn is_unsupported_term() -> bool {
    let term = std::env::var("TERM").ok().unwrap();
    let mut unsupported = false;
    for iter in &UNSUPPORTED_TERM {
        unsupported = term == *iter
    }
    unsupported
}

fn enable_raw_mode() -> Result<termios::Termios, nix::Error> {
    if !is_a_tty() {
        Err(Sys(Errno::ENOTTY))
    } else {
        let original_term = try!(termios::tcgetattr(libc::STDIN_FILENO));
        let mut raw = original_term;
        raw.c_iflag = raw.c_iflag   & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        raw.c_oflag = raw.c_oflag   & !(OPOST);
        raw.c_cflag = raw.c_cflag   | (CS8);
        raw.c_lflag = raw.c_lflag   & !(ECHO | ICANON | IEXTEN | ISIG);
        raw.c_cc[VMIN] = 1;
        raw.c_cc[VTIME] = 0;
        try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &raw));
        Ok(original_term)
    }
}

fn disable_raw_mode(original_termios: termios::Termios) -> Result<(), nix::Error> {
    try!(termios::tcsetattr(libc::STDIN_FILENO, termios::TCSAFLUSH, &original_termios));
    Ok(())
}

fn readline_edit() -> Result<String, io::Error> {
    let mut buffer = Vec::new();
    let mut input: [u8; 1] = [0];
    loop {
        let numread = io::stdin().read(&mut input).unwrap();
        match input[0] {
            CTRL_A => print!("Pressed C-a"),
            CTRL_B => print!("Pressed C-b"),
            CTRL_C => print!("Pressed C-c"),
            CTRL_D => print!("Pressed C-d"),
            CTRL_E => print!("Pressed C-e"),
            CTRL_F => print!("Pressed C-f"),
            CTRL_H => print!("Pressed C-h"),
            CTRL_K => print!("Pressed C-k"),
            CTRL_L => print!("Pressed C-l"),
            CTRL_N => print!("Pressed C-n"),
            CTRL_P => print!("Pressed C-p"),
            CTRL_T => print!("Pressed C-t"),
            CTRL_U => print!("Pressed C-u"),
            CTRL_W => print!("Pressed C-w"),
            ESC    => print!("Pressed esc") ,
            ENTER  => break,
            _      => { print!("{}", input[0]); io::stdout().flush(); }
        }
        buffer.push(input[0]);
    }
    Ok(String::from_utf8(buffer).unwrap())
}

fn readline_raw() -> Result<String, io::Error> {
    if is_a_tty() {
        let original_termios = match enable_raw_mode() {
            Err(Sys(Errno::ENOTTY)) => return Err(Error::new(ErrorKind::Other, "Not a TTY")),
            Err(Sys(Errno::EBADF))  => return Err(Error::new(ErrorKind::Other, "Not a file descriptor")),
            Err(..)                 => return Err(Error::new(ErrorKind::Other, "Unknown Error")),
            Ok(term)                => term
        };

        let user_input = readline_edit();

        match disable_raw_mode(original_termios) {
            Err(..) => return Err(Error::new(ErrorKind::Other, "Failed to revert to original termios")),
            Ok(..)  => ()
        }

        user_input
    } else {

        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(e) => Err(e),
        }
    }
}

pub fn readline(prompt: &'static str) -> Result<String, io::Error> {
    // Write prompt and flush it to stdout
    let mut stdout = io::stdout();
    try!(stdout.write(prompt.as_bytes()));
    try!(stdout.flush());

    if is_unsupported_term() {
        let mut line = String::new();
        match io::stdin().read_line(&mut line) {
            Ok(_) => Ok(line),
            Err(e) => Err(e),
        }
    } else {
        readline_raw()
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate notify;
extern crate libloading;
extern crate tempdir;

use libloading::Library;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver, Sender};
use notify::{RecommendedWatcher, Watcher, Event};
use tempdir::TempDir;
use std::time::Duration;
use std::thread;
use std::fs;
use std::env;
use std::fmt::Write;

/// Formats dll name on Windows ("test_foo" -> "test_foo.dll")
#[cfg(target_os="windows")]
fn get_dynamiclib_name(name: &str) -> String {
    format!("{}.dll", name)
}

/// Formats dll name on Mac ("test_foo" -> "libtest_foo.dylib")
#[cfg(target_os="macos")]
fn get_dynamiclib_name(name: &str) -> String {
    format!("lib{}.dylib", name)
}

/// Formats dll name on *nix ("test_foo" -> "libtest_foo.so")
#[cfg(any(target_os="linux",
          target_os="freebsd",
          target_os="dragonfly",
          target_os="netbsd",
          target_os="openbsd"))]
fn get_dynamiclib_name(name: &str) -> String {
    format!("lib{}.so", name)
}

pub struct Lib {
    pub lib: Library,
    pub loaded_path: PathBuf,
    pub original_path: Option<PathBuf>,
}

pub struct DynamicReload {
    libs: Vec<Rc<Lib>>,
    watcher: Option<RecommendedWatcher>,
    shadow_dir: Option<TempDir>,
    search_paths: Vec<&'static str>,
    watch_recv: Receiver<Event>,
}

pub enum Search {
    Default,
    Backwards,
}

#[derive(PartialEq)]
pub enum UsePlatformName {
    No,
    Yes
}

// Test

impl DynamicReload {

    ///
    ///
    pub fn new(search_paths: Option<Vec<&'static str>>, shadow_dir: Option<&'static str>, _search: Search) -> DynamicReload {
        let (tx, rx) = channel();
        DynamicReload {
            libs: Vec::new(),
            watcher: Self::get_watcher(tx),
            shadow_dir: Self::get_temp_dir(shadow_dir),
            watch_recv: rx,
            search_paths: Self::get_search_paths(search_paths),
        }
    }

    ///
    /// Add a library to be loaded and to be reloaded once updated.
    /// If UsePlatformName is set to Yes the input name will be formatted according
    /// to the standard way libraries looks on that platform examples:
    ///
    /// ```ignore
    /// Windows: foobar -> foobar.dll
    /// Linux:   foobar -> libfoobar.so
    /// Mac:     foobar -> libfoobar.dylib
    /// ````
    ///
    /// If set to no the given inputname will be used as is. This function
    /// will also search for the file in this priority order
    ///
    ///
    /// ```ignore
    /// 1. Current directory
    /// 2. In the search paths (relative to currect directory)
    /// 3. Currect directory of the executable
    /// 4. Serach backwards from executable if Backwards has been set in [new](struct.DynamicReload.html#method.new)
    /// ```
    ///
    pub fn add_library(&mut self, name: &str, name_format: UsePlatformName) -> Result<Rc<Lib>, String> {
        match Self::try_load_library(self, name, name_format) {
            Ok(lib) => {
                if let Some(w) = self.watcher.as_mut() {
                    if let Some(path) = lib.original_path.as_ref() {
                        let _ = w.watch(path);
                    }
                }
                // Bump the ref here as we keep one around to keep track of files that needs to be reloaded
                self.libs.push(lib.clone());
                Ok(lib)
            }
            Err(e) => Err(e),
        }
    }

    ///
    /// Update the will check if a dynamic library needs to be reloaded and if that is the case
    /// then the supplied callback functions will be called
    ///
    /// First the before_reload code. This allows the calling application to performe actions
    /// before the dynamic library is unloaded. This can for example be to save some internal
    /// state that needs to be restorted when relodaded
    ///
    /// After the reloading is comple the post_reload function will be called giving the host
    /// application the possibility to restore any potentially saved state
    ///
    /// If no callbacks are needed use the regular [update](struct.DynamicReload.html#method.update) call instead
    ///
    pub fn update_with_callback<F, T>(&mut self, ref before_update: F, ref after_update: F, data: &mut T) where F : Fn(&mut T, &Rc<Lib>) {
        match self.watch_recv.try_recv() {
            Ok(file) => Self::reload_libs(self, file.path.as_ref().unwrap(), before_update, after_update, data),
            _ => (),
        }
    }

    ///
    /// Updates the DynamicReload handler and reloads the dynamic libraries if needed
    ///
    ///
    pub fn update(&self) {
    }

    fn reload_libs<F, T>(&mut self, file_path: &PathBuf, ref before_update: F, ref after_update: F, data: &mut T) where F : Fn(&mut T, &Rc<Lib>) {
        let len = self.libs.len();
        for i in (0..len).rev() {
            if Self::should_reload(file_path, &self.libs[i]) {
                Self::reload_lib(self, i, file_path, before_update, after_update, data);
            }
        }
    }

    fn reload_lib<F, T>(&mut self, index: usize, file_path: &PathBuf, ref before_update: F, ref after_update: F, data: &mut T) where F : Fn(&mut T, &Rc<Lib>) {
        before_update(data, &self.libs[index]);
        self.libs.swap_remove(index);

        match Self::load_library(self, file_path) {
            Ok(lib) => {
                self.libs.push(lib.clone());
                after_update(data, &lib);
            }

            // What should we really do here?
            Err(err) => {
                println!("Unable to reload lib {:?} err {:?}", file_path, err);
            }
        }
    }

    fn try_load_library(&self, name: &str, name_format: UsePlatformName) -> Result<Rc<Lib>, String> {
        if let Some(path) = Self::search_dirs(self, name, name_format) {
            Self::load_library(self, &path)
        } else {
            let mut t = "Unable to find ".to_string();
            t.push_str(name);
            Err(t)
        }
    }

    fn load_library(&self, full_path: &PathBuf) -> Result<Rc<Lib>, String> {
        let path;
        let original_path;

        if let Some(sd) = self.shadow_dir.as_ref() {
            path = sd.path().join(full_path.file_name().unwrap());
            if !Self::try_copy(&full_path, &path) {
                let mut error = "".to_string();
                write!(error, "Unable to copy {:?} to {:?}", full_path, path).unwrap();
                return Err(error);
            }
            original_path = Some(full_path.clone());
        } else {
            original_path = None;
            path = full_path.clone();
        }

        Self::init_library(original_path, path)
    }

    fn init_library(org_path: Option<PathBuf>, path: PathBuf) -> Result<Rc<Lib>, String> {
        match Library::new(&path) {
            Ok(l) => Ok(Rc::new(Lib {
                original_path: org_path,
                loaded_path: path,
            lib: l
            })),
            Err(e) => {
                let mut error = "".to_string();
                write!(error, "Unable to load library {:?}", e).unwrap();
                Err(error)
            }
        }
    }

    fn should_reload(reload_path: &PathBuf, lib: &Lib) -> bool {
        if let Some(p) = lib.original_path.as_ref() {
            if reload_path.to_str().unwrap().contains(p.to_str().unwrap()) {
                return true;
            }
        }

        false
    }

    fn search_dirs(&self, name: &str, name_format: UsePlatformName) -> Option<PathBuf> {
        let lib_name = Self::get_library_name(name, name_format);

        // 1. Serach the current directory
        if let Some(path) = Self::search_current_dir(&lib_name) {
            return Some(path);
        }

        // 2. search the relative paths
        if let Some(path) = Self::search_relative_paths(self, &lib_name) {
            return Some(path);
        }

        // 3. searches in the executable dir and then backwards
        Self::search_backwards_from_exe(&lib_name)
    }

    fn search_current_dir(name: &String) -> Option<PathBuf> {
        Self::is_file(&Path::new(name).to_path_buf())
    }

    fn search_relative_paths(&self, name: &String) -> Option<PathBuf> {
        for p in self.search_paths.iter() {
            let path = Path::new(p).join(name);
            if let Some(file) = Self::is_file(&path) {
                return Some(file);
            }
        }

        None
    }

    fn get_parent_dir(path: &PathBuf) -> Option<PathBuf> {
        match path.parent() {
            Some(p) => Some(p.to_path_buf()),
            _ => None,
        }
    }

    fn search_backwards_from_file(path: &PathBuf, lib_name: &String) -> Option<PathBuf> {
        match Self::get_parent_dir(path) {
            Some(p) => {
                let new_path = Path::new(&p).join(lib_name);
                if Self::is_file(&new_path).is_some() {
                    return Some(new_path);
                }
                Self::search_backwards_from_file(&p, lib_name)
            },
            _ => None,
        }
    }

    fn search_backwards_from_exe(lib_name: &String) -> Option<PathBuf> {
        let exe_path = env::current_exe().unwrap_or(PathBuf::new());
        Self::search_backwards_from_file(&exe_path, lib_name)
    }

    fn get_temp_dir(shadow_dir: Option<&str>) -> Option<TempDir> {
        match shadow_dir {
            Some(dir) => {
                match TempDir::new_in(dir, "shadow_libs") {
                    Ok(td) => Some(td),
                    Err(er) => {
                        println!("Unable to create tempdir {}", er);
                        None
                    }
                }
            }
            _ => None,
        }
    }

    fn is_file(path: &PathBuf) -> Option<PathBuf> {
        match fs::metadata(path) {
            Ok(md) => {
                if md.is_file() {
                    Some(path.clone())
                } else {
                    None
                }
            }
            _ => None,
        }
    }

    //
    // In some cases when a file has been set that it's reloaded it's actually not possible
    // to read from it directly so this code does some testing first to ensure we
    // can actually read from it (by using metadata which does a stat on the file)
    // If we can't read from it we wait for 100 ms before we try again, if we can't
    // do it with in 1 sec we give up
    //
    fn try_copy(src: &Path, dest: &Path) -> bool {
        for _ in 0..10 {
            match fs::metadata(src) {
                Ok(file) => {
                    let len = file.len();
                    if len > 0 {
                        fs::copy(&src, &dest).unwrap();
                        //println!("Copy from {} {}", src.to_str().unwrap(), dest.to_str().unwrap());
                        return true;
                    }
                }
                _ => (),
            }

            thread::sleep(Duration::from_millis(100));
        }

        false
    }

    fn get_watcher(tx: Sender<Event>) -> Option<RecommendedWatcher> {
        match Watcher::new(tx) {
            Ok(watcher) => Some(watcher),
            Err(e) => {
                println!("Unable to create file watcher, no dynamic reloading will be done, error: {:?}", e);
                None
            }
        }
    }

    pub fn get_search_paths(search_paths: Option<Vec<&'static str>>) -> Vec<&'static str> {
        match search_paths {
            Some(paths) => {
                paths.clone()
            },
            None => Vec::new(),
        }
    }

    fn get_library_name(name: &str, name_format: UsePlatformName) -> String {
        if name_format == UsePlatformName::Yes  {
            get_dynamiclib_name(name)
        } else {
            name.to_string()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::channel;
    use std::path::Path;
    use std::env;

    #[test]
    fn test_search_paths_none() {
        assert_eq!(DynamicReload::get_search_paths(None).len(), 0);
    }

    #[test]
    fn test_search_paths_some() {
        assert_eq!(DynamicReload::get_search_paths(Some(vec!["test", "test"])).len(), 2);
    }

    #[test]
    fn test_get_watcher() {
        let (tx, _) = channel();
        // We expect this to always work
        assert!(DynamicReload::get_watcher(tx).is_some());
    }

    #[test]
    fn test_get_temp_dir_fail() {
        assert!(DynamicReload::get_temp_dir(Some("_no_such_dir")).is_none());
    }

    #[test]
    fn test_get_temp_dir_none() {
        assert!(DynamicReload::get_temp_dir(None).is_none());
    }

    #[test]
    fn test_get_temp_dir_ok() {
        assert!(DynamicReload::get_temp_dir(Some("")).is_some());
    }

    #[test]
    fn test_is_file_fail() {
        assert!(DynamicReload::is_file(&Path::new("haz_no_file_with_this_name").to_path_buf()).is_none());
    }

    #[test]
    fn test_is_file_ok() {
        assert!(DynamicReload::is_file(&env::current_exe().unwrap()).is_some());
    }

    #[test]
    #[cfg(target_os="macos")]
    fn test_get_library_name_mac() {
        assert_eq!(DynamicReload::get_library_name("foobar", UsePlatformName::Yes), "libfoobar.dylib");
    }

    #[test]
    fn test_get_library_name() {
        assert_eq!(DynamicReload::get_library_name("foobar", UsePlatformName::No), "foobar");
    }

    #[test]
    fn test_search_backwards_from_file_ok() {
        // While this rely on that we have a Cargo project it should be fine
        assert!(DynamicReload::search_backwards_from_exe(&"Cargo.toml".to_string()).is_some());
    }

    #[test]
    fn test_search_backwards_from_file_fail() {
        assert!(DynamicReload::search_backwards_from_exe(&"_no_such_file".to_string()).is_none());
    }
}
<commit_msg>Added test case which should fail<commit_after>extern crate libc;
extern crate notify;
extern crate libloading;
extern crate tempdir;

use libloading::Library;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver, Sender};
use notify::{RecommendedWatcher, Watcher, Event};
use tempdir::TempDir;
use std::time::Duration;
use std::thread;
use std::fs;
use std::env;
use std::fmt::Write;

/// Formats dll name on Windows ("test_foo" -> "test_foo.dll")
#[cfg(target_os="windows")]
fn get_dynamiclib_name(name: &str) -> String {
    format!("{}.dll", name)
}

/// Formats dll name on Mac ("test_foo" -> "libtest_foo.dylib")
#[cfg(target_os="macos")]
fn get_dynamiclib_name(name: &str) -> String {
    format!("lib{}.dylib", name)
}

/// Formats dll name on *nix ("test_foo" -> "libtest_foo.so")
#[cfg(any(target_os="linux",
          target_os="freebsd",
          target_os="dragonfly",
          target_os="netbsd",
          target_os="openbsd"))]
fn get_dynamiclib_name(name: &str) -> String {
    format!("lib{}.so", name)
}

pub struct Lib {
    pub lib: Library,
    pub loaded_path: PathBuf,
    pub original_path: Option<PathBuf>,
}

pub struct DynamicReload {
    libs: Vec<Rc<Lib>>,
    watcher: Option<RecommendedWatcher>,
    shadow_dir: Option<TempDir>,
    search_paths: Vec<&'static str>,
    watch_recv: Receiver<Event>,
}

pub enum Search {
    Default,
    Backwards,
}

#[derive(PartialEq)]
pub enum UsePlatformName {
    No,
    Yes
}

// Test

impl DynamicReload {

    ///
    ///
    pub fn new(search_paths: Option<Vec<&'static str>>, shadow_dir: Option<&'static str>, _search: Search) -> DynamicReload {
        let (tx, rx) = channel();
        DynamicReload {
            libs: Vec::new(),
            watcher: Self::get_watcher(tx),
            shadow_dir: Self::get_temp_dir(shadow_dir),
            watch_recv: rx,
            search_paths: Self::get_search_paths(search_paths),
        }
    }

    ///
    /// Add a library to be loaded and to be reloaded once updated.
    /// If UsePlatformName is set to Yes the input name will be formatted according
    /// to the standard way libraries looks on that platform examples:
    ///
    /// ```ignore
    /// Windows: foobar -> foobar.dll
    /// Linux:   foobar -> libfoobar.so
    /// Mac:     foobar -> libfoobar.dylib
    /// ````
    ///
    /// If set to no the given inputname will be used as is. This function
    /// will also search for the file in this priority order
    ///
    ///
    /// ```ignore
    /// 1. Current directory
    /// 2. In the search paths (relative to currect directory)
    /// 3. Currect directory of the executable
    /// 4. Serach backwards from executable if Backwards has been set in [new](struct.DynamicReload.html#method.new)
    /// ```
    ///
    pub fn add_library(&mut self, name: &str, name_format: UsePlatformName) -> Result<Rc<Lib>, String> {
        match Self::try_load_library(self, name, name_format) {
            Ok(lib) => {
                if let Some(w) = self.watcher.as_mut() {
                    if let Some(path) = lib.original_path.as_ref() {
                        let _ = w.watch(path);
                    }
                }
                // Bump the ref here as we keep one around to keep track of files that needs to be reloaded
                self.libs.push(lib.clone());
                Ok(lib)
            }
            Err(e) => Err(e),
        }
    }

    ///
    /// Update the will check if a dynamic library needs to be reloaded and if that is the case
    /// then the supplied callback functions will be called
    ///
    /// First the before_reload code. This allows the calling application to performe actions
    /// before the dynamic library is unloaded. This can for example be to save some internal
    /// state that needs to be restorted when relodaded
    ///
    /// After the reloading is comple the post_reload function will be called giving the host
    /// application the possibility to restore any potentially saved state
    ///
    /// If no callbacks are needed use the regular [update](struct.DynamicReload.html#method.update) call instead
    ///
    pub fn update_with_callback<F, T>(&mut self, ref before_update: F, ref after_update: F, data: &mut T) where F : Fn(&mut T, &Rc<Lib>) {
        match self.watch_recv.try_recv() {
            Ok(file) => Self::reload_libs(self, file.path.as_ref().unwrap(), before_update, after_update, data),
            _ => (),
        }
    }

    ///
    /// Updates the DynamicReload handler and reloads the dynamic libraries if needed
    ///
    ///
    pub fn update(&self) {
    }

    fn reload_libs<F, T>(&mut self, file_path: &PathBuf, ref before_update: F, ref after_update: F, data: &mut T) where F : Fn(&mut T, &Rc<Lib>) {
        let len = self.libs.len();
        for i in (0..len).rev() {
            if Self::should_reload(file_path, &self.libs[i]) {
                Self::reload_lib(self, i, file_path, before_update, after_update, data);
            }
        }
    }

    fn reload_lib<F, T>(&mut self, index: usize, file_path: &PathBuf, ref before_update: F, ref after_update: F, data: &mut T) where F : Fn(&mut T, &Rc<Lib>) {
        before_update(data, &self.libs[index]);
        self.libs.swap_remove(index);

        match Self::load_library(self, file_path) {
            Ok(lib) => {
                self.libs.push(lib.clone());
                after_update(data, &lib);
            }

            // What should we really do here?
            Err(err) => {
                println!("Unable to reload lib {:?} err {:?}", file_path, err);
            }
        }
    }

    fn try_load_library(&self, name: &str, name_format: UsePlatformName) -> Result<Rc<Lib>, String> {
        if let Some(path) = Self::search_dirs(self, name, name_format) {
            Self::load_library(self, &path)
        } else {
            let mut t = "Unable to find ".to_string();
            t.push_str(name);
            Err(t)
        }
    }

    fn load_library(&self, full_path: &PathBuf) -> Result<Rc<Lib>, String> {
        let path;
        let original_path;

        if let Some(sd) = self.shadow_dir.as_ref() {
            path = sd.path().join(full_path.file_name().unwrap());
            if !Self::try_copy(&full_path, &path) {
                let mut error = "".to_string();
                write!(error, "Unable to copy {:?} to {:?}", full_path, path).unwrap();
                return Err(error);
            }
            original_path = Some(full_path.clone());
        } else {
            original_path = None;
            path = full_path.clone();
        }

        Self::init_library(original_path, path)
    }

    fn init_library(org_path: Option<PathBuf>, path: PathBuf) -> Result<Rc<Lib>, String> {
        match Library::new(&path) {
            Ok(l) => Ok(Rc::new(Lib {
                original_path: org_path,
                loaded_path: path,
            lib: l
            })),
            Err(e) => {
                let mut error = "".to_string();
                write!(error, "Unable to load library {:?}", e).unwrap();
                Err(error)
            }
        }
    }

    fn should_reload(reload_path: &PathBuf, lib: &Lib) -> bool {
        if let Some(p) = lib.original_path.as_ref() {
            if reload_path.to_str().unwrap().contains(p.to_str().unwrap()) {
                return true;
            }
        }

        false
    }

    fn search_dirs(&self, name: &str, name_format: UsePlatformName) -> Option<PathBuf> {
        let lib_name = Self::get_library_name(name, name_format);

        // 1. Serach the current directory
        if let Some(path) = Self::search_current_dir(&lib_name) {
            return Some(path);
        }

        // 2. search the relative paths
        if let Some(path) = Self::search_relative_paths(self, &lib_name) {
            return Some(path);
        }

        // 3. searches in the executable dir and then backwards
        Self::search_backwards_from_exe(&lib_name)
    }

    fn search_current_dir(name: &String) -> Option<PathBuf> {
        Self::is_file(&Path::new(name).to_path_buf())
    }

    fn search_relative_paths(&self, name: &String) -> Option<PathBuf> {
        for p in self.search_paths.iter() {
            let path = Path::new(p).join(name);
            if let Some(file) = Self::is_file(&path) {
                return Some(file);
            }
        }

        None
    }

    fn get_parent_dir(path: &PathBuf) -> Option<PathBuf> {
        match path.parent() {
            Some(p) => Some(p.to_path_buf()),
            _ => None,
        }
    }

    fn search_backwards_from_file(path: &PathBuf, lib_name: &String) -> Option<PathBuf> {
        match Self::get_parent_dir(path) {
            Some(p) => {
                let new_path = Path::new(&p).join(lib_name);
                if Self::is_file(&new_path).is_some() {
                    return Some(new_path);
                }
                Self::search_backwards_from_file(&p, lib_name)
            },
            _ => None,
        }
    }

    fn search_backwards_from_exe(lib_name: &String) -> Option<PathBuf> {
        let exe_path = env::current_exe().unwrap_or(PathBuf::new());
        Self::search_backwards_from_file(&exe_path, lib_name)
    }

    fn get_temp_dir(shadow_dir: Option<&str>) -> Option<TempDir> {
        match shadow_dir {
            Some(dir) => {
                match TempDir::new_in(dir, "shadow_libs") {
                    Ok(td) => Some(td),
                    Err(er) => {
                        println!("Unable to create tempdir {}", er);
                        None
                    }
                }
            }
            _ => None,
        }
    }

    fn is_file(path: &PathBuf) -> Option<PathBuf> {
        match fs::metadata(path) {
            Ok(md) => {
                if md.is_file() {
                    Some(path.clone())
                } else {
                    None
                }
            }
            _ => None,
        }
    }

    //
    // In some cases when a file has been set that it's reloaded it's actually not possible
    // to read from it directly so this code does some testing first to ensure we
    // can actually read from it (by using metadata which does a stat on the file)
    // If we can't read from it we wait for 100 ms before we try again, if we can't
    // do it with in 1 sec we give up
    //
    fn try_copy(src: &Path, dest: &Path) -> bool {
        for _ in 0..10 {
            match fs::metadata(src) {
                Ok(file) => {
                    let len = file.len();
                    if len > 0 {
                        fs::copy(&src, &dest).unwrap();
                        //println!("Copy from {} {}", src.to_str().unwrap(), dest.to_str().unwrap());
                        return true;
                    }
                }
                _ => (),
            }

            thread::sleep(Duration::from_millis(100));
        }

        false
    }

    fn get_watcher(tx: Sender<Event>) -> Option<RecommendedWatcher> {
        match Watcher::new(tx) {
            Ok(watcher) => Some(watcher),
            Err(e) => {
                println!("Unable to create file watcher, no dynamic reloading will be done, error: {:?}", e);
                None
            }
        }
    }

    pub fn get_search_paths(search_paths: Option<Vec<&'static str>>) -> Vec<&'static str> {
        match search_paths {
            Some(paths) => {
                paths.clone()
            },
            None => Vec::new(),
        }
    }

    fn get_library_name(name: &str, name_format: UsePlatformName) -> String {
        if name_format == UsePlatformName::Yes  {
            get_dynamiclib_name(name)
        } else {
            name.to_string()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::channel;
    use std::path::Path;
    use std::env;

    #[test]
    fn test_search_paths_none() {
        assert_eq!(DynamicReload::get_search_paths(None).len(), 0);
    }

    #[test]
    fn test_search_paths_some() {
        assert_eq!(DynamicReload::get_search_paths(Some(vec!["test", "test"])).len(), 2);
    }

    #[test]
    fn test_get_watcher() {
        let (tx, _) = channel();
        // We expect this to always work
        assert!(DynamicReload::get_watcher(tx).is_some());
    }

    #[test]
    fn test_get_temp_dir_fail() {
        assert!(DynamicReload::get_temp_dir(Some("_no_such_dir")).is_none());
    }

    #[test]
    fn test_get_temp_dir_none() {
        assert!(DynamicReload::get_temp_dir(None).is_none());
    }

    #[test]
    fn test_get_temp_dir_ok() {
        assert!(DynamicReload::get_temp_dir(Some("")).is_some());
    }

    #[test]
    fn test_is_file_fail() {
        assert!(DynamicReload::is_file(&Path::new("haz_no_file_with_this_name").to_path_buf()).is_none());
    }

    #[test]
    fn test_is_file_ok() {
        assert!(DynamicReload::is_file(&env::current_exe().unwrap()).is_some());
    }

    #[test]
    #[cfg(target_os="macos")]
    fn test_get_library_name_mac() {
        assert_eq!(DynamicReload::get_library_name("foobar", UsePlatformName::Yes), "libfoobar.dylib");
    }

    #[test]
    fn test_get_library_name() {
        assert_eq!(DynamicReload::get_library_name("foobar", UsePlatformName::No), "foobar");
    }

    #[test]
    fn test_search_backwards_from_file_ok() {
        // While this rely on that we have a Cargo project it should be fine
        assert!(DynamicReload::search_backwards_from_exe(&"Cargo.toml".to_string()).is_some());
    }

    #[test]
    fn test_search_backwards_from_file_fail() {
        assert!(DynamicReload::search_backwards_from_exe(&"_no_such_file".to_string()).is_none());
    }

    #[test]
    fn test_add_library_fail() {
        let mut dr = DynamicReload::new(None, None, Search::Default);
        assert!(dr.add_library("wont_find_this_lib", UsePlatformName::No).is_err());
    }
}
<|endoftext|>


<commit_before>extern crate xml;

use std::fs::File;
use std::io::BufReader;
use std::str::FromStr;
use std::num;

use xml::reader::{EventReader, XmlEvent};
use xml::name::OwnedName;
use xml::attribute::OwnedAttribute;

pub type Coordinate = f64;

#[derive(Debug, PartialEq)]
pub struct Bounds {
    pub minlat: Coordinate,
    pub minlon: Coordinate,
    pub maxlat: Coordinate,
    pub maxlon: Coordinate,
}

pub struct OSM {
    pub bounds: Option<Bounds>
}

impl OSM {
    fn empty() -> OSM {
        OSM {
            bounds: None
        }
    }

    pub fn parse(file: File) -> Option<OSM> {
        let mut osm = OSM::empty();

        let reader = BufReader::new(file);
        let parser = EventReader::new(reader);

        for element in parser {
            match element {
                Ok(XmlEvent::StartElement { name, attributes, .. }) => {
                    handle_element(&mut osm, name, attributes);
                },
                _ => { }
            }
        }

        Some(osm)
    }
}

enum ErrorKind {
    BoundsMissing(AttributeError),
    UnkownElement
}

enum AttributeError {
    ParseFloat(num::ParseFloatError),
    Missing
}

impl From<num::ParseFloatError> for AttributeError {
    fn from(err: num::ParseFloatError) -> AttributeError {
        AttributeError::ParseFloat(err)
    }
}

#[allow(dead_code)]
enum ElementType {
    Bounds,
    Node,
    Way,
    Relation
}

impl FromStr for ElementType {
    type Err = ErrorKind;

    fn from_str(s: &str) -> Result<ElementType, ErrorKind> {
        let downcased = s.to_lowercase();

        if downcased == "bounds" {
            return Ok(ElementType::Bounds);
        }

        if downcased == "node" {
            return Ok(ElementType::Way);
        }

        if downcased == "way" {
            return Ok(ElementType::Way);
        }

        if downcased == "relation" {
            return Ok(ElementType::Relation);
        }

        Err(ErrorKind::UnkownElement)
    }
}

fn handle_element(osm: &mut OSM, name: OwnedName, attrs: Vec<OwnedAttribute>) {
    match ElementType::from_str(&name.local_name) {
        Ok(element) => {
            match element {
                ElementType::Bounds => set_bounds(osm, &attrs),
                _ => ()
            }
        },
        Err(_) => ()
    }
}

fn set_bounds(osm: &mut OSM, attrs: &Vec<OwnedAttribute>) {
    match parse_bounds(&attrs) {
        Ok(bounds) => osm.bounds = Some(bounds),
        Err(_) => osm.bounds = None
    }
}

fn parse_bounds(attrs: &Vec<OwnedAttribute>) -> Result<Bounds, ErrorKind> {
    let minlat = try!(find_attribute::<Coordinate>("minlat", attrs).map_err(ErrorKind::BoundsMissing));
    let minlon = try!(find_attribute::<Coordinate>("minlon", attrs).map_err(ErrorKind::BoundsMissing));
    let maxlat = try!(find_attribute::<Coordinate>("maxlat", attrs).map_err(ErrorKind::BoundsMissing));
    let maxlon = try!(find_attribute::<Coordinate>("maxlon", attrs).map_err(ErrorKind::BoundsMissing));

    Ok(Bounds {
        minlat: minlat,
        minlon: minlon,
        maxlat: maxlat,
        maxlon: maxlon,
    })
}

fn find_attribute<T>( name: &str, attrs: &Vec<OwnedAttribute>) -> Result<T, AttributeError>
    where AttributeError: std::convert::From<<T as std::str::FromStr>::Err>,
          T: FromStr
{
    let attr = attrs.iter().find(|attr| attr.name.local_name == name);
    match attr {
        Some(a) => {
            let val = try!(a.value.parse::<T>());
            Ok(val)
        },
        None => Err(AttributeError::Missing)
    }
}
<commit_msg>Do not specify unnecessary types<commit_after>extern crate xml;

use std::fs::File;
use std::io::BufReader;
use std::str::FromStr;
use std::num;

use xml::reader::{EventReader, XmlEvent};
use xml::name::OwnedName;
use xml::attribute::OwnedAttribute;

pub type Coordinate = f64;

#[derive(Debug, PartialEq)]
pub struct Bounds {
    pub minlat: Coordinate,
    pub minlon: Coordinate,
    pub maxlat: Coordinate,
    pub maxlon: Coordinate,
}

pub struct OSM {
    pub bounds: Option<Bounds>
}

impl OSM {
    fn empty() -> OSM {
        OSM {
            bounds: None
        }
    }

    pub fn parse(file: File) -> Option<OSM> {
        let mut osm = OSM::empty();

        let reader = BufReader::new(file);
        let parser = EventReader::new(reader);

        for element in parser {
            match element {
                Ok(XmlEvent::StartElement { name, attributes, .. }) => {
                    handle_element(&mut osm, name, attributes);
                },
                _ => { }
            }
        }

        Some(osm)
    }
}

enum ErrorKind {
    BoundsMissing(AttributeError),
    UnkownElement
}

enum AttributeError {
    ParseFloat(num::ParseFloatError),
    Missing
}

impl From<num::ParseFloatError> for AttributeError {
    fn from(err: num::ParseFloatError) -> AttributeError {
        AttributeError::ParseFloat(err)
    }
}

#[allow(dead_code)]
enum ElementType {
    Bounds,
    Node,
    Way,
    Relation
}

impl FromStr for ElementType {
    type Err = ErrorKind;

    fn from_str(s: &str) -> Result<ElementType, ErrorKind> {
        let downcased = s.to_lowercase();

        if downcased == "bounds" {
            return Ok(ElementType::Bounds);
        }

        if downcased == "node" {
            return Ok(ElementType::Way);
        }

        if downcased == "way" {
            return Ok(ElementType::Way);
        }

        if downcased == "relation" {
            return Ok(ElementType::Relation);
        }

        Err(ErrorKind::UnkownElement)
    }
}

fn handle_element(osm: &mut OSM, name: OwnedName, attrs: Vec<OwnedAttribute>) {
    match ElementType::from_str(&name.local_name) {
        Ok(element) => {
            match element {
                ElementType::Bounds => set_bounds(osm, &attrs),
                _ => ()
            }
        },
        Err(_) => ()
    }
}

fn set_bounds(osm: &mut OSM, attrs: &Vec<OwnedAttribute>) {
    match parse_bounds(&attrs) {
        Ok(bounds) => osm.bounds = Some(bounds),
        Err(_) => osm.bounds = None
    }
}

fn parse_bounds(attrs: &Vec<OwnedAttribute>) -> Result<Bounds, ErrorKind> {
    let minlat = try!(find_attribute("minlat", attrs).map_err(ErrorKind::BoundsMissing));
    let minlon = try!(find_attribute("minlon", attrs).map_err(ErrorKind::BoundsMissing));
    let maxlat = try!(find_attribute("maxlat", attrs).map_err(ErrorKind::BoundsMissing));
    let maxlon = try!(find_attribute("maxlon", attrs).map_err(ErrorKind::BoundsMissing));

    Ok(Bounds {
        minlat: minlat,
        minlon: minlon,
        maxlat: maxlat,
        maxlon: maxlon,
    })
}

fn find_attribute<T>( name: &str, attrs: &Vec<OwnedAttribute>) -> Result<T, AttributeError>
    where AttributeError: std::convert::From<<T as std::str::FromStr>::Err>,
          T: FromStr
{
    let attr = attrs.iter().find(|attr| attr.name.local_name == name);
    match attr {
        Some(a) => {
            let val = try!(a.value.parse::<T>());
            Ok(val)
        },
        None => Err(AttributeError::Missing)
    }
}
<|endoftext|>


<commit_before>//! An attempt at sane float comparisons
//!
//! First, you must read [this][1].
//!
//! [1]: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition
//!
//! # What's in the crate?
//!
//! This crate provides three methods to test for *approximate* equality between floats:
//!
//! - Absolute difference (`Abs`): Checks that the absolute difference `|lhs - rhs|` is within some
//! tolerance.
//! - Relative difference (`Rel`): Checks that the relative difference
//! `|lhs - rhs| / max(lhs, rhs)` is within some tolerance.
//! - ULP distance (`Ulp`): Checks that the "ULP" distance between `lhs` and `rhs` is within some
//! tolerance.
//!
//! The recommended way to use this crate, is to use the `approx::eq` free function:
//!
//! ``` ignore
//! use approx::{Rel, self};
//!
//! let v = create_rand_vec();
//! let x = naive_sum(&v);
//! let y = simd_sum(&v);
//!
//! assert!(aprox::eq(&x, &y, Rel::tol(1e-5)))
//! ```
//!
//! You can also use a macro to reduce verbosity:
//!
//! ``` ignore
//! macro_rules! assert_approx_eq {
//!     ($lhs:expr, $rhs:expr) => {
//!         assert!(::approx::eq(&($lhs), &($rhs), ::approx::Rel::tol(1e-5)));
//!     }
//! }
//!
//! assert_approx_eq!(x, y);
//! ```
//!
//! # What method should I use?
//!
//! There is no silver bullet, each method has it pros and cons. Some thoughts:
//!
//! - Both `Rel` and `Ulp` perform poorly when the values are near zero. `Abs` should be preferred
//!   in those cases.
//! - Picking a good tolerance for `Abs` requires having an idea of how big/small the values
//!   actually are.
//! - You can combine the methods by `||`ing them, with this approach you can counter each other
//!   weaknesses. For example:
//!
//!
//! ``` ignore
//! approx::eq(&x, &y, Abs::tol(1e-5)) || approx::eq::(&x, &y, Abs::rel(1e-5));
//! ```
//!
//! For values near zero, the `Abs` method will correctly detect approximate equality, and for
//! large values `Abs` tolerance will be too small, but then the `Rel` method will kick in and
//! catch what `Abs` missed.

#![cfg_attr(test, plugin(quickcheck_macros))]
#![deny(missing_docs)]
#![deny(warnings)]
#![feature(core)]
#![feature(plugin)]
#![feature(std_misc)]

#[cfg(test)] extern crate quickcheck;
#[cfg(test)] extern crate rand;

use std::num::{Float, Int};

mod abs;
mod rel;

pub mod ulp;

/// Approximate equality
pub trait Eq<Method> {
    /// Checks if two floats are approximately equal according to specified `Method` and
    /// `tolerance`
    fn approx_eq(&self, rhs: &Self, tolerance: Method) -> bool;
}

/// Absolute difference
///
/// Note: You should prefer this method when the values are near zero
#[derive(Copy)]
pub struct Abs<T>(T) where T: Float;

// TODO(rust-lang/rfcs#735) move this `impl` to the `abs` module
impl<T> Abs<T> where T: Float {
    /// Creates an absolute difference tolerance
    ///
    /// # Panics
    ///
    /// Panics if `x` is negative
    pub fn tol(x: T) -> Abs<T> {
        assert!(x >= Float::zero());

        Abs(x)
    }
}

/// Relative difference
///
/// Note: This method breaks down when the values are near zero
#[derive(Copy)]
pub struct Rel<T>(T) where T: Float;

// TODO(rust-lang/rfcs#735) move this `impl` to the `rel` module
impl<T> Rel<T> where T: Float {
    /// Creates a relative difference tolerance
    ///
    /// # Panics
    ///
    /// Panics if `x` is negative
    pub fn tol(x: T) -> Rel<T> {
        assert!(x >= Float::zero());

        Rel(x)
    }
}

/// "Unit of Least Precision" distance
///
/// Note: This method breaks down when the values are near zero
#[derive(Copy)]
pub struct Ulp<T>(T);

// TODO(rust-lang/rfcs#735) move this `impl` to the `ulp` module
impl<T> Ulp<T> where T: Int {
    /// Creates a ULP tolerance
    ///
    /// # Panics
    ///
    /// Panics if `x` is negative
    pub fn tol(x: T) -> Ulp<T> {
        assert!(x >= Int::zero());

        Ulp(x)
    }
}

/// Checks if `lhs` is approximately equal to `rhs` using the specified `Method` and `tolerance`
pub fn eq<A, Method>(lhs: &A, rhs: &A, tolerance: Method) -> bool where A: Eq<Method> {
    lhs.approx_eq(rhs, tolerance)
}
<commit_msg>fix: update to rust nightly<commit_after>//! An attempt at sane float comparisons
//!
//! First, you must read [this][1].
//!
//! [1]: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition
//!
//! # What's in the crate?
//!
//! This crate provides three methods to test for *approximate* equality between floats:
//!
//! - Absolute difference (`Abs`): Checks that the absolute difference `|lhs - rhs|` is within some
//! tolerance.
//! - Relative difference (`Rel`): Checks that the relative difference
//! `|lhs - rhs| / max(lhs, rhs)` is within some tolerance.
//! - ULP distance (`Ulp`): Checks that the "ULP" distance between `lhs` and `rhs` is within some
//! tolerance.
//!
//! The recommended way to use this crate, is to use the `approx::eq` free function:
//!
//! ``` ignore
//! use approx::{Rel, self};
//!
//! let v = create_rand_vec();
//! let x = naive_sum(&v);
//! let y = simd_sum(&v);
//!
//! assert!(aprox::eq(&x, &y, Rel::tol(1e-5)))
//! ```
//!
//! You can also use a macro to reduce verbosity:
//!
//! ``` ignore
//! macro_rules! assert_approx_eq {
//!     ($lhs:expr, $rhs:expr) => {
//!         assert!(::approx::eq(&($lhs), &($rhs), ::approx::Rel::tol(1e-5)));
//!     }
//! }
//!
//! assert_approx_eq!(x, y);
//! ```
//!
//! # What method should I use?
//!
//! There is no silver bullet, each method has it pros and cons. Some thoughts:
//!
//! - Both `Rel` and `Ulp` perform poorly when the values are near zero. `Abs` should be preferred
//!   in those cases.
//! - Picking a good tolerance for `Abs` requires having an idea of how big/small the values
//!   actually are.
//! - You can combine the methods by `||`ing them, with this approach you can counter each other
//!   weaknesses. For example:
//!
//!
//! ``` ignore
//! approx::eq(&x, &y, Abs::tol(1e-5)) || approx::eq::(&x, &y, Abs::rel(1e-5));
//! ```
//!
//! For values near zero, the `Abs` method will correctly detect approximate equality, and for
//! large values `Abs` tolerance will be too small, but then the `Rel` method will kick in and
//! catch what `Abs` missed.

#![cfg_attr(test, allow(trivial_casts))]
#![cfg_attr(test, plugin(quickcheck_macros))]
#![deny(missing_docs)]
#![deny(warnings)]
#![feature(core)]
#![feature(plugin)]
#![feature(std_misc)]

#[cfg(test)] extern crate quickcheck;
#[cfg(test)] extern crate rand;

use std::num::{Float, Int};

mod abs;
mod rel;

pub mod ulp;

/// Approximate equality
pub trait Eq<Method> {
    /// Checks if two floats are approximately equal according to specified `Method` and
    /// `tolerance`
    fn approx_eq(&self, rhs: &Self, tolerance: Method) -> bool;
}

/// Absolute difference
///
/// Note: You should prefer this method when the values are near zero
#[derive(Copy)]
pub struct Abs<T>(T) where T: Float;

// TODO(rust-lang/rfcs#735) move this `impl` to the `abs` module
impl<T> Abs<T> where T: Float {
    /// Creates an absolute difference tolerance
    ///
    /// # Panics
    ///
    /// Panics if `x` is negative
    pub fn tol(x: T) -> Abs<T> {
        assert!(x >= Float::zero());

        Abs(x)
    }
}

/// Relative difference
///
/// Note: This method breaks down when the values are near zero
#[derive(Copy)]
pub struct Rel<T>(T) where T: Float;

// TODO(rust-lang/rfcs#735) move this `impl` to the `rel` module
impl<T> Rel<T> where T: Float {
    /// Creates a relative difference tolerance
    ///
    /// # Panics
    ///
    /// Panics if `x` is negative
    pub fn tol(x: T) -> Rel<T> {
        assert!(x >= Float::zero());

        Rel(x)
    }
}

/// "Unit of Least Precision" distance
///
/// Note: This method breaks down when the values are near zero
#[derive(Copy)]
pub struct Ulp<T>(T);

// TODO(rust-lang/rfcs#735) move this `impl` to the `ulp` module
impl<T> Ulp<T> where T: Int {
    /// Creates a ULP tolerance
    ///
    /// # Panics
    ///
    /// Panics if `x` is negative
    pub fn tol(x: T) -> Ulp<T> {
        assert!(x >= Int::zero());

        Ulp(x)
    }
}

/// Checks if `lhs` is approximately equal to `rhs` using the specified `Method` and `tolerance`
pub fn eq<A, Method>(lhs: &A, rhs: &A, tolerance: Method) -> bool where A: Eq<Method> {
    lhs.approx_eq(rhs, tolerance)
}
<|endoftext|>


<commit_before>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable, Clone)]
pub struct Version {
    name: String,
    vers: String,
    deps: Vec<Dependency>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

impl Version {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn version(&self) -> &str {
        &self.vers
    }

    pub fn dependencies(&self) -> &[Dependency] {
        &self.deps
    }

    pub fn checksum(&self) -> &str {
        &self.cksum
    }

    pub fn features(&self) -> &HashMap<String, Vec<String>> {
        &self.features
    }

    pub fn is_yanked(&self) -> bool {
        self.yanked
    }
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable, Clone)]
pub struct Dependency {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>
}

impl Dependency {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn requirement(&self) -> &str {
        &self.req
    }

    pub fn features(&self) -> &[String] {
        &self.features
    }

    pub fn is_optional(&self) -> bool {
        self.optional
    }

    pub fn has_default_features(&self) -> bool {
        self.default_features
    }

    pub fn target(&self) -> Option<&str> {
        match self.target {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn kind(&self) -> Option<&str> {
        match self.kind {
            Some(ref s) => Some(s),
            None => None,
        }
    }
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name().unwrap().to_str().unwrap().eq_ignore_ascii_case(crate_name))
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    /// Published versions of this crate sorted chronologically by date published
    pub fn versions(&self) -> &[Version] {
        &self.versions
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
    let crate_ = index.crates().nth(0).unwrap();
    let version = crate_.latest_version();
    let _ = version.deps;
}
<commit_msg>Skip over invalid filenames in index instead of crashing<commit_after>// Copyright 2015 Corey Farwell
// Copyright 2015 Contributors of github.com/huonw/crates.io-graph
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ascii::AsciiExt;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

extern crate git2;
extern crate glob;
extern crate rustc_serialize;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

/// A single version of crate published to the index
#[derive(RustcDecodable, Clone)]
pub struct Version {
    name: String,
    vers: String,
    deps: Vec<Dependency>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

impl Version {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn version(&self) -> &str {
        &self.vers
    }

    pub fn dependencies(&self) -> &[Dependency] {
        &self.deps
    }

    pub fn checksum(&self) -> &str {
        &self.cksum
    }

    pub fn features(&self) -> &HashMap<String, Vec<String>> {
        &self.features
    }

    pub fn is_yanked(&self) -> bool {
        self.yanked
    }
}

/// A single dependency of a specific crate version
#[derive(RustcDecodable, Clone)]
pub struct Dependency {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>
}

impl Dependency {
    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn requirement(&self) -> &str {
        &self.req
    }

    pub fn features(&self) -> &[String] {
        &self.features
    }

    pub fn is_optional(&self) -> bool {
        self.optional
    }

    pub fn has_default_features(&self) -> bool {
        self.default_features
    }

    pub fn target(&self) -> Option<&str> {
        match self.target {
            Some(ref s) => Some(s),
            None => None,
        }
    }

    pub fn kind(&self) -> Option<&str> {
        match self.kind {
            Some(ref s) => Some(s),
            None => None,
        }
    }
}

/// Constructed from `Index::crates`
pub struct Crates(CrateIndexPaths);

impl Iterator for Crates {
    type Item = Crate;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next().map(|p| Crate::new(&p))
    }
}

/// Constructed from `Index::crate_index_paths`
pub struct CrateIndexPaths(std::iter::Chain<glob::Paths, glob::Paths>);

impl CrateIndexPaths {
    fn new(path: PathBuf) -> CrateIndexPaths {
        let mut match_options = glob::MatchOptions::new();
        match_options.require_literal_leading_dot = true;

        let glob_pattern = format!("{}/*/*/*", path.to_str().unwrap());
        let index_paths1 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        let glob_pattern = format!("{}/[12]/*", path.to_str().unwrap());
        let index_paths2 = glob::glob_with(&glob_pattern, &match_options).unwrap();

        CrateIndexPaths(index_paths1.chain(index_paths2))
    }
}

impl Iterator for CrateIndexPaths {
    type Item = PathBuf;
    fn next(&mut self)  -> Option<Self::Item> {
        self.0.next().map(|glob_result| glob_result.unwrap())
    }
}

/// Wrapper around managing the crates.io-index git repository
pub struct Index {
    path: PathBuf,
}

impl Index {
    /// Construct a new Index supplying a path where the index lives or should live
    pub fn new(path: PathBuf) -> Index {
        Index{path: path}
    }

    /// Determines if *anything* exists at the path specified from the constructor
    pub fn exists(&self) -> bool {
        fs::metadata(&self.path).is_ok()
    }

    /// Clones the index to the path specified from the constructor
    pub fn clone(&self) -> Result<(), git2::Error> {
        let _ = try!(git2::Repository::clone(INDEX_GIT_URL, &self.path));
        Ok(())
    }

    /// Retrieve a single crate by name (case insensitive) from the index
    pub fn crate_(&self, crate_name: &str) -> Option<Crate> {
        self.crate_index_paths()
            .find(|path| path.file_name()
                             .and_then(OsStr::to_str)
                             .map(|file_name| file_name.eq_ignore_ascii_case(crate_name))
                             .unwrap_or(false))
            .map(|p| Crate::new(&p))
    }

    /// Retrieve an iterator over all the crates in the index
    pub fn crates(&self) -> Crates {
        Crates(self.crate_index_paths())
    }

    /// Returns all the crate index file paths in the index
    pub fn crate_index_paths(&self) -> CrateIndexPaths {
        CrateIndexPaths::new(self.path.clone())  // TODO: remove this clone
    }
}

/// A single crate that contains many published versions
pub struct Crate {
    versions: Vec<Version>,
}

impl Crate {
    pub fn new(index_path: &PathBuf) -> Crate {
        let mut versions = vec![];
        let file = fs::File::open(&index_path).unwrap();
        for line in BufReader::new(file).lines() {
            let version: Version = rustc_serialize::json::decode(&line.unwrap()).unwrap();
            versions.push(version);
        }
        Crate {versions: versions}
    }

    /// Published versions of this crate sorted chronologically by date published
    pub fn versions(&self) -> &[Version] {
        &self.versions
    }

    pub fn latest_version(&self) -> &Version {
        &self.versions[self.versions.len() - 1]
    }
}

#[test]
fn test_dependencies() {
    let index = Index::new("_test".into());
    if !index.exists() {
        index.clone().unwrap();
    }
    let crate_ = index.crates().nth(0).unwrap();
    let version = crate_.latest_version();
    let _ = version.deps;
}
<|endoftext|>