<commit_before>pub use slist::List::{Cons,Nil};
use std::fmt;
use std::ops::Index;

/// Convenience macro for making lists.
///
/// # Example:
///
/// ```
/// # #[macro_use] extern crate seax_svm;
/// # use seax_svm::svm::slist;
/// # use seax_svm::svm::slist::List::{Cons, Nil};
/// # fn main () {
/// assert_eq!(
///     list!(1i32, 2i32, 3i32),
///     Cons(1i32, Box::new(Cons(2i32, Box::new(Cons(3i32, Box::new(Nil))))))
///     );
/// # }
/// ```
#[macro_export]
macro_rules! list(
    ( $e:expr, $($rest:expr),+ ) => ( Cons($e, Box::new(list!( $( $rest ),+ )) ));
    ( $e:expr ) => ( Cons($e, Box::new(Nil)) );
    () => ( Box::new(Nil) );
);

/// Common functions for an immutable Stack abstract data type.
pub trait Stack<T> {

    /// Push an item to the top of the stack, returning a new stack
    fn push(self, item : T) -> Self;

    /// Pop the top element of the stack. Returns an Option on a T and
    /// a new Stack<T> to replace this.
    fn pop(self)            -> Option<(T, Self)>;

    /// Peek at the top item of the stack.
    ///
    /// Returns Some<T> if there is an item on top of the stack,
    /// and None if the stack is empty.
    fn peek(&self)          -> Option<&T>;

    /// Returns an empty stack.
    fn empty()              -> Self;
}

/// Stack implementation using a cons list
impl<T> Stack<T> for List<T> {

    /// Push an item to the top of the stack, returning a new stack.
    ///
    /// # Examples:
    /// ```
    /// use seax_svm::svm::slist::{List,Stack};
    ///
    /// let mut s: List<isize> = Stack::empty();
    /// assert_eq!(s.peek(), None);
    /// s = s.push(1);
    /// assert_eq!(s.peek(), Some(&1));
    /// s = s.push(6);
    /// assert_eq!(s.peek(), Some(&6));
    /// ```
    fn push(self, item: T) -> List<T> {
        Cons(item, box self)
    }

    /// Pop the top element of the stack.
    ///
    /// Pop the top element of the stack. Returns an
    /// `Option<(T,List<T>)>` containing the top element and a new
    /// `List<T>` with that item removed, or `None` if the stack is
    /// empty.
    ///
    /// # Examples:
    /// ```
    /// # use seax_svm::svm::slist::{List,Stack};
    ///
    /// let mut s: List<isize> = Stack::empty();
    /// s = s.push(2);
    /// s = s.push(1);
    /// let pop_result = s.pop().unwrap();
    /// s = pop_result.1;
    /// assert_eq!(s.peek(), Some(&2));
    /// assert_eq!(pop_result.0, 1);
    /// ```
    fn pop(self) -> Option<(T,List<T>)> {
        match self {
            Cons(item, new_self)    => Some((item, *new_self)),
            Nil                     => None
        }
    }

    fn empty() -> List<T> {
        Nil
    }

    /// Peek at the top element of the stack.
    ///
    /// Peek at the top element of the stack. Returns an `Option<&T>`
    /// with a borrowed pointer to the top element, or `None` if the
    /// stack is empty.
    ///
    /// # Examples:
    /// ```
    /// # use seax_svm::svm::slist::{List,Stack};
    ///
    /// let mut s: List<isize> = Stack::empty();
    /// s = s.push(2);
    /// s = s.push(1);
    /// let pop_result = s.pop().unwrap();
    /// s = pop_result.1;
    /// assert_eq!(s.peek(), Some(&2));
    /// assert_eq!(pop_result.0, 1);
    /// ```
    fn peek(&self) -> Option<&T> {
        match self {
            &Nil => None,
            &Cons(ref it,_) => Some(it)
        }
    }

}

/// Singly-linked cons list.
///
/// This is used internally to represent list primitives in the
/// machine.
#[derive(PartialEq,Clone,Debug)]
pub enum List<T> {
    /// Cons cell containing a `T` and a link to the tail
    Cons(T, Box<List<T>>),
    /// The empty list.
    Nil,
}

/// Public implementation for List.
impl<T> List<T> {

    /// Creates a new empty list
    pub fn new() -> List<T> {
        Nil
    }

    /// Prepends the given item to the list.
    ///
    /// Returns the list containing the new  head item.
    /// This is an O(1) operation.
    pub fn prepend(self, it: T) -> List<T> {
        Cons(it, box self)
    }

    /// Appends an item to the end of the list.
    ///
    /// This is an O(n) operation.
    pub fn append(self, it: T) {
        unimplemented!()
    }

    /// Returns the length of the list.
    pub fn length (&self) -> usize {
        match *self {
            Cons(_, ref tail) => 1 + tail.length(),
            Nil => 0
        }
    }

    /// Provide a forward iterator
    #[inline]
    pub fn iter<'a>(&'a self) -> ListIterator<'a, T> {
        ListIterator{current: self}
    }

    pub fn last(&self) -> &T {
        match *self {
            Cons(ref car, box Nil) => &car,
            Cons(_, ref cdr @ box Cons(_,_)) => cdr.last(),
            Nil => panic!("Last called on empty list")
        }
    }
}

impl<'a, T> fmt::Display for List<T> where T: fmt::Display{

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: replace toString with this
        match *self {
            Cons(ref head, ref tail) => write!(f, "({}, {})", head, tail),
            Nil => write!(f,"nil")
        }
    }
}

/// Wraps a List<T> to allow it to be used as an Iterator<T>
pub struct ListIterator<'a, T:'a> {
    current: &'a List<T>
}

/// Implementation of Iterator for List. This allows iteration by
/// link hopping.
impl<'a, T> Iterator for ListIterator<'a, T> {
    type Item = &'a T;

    /// Get the next element from the list.
    ///
    /// Get the next element from the list. Returns a `Some<T>`, or `Nil`
    /// if at the end of the list.
    ///
    /// # Examples:
    /// ```
    /// # #[macro_use] extern crate seax_svm;
    /// # use seax_svm::svm::slist;
    /// # use seax_svm::svm::slist::List;
    /// # use seax_svm::svm::slist::List::{Cons, Nil};
    /// # fn main () {
    /// let list = list!(1,2,3);
    /// let mut iter = list.iter();
    /// assert_eq!(iter.next().unwrap(), &1);
    /// assert_eq!(iter.next().unwrap(), &2);
    /// assert_eq!(iter.next().unwrap(), &3);
    /// # }
    /// ```
    /// ```
    /// # #[macro_use] extern crate seax_svm;
    /// # use seax_svm::svm::slist;
    /// # use seax_svm::svm::slist::List;
    /// # use seax_svm::svm::slist::List::{Cons, Nil};
    /// # fn main () {
    /// let l: List<isize> = list!(1,2,3,4,5,6);
    /// let mut string = String::new();
    /// for item in l.iter() {
    ///     string.push_str((item.to_string() + ", ").as_slice());
    /// }
    /// assert_eq!(string.as_slice(), "1, 2, 3, 4, 5, 6, ")
    /// # }
    /// ```
    fn next(&mut self) -> Option<&'a T> {
        match self.current {
            &Cons(ref head, box ref tail) => { self.current = tail; Some(head) },
            &Nil => None
        }
    }
}

impl<'a, T> ExactSizeIterator for ListIterator<'a, T> {
    fn len(&self) -> usize {
        self.current.length()
    }
}
/// Implementation of indexing for `List<T>`.
///
/// # Examples:
/// ```
/// # #[macro_use] extern crate seax_svm;
/// # use seax_svm::svm::slist;
/// # use seax_svm::svm::slist::List;
/// # use seax_svm::svm::slist::List::{Cons, Nil};
/// # fn main () {
/// let list = list!(1,2,3,4,5,6);
/// assert_eq!(list[0us], 1);
/// # }
/// ```
impl<T> Index<usize> for List<T> {
    type Output = T;

    fn index<'a>(&'a self, _index: &usize) -> &'a T {
        match *_index {
            0usize => match *self {
                Cons(ref car, _) => car,
                Nil => panic!("List index {} out of range", _index)
            },
            1usize => match *self {
                Cons(_, box Cons(ref cdr, _)) => cdr,
                Cons(_, box Nil) => panic!("List index {} out of range", _index),
                Nil => panic!("List index {} out of range", _index)
            },
            i if i == self.length() => self.last(),
            i if i > self.length()  => panic!("List index {:?} out of range.", _index),
            i if i > 1usize => {
                let mut it = self.iter();
                for _ in 0usize .. i{
                    it.next();
                }
                it.next().unwrap()
            },
            _ => panic!("Expected an index i such that i >= 0, got {:?}.", _index)
        }
    }
}
/// Implementation of indexing for `List<T>`.
///
/// # Examples:
/// ```
/// # #[macro_use] extern crate seax_svm;
/// # use seax_svm::svm::slist;
/// # use seax_svm::svm::slist::List;
/// # use seax_svm::svm::slist::List::{Cons, Nil};
/// # fn main () {
/// let list = list!(1,2,3,4,5,6);
/// assert_eq!(list[0is], 1);
/// # }
/// ```
impl<T> Index<isize> for List<T> {
    type Output = T;

    fn index<'a>(&'a self, _index: &isize) -> &'a T {
        match *_index {
            0isize => match *self {
                Cons(ref car, _) => car,
                Nil => panic!("List index {} out of range", _index)
            },
            1isize => match *self {
                Cons(_, box Cons(ref cdr, _)) => cdr,
                Cons(_, box Nil) => panic!("List index {} out of range", _index),
                Nil => panic!("List index {} out of range", _index)
            },
            i if i == self.length() as isize => self.last(),
            i if i > self.length() as isize => panic!("List index {:?} out of range.", _index),
            i if i > 1isize => {
                let mut it = self.iter();
                for _ in 0isize .. i{
                    it.next();
                }
                it.next().unwrap()
            },
            _ => panic!("Expected an index i such that i >= 0, got {:?}.", _index)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{List, Stack};
    use super::List::{Cons,Nil};

    #[test]
    fn test_list_length() {
        let full_list: List<i32> = list!(1i32, 2i32, 3i32);
        let empty_list: List<i32> = List::new();
        assert_eq!(full_list.length(), 3);
        assert_eq!(empty_list.length(), 0);
    }

    #[test]
    fn test_list_to_string() {
        let l: List<i32> = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
        assert_eq!(l.to_string(), "(1, (2, (3, nil)))");
    }

    #[test]
    fn test_stack_length() {
        let full_stack: List<i32> = list!(1i32, 2i32, 3i32);
        let empty_stack: List<i32> = Stack::empty();
        assert_eq!(full_stack.length(), 3);
        assert_eq!(empty_stack.length(), 0);
    }

    #[test]
    fn test_stack_peek() {
        let full_stack: List<i32> = list!(1i32, 2i32, 3i32);
        let empty_stack: List<i32> = Stack::empty();
        assert_eq!(full_stack.peek(), Some(&1));
        assert_eq!(empty_stack.peek(), None);
    }

    #[test]
    fn test_stack_push() {
        let mut s: List<i32> = Stack::empty();
        assert_eq!(s.peek(), None);
        s = s.push(1);
        assert_eq!(s.peek(), Some(&1));
        s = s.push(6);
        assert_eq!(s.peek(), Some(&6));
    }

    #[test]
    fn test_stack_pop() {
        let mut s: List<i32> = Stack::empty();
        assert_eq!(s.peek(), None);
        s = s.push(1);
        assert_eq!(s.peek(), Some(&1));
        s = s.push(6);
        assert_eq!(s.peek(), Some(&6));
        let pop_result = s.pop().unwrap(); // should not break
        s = pop_result.1;
        assert_eq!(s.peek(), Some(&1));
        assert_eq!(pop_result.0, 6);
    }

    #[test]
    fn test_list_usize_indexing() {
        let l: List<isize> = list!(1,2,3,4,5,6);
        assert_eq!(l[0usize],1);
        assert_eq!(l[1usize],2);
        assert_eq!(l[2usize],3);
        assert_eq!(l[3usize],4);
        assert_eq!(l[4usize],5);
        assert_eq!(l[5usize],6);
    }

    #[test]
    fn test_list_isize_indexing() {
        let l: List<isize> = list!(1,2,3,4,5,6);
        assert_eq!(l[0isize],1);
        assert_eq!(l[1isize],2);
        assert_eq!(l[2isize],3);
        assert_eq!(l[3isize],4);
        assert_eq!(l[4isize],5);
        assert_eq!(l[5isize],6);
    }

    #[test]
    fn test_list_macro() {
        let l: List<i32> = list!(1i32, 2i32, 3i32);
        assert_eq!(l.to_string(), "(1, (2, (3, nil)))")
    }

    #[test]
    fn test_list_iter() {
        let l: List<isize> = list!(1,2,3,4,5,6);
        let mut string = String::new();
        for item in l.iter() {
            string.push_str((item.to_string() + ", ").as_slice());
        }
        assert_eq!(string.as_slice(), "1, 2, 3, 4, 5, 6, ")
    }

}
<commit_msg>Fix namespacing in doctests, too<commit_after>pub use slist::List::{Cons,Nil};
use std::fmt;
use std::ops::Index;

/// Convenience macro for making lists.
///
/// # Example:
///
/// ```
/// # #[macro_use] extern crate seax_svm;
/// # use seax_svm::slist;
/// # use seax_svm::slist::List::{Cons, Nil};
/// # fn main () {
/// assert_eq!(
///     list!(1i32, 2i32, 3i32),
///     Cons(1i32, Box::new(Cons(2i32, Box::new(Cons(3i32, Box::new(Nil))))))
///     );
/// # }
/// ```
#[macro_export]
macro_rules! list(
    ( $e:expr, $($rest:expr),+ ) => ( Cons($e, Box::new(list!( $( $rest ),+ )) ));
    ( $e:expr ) => ( Cons($e, Box::new(Nil)) );
    () => ( Box::new(Nil) );
);

/// Common functions for an immutable Stack abstract data type.
pub trait Stack<T> {

    /// Push an item to the top of the stack, returning a new stack
    fn push(self, item : T) -> Self;

    /// Pop the top element of the stack. Returns an Option on a T and
    /// a new Stack<T> to replace this.
    fn pop(self)            -> Option<(T, Self)>;

    /// Peek at the top item of the stack.
    ///
    /// Returns Some<T> if there is an item on top of the stack,
    /// and None if the stack is empty.
    fn peek(&self)          -> Option<&T>;

    /// Returns an empty stack.
    fn empty()              -> Self;
}

/// Stack implementation using a cons list
impl<T> Stack<T> for List<T> {

    /// Push an item to the top of the stack, returning a new stack.
    ///
    /// # Examples:
    /// ```
    /// use seax_svm::slist::{List,Stack};
    ///
    /// let mut s: List<isize> = Stack::empty();
    /// assert_eq!(s.peek(), None);
    /// s = s.push(1);
    /// assert_eq!(s.peek(), Some(&1));
    /// s = s.push(6);
    /// assert_eq!(s.peek(), Some(&6));
    /// ```
    fn push(self, item: T) -> List<T> {
        Cons(item, box self)
    }

    /// Pop the top element of the stack.
    ///
    /// Pop the top element of the stack. Returns an
    /// `Option<(T,List<T>)>` containing the top element and a new
    /// `List<T>` with that item removed, or `None` if the stack is
    /// empty.
    ///
    /// # Examples:
    /// ```
    /// # use seax_svm::slist::{List,Stack};
    ///
    /// let mut s: List<isize> = Stack::empty();
    /// s = s.push(2);
    /// s = s.push(1);
    /// let pop_result = s.pop().unwrap();
    /// s = pop_result.1;
    /// assert_eq!(s.peek(), Some(&2));
    /// assert_eq!(pop_result.0, 1);
    /// ```
    fn pop(self) -> Option<(T,List<T>)> {
        match self {
            Cons(item, new_self)    => Some((item, *new_self)),
            Nil                     => None
        }
    }

    fn empty() -> List<T> {
        Nil
    }

    /// Peek at the top element of the stack.
    ///
    /// Peek at the top element of the stack. Returns an `Option<&T>`
    /// with a borrowed pointer to the top element, or `None` if the
    /// stack is empty.
    ///
    /// # Examples:
    /// ```
    /// # use seax_svm::slist::{List,Stack};
    ///
    /// let mut s: List<isize> = Stack::empty();
    /// s = s.push(2);
    /// s = s.push(1);
    /// let pop_result = s.pop().unwrap();
    /// s = pop_result.1;
    /// assert_eq!(s.peek(), Some(&2));
    /// assert_eq!(pop_result.0, 1);
    /// ```
    fn peek(&self) -> Option<&T> {
        match self {
            &Nil => None,
            &Cons(ref it,_) => Some(it)
        }
    }

}

/// Singly-linked cons list.
///
/// This is used internally to represent list primitives in the
/// machine.
#[derive(PartialEq,Clone,Debug)]
pub enum List<T> {
    /// Cons cell containing a `T` and a link to the tail
    Cons(T, Box<List<T>>),
    /// The empty list.
    Nil,
}

/// Public implementation for List.
impl<T> List<T> {

    /// Creates a new empty list
    pub fn new() -> List<T> {
        Nil
    }

    /// Prepends the given item to the list.
    ///
    /// Returns the list containing the new  head item.
    /// This is an O(1) operation.
    pub fn prepend(self, it: T) -> List<T> {
        Cons(it, box self)
    }

    /// Appends an item to the end of the list.
    ///
    /// This is an O(n) operation.
    pub fn append(self, it: T) {
        unimplemented!()
    }

    /// Returns the length of the list.
    pub fn length (&self) -> usize {
        match *self {
            Cons(_, ref tail) => 1 + tail.length(),
            Nil => 0
        }
    }

    /// Provide a forward iterator
    #[inline]
    pub fn iter<'a>(&'a self) -> ListIterator<'a, T> {
        ListIterator{current: self}
    }

    pub fn last(&self) -> &T {
        match *self {
            Cons(ref car, box Nil) => &car,
            Cons(_, ref cdr @ box Cons(_,_)) => cdr.last(),
            Nil => panic!("Last called on empty list")
        }
    }
}

impl<'a, T> fmt::Display for List<T> where T: fmt::Display{

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: replace toString with this
        match *self {
            Cons(ref head, ref tail) => write!(f, "({}, {})", head, tail),
            Nil => write!(f,"nil")
        }
    }
}

/// Wraps a List<T> to allow it to be used as an Iterator<T>
pub struct ListIterator<'a, T:'a> {
    current: &'a List<T>
}

/// Implementation of Iterator for List. This allows iteration by
/// link hopping.
impl<'a, T> Iterator for ListIterator<'a, T> {
    type Item = &'a T;

    /// Get the next element from the list.
    ///
    /// Get the next element from the list. Returns a `Some<T>`, or `Nil`
    /// if at the end of the list.
    ///
    /// # Examples:
    /// ```
    /// # #[macro_use] extern crate seax_svm;
    /// # use seax_svm::slist;
    /// # use seax_svm::slist::List;
    /// # use seax_svm::slist::List::{Cons, Nil};
    /// # fn main () {
    /// let list = list!(1,2,3);
    /// let mut iter = list.iter();
    /// assert_eq!(iter.next().unwrap(), &1);
    /// assert_eq!(iter.next().unwrap(), &2);
    /// assert_eq!(iter.next().unwrap(), &3);
    /// # }
    /// ```
    /// ```
    /// # #[macro_use] extern crate seax_svm;
    /// # use seax_svm::slist;
    /// # use seax_svm::slist::List;
    /// # use seax_svm::slist::List::{Cons, Nil};
    /// # fn main () {
    /// let l: List<isize> = list!(1,2,3,4,5,6);
    /// let mut string = String::new();
    /// for item in l.iter() {
    ///     string.push_str((item.to_string() + ", ").as_slice());
    /// }
    /// assert_eq!(string.as_slice(), "1, 2, 3, 4, 5, 6, ")
    /// # }
    /// ```
    fn next(&mut self) -> Option<&'a T> {
        match self.current {
            &Cons(ref head, box ref tail) => { self.current = tail; Some(head) },
            &Nil => None
        }
    }
}

impl<'a, T> ExactSizeIterator for ListIterator<'a, T> {
    fn len(&self) -> usize {
        self.current.length()
    }
}
/// Implementation of indexing for `List<T>`.
///
/// # Examples:
/// ```
/// # #[macro_use] extern crate seax_svm;
/// # use seax_svm::slist;
/// # use seax_svm::slist::List;
/// # use seax_svm::slist::List::{Cons, Nil};
/// # fn main () {
/// let list = list!(1,2,3,4,5,6);
/// assert_eq!(list[0us], 1);
/// # }
/// ```
impl<T> Index<usize> for List<T> {
    type Output = T;

    fn index<'a>(&'a self, _index: &usize) -> &'a T {
        match *_index {
            0usize => match *self {
                Cons(ref car, _) => car,
                Nil => panic!("List index {} out of range", _index)
            },
            1usize => match *self {
                Cons(_, box Cons(ref cdr, _)) => cdr,
                Cons(_, box Nil) => panic!("List index {} out of range", _index),
                Nil => panic!("List index {} out of range", _index)
            },
            i if i == self.length() => self.last(),
            i if i > self.length()  => panic!("List index {:?} out of range.", _index),
            i if i > 1usize => {
                let mut it = self.iter();
                for _ in 0usize .. i{
                    it.next();
                }
                it.next().unwrap()
            },
            _ => panic!("Expected an index i such that i >= 0, got {:?}.", _index)
        }
    }
}
/// Implementation of indexing for `List<T>`.
///
/// # Examples:
/// ```
/// # #[macro_use] extern crate seax_svm;
/// # use seax_svm::slist;
/// # use seax_svm::slist::List;
/// # use seax_svm::slist::List::{Cons, Nil};
/// # fn main () {
/// let list = list!(1,2,3,4,5,6);
/// assert_eq!(list[0is], 1);
/// # }
/// ```
impl<T> Index<isize> for List<T> {
    type Output = T;

    fn index<'a>(&'a self, _index: &isize) -> &'a T {
        match *_index {
            0isize => match *self {
                Cons(ref car, _) => car,
                Nil => panic!("List index {} out of range", _index)
            },
            1isize => match *self {
                Cons(_, box Cons(ref cdr, _)) => cdr,
                Cons(_, box Nil) => panic!("List index {} out of range", _index),
                Nil => panic!("List index {} out of range", _index)
            },
            i if i == self.length() as isize => self.last(),
            i if i > self.length() as isize => panic!("List index {:?} out of range.", _index),
            i if i > 1isize => {
                let mut it = self.iter();
                for _ in 0isize .. i{
                    it.next();
                }
                it.next().unwrap()
            },
            _ => panic!("Expected an index i such that i >= 0, got {:?}.", _index)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{List, Stack};
    use super::List::{Cons,Nil};

    #[test]
    fn test_list_length() {
        let full_list: List<i32> = list!(1i32, 2i32, 3i32);
        let empty_list: List<i32> = List::new();
        assert_eq!(full_list.length(), 3);
        assert_eq!(empty_list.length(), 0);
    }

    #[test]
    fn test_list_to_string() {
        let l: List<i32> = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
        assert_eq!(l.to_string(), "(1, (2, (3, nil)))");
    }

    #[test]
    fn test_stack_length() {
        let full_stack: List<i32> = list!(1i32, 2i32, 3i32);
        let empty_stack: List<i32> = Stack::empty();
        assert_eq!(full_stack.length(), 3);
        assert_eq!(empty_stack.length(), 0);
    }

    #[test]
    fn test_stack_peek() {
        let full_stack: List<i32> = list!(1i32, 2i32, 3i32);
        let empty_stack: List<i32> = Stack::empty();
        assert_eq!(full_stack.peek(), Some(&1));
        assert_eq!(empty_stack.peek(), None);
    }

    #[test]
    fn test_stack_push() {
        let mut s: List<i32> = Stack::empty();
        assert_eq!(s.peek(), None);
        s = s.push(1);
        assert_eq!(s.peek(), Some(&1));
        s = s.push(6);
        assert_eq!(s.peek(), Some(&6));
    }

    #[test]
    fn test_stack_pop() {
        let mut s: List<i32> = Stack::empty();
        assert_eq!(s.peek(), None);
        s = s.push(1);
        assert_eq!(s.peek(), Some(&1));
        s = s.push(6);
        assert_eq!(s.peek(), Some(&6));
        let pop_result = s.pop().unwrap(); // should not break
        s = pop_result.1;
        assert_eq!(s.peek(), Some(&1));
        assert_eq!(pop_result.0, 6);
    }

    #[test]
    fn test_list_usize_indexing() {
        let l: List<isize> = list!(1,2,3,4,5,6);
        assert_eq!(l[0usize],1);
        assert_eq!(l[1usize],2);
        assert_eq!(l[2usize],3);
        assert_eq!(l[3usize],4);
        assert_eq!(l[4usize],5);
        assert_eq!(l[5usize],6);
    }

    #[test]
    fn test_list_isize_indexing() {
        let l: List<isize> = list!(1,2,3,4,5,6);
        assert_eq!(l[0isize],1);
        assert_eq!(l[1isize],2);
        assert_eq!(l[2isize],3);
        assert_eq!(l[3isize],4);
        assert_eq!(l[4isize],5);
        assert_eq!(l[5isize],6);
    }

    #[test]
    fn test_list_macro() {
        let l: List<i32> = list!(1i32, 2i32, 3i32);
        assert_eq!(l.to_string(), "(1, (2, (3, nil)))")
    }

    #[test]
    fn test_list_iter() {
        let l: List<isize> = list!(1,2,3,4,5,6);
        let mut string = String::new();
        for item in l.iter() {
            string.push_str((item.to_string() + ", ").as_slice());
        }
        assert_eq!(string.as_slice(), "1, 2, 3, 4, 5, 6, ")
    }

}
<|endoftext|>


<commit_before>extern crate getopts;
use getopts::Options;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::mem;

fn pointer_size() -> usize {
    let tmp = 0u8;
    let boxed = Box::new(tmp);
    mem::size_of_val(&boxed)
}

fn read_blend_file(inp: &str) -> io::Result<()> {
    // open file
    let mut file = File::open(inp).unwrap();
    // read 12 bytes from the Blender file
    let mut buf = [0u8; 12];
    file.read(&mut buf).unwrap();
    let mut header = String::new();
    for e in buf.iter() {
        header.push(*e as char);
    }
    println!("header = \"{}\"", header);
    // compare first 7 chars to "BLENDER"
    if header.len() >= 7 {
        // create copy of header without moving value
        let mut blender = String::new();
        blender = blender + &header;
        blender.truncate(7); // first 7 chars
        if blender == "BLENDER" {
            println!("starts with \"BLENDER\" ...");
            // switch to byte copy of String representation
            let bytes = header.into_bytes();
            // check 8th char of header
            println!("8th char of header = '{}'", bytes[7] as char);
            // check for 32-bit pointers vs. 64-bit pointers
            let ptr_size = pointer_size();
            println!("size of pointer in bytes: {}", ptr_size);
            let mut ptr_size_differs = false;
            if bytes[7] as char == '_' {
                // 32-bit pointers expected
                if ptr_size != 4 {
                    ptr_size_differs = true;
                }
                println!("32-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            } else {
                // 64-bit pointers expected
                if ptr_size != 8 {
                    ptr_size_differs = true;
                }
                println!("64-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            }
            // little endian or big endian?
            let mut l_endian;
            let endian_test = 1u16; // value one stored in two bytes
            if endian_test.to_le() != endian_test {
                l_endian = false;
            } else {
                // if we are on a little endian machine to_le() is a no-op
                l_endian = true;
            }
            println!("l_endian = {}", l_endian);
            let mut switch_endian;
            if bytes[8] as char == 'v' {
                // file stores little endian
                if !l_endian {
                    switch_endian = true;
                } else {
                    switch_endian = false;
                }
            } else {
                // file stores big endian
                if l_endian {
                    switch_endian = true;
                } else {
                    switch_endian = false;
                }
            }
            println!("switch_endian = {}", switch_endian);
            // get the version number
            let last3c = vec!(bytes[9], bytes[10], bytes[11]);
            let version = String::from_utf8(last3c).unwrap(); // last 3 chars
            println!("version = {}", version);
            if ptr_size == 8 && (ptr_size_differs | switch_endian) == false {
                // assumes 64-bit pointers (in file as well as on platform)
                // we also don't handle endian switching (yet)
                return read_remaining_blend_file(file);
            } else {
                println!("TODO: ptr_size = {}", ptr_size);
                println!("TODO: ptr_size_differs = {}", ptr_size_differs);
                println!("TODO: switch_endian = {}", switch_endian);
            }
        } else {
            println!("ERROR: FILE is not a Blender file");
        }
    } else {
        println!("ERROR: FILE is not a Blender file");
    }
    Ok(())
}

fn read_remaining_blend_file(mut file: File) -> io::Result<()> {
    // read_file_dna
    // 4 * int + 64-bit pointer
    let mut buf = [0u8; 24];
    file.read(&mut buf).unwrap();
    let mut bhead = String::new();
    for e in buf.iter() {
        bhead.push(*e as char);
    }
    let mut code = String::new();
    code.push_str(&bhead); // copy
    code.truncate(4); // first 4 chars
    println!("code = {}", code);
    // WORK: read remaining file
    Ok(())
}

fn do_work(inp: &str, out: Option<String>) {
    println!("FILE = {}", inp);
    match out {
        Some(x) => println!("output file name: {}", x),
        None => println!("no output file name"),
    }
    match read_blend_file(inp) {
        Ok(_) => { ; }
        Err(f) => { panic!(f.to_string()) }
    };
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "NAME");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };
    do_work(&input, output);
}
<commit_msg>Interpret the first integer as len.<commit_after>extern crate getopts;
use getopts::Options;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::mem;

fn pointer_size() -> usize {
    let tmp = 0u8;
    let boxed = Box::new(tmp);
    mem::size_of_val(&boxed)
}

fn read_blend_file(inp: &str) -> io::Result<()> {
    // open file
    let mut file = File::open(inp).unwrap();
    // read 12 bytes from the Blender file
    let mut buf = [0u8; 12];
    file.read(&mut buf).unwrap();
    let mut header = String::new();
    for e in buf.iter() {
        header.push(*e as char);
    }
    println!("header = \"{}\"", header);
    // compare first 7 chars to "BLENDER"
    if header.len() >= 7 {
        // create copy of header without moving value
        let mut blender = String::new();
        blender = blender + &header;
        blender.truncate(7); // first 7 chars
        if blender == "BLENDER" {
            println!("starts with \"BLENDER\" ...");
            // switch to byte copy of String representation
            let bytes = header.into_bytes();
            // check 8th char of header
            println!("8th char of header = '{}'", bytes[7] as char);
            // check for 32-bit pointers vs. 64-bit pointers
            let ptr_size = pointer_size();
            println!("size of pointer in bytes: {}", ptr_size);
            let mut ptr_size_differs = false;
            if bytes[7] as char == '_' {
                // 32-bit pointers expected
                if ptr_size != 4 {
                    ptr_size_differs = true;
                }
                println!("32-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            } else {
                // 64-bit pointers expected
                if ptr_size != 8 {
                    ptr_size_differs = true;
                }
                println!("64-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            }
            // little endian or big endian?
            let mut l_endian;
            let endian_test = 1u16; // value one stored in two bytes
            if endian_test.to_le() != endian_test {
                l_endian = false;
            } else {
                // if we are on a little endian machine to_le() is a no-op
                l_endian = true;
            }
            println!("l_endian = {}", l_endian);
            let mut switch_endian;
            if bytes[8] as char == 'v' {
                // file stores little endian
                if !l_endian {
                    switch_endian = true;
                } else {
                    switch_endian = false;
                }
            } else {
                // file stores big endian
                if l_endian {
                    switch_endian = true;
                } else {
                    switch_endian = false;
                }
            }
            println!("switch_endian = {}", switch_endian);
            // get the version number
            let last3c = vec!(bytes[9], bytes[10], bytes[11]);
            let version = String::from_utf8(last3c).unwrap(); // last 3 chars
            println!("version = {}", version);
            if ptr_size == 8 && (ptr_size_differs | switch_endian) == false {
                // assumes 64-bit pointers (in file as well as on platform)
                // we also don't handle endian switching (yet)
                return read_remaining_blend_file(file);
            } else {
                println!("TODO: ptr_size = {}", ptr_size);
                println!("TODO: ptr_size_differs = {}", ptr_size_differs);
                println!("TODO: switch_endian = {}", switch_endian);
            }
        } else {
            println!("ERROR: FILE is not a Blender file");
        }
    } else {
        println!("ERROR: FILE is not a Blender file");
    }
    Ok(())
}

fn read_remaining_blend_file(mut file: File) -> io::Result<()> {
    // read_file_dna
    // 4 * int + 64-bit pointer
    let mut buf = [0u8; 24];
    file.read(&mut buf).unwrap();
    let mut bhead = String::new();
    for e in buf.iter() {
        bhead.push(*e as char);
    }
    let mut code = String::new();
    code.push_str(&bhead); // copy
    code.truncate(4); // first 4 chars
    println!("code = {}", code);
    // first int is 'len'
    let mut len: u32 = 0;
    len += (buf[4] as u32) <<  0;
    len += (buf[5] as u32) <<  8;
    len += (buf[6] as u32) << 16;
    len += (buf[7] as u32) << 24;
    println!("len = {}", len);
    // WORK: read remaining file
    Ok(())
}

fn do_work(inp: &str, out: Option<String>) {
    println!("FILE = {}", inp);
    match out {
        Some(x) => println!("output file name: {}", x),
        None => println!("no output file name"),
    }
    match read_blend_file(inp) {
        Ok(_) => { ; }
        Err(f) => { panic!(f.to_string()) }
    };
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "NAME");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };
    do_work(&input, output);
}
<|endoftext|>


<commit_before>use rustc::hir::def_id::DefId;
use rustc::mir;
use rustc::ty::layout::{Size, Align};
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty};
use rustc_data_structures::indexed_vec::Idx;

use error::EvalResult;
use eval_context::{EvalContext};
use memory::Pointer;
use value::{PrimVal, Value};

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Lvalue<'tcx> {
    /// An lvalue referring to a value allocated in the `Memory` system.
    Ptr {
        ptr: Pointer,
        extra: LvalueExtra,
    },

    /// An lvalue referring to a value on the stack. Represented by a stack frame index paired with
    /// a Mir local index.
    Local {
        frame: usize,
        local: mir::Local,
        /// Optionally, this lvalue can point to a field of the stack value
        field: Option<(usize, Ty<'tcx>)>,
    },

    /// An lvalue referring to a global
    Global(GlobalId<'tcx>),
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LvalueExtra {
    None,
    Length(u64),
    Vtable(Pointer),
    DowncastVariant(usize),
}

/// Uniquely identifies a specific constant or static.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct GlobalId<'tcx> {
    /// For a constant or static, the `DefId` of the item itself.
    /// For a promoted global, the `DefId` of the function they belong to.
    pub(super) def_id: DefId,

    /// For statics and constants this is `Substs::empty()`, so only promoteds and associated
    /// constants actually have something useful here. We could special case statics and constants,
    /// but that would only require more branching when working with constants, and not bring any
    /// real benefits.
    pub(super) substs: &'tcx Substs<'tcx>,

    /// The index for promoted globals within their function's `Mir`.
    pub(super) promoted: Option<mir::Promoted>,
}

#[derive(Copy, Clone, Debug)]
pub struct Global<'tcx> {
    pub(super) value: Value,
    /// Only used in `force_allocation` to ensure we don't mark the memory
    /// before the static is initialized. It is possible to convert a
    /// global which initially is `Value::ByVal(PrimVal::Undef)` and gets
    /// lifted to an allocation before the static is fully initialized
    pub(super) initialized: bool,
    pub(super) mutable: bool,
    pub(super) ty: Ty<'tcx>,
}

impl<'tcx> Lvalue<'tcx> {
    pub fn from_ptr(ptr: Pointer) -> Self {
        Lvalue::Ptr { ptr, extra: LvalueExtra::None }
    }

    pub(super) fn to_ptr_and_extra(self) -> (Pointer, LvalueExtra) {
        match self {
            Lvalue::Ptr { ptr, extra } => (ptr, extra),
            _ => bug!("to_ptr_and_extra: expected Lvalue::Ptr, got {:?}", self),

        }
    }

    pub(super) fn to_ptr(self) -> Pointer {
        let (ptr, extra) = self.to_ptr_and_extra();
        assert_eq!(extra, LvalueExtra::None);
        ptr
    }

    pub(super) fn elem_ty_and_len(self, ty: Ty<'tcx>) -> (Ty<'tcx>, u64) {
        match ty.sty {
            ty::TyArray(elem, n) => (elem, n as u64),

            ty::TySlice(elem) => {
                match self {
                    Lvalue::Ptr { extra: LvalueExtra::Length(len), .. } => (elem, len),
                    _ => bug!("elem_ty_and_len of a TySlice given non-slice lvalue: {:?}", self),
                }
            }

            _ => bug!("elem_ty_and_len expected array or slice, got {:?}", ty),
        }
    }
}

impl<'tcx> Global<'tcx> {
    pub(super) fn uninitialized(ty: Ty<'tcx>) -> Self {
        Global {
            value: Value::ByVal(PrimVal::Undef),
            mutable: true,
            ty,
            initialized: false,
        }
    }
}

impl<'a, 'tcx> EvalContext<'a, 'tcx> {
    pub(super) fn eval_and_read_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<'tcx, Value> {
        if let mir::Lvalue::Projection(ref proj) = *lvalue {
            if let mir::Lvalue::Local(index) = proj.base {
                if let Value::ByValPair(a, b) = self.frame().get_local(index, None) {
                    if let mir::ProjectionElem::Field(ref field, _) = proj.elem {
                        let val = [a, b][field.index()];
                        return Ok(Value::ByVal(val));
                    }
                }
            }
        }
        let lvalue = self.eval_lvalue(lvalue)?;
        Ok(self.read_lvalue(lvalue))
    }

    pub fn read_lvalue(&self, lvalue: Lvalue<'tcx>) -> Value {
        match lvalue {
            Lvalue::Ptr { ptr, extra } => {
                assert_eq!(extra, LvalueExtra::None);
                Value::ByRef(ptr)
            }
            Lvalue::Local { frame, local, field } => self.stack[frame].get_local(local, field.map(|(i, _)| i)),
            Lvalue::Global(cid) => self.globals.get(&cid).expect("global not cached").value,
        }
    }

    pub(super) fn eval_lvalue(&mut self, mir_lvalue: &mir::Lvalue<'tcx>) -> EvalResult<'tcx, Lvalue<'tcx>> {
        use rustc::mir::Lvalue::*;
        let lvalue = match *mir_lvalue {
            Local(mir::RETURN_POINTER) => self.frame().return_lvalue,
            Local(local) => Lvalue::Local { frame: self.stack.len() - 1, local, field: None },

            Static(def_id) => {
                let substs = self.tcx.intern_substs(&[]);
                Lvalue::Global(GlobalId { def_id, substs, promoted: None })
            }

            Projection(ref proj) => return self.eval_lvalue_projection(proj),
        };

        if log_enabled!(::log::LogLevel::Trace) {
            self.dump_local(lvalue);
        }

        Ok(lvalue)
    }

    pub fn lvalue_field(
        &mut self,
        base: Lvalue<'tcx>,
        field_index: usize,
        base_ty: Ty<'tcx>,
        field_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Lvalue<'tcx>> {
        let base_layout = self.type_layout(base_ty)?;

        use rustc::ty::layout::Layout::*;
        let (offset, packed) = match *base_layout {
            Univariant { ref variant, .. } => {
                (variant.offsets[field_index], variant.packed)
            },

            General { ref variants, .. } => {
                let (_, base_extra) = base.to_ptr_and_extra();
                if let LvalueExtra::DowncastVariant(variant_idx) = base_extra {
                    // +1 for the discriminant, which is field 0
                    (variants[variant_idx].offsets[field_index + 1], variants[variant_idx].packed)
                } else {
                    bug!("field access on enum had no variant index");
                }
            }

            RawNullablePointer { .. } => {
                assert_eq!(field_index, 0);
                return Ok(base);
            }

            StructWrappedNullablePointer { ref nonnull, .. } => {
                (nonnull.offsets[field_index], nonnull.packed)
            }

            UntaggedUnion { .. } => return Ok(base),

            Vector { element, count } => {
                let field = field_index as u64;
                assert!(field < count);
                let elem_size = element.size(&self.tcx.data_layout).bytes();
                (Size::from_bytes(field * elem_size), false)
            }

            _ => bug!("field access on non-product type: {:?}", base_layout),
        };

        let (base_ptr, base_extra) = match base {
            Lvalue::Ptr { ptr, extra } => (ptr, extra),
            Lvalue::Local { frame, local, field } => match self.stack[frame].get_local(local, field.map(|(i, _)| i)) {
                Value::ByRef(ptr) => {
                    assert!(field.is_none(), "local can't be ByRef and have a field offset");
                    (ptr, LvalueExtra::None)
                },
                Value::ByVal(_) => {
                    assert_eq!(offset.bytes(), 0, "ByVal can only have 1 non zst field with offset 0");
                    return Ok(base);
                },
                Value::ByValPair(_, _) => {
                    assert!(field_index < 2);
                    return Ok(Lvalue::Local {
                        frame,
                        local,
                        field: Some((field_index, field_ty)),
                    });
                },
            },
            // FIXME: do for globals what we did for locals
            Lvalue::Global(_) => self.force_allocation(base)?.to_ptr_and_extra(),
        };

        let offset = match base_extra {
            LvalueExtra::Vtable(tab) => {
                let (_, align) = self.size_and_align_of_dst(base_ty, Value::ByValPair(PrimVal::Ptr(base_ptr), PrimVal::Ptr(tab)))?;
                offset.abi_align(Align::from_bytes(align, align).unwrap()).bytes()
            }
            _ => offset.bytes(),
        };

        let ptr = base_ptr.offset(offset);

        let field_ty = self.monomorphize(field_ty, self.substs());

        if packed {
            let size = self.type_size(field_ty)?.expect("packed struct must be sized");
            self.memory.mark_packed(ptr, size);
        }

        let extra = if self.type_is_sized(field_ty) {
            LvalueExtra::None
        } else {
            match base_extra {
                LvalueExtra::None => bug!("expected fat pointer"),
                LvalueExtra::DowncastVariant(..) =>
                    bug!("Rust doesn't support unsized fields in enum variants"),
                LvalueExtra::Vtable(_) |
                LvalueExtra::Length(_) => {},
            }
            base_extra
        };

        Ok(Lvalue::Ptr { ptr, extra })
    }

    fn eval_lvalue_projection(
        &mut self,
        proj: &mir::LvalueProjection<'tcx>,
    ) -> EvalResult<'tcx, Lvalue<'tcx>> {
        use rustc::mir::ProjectionElem::*;
        let (ptr, extra) = match proj.elem {
            Field(field, field_ty) => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                return self.lvalue_field(base, field.index(), base_ty, field_ty);
            }

            Downcast(_, variant) => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                let base_layout = self.type_layout(base_ty)?;
                // FIXME(solson)
                let base = self.force_allocation(base)?;
                let (base_ptr, base_extra) = base.to_ptr_and_extra();

                use rustc::ty::layout::Layout::*;
                let extra = match *base_layout {
                    General { .. } => LvalueExtra::DowncastVariant(variant),
                    RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => base_extra,
                    _ => bug!("variant downcast on non-aggregate: {:?}", base_layout),
                };
                (base_ptr, extra)
            }

            Deref => {
                let base_ty = self.lvalue_ty(&proj.base);
                let val = self.eval_and_read_lvalue(&proj.base)?;

                let pointee_type = match base_ty.sty {
                    ty::TyRawPtr(ref tam) |
                    ty::TyRef(_, ref tam) => tam.ty,
                    ty::TyAdt(ref def, _) if def.is_box() => base_ty.boxed_ty(),
                    _ => bug!("can only deref pointer types"),
                };

                trace!("deref to {} on {:?}", pointee_type, val);

                match self.tcx.struct_tail(pointee_type).sty {
                    ty::TyDynamic(..) => {
                        let (ptr, vtable) = val.expect_ptr_vtable_pair(&self.memory)?;
                        (ptr, LvalueExtra::Vtable(vtable))
                    },
                    ty::TyStr | ty::TySlice(_) => {
                        let (ptr, len) = val.expect_slice(&self.memory)?;
                        (ptr, LvalueExtra::Length(len))
                    },
                    _ => (val.read_ptr(&self.memory)?, LvalueExtra::None),
                }
            }

            Index(ref operand) => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                // FIXME(solson)
                let base = self.force_allocation(base)?;
                let (base_ptr, _) = base.to_ptr_and_extra();

                let (elem_ty, len) = base.elem_ty_and_len(base_ty);
                let elem_size = self.type_size(elem_ty)?.expect("slice element must be sized");
                let n_ptr = self.eval_operand(operand)?;
                let usize = self.tcx.types.usize;
                let n = self.value_to_primval(n_ptr, usize)?.to_u64()?;
                assert!(n < len);
                let ptr = base_ptr.offset(n * elem_size);
                (ptr, LvalueExtra::None)
            }

            ConstantIndex { offset, min_length, from_end } => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                // FIXME(solson)
                let base = self.force_allocation(base)?;
                let (base_ptr, _) = base.to_ptr_and_extra();

                let (elem_ty, n) = base.elem_ty_and_len(base_ty);
                let elem_size = self.type_size(elem_ty)?.expect("sequence element must be sized");
                assert!(n >= min_length as u64);

                let index = if from_end {
                    n - u64::from(offset)
                } else {
                    u64::from(offset)
                };

                let ptr = base_ptr.offset(index * elem_size);
                (ptr, LvalueExtra::None)
            }

            Subslice { from, to } => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                // FIXME(solson)
                let base = self.force_allocation(base)?;
                let (base_ptr, _) = base.to_ptr_and_extra();

                let (elem_ty, n) = base.elem_ty_and_len(base_ty);
                let elem_size = self.type_size(elem_ty)?.expect("slice element must be sized");
                assert!(u64::from(from) <= n - u64::from(to));
                let ptr = base_ptr.offset(u64::from(from) * elem_size);
                let extra = LvalueExtra::Length(n - u64::from(to) - u64::from(from));
                (ptr, extra)
            }
        };

        Ok(Lvalue::Ptr { ptr, extra })
    }

    pub(super) fn lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> {
        self.monomorphize(lvalue.ty(&self.mir(), self.tcx).to_ty(self.tcx), self.substs())
    }
}
<commit_msg>remove a hack that is now useless<commit_after>use rustc::hir::def_id::DefId;
use rustc::mir;
use rustc::ty::layout::{Size, Align};
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty};
use rustc_data_structures::indexed_vec::Idx;

use error::EvalResult;
use eval_context::{EvalContext};
use memory::Pointer;
use value::{PrimVal, Value};

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Lvalue<'tcx> {
    /// An lvalue referring to a value allocated in the `Memory` system.
    Ptr {
        ptr: Pointer,
        extra: LvalueExtra,
    },

    /// An lvalue referring to a value on the stack. Represented by a stack frame index paired with
    /// a Mir local index.
    Local {
        frame: usize,
        local: mir::Local,
        /// Optionally, this lvalue can point to a field of the stack value
        field: Option<(usize, Ty<'tcx>)>,
    },

    /// An lvalue referring to a global
    Global(GlobalId<'tcx>),
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LvalueExtra {
    None,
    Length(u64),
    Vtable(Pointer),
    DowncastVariant(usize),
}

/// Uniquely identifies a specific constant or static.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct GlobalId<'tcx> {
    /// For a constant or static, the `DefId` of the item itself.
    /// For a promoted global, the `DefId` of the function they belong to.
    pub(super) def_id: DefId,

    /// For statics and constants this is `Substs::empty()`, so only promoteds and associated
    /// constants actually have something useful here. We could special case statics and constants,
    /// but that would only require more branching when working with constants, and not bring any
    /// real benefits.
    pub(super) substs: &'tcx Substs<'tcx>,

    /// The index for promoted globals within their function's `Mir`.
    pub(super) promoted: Option<mir::Promoted>,
}

#[derive(Copy, Clone, Debug)]
pub struct Global<'tcx> {
    pub(super) value: Value,
    /// Only used in `force_allocation` to ensure we don't mark the memory
    /// before the static is initialized. It is possible to convert a
    /// global which initially is `Value::ByVal(PrimVal::Undef)` and gets
    /// lifted to an allocation before the static is fully initialized
    pub(super) initialized: bool,
    pub(super) mutable: bool,
    pub(super) ty: Ty<'tcx>,
}

impl<'tcx> Lvalue<'tcx> {
    pub fn from_ptr(ptr: Pointer) -> Self {
        Lvalue::Ptr { ptr, extra: LvalueExtra::None }
    }

    pub(super) fn to_ptr_and_extra(self) -> (Pointer, LvalueExtra) {
        match self {
            Lvalue::Ptr { ptr, extra } => (ptr, extra),
            _ => bug!("to_ptr_and_extra: expected Lvalue::Ptr, got {:?}", self),

        }
    }

    pub(super) fn to_ptr(self) -> Pointer {
        let (ptr, extra) = self.to_ptr_and_extra();
        assert_eq!(extra, LvalueExtra::None);
        ptr
    }

    pub(super) fn elem_ty_and_len(self, ty: Ty<'tcx>) -> (Ty<'tcx>, u64) {
        match ty.sty {
            ty::TyArray(elem, n) => (elem, n as u64),

            ty::TySlice(elem) => {
                match self {
                    Lvalue::Ptr { extra: LvalueExtra::Length(len), .. } => (elem, len),
                    _ => bug!("elem_ty_and_len of a TySlice given non-slice lvalue: {:?}", self),
                }
            }

            _ => bug!("elem_ty_and_len expected array or slice, got {:?}", ty),
        }
    }
}

impl<'tcx> Global<'tcx> {
    pub(super) fn uninitialized(ty: Ty<'tcx>) -> Self {
        Global {
            value: Value::ByVal(PrimVal::Undef),
            mutable: true,
            ty,
            initialized: false,
        }
    }
}

impl<'a, 'tcx> EvalContext<'a, 'tcx> {
    pub(super) fn eval_and_read_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<'tcx, Value> {
        let lvalue = self.eval_lvalue(lvalue)?;
        Ok(self.read_lvalue(lvalue))
    }

    pub fn read_lvalue(&self, lvalue: Lvalue<'tcx>) -> Value {
        match lvalue {
            Lvalue::Ptr { ptr, extra } => {
                assert_eq!(extra, LvalueExtra::None);
                Value::ByRef(ptr)
            }
            Lvalue::Local { frame, local, field } => self.stack[frame].get_local(local, field.map(|(i, _)| i)),
            Lvalue::Global(cid) => self.globals.get(&cid).expect("global not cached").value,
        }
    }

    pub(super) fn eval_lvalue(&mut self, mir_lvalue: &mir::Lvalue<'tcx>) -> EvalResult<'tcx, Lvalue<'tcx>> {
        use rustc::mir::Lvalue::*;
        let lvalue = match *mir_lvalue {
            Local(mir::RETURN_POINTER) => self.frame().return_lvalue,
            Local(local) => Lvalue::Local { frame: self.stack.len() - 1, local, field: None },

            Static(def_id) => {
                let substs = self.tcx.intern_substs(&[]);
                Lvalue::Global(GlobalId { def_id, substs, promoted: None })
            }

            Projection(ref proj) => return self.eval_lvalue_projection(proj),
        };

        if log_enabled!(::log::LogLevel::Trace) {
            self.dump_local(lvalue);
        }

        Ok(lvalue)
    }

    pub fn lvalue_field(
        &mut self,
        base: Lvalue<'tcx>,
        field_index: usize,
        base_ty: Ty<'tcx>,
        field_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Lvalue<'tcx>> {
        let base_layout = self.type_layout(base_ty)?;

        use rustc::ty::layout::Layout::*;
        let (offset, packed) = match *base_layout {
            Univariant { ref variant, .. } => {
                (variant.offsets[field_index], variant.packed)
            },

            General { ref variants, .. } => {
                let (_, base_extra) = base.to_ptr_and_extra();
                if let LvalueExtra::DowncastVariant(variant_idx) = base_extra {
                    // +1 for the discriminant, which is field 0
                    (variants[variant_idx].offsets[field_index + 1], variants[variant_idx].packed)
                } else {
                    bug!("field access on enum had no variant index");
                }
            }

            RawNullablePointer { .. } => {
                assert_eq!(field_index, 0);
                return Ok(base);
            }

            StructWrappedNullablePointer { ref nonnull, .. } => {
                (nonnull.offsets[field_index], nonnull.packed)
            }

            UntaggedUnion { .. } => return Ok(base),

            Vector { element, count } => {
                let field = field_index as u64;
                assert!(field < count);
                let elem_size = element.size(&self.tcx.data_layout).bytes();
                (Size::from_bytes(field * elem_size), false)
            }

            _ => bug!("field access on non-product type: {:?}", base_layout),
        };

        let (base_ptr, base_extra) = match base {
            Lvalue::Ptr { ptr, extra } => (ptr, extra),
            Lvalue::Local { frame, local, field } => match self.stack[frame].get_local(local, field.map(|(i, _)| i)) {
                Value::ByRef(ptr) => {
                    assert!(field.is_none(), "local can't be ByRef and have a field offset");
                    (ptr, LvalueExtra::None)
                },
                Value::ByVal(_) => {
                    assert_eq!(offset.bytes(), 0, "ByVal can only have 1 non zst field with offset 0");
                    return Ok(base);
                },
                Value::ByValPair(_, _) => {
                    assert!(field_index < 2);
                    return Ok(Lvalue::Local {
                        frame,
                        local,
                        field: Some((field_index, field_ty)),
                    });
                },
            },
            // FIXME: do for globals what we did for locals
            Lvalue::Global(_) => self.force_allocation(base)?.to_ptr_and_extra(),
        };

        let offset = match base_extra {
            LvalueExtra::Vtable(tab) => {
                let (_, align) = self.size_and_align_of_dst(base_ty, Value::ByValPair(PrimVal::Ptr(base_ptr), PrimVal::Ptr(tab)))?;
                offset.abi_align(Align::from_bytes(align, align).unwrap()).bytes()
            }
            _ => offset.bytes(),
        };

        let ptr = base_ptr.offset(offset);

        let field_ty = self.monomorphize(field_ty, self.substs());

        if packed {
            let size = self.type_size(field_ty)?.expect("packed struct must be sized");
            self.memory.mark_packed(ptr, size);
        }

        let extra = if self.type_is_sized(field_ty) {
            LvalueExtra::None
        } else {
            match base_extra {
                LvalueExtra::None => bug!("expected fat pointer"),
                LvalueExtra::DowncastVariant(..) =>
                    bug!("Rust doesn't support unsized fields in enum variants"),
                LvalueExtra::Vtable(_) |
                LvalueExtra::Length(_) => {},
            }
            base_extra
        };

        Ok(Lvalue::Ptr { ptr, extra })
    }

    fn eval_lvalue_projection(
        &mut self,
        proj: &mir::LvalueProjection<'tcx>,
    ) -> EvalResult<'tcx, Lvalue<'tcx>> {
        use rustc::mir::ProjectionElem::*;
        let (ptr, extra) = match proj.elem {
            Field(field, field_ty) => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                return self.lvalue_field(base, field.index(), base_ty, field_ty);
            }

            Downcast(_, variant) => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                let base_layout = self.type_layout(base_ty)?;
                // FIXME(solson)
                let base = self.force_allocation(base)?;
                let (base_ptr, base_extra) = base.to_ptr_and_extra();

                use rustc::ty::layout::Layout::*;
                let extra = match *base_layout {
                    General { .. } => LvalueExtra::DowncastVariant(variant),
                    RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => base_extra,
                    _ => bug!("variant downcast on non-aggregate: {:?}", base_layout),
                };
                (base_ptr, extra)
            }

            Deref => {
                let base_ty = self.lvalue_ty(&proj.base);
                let val = self.eval_and_read_lvalue(&proj.base)?;

                let pointee_type = match base_ty.sty {
                    ty::TyRawPtr(ref tam) |
                    ty::TyRef(_, ref tam) => tam.ty,
                    ty::TyAdt(ref def, _) if def.is_box() => base_ty.boxed_ty(),
                    _ => bug!("can only deref pointer types"),
                };

                trace!("deref to {} on {:?}", pointee_type, val);

                match self.tcx.struct_tail(pointee_type).sty {
                    ty::TyDynamic(..) => {
                        let (ptr, vtable) = val.expect_ptr_vtable_pair(&self.memory)?;
                        (ptr, LvalueExtra::Vtable(vtable))
                    },
                    ty::TyStr | ty::TySlice(_) => {
                        let (ptr, len) = val.expect_slice(&self.memory)?;
                        (ptr, LvalueExtra::Length(len))
                    },
                    _ => (val.read_ptr(&self.memory)?, LvalueExtra::None),
                }
            }

            Index(ref operand) => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                // FIXME(solson)
                let base = self.force_allocation(base)?;
                let (base_ptr, _) = base.to_ptr_and_extra();

                let (elem_ty, len) = base.elem_ty_and_len(base_ty);
                let elem_size = self.type_size(elem_ty)?.expect("slice element must be sized");
                let n_ptr = self.eval_operand(operand)?;
                let usize = self.tcx.types.usize;
                let n = self.value_to_primval(n_ptr, usize)?.to_u64()?;
                assert!(n < len);
                let ptr = base_ptr.offset(n * elem_size);
                (ptr, LvalueExtra::None)
            }

            ConstantIndex { offset, min_length, from_end } => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                // FIXME(solson)
                let base = self.force_allocation(base)?;
                let (base_ptr, _) = base.to_ptr_and_extra();

                let (elem_ty, n) = base.elem_ty_and_len(base_ty);
                let elem_size = self.type_size(elem_ty)?.expect("sequence element must be sized");
                assert!(n >= min_length as u64);

                let index = if from_end {
                    n - u64::from(offset)
                } else {
                    u64::from(offset)
                };

                let ptr = base_ptr.offset(index * elem_size);
                (ptr, LvalueExtra::None)
            }

            Subslice { from, to } => {
                let base = self.eval_lvalue(&proj.base)?;
                let base_ty = self.lvalue_ty(&proj.base);
                // FIXME(solson)
                let base = self.force_allocation(base)?;
                let (base_ptr, _) = base.to_ptr_and_extra();

                let (elem_ty, n) = base.elem_ty_and_len(base_ty);
                let elem_size = self.type_size(elem_ty)?.expect("slice element must be sized");
                assert!(u64::from(from) <= n - u64::from(to));
                let ptr = base_ptr.offset(u64::from(from) * elem_size);
                let extra = LvalueExtra::Length(n - u64::from(to) - u64::from(from));
                (ptr, extra)
            }
        };

        Ok(Lvalue::Ptr { ptr, extra })
    }

    pub(super) fn lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> {
        self.monomorphize(lvalue.ty(&self.mir(), self.tcx).to_ty(self.tcx), self.substs())
    }
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! list_commands {
    () => {{
        let mut c:Vec<&str> = Vec::new();
        c.push("up");
        c.push("halt");
        c.push("destroy");
        c.push("status");
        c.push("suspend");
        c.push("reload");
        c.push("resume");
        c
    }}
}
<commit_msg>Add missing command<commit_after>#[macro_export]
macro_rules! list_commands {
    () => {{
        let mut c:Vec<&str> = Vec::new();
        c.push("up");
        c.push("halt");
        c.push("ssh");
        c.push("destroy");
        c.push("status");
        c.push("suspend");
        c.push("reload");
        c.push("resume");
        c
    }}
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// The standard logging macro.
///
/// This macro will generically log with the specified `Level` and `format!`
/// based argument list.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level;
///
/// # fn main() {
/// let data = (42, "Forty-two");
/// let private_data = "private";
///
/// log!(Level::Error, "Received errors: {}, {}", data.0, data.1);
/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}",
///     data.0, data.1, private_data);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
        let lvl = $lvl;
        if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
            $crate::__private_api_log(
                __log_format_args!($($arg)+),
                lvl,
                &($target, __log_module_path!(), __log_file!(), __log_line!()),
            );
        }
    });
    ($lvl:expr, $($arg:tt)+) => (log!(target: __log_module_path!(), $lvl, $($arg)+))
}

/// Logs a message at the error level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Error, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Error, $($arg)*);
    )
}

/// Logs a message at the warn level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Warn, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Warn, $($arg)*);
    )
}

/// Logs a message at the info level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
///
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
///       conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Info, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Info, $($arg)*);
    )
}

/// Logs a message at the debug level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Debug, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Debug, $($arg)*);
    )
}

/// Logs a message at the trace level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
/// trace!(target: "app_events", "x is {} and y is {}",
///        if pos.x >= 0.0 { "positive" } else { "negative" },
///        if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::Level::Trace, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::Level::Trace, $($arg)*);
    )
}

/// Determines if a message logged at the specified level in that module will
/// be logged.
///
/// This can be used to avoid expensive computation of log message arguments if
/// the message would be ignored anyway.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level::Debug;
///
/// # fn foo() {
/// if log_enabled!(Debug) {
///     let data = expensive_call();
///     debug!("expensive debug data: {} {}", data.x, data.y);
/// }
/// if log_enabled!(target: "Global", Debug) {
///    let data = expensive_call();
///    debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y);
/// }
/// # }
/// # struct Data { x: u32, y: u32 }
/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
/// # fn main() {}
/// ```
#[macro_export(local_inner_macros)]
macro_rules! log_enabled {
    (target: $target:expr, $lvl:expr) => {{
        let lvl = $lvl;
        lvl <= $crate::STATIC_MAX_LEVEL
            && lvl <= $crate::max_level()
            && $crate::__private_api_enabled(lvl, $target)
    }};
    ($lvl:expr) => {
        log_enabled!(target: __log_module_path!(), $lvl)
    };
}

// The log macro above cannot invoke format_args directly because it uses
// local_inner_macros. A format_args invocation there would resolve to
// $crate::format_args which does not exist. Instead invoke format_args here
// outside of local_inner_macros so that it resolves (probably) to
// core::format_args or std::format_args. Same for the several macros that
// follow.
//
// This is a workaround until we drop support for pre-1.30 compilers. At that
// point we can remove use of local_inner_macros, use $crate:: when invoking
// local macros, and invoke format_args directly.
#[doc(hidden)]
#[macro_export]
macro_rules! __log_format_args {
    ($($args:tt)*) => {
        format_args!($($args)*)
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! __log_module_path {
    () => {
        module_path!()
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! __log_file {
    () => {
        file!()
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! __log_line {
    () => {
        line!()
    };
}
<commit_msg>Improve error when missing macro argument<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// The standard logging macro.
///
/// This macro will generically log with the specified `Level` and `format!`
/// based argument list.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level;
///
/// # fn main() {
/// let data = (42, "Forty-two");
/// let private_data = "private";
///
/// log!(Level::Error, "Received errors: {}, {}", data.0, data.1);
/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}",
///     data.0, data.1, private_data);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
        let lvl = $lvl;
        if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
            $crate::__private_api_log(
                __log_format_args!($($arg)+),
                lvl,
                &($target, __log_module_path!(), __log_file!(), __log_line!()),
            );
        }
    });
    ($lvl:expr, $($arg:tt)+) => (log!(target: __log_module_path!(), $lvl, $($arg)+))
}

/// Logs a message at the error level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! error {
    (target: $target:expr, $($arg:tt)+) => (
        log!(target: $target, $crate::Level::Error, $($arg)+);
    );
    ($($arg:tt)+) => (
        log!($crate::Level::Error, $($arg)+);
    )
}

/// Logs a message at the warn level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! warn {
    (target: $target:expr, $($arg:tt)+) => (
        log!(target: $target, $crate::Level::Warn, $($arg)+);
    );
    ($($arg:tt)+) => (
        log!($crate::Level::Warn, $($arg)+);
    )
}

/// Logs a message at the info level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
///
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
///       conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! info {
    (target: $target:expr, $($arg:tt)+) => (
        log!(target: $target, $crate::Level::Info, $($arg)+);
    );
    ($($arg:tt)+) => (
        log!($crate::Level::Info, $($arg)+);
    )
}

/// Logs a message at the debug level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! debug {
    (target: $target:expr, $($arg:tt)+) => (
        log!(target: $target, $crate::Level::Debug, $($arg)+);
    );
    ($($arg:tt)+) => (
        log!($crate::Level::Debug, $($arg)+);
    )
}

/// Logs a message at the trace level.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
/// trace!(target: "app_events", "x is {} and y is {}",
///        if pos.x >= 0.0 { "positive" } else { "negative" },
///        if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! trace {
    (target: $target:expr, $($arg:tt)+) => (
        log!(target: $target, $crate::Level::Trace, $($arg)+);
    );
    ($($arg:tt)+) => (
        log!($crate::Level::Trace, $($arg)+);
    )
}

/// Determines if a message logged at the specified level in that module will
/// be logged.
///
/// This can be used to avoid expensive computation of log message arguments if
/// the message would be ignored anyway.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::Level::Debug;
///
/// # fn foo() {
/// if log_enabled!(Debug) {
///     let data = expensive_call();
///     debug!("expensive debug data: {} {}", data.x, data.y);
/// }
/// if log_enabled!(target: "Global", Debug) {
///    let data = expensive_call();
///    debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y);
/// }
/// # }
/// # struct Data { x: u32, y: u32 }
/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
/// # fn main() {}
/// ```
#[macro_export(local_inner_macros)]
macro_rules! log_enabled {
    (target: $target:expr, $lvl:expr) => {{
        let lvl = $lvl;
        lvl <= $crate::STATIC_MAX_LEVEL
            && lvl <= $crate::max_level()
            && $crate::__private_api_enabled(lvl, $target)
    }};
    ($lvl:expr) => {
        log_enabled!(target: __log_module_path!(), $lvl)
    };
}

// The log macro above cannot invoke format_args directly because it uses
// local_inner_macros. A format_args invocation there would resolve to
// $crate::format_args which does not exist. Instead invoke format_args here
// outside of local_inner_macros so that it resolves (probably) to
// core::format_args or std::format_args. Same for the several macros that
// follow.
//
// This is a workaround until we drop support for pre-1.30 compilers. At that
// point we can remove use of local_inner_macros, use $crate:: when invoking
// local macros, and invoke format_args directly.
#[doc(hidden)]
#[macro_export]
macro_rules! __log_format_args {
    ($($args:tt)*) => {
        format_args!($($args)*)
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! __log_module_path {
    () => {
        module_path!()
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! __log_file {
    () => {
        file!()
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! __log_line {
    () => {
        line!()
    };
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate eve;

use test::Bencher;
use std::collections::BTreeMap;
use std::io::prelude::*;
use std::fs::File;

use eve::map::*;

#[bench]
fn bench_insert_int_map_3(b: &mut Bencher) {
    b.iter(|| {
        let mut map = Map::new(3);
        for i in (0i64..1000000) {
            map.insert(i * 25214903917, 1);
        }
        map
    });
}

#[bench]
fn bench_insert_int_map_1(b: &mut Bencher) {
    b.iter(|| {
        let mut map = Map::new(1);
        for i in (0i64..1000000) {
            map.insert(i * 25214903917, 1);
        }
        map
    });
}

#[bench]
fn bench_insert_int_btree(b: &mut Bencher) {
    b.iter(|| {
        let mut map = BTreeMap::new();
        for i in (0i64..1000000) {
            map.insert(i * 25214903917, 1);
        }
        map
    });
}

fn words() -> Vec<String> {
    let mut contents = String::new();
    File::open("/usr/share/dict/words").unwrap().read_to_string(&mut contents).unwrap();
    contents.lines().map(|word| word.to_owned()).collect()
}

#[bench]
fn bench_insert_string_map_3(b: &mut Bencher) {
    let words = words();
    b.iter(|| {
        let mut map = Map::new(3);
        for word in words.iter() {
            map.insert(word.clone(), 1);
        }
        map
    });
}

#[bench]
fn bench_insert_string_map_1(b: &mut Bencher) {
    let words = words();
    b.iter(|| {
        let mut map = Map::new(1);
        for word in words.iter() {
            map.insert(word.clone(), 1);
        }
        map
    });
}

#[bench]
fn bench_insert_string_btree(b: &mut Bencher) {
    let words = words();
    b.iter(|| {
        let mut map = BTreeMap::new();
        for word in words.iter() {
            map.insert(word.clone(), 1);
        }
        map
    });
}

#[bench]
fn bench_clone_int_map_3(b: &mut Bencher) {
    b.iter(|| {
        let mut map = Map::new(3);
        let mut maps = Vec::new();
        for i in (0i64..100) {
            for j in (0i64..100) {
                map.insert(((i*100) + j) * 25214903917, 1);
            }
            maps.push(map.clone());
        }
        maps
    });
}

#[bench]
fn bench_clone_int_btree(b: &mut Bencher) {
    b.iter(|| {
        let mut map = BTreeMap::new();
        let mut maps = Vec::new();
        for i in (0i64..100) {
            for j in (0i64..100) {
                map.insert(((i*100) + j) * 25214903917, 1);
            }
            maps.push(map.clone());
        }
        maps
    });
}

#[allow(dead_code)]
fn main() {
    let mut map = Map::new(1);
    for i in (0..10) {
        map.insert(i, 1);
        println!("{:?}", map);
    }
    for i in (10..20).rev() {
        map.insert(i, 1);
        println!("{:?}", map);
    }

    let mut map = Map::new(3);
    for i in (0..10) {
        map.insert(i, 1);
        println!("{:?}", map);
    }
    for i in (10..20).rev() {
        map.insert(i, 1);
        println!("{:?}", map);
    }
}<commit_msg>Comment out all map uses<commit_after>// #![feature(test)]

// extern crate test;
// extern crate eve;

// use test::Bencher;
// use std::collections::BTreeMap;
// use std::io::prelude::*;
// use std::fs::File;

// use eve::map::*;

// #[bench]
// fn bench_insert_int_map_3(b: &mut Bencher) {
//     b.iter(|| {
//         let mut map = Map::new(3);
//         for i in (0i64..1000000) {
//             map.insert(i * 25214903917, 1);
//         }
//         map
//     });
// }

// #[bench]
// fn bench_insert_int_map_1(b: &mut Bencher) {
//     b.iter(|| {
//         let mut map = Map::new(1);
//         for i in (0i64..1000000) {
//             map.insert(i * 25214903917, 1);
//         }
//         map
//     });
// }

// #[bench]
// fn bench_insert_int_btree(b: &mut Bencher) {
//     b.iter(|| {
//         let mut map = BTreeMap::new();
//         for i in (0i64..1000000) {
//             map.insert(i * 25214903917, 1);
//         }
//         map
//     });
// }

// fn words() -> Vec<String> {
//     let mut contents = String::new();
//     File::open("/usr/share/dict/words").unwrap().read_to_string(&mut contents).unwrap();
//     contents.lines().map(|word| word.to_owned()).collect()
// }

// #[bench]
// fn bench_insert_string_map_3(b: &mut Bencher) {
//     let words = words();
//     b.iter(|| {
//         let mut map = Map::new(3);
//         for word in words.iter() {
//             map.insert(word.clone(), 1);
//         }
//         map
//     });
// }

// #[bench]
// fn bench_insert_string_map_1(b: &mut Bencher) {
//     let words = words();
//     b.iter(|| {
//         let mut map = Map::new(1);
//         for word in words.iter() {
//             map.insert(word.clone(), 1);
//         }
//         map
//     });
// }

// #[bench]
// fn bench_insert_string_btree(b: &mut Bencher) {
//     let words = words();
//     b.iter(|| {
//         let mut map = BTreeMap::new();
//         for word in words.iter() {
//             map.insert(word.clone(), 1);
//         }
//         map
//     });
// }

// #[bench]
// fn bench_clone_int_map_3(b: &mut Bencher) {
//     b.iter(|| {
//         let mut map = Map::new(3);
//         let mut maps = Vec::new();
//         for i in (0i64..100) {
//             for j in (0i64..100) {
//                 map.insert(((i*100) + j) * 25214903917, 1);
//             }
//             maps.push(map.clone());
//         }
//         maps
//     });
// }

// #[bench]
// fn bench_clone_int_btree(b: &mut Bencher) {
//     b.iter(|| {
//         let mut map = BTreeMap::new();
//         let mut maps = Vec::new();
//         for i in (0i64..100) {
//             for j in (0i64..100) {
//                 map.insert(((i*100) + j) * 25214903917, 1);
//             }
//             maps.push(map.clone());
//         }
//         maps
//     });
// }

// #[allow(dead_code)]
// fn main() {
//     let mut map = Map::new(1);
//     for i in (0..10) {
//         map.insert(i, 1);
//         println!("{:?}", map);
//     }
//     for i in (10..20).rev() {
//         map.insert(i, 1);
//         println!("{:?}", map);
//     }

//     let mut map = Map::new(3);
//     for i in (0..10) {
//         map.insert(i, 1);
//         println!("{:?}", map);
//     }
//     for i in (10..20).rev() {
//         map.insert(i, 1);
//         println!("{:?}", map);
//     }
// }<|endoftext|>


<commit_before>use std::env;
use std::io::Read;
use std::fs::File;

fn main() {
    let mut data_path: std::path::PathBuf = env::current_dir().unwrap();
    data_path.push("data");
    data_path.push("input.txt");

    data_from_file(data_path);
}

fn data_from_file(file_name: std::path::PathBuf) {
    println!("The path is: {}", file_name.display());

    let mut data_file = File::open(file_name).unwrap();

    let mut line = String::new();

    data_file.read_to_string(&mut line).unwrap();

    println!("The data is: {}", line);
}<commit_msg>More rust.<commit_after>use std::env;
use std::fs::File;
use std::path::Path;
use std::io::BufRead;

fn main() {
    let mut temp: Vec<String> = Vec::new();
    let mut data_path: std::path::PathBuf = env::current_dir().unwrap();
    data_path.push("data");
    data_path.push("input.txt");

    println!("The path is: {}", data_path.display());

    let data: std::io::Lines<std::io::BufReader<File>> =
        data_from_file(&data_path).unwrap();

    for data_line in data {
        temp = data_line.unwrap().split(',').map(|s| s.to_owned()).collect();
    }

    println!("{:?}", temp);
}

fn data_from_file<P: AsRef<Path>>(file_name: &P) ->
        Result<std::io::Lines<std::io::BufReader<File>>, std::io::Error> {
    let data_file: File = File::open(file_name)?;

    Ok(std::io::BufReader::new(data_file).lines())
}<|endoftext|>


<commit_before>//! Check the load average of the system
//!
//! Load average is the number of processes *waiting* to do work in a queue,
//! either due to IO or CPU constraints, averaged over 1, 5 and 15 minutes.

extern crate rustc_serialize;

extern crate docopt;

extern crate turbine_plugins;

use docopt::Docopt;
use turbine_plugins::ExitStatus;
use turbine_plugins::procfs::{LoadAvg};

static USAGE: &'static str = "
Usage: check-load [options]

Options:
    -h, --help              Show this message and exit
    -v, --verbose           Print even when things are okay

Threshold Behavior:
    -w, --warn=<averages>   Averages to warn at         [default: 5,3.5,2.5]
    -c, --crit=<averages>   Averages to go critical at  [default: 10,5,3]
";

#[derive(RustcDecodable, Debug)]
struct RawArgs {
    flag_help: bool,
    flag_warn: String,
    flag_crit: String,
    flag_verbose: bool,
}

struct Args {
    flag_help: bool,
    flag_warn: LoadAvg,
    flag_crit: LoadAvg,
    flag_verbose: bool,
}

impl From<RawArgs> for Args {
    fn from(args: RawArgs) -> Args {
        Args {
            flag_warn: args.flag_warn.parse().ok().expect(
                &format!("--warn should look like 'n.m,n.m,n.m' not {}", args.flag_warn)),
            flag_crit: args.flag_crit.parse().ok().expect(
                &format!("--crit should look like 'n.m,n.m,n.m' not {}", args.flag_warn)),
            flag_help: args.flag_help,
            flag_verbose: args.flag_verbose,
        }
    }
}

fn parse_args() -> Result<Args, docopt::Error> {
    let args: RawArgs = try!(Docopt::new(USAGE)
                             .and_then(|d| d.decode()));
    Ok(Args::from(args))
}

fn do_check(args: Args, actual: LoadAvg) -> ExitStatus {
    if actual > args.flag_crit {
        println!("[check-load] CRITICAL: load average is {} (> {})",
                 actual, args.flag_crit);
        ExitStatus::Critical
    } else if actual > args.flag_warn {
        println!("[check-load] WARNING: load average is {} (> {})",
                 actual, args.flag_warn);
        ExitStatus::Warning
    } else {
        if args.flag_verbose {
            println!("[check-load] OK: load average is {} (< {})",
                 actual, args.flag_warn);
        }
        ExitStatus::Ok
    }
}

fn main() {
    let args = parse_args().unwrap_or_else(|e| e.exit());;
    let status = do_check(args, LoadAvg::load().unwrap());
    status.exit();
}

#[cfg(test)]
mod test {
    use docopt::Docopt;
    use turbine_plugins::ExitStatus;

    use super::{USAGE, RawArgs, Args, parse_args, do_check};

    #[test] // one day syntax extensions won't require nightly.
    fn parse_args_is_valid() {
        parse_args().unwrap();
    }

    fn docopt(argv: Vec<&str>) -> Args {
        Args::from(Docopt::new(USAGE)
                   .and_then(|d| d.argv(argv.into_iter()).decode::<RawArgs>())
                   .unwrap())
    }

    #[test]
    fn statuses() {
        let args = docopt(vec!["check-load", "-c", "1,2,3"]);
        assert_eq!(
            do_check(args,
                     "2 1 1".parse().unwrap()),
            ExitStatus::Critical
        );

        let args = docopt(vec!["check-load", "-w", "1,2,3"]);
        assert_eq!(
            do_check(args,
                     "1.1 1 1".parse().unwrap()),
            ExitStatus::Warning
        );

        let args = docopt(vec!["check-load"]);
        assert_eq!(
            do_check(args,
                     "2 1 1".parse().unwrap()),
            ExitStatus::Ok
        );

        let args = docopt(vec!["check-load"]);
        assert_eq!(
            do_check(args,
                     "12 1 1".parse().unwrap()),
            ExitStatus::Critical
        );

        let args = docopt(vec!["check-load", "-c", "2,3,4", "-w", "1,2,3"]);
        assert_eq!(
            do_check(args,
                     ".5 .5 .5".parse().unwrap()),
            ExitStatus::Ok
        );
    }
}
<commit_msg>check-load: use docopt magic help<commit_after>//! Check the load average of the system
//!
//! Load average is the number of processes *waiting* to do work in a queue,
//! either due to IO or CPU constraints, averaged over 1, 5 and 15 minutes.

extern crate rustc_serialize;

extern crate docopt;

extern crate turbine_plugins;

use docopt::Docopt;
use turbine_plugins::ExitStatus;
use turbine_plugins::procfs::{LoadAvg};

static USAGE: &'static str = "
Usage: check-load [options]

Options:
    -h, --help              Show this message and exit
    -v, --verbose           Print even when things are okay

Threshold Behavior:
    -w, --warn=<averages>   Averages to warn at         [default: 5,3.5,2.5]
    -c, --crit=<averages>   Averages to go critical at  [default: 10,5,3]
";

#[derive(RustcDecodable, Debug)]
struct RawArgs {
    flag_warn: String,
    flag_crit: String,
    flag_verbose: bool,
}

struct Args {
    flag_warn: LoadAvg,
    flag_crit: LoadAvg,
    flag_verbose: bool,
}

impl From<RawArgs> for Args {
    fn from(args: RawArgs) -> Args {
        Args {
            flag_warn: args.flag_warn.parse().ok().expect(
                &format!("--warn should look like 'n.m,n.m,n.m' not {}", args.flag_warn)),
            flag_crit: args.flag_crit.parse().ok().expect(
                &format!("--crit should look like 'n.m,n.m,n.m' not {}", args.flag_warn)),
            flag_verbose: args.flag_verbose,
        }
    }
}

fn parse_args() -> Result<Args, docopt::Error> {
    let args: RawArgs = try!(Docopt::new(USAGE)
                             .and_then(|d| d.help(true).decode()));
    Ok(args.into())
}

fn do_check(args: Args, actual: LoadAvg) -> ExitStatus {
    if actual > args.flag_crit {
        println!("[check-load] CRITICAL: load average is {} (> {})",
                 actual, args.flag_crit);
        ExitStatus::Critical
    } else if actual > args.flag_warn {
        println!("[check-load] WARNING: load average is {} (> {})",
                 actual, args.flag_warn);
        ExitStatus::Warning
    } else {
        if args.flag_verbose {
            println!("[check-load] OK: load average is {} (< {})",
                 actual, args.flag_warn);
        }
        ExitStatus::Ok
    }
}

fn main() {
    let args = parse_args().unwrap_or_else(|e| e.exit());;
    let status = do_check(args, LoadAvg::load().unwrap());
    status.exit();
}

#[cfg(test)]
mod test {
    use docopt::Docopt;
    use turbine_plugins::ExitStatus;

    use super::{USAGE, RawArgs, Args, parse_args, do_check};

    #[test] // one day syntax extensions won't require nightly.
    fn parse_args_is_valid() {
        parse_args().unwrap();
    }

    fn docopt(argv: Vec<&str>) -> Args {
        Args::from(Docopt::new(USAGE)
                   .and_then(|d| d.argv(argv.into_iter()).decode::<RawArgs>())
                   .unwrap())
    }

    #[test]
    fn statuses() {
        let args = docopt(vec!["check-load", "-c", "1,2,3"]);
        assert_eq!(
            do_check(args,
                     "2 1 1".parse().unwrap()),
            ExitStatus::Critical
        );

        let args = docopt(vec!["check-load", "-w", "1,2,3"]);
        assert_eq!(
            do_check(args,
                     "1.1 1 1".parse().unwrap()),
            ExitStatus::Warning
        );

        let args = docopt(vec!["check-load"]);
        assert_eq!(
            do_check(args,
                     "2 1 1".parse().unwrap()),
            ExitStatus::Ok
        );

        let args = docopt(vec!["check-load"]);
        assert_eq!(
            do_check(args,
                     "12 1 1".parse().unwrap()),
            ExitStatus::Critical
        );

        let args = docopt(vec!["check-load", "-c", "2,3,4", "-w", "1,2,3"]);
        assert_eq!(
            do_check(args,
                     ".5 .5 .5".parse().unwrap()),
            ExitStatus::Ok
        );
    }
}
<|endoftext|>


<commit_before><commit_msg>Update for #68718<commit_after><|endoftext|>