<commit_before>use std::iter::Iterator;
use super::{StackOfStrings, Stack};

struct Node<T> {
    item: T,
    next: Option<Box<Node<T>>>
}

impl<T> Node<T> {
    /// work around for moved value
    fn into_item_and_next(self) -> (T, Option<Box<Node<T>>>) {
        (self.item, self.next)
    }
}

pub struct LinkedStackOfStrings {
    first: Option<Box<Node<String>>>
}

impl StackOfStrings for LinkedStackOfStrings {
    fn new() -> LinkedStackOfStrings {
        LinkedStackOfStrings { first: None }
    }

    fn is_empty(&self) -> bool {
        self.first.is_none()
    }

    fn push(&mut self, item: String) {
        // Takes the value out of the option, leaving a None in its place.
        let old_first = self.first.take();
        let first = Node {
            item: item,
            next: old_first
        };
        self.first = Some(Box::new(first));
    }

    fn pop(&mut self) -> String {
        let old_first = self.first.take();
        let (item, first) = old_first.unwrap().into_item_and_next();
        self.first = first;
        item
    }
}

pub struct LinkedStack<T> {
    first: Option<Box<Node<T>>>
}

impl<T> Stack<T> for LinkedStack<T> {
    fn new() -> LinkedStack<T> {
        LinkedStack { first: None }
    }

    fn is_empty(&self) -> bool {
        self.first.is_none()
    }

    fn push(&mut self, item: T) {
        // Takes the value out of the option, leaving a None in its place.
        let old_first = self.first.take();
        let first = Node {
            item: item,
            next: old_first
        };
        self.first = Some(Box::new(first));
    }

    fn pop(&mut self) -> Option<T> {
        match self.first.take() {
            None => None,
            old_first @ Some(_) => {
                let (item, first) = old_first.unwrap().into_item_and_next();
                self.first = first;
                Some(item)
            }
        }
    }
}

pub struct Iter<'a, T: 'a> {
    ptr: &'a Option<Box<Node<T>>>
}

unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}

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

    fn next(&mut self) -> Option<&'a T> {
        self.ptr.as_ref().map(|head| {
            self.ptr = &head.next;
            &head.item
        })
    }
}

impl<T> LinkedStack<T> {
    pub fn iter(&self) -> Iter<T> {
        Iter { ptr: &self.first }
    }
}

#[test]
fn test_linked_stack_of_strings() {
    let mut stack: LinkedStackOfStrings = StackOfStrings::new();

    let mut result = "to be not that or be".split(' ');

    for s in "to be or not to - be - - that - - - is".split(' ') {
        if s == "-" {
            assert_eq!(&stack.pop(), result.next().unwrap())
        } else {
            stack.push(s.into())
        }
    }
}

#[test]
fn test_linked_stack() {
    let mut stack: LinkedStack<i32> = Stack::new();

    let result = [1, 3, 4, 3, 5, 3];
    let mut rit = result.iter();

    for s in vec![1, 3, 5, 4, 1, 0, 3, 0, 0, 3, 0, 0, 0, 4] {
        if s == 0 {
            assert_eq!(stack.pop(), rit.next().map(|&n| n))
        } else {
            stack.push(s)
        }
    }
}

#[test]
fn test_linked_stack_iter() {
    let mut stack: LinkedStack<i32> = Stack::new();

    let result = [3, 3, 1];
    let mut rit = result.iter();

    for s in vec![1, 3, 5, 0, 1, 0, 3] {
        if s == 0 {
            stack.pop();
        } else {
            stack.push(s);
        }
    }

    for v in stack.iter() {
        assert_eq!(v, rit.next().unwrap())
    }
}

#[test]
fn test_linked_stack_iter_string() {
    let mut stack: LinkedStack<String> = Stack::new();

    let mut result = "is that or be to".split(' ');

    for s in "to be or not to - be - - that is".split(' ') {
        if s == "-" {
            stack.pop();
        } else {
            stack.push(s.into());
        }
    }

    for v in stack.iter() {
        assert_eq!(v, result.next().unwrap())
    }
}
<commit_msg>stacks_and_queues/linked_stack: impl IntoIterator for LinkedStack<commit_after>use std::iter::Iterator;
use super::{StackOfStrings, Stack};

struct Node<T> {
    item: T,
    next: Option<Box<Node<T>>>
}

impl<T> Node<T> {
    /// work around for moved value
    fn into_item_and_next(self) -> (T, Option<Box<Node<T>>>) {
        (self.item, self.next)
    }
}

pub struct LinkedStackOfStrings {
    first: Option<Box<Node<String>>>
}

impl StackOfStrings for LinkedStackOfStrings {
    fn new() -> LinkedStackOfStrings {
        LinkedStackOfStrings { first: None }
    }

    fn is_empty(&self) -> bool {
        self.first.is_none()
    }

    fn push(&mut self, item: String) {
        // Takes the value out of the option, leaving a None in its place.
        let old_first = self.first.take();
        let first = Node {
            item: item,
            next: old_first
        };
        self.first = Some(Box::new(first));
    }

    fn pop(&mut self) -> String {
        let old_first = self.first.take();
        let (item, first) = old_first.unwrap().into_item_and_next();
        self.first = first;
        item
    }
}

pub struct LinkedStack<T> {
    first: Option<Box<Node<T>>>
}

impl<T> Stack<T> for LinkedStack<T> {
    fn new() -> LinkedStack<T> {
        LinkedStack { first: None }
    }

    fn is_empty(&self) -> bool {
        self.first.is_none()
    }

    fn push(&mut self, item: T) {
        // Takes the value out of the option, leaving a None in its place.
        let old_first = self.first.take();
        let first = Node {
            item: item,
            next: old_first
        };
        self.first = Some(Box::new(first));
    }

    fn pop(&mut self) -> Option<T> {
        match self.first.take() {
            None => None,
            old_first @ Some(_) => {
                let (item, first) = old_first.unwrap().into_item_and_next();
                self.first = first;
                Some(item)
            }
        }
    }
}

pub struct Iter<'a, T: 'a> {
    ptr: &'a Option<Box<Node<T>>>
}

unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}

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

    fn next(&mut self) -> Option<&'a T> {
        self.ptr.as_ref().map(|head| {
            self.ptr = &head.next;
            &head.item
        })
    }
}

impl<T> LinkedStack<T> {
    pub fn iter(&self) -> Iter<T> {
        Iter { ptr: &self.first }
    }
}

pub struct IntoIter<T> {
    stack: LinkedStack<T>
}

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

    fn next(&mut self) -> Option<T> {
        self.stack.pop()
    }
}

impl<T> IntoIterator for LinkedStack<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        IntoIter { stack: self }
    }
}

#[test]
fn test_linked_stack_of_strings() {
    let mut stack: LinkedStackOfStrings = StackOfStrings::new();

    let mut result = "to be not that or be".split(' ');

    for s in "to be or not to - be - - that - - - is".split(' ') {
        if s == "-" {
            assert_eq!(&stack.pop(), result.next().unwrap())
        } else {
            stack.push(s.into())
        }
    }
}

#[test]
fn test_linked_stack() {
    let mut stack: LinkedStack<i32> = Stack::new();

    let result = [1, 3, 4, 3, 5, 3];
    let mut rit = result.iter();

    for s in vec![1, 3, 5, 4, 1, 0, 3, 0, 0, 3, 0, 0, 0, 4] {
        if s == 0 {
            assert_eq!(stack.pop(), rit.next().map(|&n| n))
        } else {
            stack.push(s)
        }
    }
}

#[test]
fn test_linked_stack_iter() {
    let mut stack: LinkedStack<i32> = Stack::new();

    let result = [3, 3, 1];
    let mut rit = result.iter();

    for s in vec![1, 3, 5, 0, 1, 0, 3] {
        if s == 0 {
            stack.pop();
        } else {
            stack.push(s);
        }
    }

    for v in stack.iter() {
        assert_eq!(v, rit.next().unwrap())
    }
}

#[test]
fn test_linked_stack_iter_string() {
    let mut stack: LinkedStack<String> = Stack::new();

    let mut result = "is that or be to".split(' ');

    for s in "to be or not to - be - - that is".split(' ') {
        if s == "-" {
            stack.pop();
        } else {
            stack.push(s.into());
        }
    }

    for v in stack.iter() {
        assert_eq!(v, result.next().unwrap())
    }
}
<|endoftext|>


<commit_before>pub fn add_two(a: i32) -> i32 {
    a + 2
}

pub fn greeting(name: &str) -> String {
    format!("Hello {}!", name)
}

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

    #[test]
    fn it_add_two() {
        assert_eq!(4, add_two(2));
    }

    #[test]
    fn greeting_contains_name() {
        let result = greeting("Carol");
        assert!(
            result.contains("Carol"),
            "Greeting did not contain name, value was `{}`",
            result
        );
    }

    #[test]
    #[should_panic(expected = "index out of bounds")]
    fn index_out_of_bounds() {
        vec![1][5];
    }

    #[test]
    #[ignore]
    fn expensive_test() {
        // take an hour to run
    }
}
<commit_msg>add unit test for internal function<commit_after>pub fn add_two(a: i32) -> i32 {
    a + 2
}

fn internal_adder(a: i32, b: i32) -> i32 {
    a + b
}

pub fn greeting(name: &str) -> String {
    format!("Hello {}!", name)
}

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

    #[test]
    fn it_adds_two() {
        assert_eq!(4, add_two(2));
    }

    #[test]
    fn greeting_contains_name() {
        let result = greeting("Carol");
        assert!(
            result.contains("Carol"),
            "Greeting did not contain name, value was `{}`",
            result
        );
    }

    #[test]
    #[should_panic(expected = "index out of bounds")]
    fn index_out_of_bounds() {
        vec![1][5];
    }

    #[test]
    #[ignore]
    fn expensive_test() {
        // take an hour to run
    }

    #[test]
    fn internal() {
        assert_eq!(4, internal_adder(2, 2));
    }
}
<|endoftext|>


<commit_before>use crate::iter::LoopState;
use crate::ops::Try;

/// An iterator able to yield elements from both ends.
///
/// Something that implements `DoubleEndedIterator` has one extra capability
/// over something that implements [`Iterator`]: the ability to also take
/// `Item`s from the back, as well as the front.
///
/// It is important to note that both back and forth work on the same range,
/// and do not cross: iteration is over when they meet in the middle.
///
/// In a similar fashion to the [`Iterator`] protocol, once a
/// `DoubleEndedIterator` returns `None` from a `next_back()`, calling it again
/// may or may not ever return `Some` again. `next()` and `next_back()` are
/// interchangeable for this purpose.
///
/// [`Iterator`]: trait.Iterator.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let numbers = vec![1, 2, 3, 4, 5, 6];
///
/// let mut iter = numbers.iter();
///
/// assert_eq!(Some(&1), iter.next());
/// assert_eq!(Some(&6), iter.next_back());
/// assert_eq!(Some(&5), iter.next_back());
/// assert_eq!(Some(&2), iter.next());
/// assert_eq!(Some(&3), iter.next());
/// assert_eq!(Some(&4), iter.next());
/// assert_eq!(None, iter.next());
/// assert_eq!(None, iter.next_back());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DoubleEndedIterator: Iterator {
    /// Removes and returns an element from the end of the iterator.
    ///
    /// Returns `None` when there are no more elements.
    ///
    /// The [trait-level] docs contain more details.
    ///
    /// [trait-level]: trait.DoubleEndedIterator.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let numbers = vec![1, 2, 3, 4, 5, 6];
    ///
    /// let mut iter = numbers.iter();
    ///
    /// assert_eq!(Some(&1), iter.next());
    /// assert_eq!(Some(&6), iter.next_back());
    /// assert_eq!(Some(&5), iter.next_back());
    /// assert_eq!(Some(&2), iter.next());
    /// assert_eq!(Some(&3), iter.next());
    /// assert_eq!(Some(&4), iter.next());
    /// assert_eq!(None, iter.next());
    /// assert_eq!(None, iter.next_back());
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn next_back(&mut self) -> Option<Self::Item>;

    /// Returns the `n`th element from the end of the iterator.
    ///
    /// This is essentially the reversed version of [`nth`]. Although like most indexing
    /// operations, the count starts from zero, so `nth_back(0)` returns the first value from
    /// the end, `nth_back(1)` the second, and so on.
    ///
    /// Note that all elements between the end and the returned element will be
    /// consumed, including the returned element. This also means that calling
    /// `nth_back(0)` multiple times on the same iterator will return different
    /// elements.
    ///
    /// `nth_back()` will return [`None`] if `n` is greater than or equal to the length of the
    /// iterator.
    ///
    /// [`None`]: ../../std/option/enum.Option.html#variant.None
    /// [`nth`]: ../../std/iter/trait.Iterator.html#method.nth
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert_eq!(a.iter().nth_back(2), Some(&1));
    /// ```
    ///
    /// Calling `nth_back()` multiple times doesn't rewind the iterator:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// let mut iter = a.iter();
    ///
    /// assert_eq!(iter.nth_back(1), Some(&2));
    /// assert_eq!(iter.nth_back(1), None);
    /// ```
    ///
    /// Returning `None` if there are less than `n + 1` elements:
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert_eq!(a.iter().nth_back(10), None);
    /// ```
    #[inline]
    #[stable(feature = "iter_nth_back", since = "1.37.0")]
    fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
        for x in self.rev() {
            if n == 0 {
                return Some(x);
            }
            n -= 1;
        }
        None
    }

    /// This is the reverse version of [`try_fold()`]: it takes elements
    /// starting from the back of the iterator.
    ///
    /// [`try_fold()`]: trait.Iterator.html#method.try_fold
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = ["1", "2", "3"];
    /// let sum = a.iter()
    ///     .map(|&s| s.parse::<i32>())
    ///     .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
    /// assert_eq!(sum, Ok(6));
    /// ```
    ///
    /// Short-circuiting:
    ///
    /// ```
    /// let a = ["1", "rust", "3"];
    /// let mut it = a.iter();
    /// let sum = it
    ///     .by_ref()
    ///     .map(|&s| s.parse::<i32>())
    ///     .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
    /// assert!(sum.is_err());
    ///
    /// // Because it short-circuited, the remaining elements are still
    /// // available through the iterator.
    /// assert_eq!(it.next_back(), Some(&"1"));
    /// ```
    #[inline]
    #[stable(feature = "iterator_try_fold", since = "1.27.0")]
    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
    where
        Self: Sized,
        F: FnMut(B, Self::Item) -> R,
        R: Try<Ok = B>,
    {
        let mut accum = init;
        while let Some(x) = self.next_back() {
            accum = f(accum, x)?;
        }
        Try::from_ok(accum)
    }

    /// An iterator method that reduces the iterator's elements to a single,
    /// final value, starting from the back.
    ///
    /// This is the reverse version of [`fold()`]: it takes elements starting from
    /// the back of the iterator.
    ///
    /// `rfold()` takes two arguments: an initial value, and a closure with two
    /// arguments: an 'accumulator', and an element. The closure returns the value that
    /// the accumulator should have for the next iteration.
    ///
    /// The initial value is the value the accumulator will have on the first
    /// call.
    ///
    /// After applying this closure to every element of the iterator, `rfold()`
    /// returns the accumulator.
    ///
    /// This operation is sometimes called 'reduce' or 'inject'.
    ///
    /// Folding is useful whenever you have a collection of something, and want
    /// to produce a single value from it.
    ///
    /// [`fold()`]: trait.Iterator.html#method.fold
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// // the sum of all of the elements of a
    /// let sum = a.iter()
    ///            .rfold(0, |acc, &x| acc + x);
    ///
    /// assert_eq!(sum, 6);
    /// ```
    ///
    /// This example builds a string, starting with an initial value
    /// and continuing with each element from the back until the front:
    ///
    /// ```
    /// let numbers = [1, 2, 3, 4, 5];
    ///
    /// let zero = "0".to_string();
    ///
    /// let result = numbers.iter().rfold(zero, |acc, &x| {
    ///     format!("({} + {})", x, acc)
    /// });
    ///
    /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))");
    /// ```
    #[inline]
    #[stable(feature = "iter_rfold", since = "1.27.0")]
    fn rfold<B, F>(mut self, init: B, mut f: F) -> B
    where
        Self: Sized,
        F: FnMut(B, Self::Item) -> B,
    {
        let mut accum = init;
        while let Some(x) = self.next_back() {
            accum = f(accum, x);
        }
        accum
    }

    /// Searches for an element of an iterator from the back that satisfies a predicate.
    ///
    /// `rfind()` takes a closure that returns `true` or `false`. It applies
    /// this closure to each element of the iterator, starting at the end, and if any
    /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return
    /// `false`, it returns [`None`].
    ///
    /// `rfind()` is short-circuiting; in other words, it will stop processing
    /// as soon as the closure returns `true`.
    ///
    /// Because `rfind()` takes a reference, and many iterators iterate over
    /// references, this leads to a possibly confusing situation where the
    /// argument is a double reference. You can see this effect in the
    /// examples below, with `&&x`.
    ///
    /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some
    /// [`None`]: ../../std/option/enum.Option.html#variant.None
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2));
    ///
    /// assert_eq!(a.iter().rfind(|&&x| x == 5), None);
    /// ```
    ///
    /// Stopping at the first `true`:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// let mut iter = a.iter();
    ///
    /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2));
    ///
    /// // we can still use `iter`, as there are more elements.
    /// assert_eq!(iter.next_back(), Some(&1));
    /// ```
    #[inline]
    #[stable(feature = "iter_rfind", since = "1.27.0")]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        Self: Sized,
        P: FnMut(&Self::Item) -> bool,
    {
        #[inline]
        fn check<T>(
            mut predicate: impl FnMut(&T) -> bool,
        ) -> impl FnMut((), T) -> LoopState<(), T> {
            move |(), x| {
                if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
            }
        }

        self.try_rfold((), check(predicate)).break_value()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
    fn next_back(&mut self) -> Option<I::Item> {
        (**self).next_back()
    }
    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
        (**self).nth_back(n)
    }
}
<commit_msg>Add remark regarding DoubleEndedIterator<commit_after>use crate::iter::LoopState;
use crate::ops::Try;

/// An iterator able to yield elements from both ends.
///
/// Something that implements `DoubleEndedIterator` has one extra capability
/// over something that implements [`Iterator`]: the ability to also take
/// `Item`s from the back, as well as the front.
///
/// It is important to note that both back and forth work on the same range,
/// and do not cross: iteration is over when they meet in the middle.
///
/// In a similar fashion to the [`Iterator`] protocol, once a
/// `DoubleEndedIterator` returns `None` from a `next_back()`, calling it again
/// may or may not ever return `Some` again. `next()` and `next_back()` are
/// interchangeable for this purpose.
///
/// [`Iterator`]: trait.Iterator.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let numbers = vec![1, 2, 3, 4, 5, 6];
///
/// let mut iter = numbers.iter();
///
/// assert_eq!(Some(&1), iter.next());
/// assert_eq!(Some(&6), iter.next_back());
/// assert_eq!(Some(&5), iter.next_back());
/// assert_eq!(Some(&2), iter.next());
/// assert_eq!(Some(&3), iter.next());
/// assert_eq!(Some(&4), iter.next());
/// assert_eq!(None, iter.next());
/// assert_eq!(None, iter.next_back());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DoubleEndedIterator: Iterator {
    /// Removes and returns an element from the end of the iterator.
    ///
    /// Returns `None` when there are no more elements.
    ///
    /// The [trait-level] docs contain more details.
    ///
    /// [trait-level]: trait.DoubleEndedIterator.html
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let numbers = vec![1, 2, 3, 4, 5, 6];
    ///
    /// let mut iter = numbers.iter();
    ///
    /// assert_eq!(Some(&1), iter.next());
    /// assert_eq!(Some(&6), iter.next_back());
    /// assert_eq!(Some(&5), iter.next_back());
    /// assert_eq!(Some(&2), iter.next());
    /// assert_eq!(Some(&3), iter.next());
    /// assert_eq!(Some(&4), iter.next());
    /// assert_eq!(None, iter.next());
    /// assert_eq!(None, iter.next_back());
    /// ```
    ///
    /// # Remarks
    ///
    /// The elements yielded by `DoubleEndedIterator`'s methods may differ from
    /// the ones yielded by `Iterator`'s methods:
    ///
    /// ```
    /// let vec = vec![(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b')];
    /// let uniq_by_fst_comp = || {
    ///     let mut seen = std::collections::HashSet::new();
    ///     vec.iter().copied().filter(move |x| seen.insert(x.0))
    /// };
    ///
    /// assert_eq!(uniq_by_fst_comp().last(), Some((2, 'a')));
    /// assert_eq!(uniq_by_fst_comp().next_back(), Some((2, 'b')));
    ///
    /// assert_eq!(
    ///     uniq_by_fst_comp().fold(vec![], |mut v, x| {v.push(x); v}),
    ///     vec![(1, 'a'), (2, 'a')]
    /// );
    /// assert_eq!(
    ///     uniq_by_fst_comp().rfold(vec![], |mut v, x| {v.push(x); v}),
    ///     vec![(2, 'b'), (1, 'c')]
    /// );
    /// ```
    ///
    #[stable(feature = "rust1", since = "1.0.0")]
    fn next_back(&mut self) -> Option<Self::Item>;

    /// Returns the `n`th element from the end of the iterator.
    ///
    /// This is essentially the reversed version of [`nth`]. Although like most indexing
    /// operations, the count starts from zero, so `nth_back(0)` returns the first value from
    /// the end, `nth_back(1)` the second, and so on.
    ///
    /// Note that all elements between the end and the returned element will be
    /// consumed, including the returned element. This also means that calling
    /// `nth_back(0)` multiple times on the same iterator will return different
    /// elements.
    ///
    /// `nth_back()` will return [`None`] if `n` is greater than or equal to the length of the
    /// iterator.
    ///
    /// [`None`]: ../../std/option/enum.Option.html#variant.None
    /// [`nth`]: ../../std/iter/trait.Iterator.html#method.nth
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert_eq!(a.iter().nth_back(2), Some(&1));
    /// ```
    ///
    /// Calling `nth_back()` multiple times doesn't rewind the iterator:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// let mut iter = a.iter();
    ///
    /// assert_eq!(iter.nth_back(1), Some(&2));
    /// assert_eq!(iter.nth_back(1), None);
    /// ```
    ///
    /// Returning `None` if there are less than `n + 1` elements:
    ///
    /// ```
    /// let a = [1, 2, 3];
    /// assert_eq!(a.iter().nth_back(10), None);
    /// ```
    #[inline]
    #[stable(feature = "iter_nth_back", since = "1.37.0")]
    fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
        for x in self.rev() {
            if n == 0 {
                return Some(x);
            }
            n -= 1;
        }
        None
    }

    /// This is the reverse version of [`try_fold()`]: it takes elements
    /// starting from the back of the iterator.
    ///
    /// [`try_fold()`]: trait.Iterator.html#method.try_fold
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = ["1", "2", "3"];
    /// let sum = a.iter()
    ///     .map(|&s| s.parse::<i32>())
    ///     .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
    /// assert_eq!(sum, Ok(6));
    /// ```
    ///
    /// Short-circuiting:
    ///
    /// ```
    /// let a = ["1", "rust", "3"];
    /// let mut it = a.iter();
    /// let sum = it
    ///     .by_ref()
    ///     .map(|&s| s.parse::<i32>())
    ///     .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
    /// assert!(sum.is_err());
    ///
    /// // Because it short-circuited, the remaining elements are still
    /// // available through the iterator.
    /// assert_eq!(it.next_back(), Some(&"1"));
    /// ```
    #[inline]
    #[stable(feature = "iterator_try_fold", since = "1.27.0")]
    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
    where
        Self: Sized,
        F: FnMut(B, Self::Item) -> R,
        R: Try<Ok = B>,
    {
        let mut accum = init;
        while let Some(x) = self.next_back() {
            accum = f(accum, x)?;
        }
        Try::from_ok(accum)
    }

    /// An iterator method that reduces the iterator's elements to a single,
    /// final value, starting from the back.
    ///
    /// This is the reverse version of [`fold()`]: it takes elements starting from
    /// the back of the iterator.
    ///
    /// `rfold()` takes two arguments: an initial value, and a closure with two
    /// arguments: an 'accumulator', and an element. The closure returns the value that
    /// the accumulator should have for the next iteration.
    ///
    /// The initial value is the value the accumulator will have on the first
    /// call.
    ///
    /// After applying this closure to every element of the iterator, `rfold()`
    /// returns the accumulator.
    ///
    /// This operation is sometimes called 'reduce' or 'inject'.
    ///
    /// Folding is useful whenever you have a collection of something, and want
    /// to produce a single value from it.
    ///
    /// [`fold()`]: trait.Iterator.html#method.fold
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// // the sum of all of the elements of a
    /// let sum = a.iter()
    ///            .rfold(0, |acc, &x| acc + x);
    ///
    /// assert_eq!(sum, 6);
    /// ```
    ///
    /// This example builds a string, starting with an initial value
    /// and continuing with each element from the back until the front:
    ///
    /// ```
    /// let numbers = [1, 2, 3, 4, 5];
    ///
    /// let zero = "0".to_string();
    ///
    /// let result = numbers.iter().rfold(zero, |acc, &x| {
    ///     format!("({} + {})", x, acc)
    /// });
    ///
    /// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))");
    /// ```
    #[inline]
    #[stable(feature = "iter_rfold", since = "1.27.0")]
    fn rfold<B, F>(mut self, init: B, mut f: F) -> B
    where
        Self: Sized,
        F: FnMut(B, Self::Item) -> B,
    {
        let mut accum = init;
        while let Some(x) = self.next_back() {
            accum = f(accum, x);
        }
        accum
    }

    /// Searches for an element of an iterator from the back that satisfies a predicate.
    ///
    /// `rfind()` takes a closure that returns `true` or `false`. It applies
    /// this closure to each element of the iterator, starting at the end, and if any
    /// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return
    /// `false`, it returns [`None`].
    ///
    /// `rfind()` is short-circuiting; in other words, it will stop processing
    /// as soon as the closure returns `true`.
    ///
    /// Because `rfind()` takes a reference, and many iterators iterate over
    /// references, this leads to a possibly confusing situation where the
    /// argument is a double reference. You can see this effect in the
    /// examples below, with `&&x`.
    ///
    /// [`Some(element)`]: ../../std/option/enum.Option.html#variant.Some
    /// [`None`]: ../../std/option/enum.Option.html#variant.None
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2));
    ///
    /// assert_eq!(a.iter().rfind(|&&x| x == 5), None);
    /// ```
    ///
    /// Stopping at the first `true`:
    ///
    /// ```
    /// let a = [1, 2, 3];
    ///
    /// let mut iter = a.iter();
    ///
    /// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2));
    ///
    /// // we can still use `iter`, as there are more elements.
    /// assert_eq!(iter.next_back(), Some(&1));
    /// ```
    #[inline]
    #[stable(feature = "iter_rfind", since = "1.27.0")]
    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        Self: Sized,
        P: FnMut(&Self::Item) -> bool,
    {
        #[inline]
        fn check<T>(
            mut predicate: impl FnMut(&T) -> bool,
        ) -> impl FnMut((), T) -> LoopState<(), T> {
            move |(), x| {
                if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) }
            }
        }

        self.try_rfold((), check(predicate)).break_value()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
    fn next_back(&mut self) -> Option<I::Item> {
        (**self).next_back()
    }
    fn nth_back(&mut self, n: usize) -> Option<I::Item> {
        (**self).nth_back(n)
    }
}
<|endoftext|>


<commit_before>use serde_json::Value;
// use response::string_as_i64;

#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum SI {
	I(i64),
	S(String),
}

#[derive(Debug, Clone, Deserialize)]
pub struct Fullentry {
	//#[serde(deserialize_with = "string_as_i64")]
	pub id: SI,
	pub names: Vec<Name>,
	pub genre: String,
	pub fsk: String,
	pub description: String,
	pub medium: String,
	pub count: String,
	pub state: String,
	pub rate_sum: String,
	pub rate_count: String,
	pub clicks: String,
	pub kat: String,
	pub license: String,
	pub tags: Vec<Tag>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Info {
	pub id: String,
	pub name: String,
	pub genre: String,
	pub fsk: String,
	pub description: String,
	pub medium: String,
	pub count: String,
	pub state: String,
	pub rate_sum: String,
	pub rate_count: String,
	pub clicks: String,
	pub kat: Value,
	pub license: Value,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UserList {
	pub id: i64,
	pub name: String,
	pub description: String,
	pub genre: Vec<String>,
	pub fsk: Vec<String>,
	pub medium: String,
	pub count: i64,
	pub state: i64,
	pub rate_sum: i64,
	pub rate_count: i64,
	pub clicks: i64,
	pub kat: Kat,
	pub license: License,
}

#[derive(Debug, Clone, Deserialize)]
pub enum SpoilerFlag {
	#[serde(rename = "0")]
	NoSpoiler,
	#[serde(rename = "1")]
	Spoiler
}

#[derive(Debug, Clone, Deserialize)]
pub enum RateFlag {
	#[serde(rename = "0")]
	NoMatch,
	#[serde(rename = "1")]
	Match
}

#[derive(Debug, Clone, Deserialize)]
pub struct Tag {
	pub info_id: Option<i64>,
	pub id: SI,
	#[serde(rename = "tid")]
	pub tag_id: SI,
	pub timestamp: String,
	pub rate_flag: RateFlag,
	pub spoiler_flag: SpoilerFlag,
	pub tag: String,
	pub description: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Name {
	id: String,
	eid: String,
	#[serde(rename = "type")]
	type_: String,
	name: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Comment {
	pub id: i64,
	pub info_id: i64,
	pub comment_type: String,
	pub state: i64, // Todo: use enum for state
	pub data: String,
	pub comment: String,
	pub rating: i64,
	pub episode: i64,
	pub positive: i64,
	pub timestamp: i64, //Todo: use chrono here
	pub username: String,
	pub uid: i64,
	pub avatar: String,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Userinfo {
	pub uid: i64,
	pub username: String,
	pub avatar: String, // use some sort of uri type here
	pub status: String,
	// status_time is sometimes a negative number. using i64
	pub status_time: i64,
	pub points_upload: i64,
	pub points_anime: i64,
	pub points_manga: i64,
	pub points_info: i64,
	pub points_forum: i64,
	pub points_misc: i64,
}

#[derive(Debug, Clone, Deserialize)]
pub enum Kat {
	Anime,
	Manga,
}

#[derive(Debug, Clone, Deserialize)]
pub enum License {
	Unknown,
	Unlicensed,
	Licensed,
}
<commit_msg>add type conversion for SI<commit_after>use serde_json::Value;
use std::fmt;

/// `S`ring/`I`nteger
/// a temporary type for strings that are integers
/// if a field with an integer as string is used, just use `.into()`

#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum SI {
	I(i64),
	S(String),
}

impl From<SI> for i64 {
	fn from(si: SI) -> Self {
		match si {
			SI::I(i) => i,
			SI::S(s) => s.parse::<i64>().unwrap()
		}
	}
}

impl fmt::Display for SI {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", i64::from(self.to_owned()))
	}
}

#[derive(Debug, Clone, Deserialize)]
pub struct Fullentry {
	//#[serde(deserialize_with = "string_as_i64")]
	pub id: SI,
	pub names: Vec<Name>,
	pub genre: String,
	pub fsk: String,
	pub description: String,
	pub medium: String,
	pub count: String,
	pub state: String,
	pub rate_sum: String,
	pub rate_count: String,
	pub clicks: String,
	pub kat: String,
	pub license: String,
	pub tags: Vec<Tag>,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Info {
	pub id: String,
	pub name: String,
	pub genre: String,
	pub fsk: String,
	pub description: String,
	pub medium: String,
	pub count: String,
	pub state: String,
	pub rate_sum: String,
	pub rate_count: String,
	pub clicks: String,
	pub kat: Value,
	pub license: Value,
}

#[derive(Debug, Clone, Deserialize)]
pub struct UserList {
	pub id: i64,
	pub name: String,
	pub description: String,
	pub genre: Vec<String>,
	pub fsk: Vec<String>,
	pub medium: String,
	pub count: i64,
	pub state: i64,
	pub rate_sum: i64,
	pub rate_count: i64,
	pub clicks: i64,
	pub kat: Kat,
	pub license: License,
}

#[derive(Debug, Clone, Deserialize)]
pub enum SpoilerFlag {
	#[serde(rename = "0")]
	NoSpoiler,
	#[serde(rename = "1")]
	Spoiler
}

#[derive(Debug, Clone, Deserialize)]
pub enum RateFlag {
	#[serde(rename = "0")]
	NoMatch,
	#[serde(rename = "1")]
	Match
}

#[derive(Debug, Clone, Deserialize)]
pub struct Tag {
	pub info_id: Option<i64>,
	pub id: SI,
	#[serde(rename = "tid")]
	pub tag_id: SI,
	pub timestamp: String,
	pub rate_flag: RateFlag,
	pub spoiler_flag: SpoilerFlag,
	pub tag: String,
	pub description: String,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Name {
	id: String,
	eid: String,
	#[serde(rename = "type")]
	type_: String,
	name: String,
}

#[derive(Debug, Clone, Deserialize)]
pub enum WatchState {
	#[serde(rename = "0")]
	Watched,
	#[serde(rename = "1")]
	Watching,
	#[serde(rename = "2")]
	WillWatch,
	#[serde(rename = "3")]
	Cancelled,
}

#[derive(Debug, Clone, Deserialize)]
pub struct Comment {
	pub id: SI,
	#[serde(rename = "tid")]
	pub info_id: SI,
	#[serde(rename = "type")]
	pub comment_type: String, // i have no idea what this is
	pub state: WatchState,
	pub data: String,
	pub comment: String,
	pub rating: SI,
	pub episode: SI,
	pub positive: SI,
	pub timestamp: SI, //Todo: use chrono here
	pub username: String,
	pub uid: String,
	pub avatar: String,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Userinfo {
	pub uid: i64,
	pub username: String,
	pub avatar: String, // use some sort of uri type here
	pub status: String,
	// status_time is sometimes a negative number. using i64
	pub status_time: i64,
	pub points_upload: i64,
	pub points_anime: i64,
	pub points_manga: i64,
	pub points_info: i64,
	pub points_forum: i64,
	pub points_misc: i64,
}

#[derive(Debug, Clone, Deserialize)]
pub enum Kat {
	Anime,
	Manga,
}

#[derive(Debug, Clone, Deserialize)]
pub enum License {
	Unknown,
	Unlicensed,
	Licensed,
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

use session::config::Options;

use std::fs;
use std::io::{self, StdoutLock, Write};
use std::time::Instant;

macro_rules! define_categories {
    ($($name:ident,)*) => {
        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
        pub enum ProfileCategory {
            $($name),*
        }

        #[allow(nonstandard_style)]
        struct Categories<T> {
            $($name: T),*
        }

        impl<T: Default> Categories<T> {
            fn new() -> Categories<T> {
                Categories {
                    $($name: T::default()),*
                }
            }
        }

        impl<T> Categories<T> {
            fn get(&self, category: ProfileCategory) -> &T {
                match category {
                    $(ProfileCategory::$name => &self.$name),*
                }
            }

            fn set(&mut self, category: ProfileCategory, value: T) {
                match category {
                    $(ProfileCategory::$name => self.$name = value),*
                }
            }
        }

        struct CategoryData {
            times: Categories<u64>,
            query_counts: Categories<(u64, u64)>,
        }

        impl CategoryData {
            fn new() -> CategoryData {
                CategoryData {
                    times: Categories::new(),
                    query_counts: Categories::new(),
                }
            }

            fn print(&self, lock: &mut StdoutLock<'_>) {
                writeln!(lock, "| Phase            | Time (ms)      | Queries        | Hits (%) |")
                    .unwrap();
                writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |")
                    .unwrap();

                $(
                    let (hits, total) = self.query_counts.$name;
                    let (hits, total) = if total > 0 {
                        (format!("{:.2}",
                        (((hits as f32) / (total as f32)) * 100.0)), total.to_string())
                    } else {
                        (String::new(), String::new())
                    };

                    writeln!(
                        lock,
                        "| {0: <16} | {1: <14} | {2: <14} | {3: <8} |",
                        stringify!($name),
                        self.times.$name / 1_000_000,
                        total,
                        hits
                    ).unwrap();
                )*
            }

            fn json(&self) -> String {
                let mut json = String::from("[");

                $(
                    let (hits, total) = self.query_counts.$name;

                    json.push_str(&format!(
                        "{{ \"category\": {}, \"time_ms\": {},
                            \"query_count\": {}, \"query_hits\": {} }}",
                        stringify!($name),
                        self.times.$name / 1_000_000,
                        total,
                        format!("{:.2}", (((hits as f32) / (total as f32)) * 100.0))
                    ));
                )*

                json.push(']');

                json
            }
        }
    }
}

define_categories! {
    Parsing,
    Expansion,
    TypeChecking,
    BorrowChecking,
    Codegen,
    Linking,
    Other,
}

pub struct SelfProfiler {
    timer_stack: Vec<ProfileCategory>,
    data: CategoryData,
    current_timer: Instant,
}

impl SelfProfiler {
    pub fn new() -> SelfProfiler {
        let mut profiler = SelfProfiler {
            timer_stack: Vec::new(),
            data: CategoryData::new(),
            current_timer: Instant::now(),
        };

        profiler.start_activity(ProfileCategory::Other);

        profiler
    }

    pub fn start_activity(&mut self, category: ProfileCategory) {
        match self.timer_stack.last().cloned() {
            None => {
                self.current_timer = Instant::now();
            },
            Some(current_category) if current_category == category => {
                //since the current category is the same as the new activity's category,
                //we don't need to do anything with the timer, we just need to push it on the stack
            }
            Some(current_category) => {
                let elapsed = self.stop_timer();

                //record the current category's time
                let new_time = self.data.times.get(current_category) + elapsed;
                self.data.times.set(current_category, new_time);
            }
        }

        //push the new category
        self.timer_stack.push(category);
    }

    pub fn record_query(&mut self, category: ProfileCategory) {
        let (hits, total) = *self.data.query_counts.get(category);
        self.data.query_counts.set(category, (hits, total + 1));
    }

    pub fn record_query_hit(&mut self, category: ProfileCategory) {
        let (hits, total) = *self.data.query_counts.get(category);
        self.data.query_counts.set(category, (hits + 1, total));
    }

    pub fn end_activity(&mut self, category: ProfileCategory) {
        match self.timer_stack.pop() {
            None => bug!("end_activity() was called but there was no running activity"),
            Some(c) =>
                assert!(
                    c == category,
                    "end_activity() was called but a different activity was running"),
        }

        //check if the new running timer is in the same category as this one
        //if it is, we don't need to do anything
        if let Some(c) = self.timer_stack.last() {
            if *c == category {
                return;
            }
        }

        //the new timer is different than the previous,
        //so record the elapsed time and start a new timer
        let elapsed = self.stop_timer();
        let new_time = self.data.times.get(category) + elapsed;
        self.data.times.set(category, new_time);
    }

    fn stop_timer(&mut self) -> u64 {
        let elapsed = self.current_timer.elapsed();

        self.current_timer = Instant::now();

        (elapsed.as_secs() * 1_000_000_000) + (elapsed.subsec_nanos() as u64)
    }

    pub fn print_results(&mut self, opts: &Options) {
        self.end_activity(ProfileCategory::Other);

        assert!(
            self.timer_stack.is_empty(),
            "there were timers running when print_results() was called");

        let out = io::stdout();
        let mut lock = out.lock();

        let crate_name =
            opts.crate_name
            .as_ref()
            .map(|n| format!(" for {}", n))
            .unwrap_or_default();

        writeln!(lock, "Self profiling results{}:", crate_name).unwrap();
        writeln!(lock).unwrap();

        self.data.print(&mut lock);

        writeln!(lock).unwrap();
        writeln!(lock, "Optimization level: {:?}", opts.optimize).unwrap();

        let incremental = if opts.incremental.is_some() { "on" } else { "off" };
        writeln!(lock, "Incremental: {}", incremental).unwrap();
    }

    pub fn save_results(&self, opts: &Options) {
        let category_data = self.data.json();
        let compilation_options =
            format!("{{ \"optimization_level\": \"{:?}\", \"incremental\": {} }}",
                    opts.optimize,
                    if opts.incremental.is_some() { "true" } else { "false" });

        let json = format!("{{ \"category_data\": {}, \"compilation_options\": {} }}",
                        category_data,
                        compilation_options);

        fs::write("self_profiler_results.json", json).unwrap();
    }
}
<commit_msg>Fix json output in the self-profiler<commit_after>// Copyright 2018 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.

use session::config::Options;

use std::fs;
use std::io::{self, StdoutLock, Write};
use std::time::Instant;

macro_rules! define_categories {
    ($($name:ident,)*) => {
        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
        pub enum ProfileCategory {
            $($name),*
        }

        #[allow(nonstandard_style)]
        struct Categories<T> {
            $($name: T),*
        }

        impl<T: Default> Categories<T> {
            fn new() -> Categories<T> {
                Categories {
                    $($name: T::default()),*
                }
            }
        }

        impl<T> Categories<T> {
            fn get(&self, category: ProfileCategory) -> &T {
                match category {
                    $(ProfileCategory::$name => &self.$name),*
                }
            }

            fn set(&mut self, category: ProfileCategory, value: T) {
                match category {
                    $(ProfileCategory::$name => self.$name = value),*
                }
            }
        }

        struct CategoryData {
            times: Categories<u64>,
            query_counts: Categories<(u64, u64)>,
        }

        impl CategoryData {
            fn new() -> CategoryData {
                CategoryData {
                    times: Categories::new(),
                    query_counts: Categories::new(),
                }
            }

            fn print(&self, lock: &mut StdoutLock<'_>) {
                writeln!(lock, "| Phase            | Time (ms)      | Queries        | Hits (%) |")
                    .unwrap();
                writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |")
                    .unwrap();

                $(
                    let (hits, total) = self.query_counts.$name;
                    let (hits, total) = if total > 0 {
                        (format!("{:.2}",
                        (((hits as f32) / (total as f32)) * 100.0)), total.to_string())
                    } else {
                        (String::new(), String::new())
                    };

                    writeln!(
                        lock,
                        "| {0: <16} | {1: <14} | {2: <14} | {3: <8} |",
                        stringify!($name),
                        self.times.$name / 1_000_000,
                        total,
                        hits
                    ).unwrap();
                )*
            }

            fn json(&self) -> String {
                let mut json = String::from("[");

                $(
                    let (hits, total) = self.query_counts.$name;

                    //normalize hits to 0%
                    let hit_percent =
                        if total > 0 {
                            ((hits as f32) / (total as f32)) * 100.0
                        } else {
                            0.0
                        };

                    json.push_str(&format!(
                        "{{ \"category\": {}, \"time_ms\": {},
                            \"query_count\": {}, \"query_hits\": {} }},",
                        stringify!($name),
                        self.times.$name / 1_000_000,
                        total,
                        format!("{:.2}", hit_percent)
                    ));
                )*

                //remove the trailing ',' character
                json.pop();

                json.push(']');

                json
            }
        }
    }
}

define_categories! {
    Parsing,
    Expansion,
    TypeChecking,
    BorrowChecking,
    Codegen,
    Linking,
    Other,
}

pub struct SelfProfiler {
    timer_stack: Vec<ProfileCategory>,
    data: CategoryData,
    current_timer: Instant,
}

impl SelfProfiler {
    pub fn new() -> SelfProfiler {
        let mut profiler = SelfProfiler {
            timer_stack: Vec::new(),
            data: CategoryData::new(),
            current_timer: Instant::now(),
        };

        profiler.start_activity(ProfileCategory::Other);

        profiler
    }

    pub fn start_activity(&mut self, category: ProfileCategory) {
        match self.timer_stack.last().cloned() {
            None => {
                self.current_timer = Instant::now();
            },
            Some(current_category) if current_category == category => {
                //since the current category is the same as the new activity's category,
                //we don't need to do anything with the timer, we just need to push it on the stack
            }
            Some(current_category) => {
                let elapsed = self.stop_timer();

                //record the current category's time
                let new_time = self.data.times.get(current_category) + elapsed;
                self.data.times.set(current_category, new_time);
            }
        }

        //push the new category
        self.timer_stack.push(category);
    }

    pub fn record_query(&mut self, category: ProfileCategory) {
        let (hits, total) = *self.data.query_counts.get(category);
        self.data.query_counts.set(category, (hits, total + 1));
    }

    pub fn record_query_hit(&mut self, category: ProfileCategory) {
        let (hits, total) = *self.data.query_counts.get(category);
        self.data.query_counts.set(category, (hits + 1, total));
    }

    pub fn end_activity(&mut self, category: ProfileCategory) {
        match self.timer_stack.pop() {
            None => bug!("end_activity() was called but there was no running activity"),
            Some(c) =>
                assert!(
                    c == category,
                    "end_activity() was called but a different activity was running"),
        }

        //check if the new running timer is in the same category as this one
        //if it is, we don't need to do anything
        if let Some(c) = self.timer_stack.last() {
            if *c == category {
                return;
            }
        }

        //the new timer is different than the previous,
        //so record the elapsed time and start a new timer
        let elapsed = self.stop_timer();
        let new_time = self.data.times.get(category) + elapsed;
        self.data.times.set(category, new_time);
    }

    fn stop_timer(&mut self) -> u64 {
        let elapsed = self.current_timer.elapsed();

        self.current_timer = Instant::now();

        (elapsed.as_secs() * 1_000_000_000) + (elapsed.subsec_nanos() as u64)
    }

    pub fn print_results(&mut self, opts: &Options) {
        self.end_activity(ProfileCategory::Other);

        assert!(
            self.timer_stack.is_empty(),
            "there were timers running when print_results() was called");

        let out = io::stdout();
        let mut lock = out.lock();

        let crate_name =
            opts.crate_name
            .as_ref()
            .map(|n| format!(" for {}", n))
            .unwrap_or_default();

        writeln!(lock, "Self profiling results{}:", crate_name).unwrap();
        writeln!(lock).unwrap();

        self.data.print(&mut lock);

        writeln!(lock).unwrap();
        writeln!(lock, "Optimization level: {:?}", opts.optimize).unwrap();

        let incremental = if opts.incremental.is_some() { "on" } else { "off" };
        writeln!(lock, "Incremental: {}", incremental).unwrap();
    }

    pub fn save_results(&self, opts: &Options) {
        let category_data = self.data.json();
        let compilation_options =
            format!("{{ \"optimization_level\": \"{:?}\", \"incremental\": {} }}",
                    opts.optimize,
                    if opts.incremental.is_some() { "true" } else { "false" });

        let json = format!("{{ \"category_data\": {}, \"compilation_options\": {} }}",
                        category_data,
                        compilation_options);

        fs::write("self_profiler_results.json", json).unwrap();
    }
}
<|endoftext|>


<commit_before>use crate::schema::*;

use rustc::hir::def_id::{DefId, DefIndex};
use rustc_serialize::opaque::Encoder;
use std::marker::PhantomData;
use std::u32;
use log::debug;

/// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
trait FixedSizeEncoding {
    const BYTE_LEN: usize;

    // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead,
    // once that starts being allowed by the compiler (i.e. lazy normalization).
    fn from_bytes(b: &[u8]) -> Self;
    fn write_to_bytes(self, b: &mut [u8]);

    // FIXME(eddyb) make these generic functions, or at least defaults here.
    // (same problem as above, needs `[u8; Self::BYTE_LEN]`)
    // For now, a macro (`fixed_size_encoding_byte_len_and_defaults`) is used.
    fn read_from_bytes_at(b: &[u8], i: usize) -> Self;
    fn write_to_bytes_at(self, b: &mut [u8], i: usize);
}

// HACK(eddyb) this shouldn't be needed (see comments on the methods above).
macro_rules! fixed_size_encoding_byte_len_and_defaults {
    ($byte_len:expr) => {
        const BYTE_LEN: usize = $byte_len;
        fn read_from_bytes_at(b: &[u8], i: usize) -> Self {
            const BYTE_LEN: usize = $byte_len;
            // HACK(eddyb) ideally this would be done with fully safe code,
            // but slicing `[u8]` with `i * N..` is optimized worse, due to the
            // possibility of `i * N` overflowing, than indexing `[[u8; N]]`.
            let b = unsafe {
                std::slice::from_raw_parts(
                    b.as_ptr() as *const [u8; BYTE_LEN],
                    b.len() / BYTE_LEN,
                )
            };
            Self::from_bytes(&b[i])
        }
        fn write_to_bytes_at(self, b: &mut [u8], i: usize) {
            const BYTE_LEN: usize = $byte_len;
            // HACK(eddyb) ideally this would be done with fully safe code,
            // see similar comment in `read_from_bytes_at` for why it can't yet.
            let b = unsafe {
                std::slice::from_raw_parts_mut(
                    b.as_mut_ptr() as *mut [u8; BYTE_LEN],
                    b.len() / BYTE_LEN,
                )
            };
            self.write_to_bytes(&mut b[i]);
        }
    }
}

impl FixedSizeEncoding for u32 {
    fixed_size_encoding_byte_len_and_defaults!(4);

    fn from_bytes(b: &[u8]) -> Self {
        let mut bytes = [0; Self::BYTE_LEN];
        bytes.copy_from_slice(&b[..Self::BYTE_LEN]);
        Self::from_le_bytes(bytes)
    }

    fn write_to_bytes(self, b: &mut [u8]) {
        b[..Self::BYTE_LEN].copy_from_slice(&self.to_le_bytes());
    }
}

/// While we are generating the metadata, we also track the position
/// of each DefIndex. It is not required that all definitions appear
/// in the metadata, nor that they are serialized in order, and
/// therefore we first allocate the vector here and fill it with
/// `u32::MAX`. Whenever an index is visited, we fill in the
/// appropriate spot by calling `record_position`. We should never
/// visit the same index twice.
crate struct Index<'tcx> {
    positions: Vec<u8>,
    _marker: PhantomData<&'tcx ()>,
}

impl Index<'tcx> {
    crate fn new(max_index: usize) -> Self {
        Index {
            positions: vec![0xff; max_index * 4],
            _marker: PhantomData,
        }
    }

    crate fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'tcx>>) {
        assert!(def_id.is_local());
        self.record_index(def_id.index, entry);
    }

    fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'tcx>>) {
        assert!(entry.position < (u32::MAX as usize));
        let position = entry.position as u32;
        let array_index = item.index();

        let positions = &mut self.positions;
        assert!(u32::read_from_bytes_at(positions, array_index) == u32::MAX,
                "recorded position for item {:?} twice, first at {:?} and now at {:?}",
                item,
                u32::read_from_bytes_at(positions, array_index),
                position);

        position.write_to_bytes_at(positions, array_index)
    }

    crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> {
        let pos = buf.position();

        // First we write the length of the lower range ...
        buf.emit_raw_bytes(&(self.positions.len() as u32 / 4).to_le_bytes());
        // ... then the values.
        buf.emit_raw_bytes(&self.positions);
        Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4 + 1)
    }
}

impl Lazy<[Index<'tcx>]> {
    /// Given the metadata, extract out the offset of a particular
    /// DefIndex (if any).
    #[inline(never)]
    crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
        let bytes = &bytes[self.position..];
        debug!("Index::lookup: index={:?} len={:?}",
               def_index,
               self.meta);

        let position = u32::read_from_bytes_at(bytes, 1 + def_index.index());
        if position == u32::MAX {
            debug!("Index::lookup: position=u32::MAX");
            None
        } else {
            debug!("Index::lookup: position={:?}", position);
            Some(Lazy::from_position(position as usize))
        }
    }
}
<commit_msg>rustc_metadata: remove now-redundant length from the start of the encoding.<commit_after>use crate::schema::*;

use rustc::hir::def_id::{DefId, DefIndex};
use rustc_serialize::opaque::Encoder;
use std::marker::PhantomData;
use std::u32;
use log::debug;

/// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
trait FixedSizeEncoding {
    const BYTE_LEN: usize;

    // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead,
    // once that starts being allowed by the compiler (i.e. lazy normalization).
    fn from_bytes(b: &[u8]) -> Self;
    fn write_to_bytes(self, b: &mut [u8]);

    // FIXME(eddyb) make these generic functions, or at least defaults here.
    // (same problem as above, needs `[u8; Self::BYTE_LEN]`)
    // For now, a macro (`fixed_size_encoding_byte_len_and_defaults`) is used.
    fn read_from_bytes_at(b: &[u8], i: usize) -> Self;
    fn write_to_bytes_at(self, b: &mut [u8], i: usize);
}

// HACK(eddyb) this shouldn't be needed (see comments on the methods above).
macro_rules! fixed_size_encoding_byte_len_and_defaults {
    ($byte_len:expr) => {
        const BYTE_LEN: usize = $byte_len;
        fn read_from_bytes_at(b: &[u8], i: usize) -> Self {
            const BYTE_LEN: usize = $byte_len;
            // HACK(eddyb) ideally this would be done with fully safe code,
            // but slicing `[u8]` with `i * N..` is optimized worse, due to the
            // possibility of `i * N` overflowing, than indexing `[[u8; N]]`.
            let b = unsafe {
                std::slice::from_raw_parts(
                    b.as_ptr() as *const [u8; BYTE_LEN],
                    b.len() / BYTE_LEN,
                )
            };
            Self::from_bytes(&b[i])
        }
        fn write_to_bytes_at(self, b: &mut [u8], i: usize) {
            const BYTE_LEN: usize = $byte_len;
            // HACK(eddyb) ideally this would be done with fully safe code,
            // see similar comment in `read_from_bytes_at` for why it can't yet.
            let b = unsafe {
                std::slice::from_raw_parts_mut(
                    b.as_mut_ptr() as *mut [u8; BYTE_LEN],
                    b.len() / BYTE_LEN,
                )
            };
            self.write_to_bytes(&mut b[i]);
        }
    }
}

impl FixedSizeEncoding for u32 {
    fixed_size_encoding_byte_len_and_defaults!(4);

    fn from_bytes(b: &[u8]) -> Self {
        let mut bytes = [0; Self::BYTE_LEN];
        bytes.copy_from_slice(&b[..Self::BYTE_LEN]);
        Self::from_le_bytes(bytes)
    }

    fn write_to_bytes(self, b: &mut [u8]) {
        b[..Self::BYTE_LEN].copy_from_slice(&self.to_le_bytes());
    }
}

/// While we are generating the metadata, we also track the position
/// of each DefIndex. It is not required that all definitions appear
/// in the metadata, nor that they are serialized in order, and
/// therefore we first allocate the vector here and fill it with
/// `u32::MAX`. Whenever an index is visited, we fill in the
/// appropriate spot by calling `record_position`. We should never
/// visit the same index twice.
crate struct Index<'tcx> {
    positions: Vec<u8>,
    _marker: PhantomData<&'tcx ()>,
}

impl Index<'tcx> {
    crate fn new(max_index: usize) -> Self {
        Index {
            positions: vec![0xff; max_index * 4],
            _marker: PhantomData,
        }
    }

    crate fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'tcx>>) {
        assert!(def_id.is_local());
        self.record_index(def_id.index, entry);
    }

    fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'tcx>>) {
        assert!(entry.position < (u32::MAX as usize));
        let position = entry.position as u32;
        let array_index = item.index();

        let positions = &mut self.positions;
        assert!(u32::read_from_bytes_at(positions, array_index) == u32::MAX,
                "recorded position for item {:?} twice, first at {:?} and now at {:?}",
                item,
                u32::read_from_bytes_at(positions, array_index),
                position);

        position.write_to_bytes_at(positions, array_index)
    }

    crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> {
        let pos = buf.position();
        buf.emit_raw_bytes(&self.positions);
        Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4)
    }
}

impl Lazy<[Index<'tcx>]> {
    /// Given the metadata, extract out the offset of a particular
    /// DefIndex (if any).
    #[inline(never)]
    crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
        debug!("Index::lookup: index={:?} len={:?}",
               def_index,
               self.meta);

        let bytes = &bytes[self.position..][..self.meta * 4];
        let position = u32::read_from_bytes_at(bytes, def_index.index());
        if position == u32::MAX {
            debug!("Index::lookup: position=u32::MAX");
            None
        } else {
            debug!("Index::lookup: position={:?}", position);
            Some(Lazy::from_position(position as usize))
        }
    }
}
<|endoftext|>


<commit_before>/*
    Contribuidores
        - Dromedario de Chapéu

    Fatorial é uma função matematica que consistem em realizar
	a multiplicação de todos os antecessores de um numero.

	Ex: 5! = 5 * 4 * 3 * 2 * 1 = 120
*/

// A diferença desta implementação para a com recursão é
// que nesta versão o retorno, é feito utilizado um for
// que percorre uma lista que vai de 0 a valor + 1
fn fatorial(valor: usize) -> usize {
    let mut total = 1;
    // (0..valor + 1) retorna um range, que para ser utlizado é
    // preciso coletar todos os itens dentro de um vetor para assim
    // setr interado, que é isso que .collect::<Vec<usize>>() faz
    for i in (0..valor + 1).collect::<Vec<usize>>().iter() {
        if *i != 0 {
            total *= *i;
        }
    }
    return total
}

fn main() {
    println!("{}", fatorial(10));
}

#[cfg(test)]
mod test {
    use super::*;
    fn teste_fatorial() {
        assert_eq!(fatorial(0), 1);
        assert_eq!(fatorial(1), 1);
        assert_eq!(fatorial(10), 3628800);
    }
}<commit_msg>Corrigindo Fatorial<commit_after>/*
    Contribuidores
        - Dromedario de Chapéu

    Fatorial é uma função matematica que consistem em realizar
	a multiplicação de todos os antecessores de um numero.

	Ex: 5! = 5 * 4 * 3 * 2 * 1 = 120
*/

// A diferença desta implementação para a com recursão é
// que nesta versão o retorno, é feito utilizado interadores.
fn fatorial(valor: u128) -> u128 {
    let total = match valor {
        0  => 1,
        // Product faz a multiplicação de todos os valores em um array
        1.. => (1..valor+1).product(),
    };
    return total
}

fn main() {
    println!("{}", fatorial(21));
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn teste_fatorial() {
        assert_eq!(fatorial(0), 1);
        assert_eq!(fatorial(1), 1);
        assert_eq!(fatorial(10), 3628800);
    }
}<|endoftext|>


<commit_before>// Copyright 2013-2014 Jeffery Olson
//
// Licensed under the 3-Clause BSD License, see LICENSE.txt
// at the top-level of this repository.
// This file may not be copied, modified, or distributed
// except according to those terms.
use std::os::args;

// this is starting out as a straight port of Peter Norvig's
// lis.py (the first iteration) to Rust

fn main() {
    let _args = args();
    println!("{}", ~"");
}

fn pad_input(input: ~str) -> ~str {
    input.replace("(", " ( ").replace(")", " ) ")
}

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

    #[test]
    fn pad_input_should_insert_spaces_before_and_after_parens() {
        assert!(pad_input(~"(x 1 2 3)") == ~" ( x 1 2 3 ) ");
    }
}
<commit_msg>test/impl for tokenize() + some flush-out of main()<commit_after>// Copyright 2013-2014 Jeffery Olson
//
// Licensed under the 3-Clause BSD License, see LICENSE.txt
// at the top-level of this repository.
// This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="http://olsonjeffery.github.io#schemers:0.0.1"]
#![desc = "Simple Scheme Interpreter"]
#![license = "3-Clause BSD"]

// this is starting out as a straight port of Peter Norvig's
// lis.py (the first iteration) to Rust

#[cfg(not(test))]
fn main() {
    use std::os::args;
    let args: Vec<~str> = args().move_iter().skip(1).collect();
    if args.len() == 0 {
        fail!("no program provided");
    }
    let program: ~str = args.move_iter()
        .fold(~"", |memo, arg| memo + arg + " ").trim().to_owned();
    println!("{}", tokenize(program));
}

// parser impl
fn pad_input(input: ~str) -> ~str {
    input.replace("(", " ( ").replace(")", " ) ")
}

fn tokenize(input: ~str) -> Vec<~str> {
    pad_input(input).split_str(" ")
        .filter(|i| *i != "").map(|i| i.to_owned()).collect()
}

#[cfg(test)]
mod parser_test {
    use super::pad_input;
    use super::tokenize;

    #[test]
    fn pad_input_should_insert_spaces_before_and_after_parens() {
        assert_eq!(pad_input(~"(x 1 2 3)"), ~" ( x 1 2 3 ) ");
    }

    #[test]
    fn tokenize_should_split_string_into_tokens() {
        let tokens = tokenize(~"(foo 12 3)");
        assert_eq!(tokens.len(), 5);
    }
}
<|endoftext|>


<commit_before>extern crate mio;
extern crate rand;

use mio::{EventLoop,Token,TryWrite, Interest, PollOpt};
use mio::tcp::*;
use mio::udp::*;
use mio::buf::*;
use rand::{thread_rng, Rng};
use std::fs::File;
use std::io::*;

trait QuoteProviderImpl {
  fn get_quote(&self, usize) -> String;
  fn get_random_quote(&self) -> String;
  fn new() -> Self;
}

struct QuoteProvider {
  quotes: Vec<String>,
}

impl QuoteProviderImpl for QuoteProvider {

  fn get_quote(&self, index: usize) -> String {
    //todo: pointers not clones?
    self.quotes[index].clone()
  }

  fn get_random_quote(&self) -> String {
    //todo: cache rng for improved perf
    let mut rng = thread_rng();
    let index: usize = rng.gen_range(0, self.quotes.len());
    self.get_quote(index)
  }

  fn new() -> QuoteProvider {
    let mut quotes: Vec<String> = Vec::new();
    println!("Reading wisdom...");
    //todo: check exists
    //todo: pass in as arg
    let path = "../../src/server/wisdom.txt";
    let result = File::open(path);
    match result {
        Ok(file) => {
            let reader = BufReader::new(file);
            for line in reader.lines() {
                match line {
                    Ok (line_str) => {
                        if line_str.len() > 0 {
                            quotes.push(line_str + "\r\n");
                        } else {
                            println!("Skipped blank line in file.");
                        }
                    },
                    Err(e) => println!("Invalid line. Skipping... {:?}",e)
                }
            }

        },
        Err(e) => println!("Failed to open wisdom file {:?}. {:?}", path, e)
    }

    QuoteProvider {quotes: quotes}
  }
}

const TCP_SERVER: mio::Token = mio::Token(0);
const UDP_SERVER: mio::Token = mio::Token(1);

struct Pong {
    tcp_server: TcpListener,
    udp_server: UdpSocket,
    quote_provider: QuoteProvider
}

impl mio::Handler for Pong {
    type Timeout = ();
    type Message = ();

    fn readable(&mut self, event_loop: &mut mio::EventLoop<Pong>, token: mio::Token, hint: mio::ReadHint) {
        match token {
            TCP_SERVER => {
                println!("the server socket is ready to accept a TCP connection");
                match self.tcp_server.accept() {
                    Ok(Some(mut connection)) => {
                        println!("accepted a socket {:?}", connection);
                        let quote = self.quote_provider.get_random_quote();
                        match connection.write_slice(quote.as_bytes()) {
                            Ok(x) => println!("Wrote to tcp"),
                            Err(e) => println!("Failed to write")

                        }
                    }
                    Ok(None) => {
                        println!("the server socket wasn't actually ready")
                    }
                    Err(e) => {
                        println!("listener.accept() errored: {}", e);
                        event_loop.shutdown();
                    }
                }
            }
            UDP_SERVER => {
                println!("the server socket is ready to accept a UDP connection");
                let mut buf = [0; 128];
                match self.udp_server.recv_from(&mut MutSliceBuf::wrap(&mut buf)) {
                    Ok(Some(addr)) => {
                        let mut quote = self.quote_provider.get_random_quote();
                        let mut quote_buf = SliceBuf::wrap(&mut quote.as_bytes());
                        match self.udp_server.send_to(&mut quote_buf, &addr) {
                            Ok(_) => println!("Wrote to udp"),
                            Err(e) => println!("Faile to write to udp")
                        }
                    }
                    Ok(None) => println!("Couldn't write to socket? Or was it just empty?"),
                    Err(e) => println!("couldn't receive a datagram: {}", e)
                }
            }
            _ => panic!("Received unknown token"),
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Pong>, token: Token) {
        match token {
            TCP_SERVER => println!("received writable for TCP_SERVER"),
            UDP_SERVER => println!("received writable for UDP_SERVER"),
            _ => panic!("Unexpected token")
        };
    }
}

fn main() {

    let quote_provider: QuoteProvider = QuoteProviderImpl::new();
    println!("Sample quote: {:?}", quote_provider.get_random_quote());

    let address = "0.0.0.0:6567".parse().unwrap();
    let tcp_server = TcpListener::bind(&address).unwrap();
    let udp_server = UdpSocket::v4().unwrap();
    let _ = udp_server.bind(&address);

    let mut event_loop = mio::EventLoop::new().unwrap();
    let _ = event_loop.register_opt(&tcp_server, TCP_SERVER, Interest::all(), PollOpt::edge());
    let _ = event_loop.register_opt(&udp_server, UDP_SERVER, Interest::readable(), PollOpt::edge());

    println!("running pingpong server");
    let mut pong = Pong
    {
        tcp_server: tcp_server,
        udp_server: udp_server,
        quote_provider: quote_provider
    };
    let _ = event_loop.run(&mut pong);

    drop(pong.udp_server); // close the socket
    drop(pong.tcp_server);

}<commit_msg>udp working with nc -4u<commit_after>extern crate mio;
extern crate rand;

use mio::{EventLoop,Token,TryWrite, Interest, PollOpt};
use mio::tcp::*;
use mio::udp::*;
use mio::buf::*;
use rand::{thread_rng, Rng};
use std::fs::File;
use std::io::*;

trait QuoteProviderImpl {
  fn get_quote(&self, usize) -> String;
  fn get_random_quote(&self) -> String;
  fn new() -> Self;
}

struct QuoteProvider {
  quotes: Vec<String>,
}

impl QuoteProviderImpl for QuoteProvider {

  fn get_quote(&self, index: usize) -> String {
    //todo: pointers not clones?
    self.quotes[index].clone()
  }

  fn get_random_quote(&self) -> String {
    //todo: cache rng for improved perf
    let mut rng = thread_rng();
    let index: usize = rng.gen_range(0, self.quotes.len());
    self.get_quote(index)
  }

  fn new() -> QuoteProvider {
    let mut quotes: Vec<String> = Vec::new();
    println!("Reading wisdom...");
    //todo: check exists
    //todo: pass in as arg
    let path = "../../src/server/wisdom.txt";
    let result = File::open(path);
    match result {
        Ok(file) => {
            let reader = BufReader::new(file);
            for line in reader.lines() {
                match line {
                    Ok (line_str) => {
                        if line_str.len() > 0 {
                            quotes.push(line_str + "\n");
                        } else {
                            println!("Skipped blank line in file.");
                        }
                    },
                    Err(e) => println!("Invalid line. Skipping... {:?}",e)
                }
            }

        },
        Err(e) => println!("Failed to open wisdom file {:?}. {:?}", path, e)
    }

    QuoteProvider {quotes: quotes}
  }
}

const TCP_SERVER: mio::Token = mio::Token(0);
const UDP_SERVER: mio::Token = mio::Token(1);

struct QotdServer {
    tcp_server: TcpListener,
    udp_server: UdpSocket,
    quote_provider: QuoteProvider
}

impl mio::Handler for QotdServer {
    type Timeout = ();
    type Message = ();

    #[allow(unused_variables)]
    fn readable(&mut self, event_loop: &mut mio::EventLoop<QotdServer>, token: mio::Token, hint: mio::ReadHint) {
        match token {
            TCP_SERVER => {
                println!("the server socket is ready to accept a TCP connection");
                match self.tcp_server.accept() {
                    Ok(Some(mut connection)) => {
                        println!("accepted a socket {:?}", connection);
                        let quote = self.quote_provider.get_random_quote();
                        match connection.write_slice(quote.as_bytes()) {
                            Ok(Some(_)) => println!("Wrote to tcp"),
                            Ok(None) => println!("Didn't write anything to tcp"),
                            Err(e) => println!("Failed to write. {:?}", e)

                        }
                        drop(connection);
                    }
                    Ok(None) => {
                        println!("the server socket wasn't actually ready")
                    }
                    Err(e) => {
                        println!("listener.accept() errored: {}", e);
                        event_loop.shutdown();
                    }
                }
            }
            UDP_SERVER => {
                println!("the server socket is ready to accept a UDP connection");
                let mut buf = [0; 128];
                match self.udp_server.recv_from(&mut MutSliceBuf::wrap(&mut buf)) {
                    Ok(Some(addr)) => {
                        let quote = self.quote_provider.get_random_quote();
                        let mut quote_buf = SliceBuf::wrap(&mut quote.as_bytes());
                        match self.udp_server.send_to(&mut quote_buf, &addr) {
                            Ok(Some(_)) => println!("Wrote to udp"),
                            Ok(None) => println!("Failed to write any bytes"),
                            Err(e) => println!("Faile to write to udp. {:?}", e)
                        }
                    }
                    Ok(None) => println!("Couldn't write to socket? Or was it just empty?"),
                    Err(e) => println!("couldn't receive a datagram: {}", e)
                }
            }
            _ => panic!("Received unknown token"),
        }
    }
}

fn main() {

    let quote_provider: QuoteProvider = QuoteProviderImpl::new();
    println!("Sample quote: {:?}", quote_provider.get_random_quote());

    let address = "0.0.0.0:6567".parse().unwrap();
    let tcp_server = TcpListener::bind(&address).unwrap();
    let udp_server = UdpSocket::v4().unwrap();
    let _ = udp_server.bind(&address);

    let mut event_loop = mio::EventLoop::new().unwrap();
    let _ = event_loop.register_opt(&tcp_server, TCP_SERVER, Interest::readable(), PollOpt::edge());
    let _ = event_loop.register_opt(&udp_server, UDP_SERVER, Interest::readable(), PollOpt::edge());

    println!("running qotd server");
    let mut qotd_server = QotdServer
    {
        tcp_server: tcp_server,
        udp_server: udp_server,
        quote_provider: quote_provider
    };
    let _ = event_loop.run(&mut qotd_server);

    drop(qotd_server.udp_server);
    drop(qotd_server.tcp_server);

}<|endoftext|>