<commit_before>use hand::Hand;
use card::Value;
use vec_map::VecMap;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum Rank {
    HighCard,
    OnePair,
    TwoPair,
    ThreeOfAKind,
    Straight,
    Flush,
    FullHouse,
    FourOfAKind,
    StraightFlush,
}

// Big ugly constant for all the straghts.
pub const STRAIGHTS: [usize; 10] =
    [// Wheel.
     1 << (Value::Ace as usize) | 1 << (Value::Two as usize) | 1 << (Value::Three as usize) |
     1 << (Value::Four as usize) | 1 << (Value::Five as usize),
     // "Normal" straights starting at two to six.
     1 << (Value::Two as usize) | 1 << (Value::Three as usize) | 1 << (Value::Four as usize) |
     1 << (Value::Five as usize) | 1 << (Value::Six as usize),
     // Three to Seven
     1 << (Value::Three as usize) | 1 << (Value::Four as usize) | 1 << (Value::Five as usize) |
     1 << (Value::Six as usize) | 1 << (Value::Seven as usize),
     // Four to Eight
     1 << (Value::Four as usize) | 1 << (Value::Five as usize) | 1 << (Value::Six as usize) |
     1 << (Value::Seven as usize) | 1 << (Value::Eight as usize),
     // Five to Nine
     1 << (Value::Five as usize) | 1 << (Value::Six as usize) | 1 << (Value::Seven as usize) |
     1 << (Value::Eight as usize) | 1 << (Value::Nine as usize),
     // Six to Ten
     1 << (Value::Six as usize) | 1 << (Value::Seven as usize) | 1 << (Value::Eight as usize) |
     1 << (Value::Nine as usize) | 1 << (Value::Ten as usize),
     // Seven to Jack.
     1 << (Value::Seven as usize) | 1 << (Value::Eight as usize) | 1 << (Value::Nine as usize) |
     1 << (Value::Ten as usize) | 1 << (Value::Jack as usize),
     // Eight to Queen
     1 << (Value::Eight as usize) | 1 << (Value::Nine as usize) | 1 << (Value::Ten as usize) |
     1 << (Value::Jack as usize) | 1 << (Value::Queen as usize),
     // Nine to king
     1 << (Value::Nine as usize) | 1 << (Value::Ten as usize) | 1 << (Value::Jack as usize) |
     1 << (Value::Queen as usize) | 1 << (Value::King as usize),
     // Royal straight
     1 << (Value::Ten as usize) | 1 << (Value::Jack as usize) | 1 << (Value::Queen as usize) |
     1 << (Value::King as usize) | 1 << (Value::Ace as usize)];

pub trait Rankable {
    fn rank(&self) -> Rank;
    fn rank_straight(&self, hand_rank: usize) -> Option<usize> {
        for (i, hand) in STRAIGHTS.iter().enumerate() {
            if *hand == hand_rank {
                return Some(i);
            }
        }
        None
    }
}

impl Rankable for Hand {
    fn rank(&self) -> Rank {
        // use for bitset
        let mut suit_set: usize = 0;
        // Use for bitset
        let mut value_set: usize = 0;
        let mut value_to_count: VecMap<usize> = VecMap::with_capacity(13);
        let mut count_to_value: VecMap<Vec<Value>> = VecMap::with_capacity(13);
        let mut potential_hand_rank = 0;
        // TODO(eclark): make this more generic
        for c in self[..].iter() {
            let v = c.value.clone() as usize;
            let s = c.suit.clone() as usize;

            // Will be used for flush
            suit_set |= 1 << s as usize;
            // Will be used to determine straights.
            value_set |= 1 << v as usize;

            // If this is high card or a flush we need this.
            // It will be used to differentiate strenght of the same rank
            potential_hand_rank |= 1 << v;
            // Keep track of counts for each card.
            if value_to_count.contains_key(v) {
                value_to_count[v] += 1;
            } else {
                value_to_count.insert(v, 1);
            }
        }

        // Now rotate the value to count map.
        for (value, count) in value_to_count {
            if count_to_value.contains_key(count) {
                count_to_value[count].push(Value::from_usize(value));
            } else {
                count_to_value.insert(count, vec![Value::from_usize(value)]);
            }
        }

        let unique_card_count = value_set.count_ones();

        // Now that we should have all the information needed.
        // Lets do this.
        if unique_card_count == 5 {
            // If there are five different cards it can be a straight
            // a straight flush, a flush, or just a high card.
            // Need to check for all of them.
            let suit_count = suit_set.count_ones();
            let is_flush = suit_count == 1;
            match (self.rank_straight(potential_hand_rank), is_flush) {
                (Some(_), true) => Rank::StraightFlush,
                (Some(_), false) => Rank::Straight,
                (None, true) => Rank::Flush,
                (None, false) => Rank::HighCard,
            }
        } else if unique_card_count == 2 {
            // This can either be full house, or four of a kind.
            if count_to_value.contains_key(3) {
                Rank::FullHouse
            } else {
                Rank::FourOfAKind
            }
        } else if unique_card_count == 3 {
            // this can be three of a kind or two pair.
            if count_to_value.contains_key(3) {
                Rank::ThreeOfAKind
            } else {
                Rank::TwoPair
            }
        } else {
            // this is unique_card_count == 4
            assert!(unique_card_count == 4);
            Rank::OnePair
        }
    }
}

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

    #[test]
    fn test_cmp() {
        assert!(Rank::HighCard < Rank::StraightFlush);
        assert!(Rank::HighCard < Rank::FourOfAKind);
        assert!(Rank::HighCard < Rank::ThreeOfAKind);
    }

    #[test]
    fn test_high_card_hand() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Eight, suit: Suit::Heart},
                                             Card{value: Value::Nine, suit: Suit::Club},
                                             Card{value: Value::Ten, suit: Suit::Club},
                                             Card{value: Value::Five, suit: Suit::Club},
                                             ]);

        assert!(Rank::HighCard == hand.rank());
    }

    #[test]
    fn test_flush() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Eight, suit: Suit::Diamond},
                                             Card{value: Value::Nine, suit: Suit::Diamond},
                                             Card{value: Value::Ten, suit: Suit::Diamond},
                                             Card{value: Value::Five, suit: Suit::Diamond},
                                             ]);

        assert!(Rank::Flush == hand.rank());
    }

    #[test]
    fn test_full_house() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Ace, suit: Suit::Club},
                                             Card{value: Value::Nine, suit: Suit::Diamond},
                                             Card{value: Value::Nine, suit: Suit::Club},
                                             Card{value: Value::Nine, suit: Suit::Spade},
                                             ]);

        assert!(Rank::FullHouse == hand.rank());
    }

    #[test]
    fn test_two_pair() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Ace, suit: Suit::Club},
                                             Card{value: Value::Nine, suit: Suit::Diamond},
                                             Card{value: Value::Nine, suit: Suit::Club},
                                             Card{value: Value::Ten, suit: Suit::Spade},
                                             ]);

        assert!(Rank::TwoPair == hand.rank());
    }

    #[test]
    fn test_one_pair() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Ace, suit: Suit::Club},
                                             Card{value: Value::Nine, suit: Suit::Diamond},
                                             Card{value: Value::Eight, suit: Suit::Club},
                                             Card{value: Value::Ten, suit: Suit::Spade},
                                             ]);

        assert!(Rank::OnePair == hand.rank());
    }

    #[test]
    fn test_four_of_a_kind() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Ace, suit: Suit::Club},
                                             Card{value: Value::Ace, suit: Suit::Spade},
                                             Card{value: Value::Ace, suit: Suit::Heart},
                                             Card{value: Value::Ten, suit: Suit::Spade},
                                             ]);

        assert!(Rank::FourOfAKind == hand.rank());
    }

    #[test]
    fn test_wheel() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Two, suit: Suit::Club},
                                             Card{value: Value::Three, suit: Suit::Spade},
                                             Card{value: Value::Four, suit: Suit::Heart},
                                             Card{value: Value::Five, suit: Suit::Spade},
                                             ]);

        assert!(Rank::Straight == hand.rank());
    }

    #[test]
    fn test_straight() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Two, suit: Suit::Club},
                                             Card{value: Value::Three, suit: Suit::Spade},
                                             Card{value: Value::Four, suit: Suit::Heart},
                                             Card{value: Value::Five, suit: Suit::Spade},
                                             Card{value: Value::Six, suit: Suit::Diamond},
                                             ]);

        assert!(Rank::Straight == hand.rank());
    }

    #[test]
    fn test_three_of_a_kind() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Two, suit: Suit::Club},
                                             Card{value: Value::Two, suit: Suit::Spade},
                                             Card{value: Value::Two, suit: Suit::Heart},
                                             Card{value: Value::Five, suit: Suit::Spade},
                                             Card{value: Value::Six, suit: Suit::Diamond},
                                             ]);

        assert!(Rank::ThreeOfAKind == hand.rank());
    }

    #[test]
    fn test_straight_constants() {
        for c in STRAIGHTS.iter() {
            // Make sure that all of the constant hands have exactly 5 ones.
            assert!(5 == c.count_ones());
        }
    }
}
<commit_msg>Add on tie breaking ranks.<commit_after>use hand::Hand;
use card::Value;
use vec_map::VecMap;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum Rank {
    HighCard(usize),
    OnePair(usize),
    TwoPair(usize),
    ThreeOfAKind(usize),
    Straight(usize),
    Flush(usize),
    FullHouse(usize),
    FourOfAKind(usize),
    StraightFlush(usize),
}

// Big ugly constant for all the straghts.
pub const STRAIGHTS: [usize; 10] =
    [// Wheel.
     1 << (Value::Ace as usize) | 1 << (Value::Two as usize) | 1 << (Value::Three as usize) |
     1 << (Value::Four as usize) | 1 << (Value::Five as usize),
     // "Normal" straights starting at two to six.
     1 << (Value::Two as usize) | 1 << (Value::Three as usize) | 1 << (Value::Four as usize) |
     1 << (Value::Five as usize) | 1 << (Value::Six as usize),
     // Three to Seven
     1 << (Value::Three as usize) | 1 << (Value::Four as usize) | 1 << (Value::Five as usize) |
     1 << (Value::Six as usize) | 1 << (Value::Seven as usize),
     // Four to Eight
     1 << (Value::Four as usize) | 1 << (Value::Five as usize) | 1 << (Value::Six as usize) |
     1 << (Value::Seven as usize) | 1 << (Value::Eight as usize),
     // Five to Nine
     1 << (Value::Five as usize) | 1 << (Value::Six as usize) | 1 << (Value::Seven as usize) |
     1 << (Value::Eight as usize) | 1 << (Value::Nine as usize),
     // Six to Ten
     1 << (Value::Six as usize) | 1 << (Value::Seven as usize) | 1 << (Value::Eight as usize) |
     1 << (Value::Nine as usize) | 1 << (Value::Ten as usize),
     // Seven to Jack.
     1 << (Value::Seven as usize) | 1 << (Value::Eight as usize) | 1 << (Value::Nine as usize) |
     1 << (Value::Ten as usize) | 1 << (Value::Jack as usize),
     // Eight to Queen
     1 << (Value::Eight as usize) | 1 << (Value::Nine as usize) | 1 << (Value::Ten as usize) |
     1 << (Value::Jack as usize) | 1 << (Value::Queen as usize),
     // Nine to king
     1 << (Value::Nine as usize) | 1 << (Value::Ten as usize) | 1 << (Value::Jack as usize) |
     1 << (Value::Queen as usize) | 1 << (Value::King as usize),
     // Royal straight
     1 << (Value::Ten as usize) | 1 << (Value::Jack as usize) | 1 << (Value::Queen as usize) |
     1 << (Value::King as usize) | 1 << (Value::Ace as usize)];

pub trait Rankable {
    fn rank(&self) -> Rank;
    fn rank_straight(&self, hand_rank: usize) -> Option<usize> {
        for (i, hand) in STRAIGHTS.iter().enumerate() {
            if *hand == hand_rank {
                return Some(i);
            }
        }
        None
    }
}

impl Rankable for Hand {
    fn rank(&self) -> Rank {
        // use for bitset
        let mut suit_set: usize = 0;
        // Use for bitset
        let mut value_set: usize = 0;
        let mut value_to_count: VecMap<usize> = VecMap::with_capacity(13);
        let mut count_to_value: VecMap<Vec<Value>> = VecMap::with_capacity(13);
        let mut potential_hand_rank = 0;
        // TODO(eclark): make this more generic
        for c in self[..].iter() {
            let v = c.value.clone() as usize;
            let s = c.suit.clone() as usize;

            // Will be used for flush
            suit_set |= 1 << s as usize;
            // Will be used to determine straights.
            value_set |= 1 << v as usize;

            // If this is high card or a flush we need this.
            // It will be used to differentiate strenght of the same rank
            potential_hand_rank |= 1 << v;
            // Keep track of counts for each card.
            let e = value_to_count.entry(v).or_insert(0);
            *e += 1;
        }

        // Now rotate the value to count map.
        for (value, count) in value_to_count {
            // Get the entry for the map, or insert it into the map.
            let e = count_to_value.entry(count).or_insert_with(|| vec![]);
            // Now that it has to be there, push the new value.
            (*e).push(Value::from_usize(value));
        }

        // The major deciding factor for hand rank
        // is the number of unique card values.
        let unique_card_count = value_set.count_ones();

        // Now that we should have all the information needed.
        // Lets do this.
        if unique_card_count == 5 {
            // If there are five different cards it can be a straight
            // a straight flush, a flush, or just a high card.
            // Need to check for all of them.
            let suit_count = suit_set.count_ones();
            let is_flush = suit_count == 1;
            match (self.rank_straight(potential_hand_rank), is_flush) {
                (Some(rank), true) => Rank::StraightFlush(rank),
                (Some(rank), false) => Rank::Straight(rank),
                (None, true) => Rank::Flush(potential_hand_rank),
                (None, false) => Rank::HighCard(potential_hand_rank),
            }
        } else if unique_card_count == 2 {
            // This can either be full house, or four of a kind.
            match count_to_value.get(3) {
                Some(three_value) => {
                    let major_rank = 1 << three_value[0].clone() as usize;
                    // Remove the card that we have three of from the minor rank.
                    let minor_rank = potential_hand_rank ^ major_rank;
                    // then join the two ranks
                    Rank::FullHouse(major_rank << 13 | minor_rank)
                }
                None => {
                    let major_rank = 1 << (count_to_value[4][0].clone() as usize);
                    let minor_rank = potential_hand_rank ^ major_rank;
                    Rank::FourOfAKind(major_rank << 13 | minor_rank)
                }
            }
        } else if unique_card_count == 3 {
            // this can be three of a kind or two pair.
            match count_to_value.get(3) {
                Some(three_value) => {
                    let major_rank = 1 << (three_value[0].clone() as usize);
                    let minor_rank = potential_hand_rank ^ major_rank;
                    Rank::ThreeOfAKind(major_rank << 13 | minor_rank)
                }
                None => {
                    // get the values of the pairs
                    let pairs = &count_to_value[2];
                    let major_rank = 1 << pairs[0].clone() as usize |
                                     1 << pairs[1].clone() as usize;
                    let minor_rank = potential_hand_rank ^ major_rank;
                    Rank::TwoPair(major_rank << 13 | minor_rank)
                }
            }
        } else {
            // this is unique_card_count == 4
            assert!(unique_card_count == 4);
            let major_rank = 1 << count_to_value[2][0].clone() as usize;
            let minor_rank = potential_hand_rank ^ major_rank;
            Rank::OnePair(major_rank << 13 | minor_rank)
        }
    }
}

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

    #[test]
    fn test_cmp() {
        assert!(Rank::HighCard(0) < Rank::StraightFlush(0));
        assert!(Rank::HighCard(0) < Rank::FourOfAKind(0));
        assert!(Rank::HighCard(0) < Rank::ThreeOfAKind(0));
    }

    #[test]
    fn test_cmp_high() {
        assert!(Rank::HighCard(0) < Rank::HighCard(100));
    }

    #[test]
    fn test_high_card_hand() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Eight, suit: Suit::Heart},
                                             Card{value: Value::Nine, suit: Suit::Club},
                                             Card{value: Value::Ten, suit: Suit::Club},
                                             Card{value: Value::Five, suit: Suit::Club},
                                             ]);

        let rank = 1 << Value::Ace as usize | 1 << Value::Eight as usize |
                   1 << Value::Nine as usize | 1 << Value::Ten as usize |
                   1 << Value::Five as usize;

        assert!(Rank::HighCard(rank) == hand.rank());
    }

    #[test]
    fn test_flush() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Eight, suit: Suit::Diamond},
                                             Card{value: Value::Nine, suit: Suit::Diamond},
                                             Card{value: Value::Ten, suit: Suit::Diamond},
                                             Card{value: Value::Five, suit: Suit::Diamond},
                                             ]);

        let rank = 1 << Value::Ace as usize | 1 << Value::Eight as usize |
                   1 << Value::Nine as usize | 1 << Value::Ten as usize |
                   1 << Value::Five as usize;

        assert!(Rank::Flush(rank) == hand.rank());
    }

    #[test]
    fn test_full_house() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Ace, suit: Suit::Club},
                                             Card{value: Value::Nine, suit: Suit::Diamond},
                                             Card{value: Value::Nine, suit: Suit::Club},
                                             Card{value: Value::Nine, suit: Suit::Spade},
                                             ]);

        let rank = (1 << (Value::Nine as usize)) << 13 | 1 << (Value::Ace as usize);
        assert!(Rank::FullHouse(rank) == hand.rank());
    }

    #[test]
    fn test_two_pair() {
        // Make a two pair hand.
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Ace, suit: Suit::Club},
                                             Card{value: Value::Nine, suit: Suit::Diamond},
                                             Card{value: Value::Nine, suit: Suit::Club},
                                             Card{value: Value::Ten, suit: Suit::Spade},
                                             ]);

        let rank = (1 << Value::Ace as usize | 1 << Value::Nine as usize) << 13 |
                   1 << Value::Ten as usize;
        assert!(Rank::TwoPair(rank) == hand.rank());
    }

    #[test]
    fn test_one_pair() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Ace, suit: Suit::Club},
                                             Card{value: Value::Nine, suit: Suit::Diamond},
                                             Card{value: Value::Eight, suit: Suit::Club},
                                             Card{value: Value::Ten, suit: Suit::Spade},
                                             ]);

        let rank = (1 << Value::Ace as usize) << 13 | 1 << Value::Nine as usize |
                   1 << Value::Eight as usize | 1 << Value::Ten as usize;

        assert!(Rank::OnePair(rank) == hand.rank());
    }

    #[test]
    fn test_four_of_a_kind() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Ace, suit: Suit::Club},
                                             Card{value: Value::Ace, suit: Suit::Spade},
                                             Card{value: Value::Ace, suit: Suit::Heart},
                                             Card{value: Value::Ten, suit: Suit::Spade},
                                             ]);

        assert!(Rank::FourOfAKind((1 << (Value::Ace as usize) << 13) |
                                  1 << (Value::Ten as usize)) == hand.rank());
    }

    #[test]
    fn test_wheel() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Ace, suit: Suit::Diamond},
                                             Card{value: Value::Two, suit: Suit::Club},
                                             Card{value: Value::Three, suit: Suit::Spade},
                                             Card{value: Value::Four, suit: Suit::Heart},
                                             Card{value: Value::Five, suit: Suit::Spade},
                                             ]);

        assert!(Rank::Straight(0) == hand.rank());
    }

    #[test]
    fn test_straight() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Two, suit: Suit::Club},
                                             Card{value: Value::Three, suit: Suit::Spade},
                                             Card{value: Value::Four, suit: Suit::Heart},
                                             Card{value: Value::Five, suit: Suit::Spade},
                                             Card{value: Value::Six, suit: Suit::Diamond},
                                             ]);

        assert!(Rank::Straight(1) == hand.rank());
    }

    #[test]
    fn test_three_of_a_kind() {
        let hand = Hand::new_with_cards(vec![
                                             Card{value: Value::Two, suit: Suit::Club},
                                             Card{value: Value::Two, suit: Suit::Spade},
                                             Card{value: Value::Two, suit: Suit::Heart},
                                             Card{value: Value::Five, suit: Suit::Spade},
                                             Card{value: Value::Six, suit: Suit::Diamond},
                                             ]);

        let rank = (1 << (Value::Two as usize)) << 13 | 1 << (Value::Five as usize) |
                   1 << (Value::Six as usize);

        assert!(Rank::ThreeOfAKind(rank) == hand.rank());
    }

    #[test]
    fn test_straight_constants() {
        for c in STRAIGHTS.iter() {
            // Make sure that all of the constant hands have exactly 5 ones.
            assert!(5 == c.count_ones());
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;
use std::marker::PhantomData;
use Event;

pub struct ReadHtml<'a, I> where I: Iterator<Item=Event<'a>> + 'a {
    events: I,
    buffer: Vec<u8>,
    ev_life: PhantomData<Event<'a>>,
}

impl<'a, I> ReadHtml<'a, I> where I: Iterator<Item=Event<'a>> {
    pub fn new<II>(events: II) -> ReadHtml<'a, I> where II: IntoIterator<IntoIter=I, Item=Event<'a>> {
        ReadHtml {
            events: events.into_iter(),
            buffer: Vec::new(),
            ev_life: PhantomData,
        }
    }
}

impl<'a, I> io::Read for ReadHtml<'a, I> where I: Iterator<Item=Event<'a>> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        while self.buffer.len() == 0 {
            if let Some(event) = self.events.next() {
                // Possible to do better?
                try!(write!(&mut self.buffer, "{}", event));
            } else {
                return Ok(0)
            }
        }
        let curlen = self.buffer.len();
        let len = ::std::cmp::min(curlen, buf.len());
        buf[..len].clone_from_slice(&self.buffer[..len]);
        for i in len..curlen {
            self.buffer[i - len] = self.buffer[i];
        }
        self.buffer.truncate(curlen - len);
        Ok(len)
    }
}

#[cfg(test)]
mod tests {
    use std::io::Read;
    use ReadHtml;

    #[test]
    fn test() {
        let events = vec![
            start_tag!("h1", id="hello", class="fun"),
            text!("Hello, "),
            raw_html!(""), // empty event
            start_tag!("small"),
            text!("world"),
            end_tag!("small"),
            closed_tag!("img", src="foo-link"),
            end_tag!("h1"),
        ];

        let mut result = String::new();
        ReadHtml::new(events).read_to_string(&mut result).unwrap();

        assert_eq!(result, "
Hello, \
                            world
");
    }
}
<commit_msg>Optimize read_to_end for read::ReadHtml<commit_after>use std::io;
use std::io::Write;
use std::marker::PhantomData;
use Event;

pub struct ReadHtml<'a, I> where I: Iterator<Item=Event<'a>> + 'a {
    events: I,
    buffer: Vec<u8>,
    ev_life: PhantomData<Event<'a>>,
}

impl<'a, I> ReadHtml<'a, I> where I: Iterator<Item=Event<'a>> {
    pub fn new<II>(events: II) -> ReadHtml<'a, I> where II: IntoIterator<IntoIter=I, Item=Event<'a>> {
        ReadHtml {
            events: events.into_iter(),
            buffer: Vec::new(),
            ev_life: PhantomData,
        }
    }
}

impl<'a, I> io::Read for ReadHtml<'a, I> where I: Iterator<Item=Event<'a>> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        while self.buffer.len() == 0 {
            if let Some(event) = self.events.next() {
                // Possible to do better?
                try!(write!(&mut self.buffer, "{}", event));
            } else {
                return Ok(0)
            }
        }
        let curlen = self.buffer.len();
        let len = ::std::cmp::min(curlen, buf.len());
        buf[..len].clone_from_slice(&self.buffer[..len]);
        for i in len..curlen {
            self.buffer[i - len] = self.buffer[i];
        }
        self.buffer.truncate(curlen - len);
        Ok(len)
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let start = buf.len();
        while let Some(event) = self.events.next() {
            try!(write!(buf, "{}", event));
        }
        Ok(buf.len() - start)
    }
}

#[cfg(test)]
mod tests {
    use std::io::Read;
    use ReadHtml;

    #[test]
    fn test() {
        let events = vec![
            start_tag!("h1", id="hello", class="fun"),
            text!("Hello, "),
            raw_html!(""), // empty event
            start_tag!("small"),
            text!("world"),
            end_tag!("small"),
            closed_tag!("img", src="foo-link"),
            end_tag!("h1"),
        ];

        let mut result = String::new();
        ReadHtml::new(events).read_to_string(&mut result).unwrap();

        assert_eq!(result, "
Hello, \
                            world
");
    }
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::collections::BTreeMap;

use url::{Url, ParseError};
use sidekiq::{Job, JobOpts, Value};
use url_serde::Serde;
use html5ever::tokenizer::{TokenSink, Token, TagToken, TokenSinkResult};

#[derive(Serialize, Debug)]
pub struct Page {
    pub url: Serde<Url>,
    pub document: String,
    pub headers: BTreeMap<String, String>,
    pub urls: Vec<Serde<Url>>,
}

impl TokenSink for Page {
    type Handle = ();

    fn process_token(&mut self, token: Token) -> TokenSinkResult<()> {
        match token {
            TagToken(tag) => {
                match tag.name {
                    local_name!("a") => {
                        for attr in tag.attrs.iter() {
                            if attr.name.local.to_string() == "href" {
                                match self.can_enqueue(&attr.value) {
                                    Some(u) => {
                                        self.urls.push(Serde(u));
                                    }
                                    None => {}
                                }
                            }
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
        TokenSinkResult::Continue
    }
}

impl Page {
    pub fn new(url: Url, document: String, headers: BTreeMap<String, String>) -> Self {
        Page {
            url: Serde(url),
            document: document,
            headers: headers,
            urls: Vec::new(),
        }
    }

    pub fn to_job(&self) -> Job {
        let job_opts = JobOpts {
            queue: maman_name!().to_string().to_lowercase(),
            ..Default::default()
        };
        Job::new(maman_name!().to_string(), vec![self.as_object()], job_opts)
    }

    pub fn as_object(&self) -> Value {
        json!({
            "url": &self.url,
            "document": &self.document,
            "headers": &self.headers,
            "urls": &self.urls,
        })
    }

    fn normalize_url(&self, url: &str) -> Option<Url> {
        match Url::parse(url) {
            Ok(u) => Some(u),
            Err(ParseError::RelativeUrlWithoutBase) => Some(self.url.join(url).unwrap()),
            Err(_) => None,
        }
    }

    fn url_without_fragment(&self, url: &str) -> Option<Url> {
        match self.normalize_url(url) {
            Some(mut u) => {
                u.set_fragment(None);
                Some(u)
            }
            None => None,
        }
    }

    fn url_eq(&self, url: &Url) -> bool {
        self.url == *url
    }

    fn domain_eq(&self, url: &Url) -> bool {
        self.url.domain() == url.domain()
    }

    fn can_enqueue(&self, url: &str) -> Option<Url> {
        match self.url_without_fragment(url) {
            Some(u) => {
                match u.scheme() {
                    "http" | "https" => {
                        if !self.url_eq(&u) && self.domain_eq(&u) {
                            Some(u)
                        } else {
                            None
                        }
                    }
                    _ => None,
                }
            }
            None => None,
        }
    }
}
<commit_msg>Fix clippy on process_token<commit_after>use std::default::Default;
use std::collections::BTreeMap;

use url::{Url, ParseError};
use sidekiq::{Job, JobOpts, Value};
use url_serde::Serde;
use html5ever::tokenizer::{TokenSink, Token, TagToken, TokenSinkResult};

#[derive(Serialize, Debug)]
pub struct Page {
    pub url: Serde<Url>,
    pub document: String,
    pub headers: BTreeMap<String, String>,
    pub urls: Vec<Serde<Url>>,
}

impl TokenSink for Page {
    type Handle = ();

    fn process_token(&mut self, token: Token) -> TokenSinkResult<()> {
        if let TagToken(tag) = token {
            match tag.name {
                local_name!("a") => {
                    for attr in &tag.attrs {
                        if attr.name.local.to_string() == "href" {
                            if let Some(u) = self.can_enqueue(&attr.value) {
                                self.urls.push(Serde(u));
                            }
                        }
                    }
                }
                _ => {}
            }
        }
        TokenSinkResult::Continue
    }
}

impl Page {
    pub fn new(url: Url, document: String, headers: BTreeMap<String, String>) -> Self {
        Page {
            url: Serde(url),
            document: document,
            headers: headers,
            urls: Vec::new(),
        }
    }

    pub fn to_job(&self) -> Job {
        let job_opts = JobOpts {
            queue: maman_name!().to_string().to_lowercase(),
            ..Default::default()
        };
        Job::new(maman_name!().to_string(), vec![self.as_object()], job_opts)
    }

    pub fn as_object(&self) -> Value {
        json!({
            "url": &self.url,
            "document": &self.document,
            "headers": &self.headers,
            "urls": &self.urls,
        })
    }

    fn normalize_url(&self, url: &str) -> Option<Url> {
        match Url::parse(url) {
            Ok(u) => Some(u),
            Err(ParseError::RelativeUrlWithoutBase) => Some(self.url.join(url).unwrap()),
            Err(_) => None,
        }
    }

    fn url_without_fragment(&self, url: &str) -> Option<Url> {
        match self.normalize_url(url) {
            Some(mut u) => {
                u.set_fragment(None);
                Some(u)
            }
            None => None,
        }
    }

    fn url_eq(&self, url: &Url) -> bool {
        self.url == *url
    }

    fn domain_eq(&self, url: &Url) -> bool {
        self.url.domain() == url.domain()
    }

    fn can_enqueue(&self, url: &str) -> Option<Url> {
        match self.url_without_fragment(url) {
            Some(u) => {
                match u.scheme() {
                    "http" | "https" => {
                        if !self.url_eq(&u) && self.domain_eq(&u) {
                            Some(u)
                        } else {
                            None
                        }
                    }
                    _ => None,
                }
            }
            None => None,
        }
    }
}
<|endoftext|>


<commit_before>
use crate::parse::*;
use crate::util::*;
use std::collections::HashMap;
use std::mem;
use std::sync::Mutex;

lazy_static! {
    static ref VARS: Mutex<HashMap<String, Var>> = Mutex::new(HashMap::new());
    static ref STACKSIZE: Mutex<i32> = Mutex::new(0);
}

#[derive(Clone, Debug, PartialEq)]
struct Var {
    ty: Type,
    offset: i32,
}

#[allow(dead_code)]
fn print_vars() {
    match VARS.lock() {
        Ok(vars) => {
            println!("[VARS]> {:?}", *vars);
        }
        _ => {}
    }
}

fn vars_put(name: String, var: Var) {
    let mut vars = VARS.lock().unwrap();
    vars.insert(name, var);
}

#[allow(dead_code)]
fn vars_exist(name: & String) -> bool {
    let vars = VARS.lock().unwrap();
    return None != vars.get(name);
}

fn stacksize() -> i32 {
    *STACKSIZE.lock().unwrap()
}

fn init_stacksize() {
    let mut stacksize = STACKSIZE.lock().unwrap();
    *stacksize = 0;
}

fn add_stacksize(i: i32) {
    let mut stacksize = STACKSIZE.lock().unwrap();
    *stacksize += i;
}

fn swap(p: &mut Node, q: &mut Node) {
    mem::swap(p, q);
}

fn addr_of(base: Node, ty: Type) -> Node {
    let mut node = alloc_node();
    node.op = NodeType::ADDR;
    node.ty = ptr_of(ty);

    let mut copy = alloc_node();
    mem::replace(&mut copy, base);
    node.expr = Some(Box::new(copy));
    return node;
}

macro_rules! walk_some {
    ($opt:expr, $decay:expr) => {
        match &mut $opt {
            Some(n) => {
                walk(n, $decay);
            }
            None => {}
        };
    };
}

fn walk(node: &mut Node, decay: bool) {
    match node.op {
        NodeType::NUM => { }
        NodeType::IDENT => {
            match VARS.lock().unwrap().get(&node.name) {
                None => {
                    panic!("undefined variable: {}", node.name);
                }
                Some(var) => {
                    //node.ty = var.ty.clone();
                    node.op = NodeType::LVAR;
                    node.offset = var.offset;

                    if decay && var.ty.ty == CType::ARY {
                        let node_tmp = node.clone();
                        mem::replace(node, addr_of(node_tmp, *var.clone().ty.ary_of.unwrap()));
                    } else {
                        node.ty = var.clone().ty;
                    }
                }
            }
        }
        NodeType::VARDEF => {
            add_stacksize(size_of(node.clone().ty));
            node.offset = stacksize();

            let var = Var {
                ty: node.ty.clone(),
                offset: stacksize(),
            };
            vars_put(node.name.clone(), var.clone());

            walk_some!(node.init, true);
        }
        NodeType::IF => {
            walk_some!(node.cond, true);
            walk_some!(node.then, true);
            walk_some!(node.els, true);
        }
        NodeType::FOR => {
            walk_some!(node.init, true);
            walk_some!(node.cond, true);
            walk_some!(node.inc, true);
            walk_some!(node.body, true);
        }
        NodeType::ADD | NodeType::SUB => {
            walk_some!(node.lhs, true);
            walk_some!(node.rhs, true);

            match (&mut node.lhs, &mut node.rhs) {
                (Some(ref mut lhs), Some(ref mut rhs)) => {
                    if rhs.ty.ty == CType::PTR {
                        swap(lhs, rhs);
                    }
                }
                _ => {}
            }
            match node.rhs {
                Some(ref rhs) => {
                    if rhs.ty.ty == CType::PTR {
                        panic!("'pointer {:?} pointer' is not defined", node.op);
                    }
                }
                None => {
                }
            }

            match node.lhs {
                Some(ref lhs) => {
                    node.ty = lhs.ty.clone();
                }
                None => { }
            }

        }
        NodeType::EQ => {
            walk_some!(node.lhs, false);
            walk_some!(node.rhs, true);
            node.ty = node.clone().lhs.unwrap().ty;
        }
        NodeType::MUL |
            NodeType::DIV |
            NodeType::LT |
            NodeType::LOGAND |
            NodeType::LOGOR => {
                walk_some!(node.lhs, true);
                walk_some!(node.rhs, true);

                match node.lhs {
                    Some(ref lhs) => {
                        node.ty = lhs.ty.clone();
                    }
                    None => { }
                }
            }
        NodeType::ADDR => {
            walk_some!(node.expr, true);
            node.ty = ptr_of(node.clone().expr.unwrap().ty);
        }
        NodeType::DEREF => {
            walk_some!(node.expr, true);
            match &mut node.expr {
                Some(ref expr) => {
                    if expr.ty.ty != CType::PTR {
                        panic!("operand must be a pointer");
                    }
                }
                None => {}
            }

            node.ty = *node.clone().expr.unwrap().ty.ptr_of.unwrap();
        }
        NodeType::RETURN => {
            walk_some!(node.expr, true);
        }
        NodeType::CALL => {
            for n in &mut node.args {
                walk(n, true);
            }
            node.ty = int_ty();
        }
        NodeType::FUNC => {
            for n in &mut node.args {
                walk(n, true);
            }
            walk_some!(node.body, true);
        }
        NodeType::COMP_STMT => {
            for n in &mut node.stmts {
                walk(n, true);
            }
        }
        NodeType::EXPR_STMT => {
            walk_some!(node.expr, true);
        }
        _ => {
            panic!("unknown node type");
        }
    }
}

pub fn sema(nodes: &mut Vec<Node>) {
    for node in nodes.iter_mut() {
        assert!(node.op == NodeType::FUNC);

        init_stacksize();
        walk(node, true);
        node.stacksize = stacksize();
    }
}
<commit_msg>Do not use struct assignment.<commit_after>
use crate::parse::*;
use crate::util::*;
use std::collections::HashMap;
use std::mem;
use std::sync::Mutex;

lazy_static! {
    static ref VARS: Mutex<HashMap<String, Var>> = Mutex::new(HashMap::new());
    static ref STACKSIZE: Mutex<i32> = Mutex::new(0);
}

#[derive(Clone, Debug, PartialEq)]
struct Var {
    ty: Type,
    offset: i32,
}

#[allow(dead_code)]
fn print_vars() {
    match VARS.lock() {
        Ok(vars) => {
            println!("[VARS]> {:?}", *vars);
        }
        _ => {}
    }
}

fn vars_put(name: String, var: Var) {
    let mut vars = VARS.lock().unwrap();
    vars.insert(name, var);
}

#[allow(dead_code)]
fn vars_exist(name: & String) -> bool {
    let vars = VARS.lock().unwrap();
    return None != vars.get(name);
}

fn stacksize() -> i32 {
    *STACKSIZE.lock().unwrap()
}

fn init_stacksize() {
    let mut stacksize = STACKSIZE.lock().unwrap();
    *stacksize = 0;
}

fn add_stacksize(i: i32) {
    let mut stacksize = STACKSIZE.lock().unwrap();
    *stacksize += i;
}

fn swap(p: &mut Node, q: &mut Node) {
    mem::swap(p, q);
}

fn addr_of(base: Node, ty: Type) -> Node {
    let mut node = alloc_node();
    node.op = NodeType::ADDR;
    node.ty = ptr_of(ty);

    node.expr = Some(Box::new(base));
    return node;
}

fn walk<'a>(node: &'a mut Node, decay: bool) -> &'a Node {
    match node.op {
        NodeType::NUM => {
            return node;
        }
        NodeType::IDENT => {
            match VARS.lock().unwrap().get(&node.name) {
                None => {
                    panic!("undefined variable: {}", node.name);
                }
                Some(var) => {
                    node.op = NodeType::LVAR;
                    node.offset = var.offset;

                    if decay && var.ty.ty == CType::ARY {
                        *node = addr_of(node.clone(), *var.clone().ty.ary_of.unwrap());
                        return node;
                    }
                    node.ty = var.clone().ty;
                    return node;
                }
            }
        }
        NodeType::VARDEF => {
            add_stacksize(size_of(node.clone().ty));
            node.offset = stacksize();

            let var = Var {
                ty: node.ty.clone(),
                offset: stacksize(),
            };
            vars_put(node.name.clone(), var.clone());

            match node.init {
                Some(_) => {
                    node.init = Some(Box::new(walk(&mut *node.clone().init.unwrap(), true).clone()));
                    //node.init = Some(Box::new(walk(&mut e, true).clone()));
                }
                None => { }
            }
            return node;
        }
        NodeType::IF => {
            node.cond = Some(Box::new(walk(&mut *node.clone().cond.unwrap(), true).clone()));
            node.then = Some(Box::new(walk(&mut *node.clone().then.unwrap(), true).clone()));

            if node.els.is_some() {
                node.els = Some(Box::new(walk(&mut *node.clone().els.unwrap(), true).clone()));
            }
            return node;
        }
        NodeType::FOR => {
            node.init = Some(Box::new(walk(&mut *node.clone().init.unwrap(), true).clone()));
            node.cond = Some(Box::new(walk(&mut *node.clone().cond.unwrap(), true).clone()));
            node.inc = Some(Box::new(walk(&mut *node.clone().inc.unwrap(), true).clone()));
            node.body = Some(Box::new(walk(&mut *node.clone().body.unwrap(), true).clone()));
            return node;
        }
        NodeType::ADD | NodeType::SUB => {
            node.lhs = Some(Box::new(walk(&mut *node.clone().lhs.unwrap(), true).clone()));
            node.rhs = Some(Box::new(walk(&mut *node.clone().rhs.unwrap(), true).clone()));

            match (&mut node.lhs, &mut node.rhs) {
                (Some(ref mut lhs), Some(ref mut rhs)) => {
                    if rhs.ty.ty == CType::PTR {
                        swap(lhs, rhs);
                    }
                }
                _ => {}
            }
            match node.rhs {
                Some(ref rhs) => {
                    if rhs.ty.ty == CType::PTR {
                        panic!("'pointer {:?} pointer' is not defined", node.op);
                    }
                }
                None => {
                }
            }

            match node.lhs {
                Some(ref lhs) => {
                    node.ty = lhs.ty.clone();
                }
                None => { }
            }

            return node;
        }
        NodeType::EQ => {
            node.lhs = Some(Box::new(walk(&mut *node.clone().lhs.unwrap(), false).clone()));
            node.rhs = Some(Box::new(walk(&mut *node.clone().rhs.unwrap(), true).clone()));
            node.ty = node.clone().lhs.unwrap().ty;
            return node;
        }
        NodeType::MUL |
            NodeType::DIV |
            NodeType::LT |
            NodeType::LOGAND |
            NodeType::LOGOR => {
                node.lhs = Some(Box::new(walk(&mut *node.clone().lhs.unwrap(), true).clone()));
                node.rhs = Some(Box::new(walk(&mut *node.clone().rhs.unwrap(), true).clone()));

                match node.lhs {
                    Some(ref lhs) => {
                        node.ty = lhs.ty.clone();
                    }
                    None => { }
                }
                return node;
            }
        NodeType::ADDR => {
            node.expr = Some(Box::new(walk(&mut *node.clone().expr.unwrap(), true).clone()));
            node.ty = ptr_of(node.clone().expr.unwrap().ty);
            return node;
        }
        NodeType::DEREF => {
            node.expr = Some(Box::new(walk(&mut *node.clone().expr.unwrap(), true).clone()));
            match &mut node.expr {
                Some(ref expr) => {
                    if expr.ty.ty != CType::PTR {
                        panic!("operand must be a pointer");
                    }
                }
                None => {}
            }

            node.ty = *node.clone().expr.unwrap().ty.ptr_of.unwrap();
            return node;
        }
        NodeType::RETURN => {
            node.expr = Some(Box::new(walk(&mut *node.clone().expr.unwrap(), true).clone()));
            return node;
        }
        NodeType::CALL => {
            for i in 0..node.args.len() {
                node.args[i] = walk(&mut node.args[i], true).clone();
            }
            node.ty = int_ty();
            return node;
        }
        NodeType::FUNC => {
            for i in 0..node.args.len() {
                node.args[i] = walk(&mut node.args[i], true).clone();
            }
            node.body = Some(Box::new(walk(&mut *node.clone().body.unwrap(), true).clone()));
            return node;
        }
        NodeType::COMP_STMT => {
            for i in 0..node.stmts.len() {
                node.stmts[i] = walk(&mut node.stmts[i], true).clone();
            }
            return node;
        }
        NodeType::EXPR_STMT => {
            node.expr = Some(Box::new(walk(&mut *node.clone().expr.unwrap(), true).clone()));
            return node;
        }
        _ => {
            panic!("unknown node type");
        }
    }
}

pub fn sema(nodes: &mut Vec<Node>) {
    for node in nodes.iter_mut() {
        assert!(node.op == NodeType::FUNC);

        init_stacksize();
        walk(node, true);
        node.stacksize = stacksize();
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/SHA-1

//! Straight port from golang crypto/sha1 library implementation
use std::num::Wrapping as wr;
use std::io::{Write, Result};

/// The size of a SHA1 checksum in bytes.
const SIZE: usize = 20;

/// The blocksize of SHA1 in bytes.
const CHUNK: usize = 64;
const INIT: [wr<u32>; 5] = [wr(0x67452301),
                            wr(0xEFCDAB89),
                            wr(0x98BADCFE),
                            wr(0x10325476),
                            wr(0xC3D2E1F0)];

fn main() {
    let mut d = Digest::new();
    let _ = write!(&mut d, "The quick brown fox jumps over the lazy dog");
    let sha1 = d.sha1();

    for h in &sha1 {
        print!("{:x} ", *h);
    }
}

/// digest represents the partial evaluation of a checksum.
struct Digest {
    h: [wr<u32>; 5],
    x: [u8; CHUNK],
    nx: usize,
    len: u64,
}

impl Digest {
    fn new() -> Digest {
        Digest {
            h: INIT,
            x: [0u8; CHUNK],
            nx: 0,
            len: 0u64,
        }
    }

    fn sha1(&mut self) -> [u8; SIZE] {
        let mut len = self.len;
        // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
        let mut tmp: [u8; 64] = [0u8; 64];
        tmp[0] = 0x80u8;

        let m: usize = (len % 64u64) as usize;
        if m < 56 {
            self.write_all(&tmp[0..56 - m]).unwrap();
        } else {
            self.write_all(&tmp[0..64 + 56 - m]).unwrap();
        }

        // Length in bits (=length in bytes*8=shift 3 bits to the right).
        len = len << 3;
        for (i, byte) in tmp.iter_mut().take(8).enumerate() {
            *byte = (len >> (56 - 8 * i)) as u8;
        }
        self.write_all(&tmp[0..8]).unwrap();

        assert!(self.nx == 0);

        let mut digest: [u8; SIZE] = [0u8; SIZE];
        for (i, s) in self.h.iter().enumerate() {
            digest[i * 4] = (*s >> 24).0 as u8;
            digest[i * 4 + 1] = (*s >> 16).0 as u8;
            digest[i * 4 + 2] = (*s >> 8).0 as u8;
            digest[i * 4 + 3] = s.0 as u8;
        }
        digest
    }

    #[cfg_attr(feature="clippy", allow(needless_range_loop))]
    fn process_block(&self, data: &[u8]) -> [wr<u32>; 5] {
        let k: [u32; 4] = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6];

        #[inline]
        fn part(a: wr<u32>, b: wr<u32>) -> (wr<u32>, wr<u32>) {
            ((a << 5 | a >> (32 - 5)), (b << 30 | b >> (32 - 30)))
        }

        let mut w: [u32; 16] = [0u32; 16];

        let (mut h0, mut h1, mut h2, mut h3, mut h4) = (self.h[0],
                                                        self.h[1],
                                                        self.h[2],
                                                        self.h[3],
                                                        self.h[4]);

        let mut p = data;

        while p.len() >= CHUNK {
            for i in 0..16 {
                let j = i * 4;
                w[i] = (p[j] as u32) << 24 | (p[j + 1] as u32) << 16 | (p[j + 2] as u32) << 8 |
                       p[j + 3] as u32;
            }

            let (mut a, mut b, mut c, mut d, mut e) = (h0, h1, h2, h3, h4);

            for i in 0..16 {
                let f = b & c | (!b) & d;
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[0]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            for i in 16..20 {
                let tmp = w[(i - 3) & 0xf] ^ w[(i - 8) & 0xf] ^ w[(i - 14) & 0xf] ^ w[(i) & 0xf];
                w[i & 0xf] = tmp << 1 | tmp >> (32 - 1);
                let f = b & c | (!b) & d;
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[0]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            for i in 20..40 {
                let tmp = w[(i - 3) & 0xf] ^ w[(i - 8) & 0xf] ^ w[(i - 14) & 0xf] ^ w[(i) & 0xf];
                w[i & 0xf] = tmp << 1 | tmp >> (32 - 1);
                let f = b ^ c ^ d;
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[1]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            for i in 40..60 {
                let tmp = w[(i - 3) & 0xf] ^ w[(i - 8) & 0xf] ^ w[(i - 14) & 0xf] ^ w[(i) & 0xf];
                w[i & 0xf] = tmp << 1 | tmp >> (32 - 1);
                let f = ((b | c) & d) | (b & c);
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[2]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            for i in 60..80 {
                let tmp = w[(i - 3) & 0xf] ^ w[(i - 8) & 0xf] ^ w[(i - 14) & 0xf] ^ w[(i) & 0xf];
                w[i & 0xf] = tmp << 1 | tmp >> (32 - 1);
                let f = b ^ c ^ d;
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[3]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            h0 = h0 + a;
            h1 = h1 + b;
            h2 = h2 + c;
            h3 = h3 + d;
            h4 = h4 + e;

            p = &p[CHUNK..];
        }
        [h0, h1, h2, h3, h4]
    }
}

impl Default for Digest {
    fn default() -> Self {
        Self::new()
    }
}

impl Write for Digest {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        try!(self.write_all(buf));
        Ok(buf.len())
    }

    #[inline]
    fn write_all(&mut self, buf: &[u8]) -> Result<()> {
        let mut buf_m = buf;

        self.len += buf_m.len() as u64;

        if self.nx > 0 {
            let mut n = buf_m.len();
            if n > CHUNK - self.nx {
                n = CHUNK - self.nx;
            }
            for i in 0..n {
                self.x[self.nx + i] = *buf_m.get(i).unwrap();
            }
            self.nx += n;
            if self.nx == CHUNK {
                let x = &(self.x[..]);
                self.h = self.process_block(x);
                self.nx = 0;
            }
            buf_m = &buf_m[n..];
        }
        if buf_m.len() >= CHUNK {
            let n = buf_m.len() & !(CHUNK - 1);
            let x = &(self.x[n..]);
            self.h = self.process_block(x);
            buf_m = &buf_m[n..];
        }
        let ln = buf_m.len();
        if ln > 0 {
            assert!(self.x.len() >= ln);
            self.x.as_mut().write_all(&buf_m).unwrap();
            self.nx = ln;
        }
        Ok(())
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

#[test]
fn known_sha1s() {
    let input_output = [("His money is twice tainted: 'taint yours and 'taint mine.",
                         [0x59u8, 0x7f, 0x6a, 0x54, 0x0, 0x10, 0xf9, 0x4c, 0x15, 0xd7, 0x18, 0x6,
                          0xa9, 0x9a, 0x2c, 0x87, 0x10, 0xe7, 0x47, 0xbd]),
                        ("The quick brown fox jumps over the lazy dog",
                         [0x2fu8, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e,
                          0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12]),
                        ("The quick brown fox jumps over the lazy cog",
                         [0xdeu8, 0x9f, 0x2c, 0x7f, 0xd2, 0x5e, 0x1b, 0x3a, 0xfa, 0xd3, 0xe8,
                          0x5a, 0x0b, 0xd1, 0x7d, 0x9b, 0x10, 0x0d, 0xb4, 0xb3])];

    for &(i, o) in &input_output {
        let mut d = Digest::new();
        let _ = write!(&mut d, "{}", i);
        let sha1 = d.sha1();

        assert_eq!(sha1, o);
    }
}
<commit_msg>fix solutions with many short variable names<commit_after>// http://rosettacode.org/wiki/SHA-1

#![cfg_attr(feature = "clippy", allow(many_single_char_names))]

//! Straight port from golang crypto/sha1 library implementation
use std::num::Wrapping as wr;
use std::io::{Write, Result};

/// The size of a SHA1 checksum in bytes.
const SIZE: usize = 20;

/// The blocksize of SHA1 in bytes.
const CHUNK: usize = 64;
const INIT: [wr<u32>; 5] = [wr(0x67452301),
                            wr(0xEFCDAB89),
                            wr(0x98BADCFE),
                            wr(0x10325476),
                            wr(0xC3D2E1F0)];

fn main() {
    let mut d = Digest::new();
    let _ = write!(&mut d, "The quick brown fox jumps over the lazy dog");
    let sha1 = d.sha1();

    for h in &sha1 {
        print!("{:x} ", *h);
    }
}

/// digest represents the partial evaluation of a checksum.
struct Digest {
    h: [wr<u32>; 5],
    x: [u8; CHUNK],
    nx: usize,
    len: u64,
}

impl Digest {
    fn new() -> Digest {
        Digest {
            h: INIT,
            x: [0u8; CHUNK],
            nx: 0,
            len: 0u64,
        }
    }

    fn sha1(&mut self) -> [u8; SIZE] {
        let mut len = self.len;
        // Padding.  Add a 1 bit and 0 bits until 56 bytes mod 64.
        let mut tmp: [u8; 64] = [0u8; 64];
        tmp[0] = 0x80u8;

        let m: usize = (len % 64u64) as usize;
        if m < 56 {
            self.write_all(&tmp[0..56 - m]).unwrap();
        } else {
            self.write_all(&tmp[0..64 + 56 - m]).unwrap();
        }

        // Length in bits (=length in bytes*8=shift 3 bits to the right).
        len = len << 3;
        for (i, byte) in tmp.iter_mut().take(8).enumerate() {
            *byte = (len >> (56 - 8 * i)) as u8;
        }
        self.write_all(&tmp[0..8]).unwrap();

        assert!(self.nx == 0);

        let mut digest: [u8; SIZE] = [0u8; SIZE];
        for (i, s) in self.h.iter().enumerate() {
            digest[i * 4] = (*s >> 24).0 as u8;
            digest[i * 4 + 1] = (*s >> 16).0 as u8;
            digest[i * 4 + 2] = (*s >> 8).0 as u8;
            digest[i * 4 + 3] = s.0 as u8;
        }
        digest
    }

    #[cfg_attr(feature="clippy", allow(needless_range_loop))]
    fn process_block(&self, data: &[u8]) -> [wr<u32>; 5] {
        let k: [u32; 4] = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6];

        #[inline]
        fn part(a: wr<u32>, b: wr<u32>) -> (wr<u32>, wr<u32>) {
            ((a << 5 | a >> (32 - 5)), (b << 30 | b >> (32 - 30)))
        }

        let mut w: [u32; 16] = [0u32; 16];

        let (mut h0, mut h1, mut h2, mut h3, mut h4) = (self.h[0],
                                                        self.h[1],
                                                        self.h[2],
                                                        self.h[3],
                                                        self.h[4]);

        let mut p = data;

        while p.len() >= CHUNK {
            for i in 0..16 {
                let j = i * 4;
                w[i] = (p[j] as u32) << 24 | (p[j + 1] as u32) << 16 | (p[j + 2] as u32) << 8 |
                       p[j + 3] as u32;
            }

            let (mut a, mut b, mut c, mut d, mut e) = (h0, h1, h2, h3, h4);

            for i in 0..16 {
                let f = b & c | (!b) & d;
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[0]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            for i in 16..20 {
                let tmp = w[(i - 3) & 0xf] ^ w[(i - 8) & 0xf] ^ w[(i - 14) & 0xf] ^ w[(i) & 0xf];
                w[i & 0xf] = tmp << 1 | tmp >> (32 - 1);
                let f = b & c | (!b) & d;
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[0]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            for i in 20..40 {
                let tmp = w[(i - 3) & 0xf] ^ w[(i - 8) & 0xf] ^ w[(i - 14) & 0xf] ^ w[(i) & 0xf];
                w[i & 0xf] = tmp << 1 | tmp >> (32 - 1);
                let f = b ^ c ^ d;
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[1]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            for i in 40..60 {
                let tmp = w[(i - 3) & 0xf] ^ w[(i - 8) & 0xf] ^ w[(i - 14) & 0xf] ^ w[(i) & 0xf];
                w[i & 0xf] = tmp << 1 | tmp >> (32 - 1);
                let f = ((b | c) & d) | (b & c);
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[2]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            for i in 60..80 {
                let tmp = w[(i - 3) & 0xf] ^ w[(i - 8) & 0xf] ^ w[(i - 14) & 0xf] ^ w[(i) & 0xf];
                w[i & 0xf] = tmp << 1 | tmp >> (32 - 1);
                let f = b ^ c ^ d;
                let (a5, b30) = part(a, b);
                let t = a5 + f + e + wr(w[i & 0xf]) + wr(k[3]);
                b = a;
                a = t;
                e = d;
                d = c;
                c = b30;
            }
            h0 = h0 + a;
            h1 = h1 + b;
            h2 = h2 + c;
            h3 = h3 + d;
            h4 = h4 + e;

            p = &p[CHUNK..];
        }
        [h0, h1, h2, h3, h4]
    }
}

impl Default for Digest {
    fn default() -> Self {
        Self::new()
    }
}

impl Write for Digest {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        try!(self.write_all(buf));
        Ok(buf.len())
    }

    #[inline]
    fn write_all(&mut self, buf: &[u8]) -> Result<()> {
        let mut buf_m = buf;

        self.len += buf_m.len() as u64;

        if self.nx > 0 {
            let mut n = buf_m.len();
            if n > CHUNK - self.nx {
                n = CHUNK - self.nx;
            }
            for i in 0..n {
                self.x[self.nx + i] = *buf_m.get(i).unwrap();
            }
            self.nx += n;
            if self.nx == CHUNK {
                let x = &(self.x[..]);
                self.h = self.process_block(x);
                self.nx = 0;
            }
            buf_m = &buf_m[n..];
        }
        if buf_m.len() >= CHUNK {
            let n = buf_m.len() & !(CHUNK - 1);
            let x = &(self.x[n..]);
            self.h = self.process_block(x);
            buf_m = &buf_m[n..];
        }
        let ln = buf_m.len();
        if ln > 0 {
            assert!(self.x.len() >= ln);
            self.x.as_mut().write_all(&buf_m).unwrap();
            self.nx = ln;
        }
        Ok(())
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

#[test]
fn known_sha1s() {
    let input_output = [("His money is twice tainted: 'taint yours and 'taint mine.",
                         [0x59u8, 0x7f, 0x6a, 0x54, 0x0, 0x10, 0xf9, 0x4c, 0x15, 0xd7, 0x18, 0x6,
                          0xa9, 0x9a, 0x2c, 0x87, 0x10, 0xe7, 0x47, 0xbd]),
                        ("The quick brown fox jumps over the lazy dog",
                         [0x2fu8, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e,
                          0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12]),
                        ("The quick brown fox jumps over the lazy cog",
                         [0xdeu8, 0x9f, 0x2c, 0x7f, 0xd2, 0x5e, 0x1b, 0x3a, 0xfa, 0xd3, 0xe8,
                          0x5a, 0x0b, 0xd1, 0x7d, 0x9b, 0x10, 0x0d, 0xb4, 0xb3])];

    for &(i, o) in &input_output {
        let mut d = Digest::new();
        let _ = write!(&mut d, "{}", i);
        let sha1 = d.sha1();

        assert_eq!(sha1, o);
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::io::{self, Read};

use hyper;
use hyper::client::Client;
use hyper::error::Error as HyperError;
use hyper::header::{Header, HeaderFormat};

#[derive(Clone, Debug)]
pub struct Action(String);

impl Action {

    pub fn new(action: &str) -> Action {
        Action(action.into())
    }

}

impl Header for Action {

    fn header_name() -> &'static str {
        "SOAPAction"
    }

    #[allow(unused_variables)]
    fn parse_header(raw: &[Vec<u8>]) -> hyper::Result<Action> {
        // Leave unimplemented as we shouldn't need it.
        unimplemented!();
    }

}

impl HeaderFormat for Action {

    fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.0)
    }

}

pub enum Error {
    HttpError(HyperError),
    IoError(io::Error),
}

impl From<HyperError> for Error {
    fn from(err: HyperError) -> Error {
        Error::HttpError(err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

pub fn send(url: &str, action: Action, body: &str) -> Result<String, Error>  {
    let client = Client::new();
    let mut resp = try!(client.post(url)
        .header(action)
        .body(body)
        .send());

    let mut text = String::new();
    try!(resp.read_to_string(&mut text));
    Ok(text)
}
<commit_msg>text/xml ContentType header with requests<commit_after>use std::fmt;
use std::io::{self, Read};

use hyper;
use hyper::mime;
use hyper::client::Client;
use hyper::error::Error as HyperError;
use hyper::header::{Header, HeaderFormat, ContentType};

#[derive(Clone, Debug)]
pub struct Action(String);

impl Action {

    pub fn new(action: &str) -> Action {
        Action(action.into())
    }

}

impl Header for Action {

    fn header_name() -> &'static str {
        "SOAPAction"
    }

    #[allow(unused_variables)]
    fn parse_header(raw: &[Vec<u8>]) -> hyper::Result<Action> {
        // Leave unimplemented as we shouldn't need it.
        unimplemented!();
    }

}

impl HeaderFormat for Action {

    fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.0)
    }

}

pub enum Error {
    HttpError(HyperError),
    IoError(io::Error),
}

impl From<HyperError> for Error {
    fn from(err: HyperError) -> Error {
        Error::HttpError(err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::IoError(err)
    }
}

pub fn send(url: &str, action: Action, body: &str) -> Result<String, Error>  {
    let client = Client::new();
    let mut resp = try!(client.post(url)
        .header(action)
        .header(ContentType(mime::Mime(mime::TopLevel::Text, mime::SubLevel::Xml, Vec::new())))
        .body(body)
        .send());

    let mut text = String::new();
    try!(resp.read_to_string(&mut text));
    Ok(text)
}
<|endoftext|>


<commit_before>use clap::ArgMatches;
use client::Client;
use hostname::get_hostname;
use member::{self, NewMember, Member};
use super::Result;

pub enum TeamId {
    Id(i32),
    Hostname(String),
}

pub fn create<C: Client>(matches: &ArgMatches, client: &C) -> Result<Team> {
    let time_per_driver_in_minutes = matches.value_of("minutes")
        .map(|minutes| minutes.parse::<f64>())
        .unwrap_or(Ok(5.0))?;

    let new_members = member::build(matches);

    let new_team = NewTeam::new(new_members, time_per_driver_in_minutes, hostname());
    let team = client.create_team(&new_team)?;

    Ok(team)
}

fn hostname() -> String {
    get_hostname().expect("system to have a hostname")
}

#[derive(Debug, Serialize)]
pub struct NewTeam {
    time: f64,
    hostname: String,
    members: Vec<NewMember>,
}

impl NewTeam {
    fn new(new_members: Vec<NewMember>, time: f64, hostname: String) -> NewTeam {
        NewTeam {
            time: time,
            hostname: hostname,
            members: new_members,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Team {
    pub id: i32,
    pub driver: Member,
    pub hostname: String,
    pub time: f64,
    pub members: Vec<Member>,
}

impl Team {
    pub fn next_driver(&self) -> Member {
        let next_driver_position = next_driver_position(
            self.driver.position + 1,
            &self.members);

        self.members
            .clone()
            .into_iter()
            .find(|member| member.position == next_driver_position)
            .expect("Member to exist at position")
    }

    pub fn change_driver(&mut self, next_driver: &Member) {
        self.driver = next_driver.to_owned()
    }
}

fn next_driver_position(next_position: i32, members: &Vec<Member>) -> i32 {
    match members.into_iter().find(|member| member.position == next_position) {
        Some(driver) => {
            if driver.is_active() {
                driver.position
            } else {
                next_driver_position(driver.position + 1, members)
            }
        }
        None => next_driver_position(0, members)

    }
}

#[cfg(test)]
mod test {
    use super::{Member, Team};

    #[test]
    fn test_next_driver() {
        let current_driver = Member::new(1, "Mike", 1, true, true);
        let next_driver = Member::new(2, "Brian", 2, true, false);
        let members: Vec<Member> = vec![
            current_driver.clone(),
            next_driver.clone(),
            Member::new(3, "Patrick", 3, true, false)];

        let team = Team {
            id: 1,
            driver: current_driver,
            hostname: "example".into(),
            time: 5.0,
            members: members,
        };

        assert_eq!(team.next_driver(), next_driver);
    }

    #[test]
    fn test_next_driver_ignores_inactive() {
        let current_driver  = Member::new(1, "Mike", 1, true, true);
        let inactive_driver  = Member::new(2, "Brian", 2, false, false);
        let next_driver  = Member::new(3, "Patrick", 3, true, false);

        let members: Vec<Member> = vec![
            current_driver.clone(),
            inactive_driver,
            next_driver.clone()];

        let team = Team {
            id: 1,
            driver: current_driver,
            hostname: "example".into(),
            time: 5.0,
            members: members,
        };

        assert_eq!(team.next_driver(), next_driver);
    }

    #[test]
    fn test_change_driver() {
        let members: Vec<Member> = vec![
            Member::new(1, "Mike", 1, true, true),
            Member::new(2, "Brian", 2, true, false),
            Member::new(3, "Patrick", 3, true, false)];

        let mut team = Team {
            id: 1,
            driver: members.first().unwrap().clone(),
            hostname: "example".into(),
            time: 5.0,
            members: members,
        };

        let next_driver = team.next_driver();
        team.change_driver(&next_driver);

        assert_eq!(next_driver, team.driver);
    }
}
<commit_msg>refactor: REmove unused function<commit_after>use clap::ArgMatches;
use client::Client;
use hostname::get_hostname;
use member::{self, NewMember, Member};
use super::Result;

pub enum TeamId {
    Id(i32),
    Hostname(String),
}

pub fn create<C: Client>(matches: &ArgMatches, client: &C) -> Result<Team> {
    let time_per_driver_in_minutes = matches.value_of("minutes")
        .map(|minutes| minutes.parse::<f64>())
        .unwrap_or(Ok(5.0))?;

    let new_members = member::build(matches);

    let new_team = NewTeam::new(new_members, time_per_driver_in_minutes, hostname());
    let team = client.create_team(&new_team)?;

    Ok(team)
}

fn hostname() -> String {
    get_hostname().expect("system to have a hostname")
}

#[derive(Debug, Serialize)]
pub struct NewTeam {
    time: f64,
    hostname: String,
    members: Vec<NewMember>,
}

impl NewTeam {
    fn new(new_members: Vec<NewMember>, time: f64, hostname: String) -> NewTeam {
        NewTeam {
            time: time,
            hostname: hostname,
            members: new_members,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Team {
    pub id: i32,
    pub driver: Member,
    pub hostname: String,
    pub time: f64,
    pub members: Vec<Member>,
}

impl Team {
    pub fn next_driver(&self) -> Member {
        let next_driver_position = next_driver_position(
            self.driver.position + 1,
            &self.members);

        self.members
            .clone()
            .into_iter()
            .find(|member| member.position == next_driver_position)
            .expect("Member to exist at position")
    }
}

fn next_driver_position(next_position: i32, members: &Vec<Member>) -> i32 {
    match members.into_iter().find(|member| member.position == next_position) {
        Some(driver) => {
            if driver.is_active() {
                driver.position
            } else {
                next_driver_position(driver.position + 1, members)
            }
        }
        None => next_driver_position(0, members)

    }
}

#[cfg(test)]
mod test {
    use super::{Member, Team};

    #[test]
    fn test_next_driver() {
        let current_driver = Member::new(1, "Mike", 1, true, true);
        let next_driver = Member::new(2, "Brian", 2, true, false);
        let members: Vec<Member> = vec![
            current_driver.clone(),
            next_driver.clone(),
            Member::new(3, "Patrick", 3, true, false)];

        let team = Team {
            id: 1,
            driver: current_driver,
            hostname: "example".into(),
            time: 5.0,
            members: members,
        };

        assert_eq!(team.next_driver(), next_driver);
    }

    #[test]
    fn test_next_driver_ignores_inactive() {
        let current_driver  = Member::new(1, "Mike", 1, true, true);
        let inactive_driver  = Member::new(2, "Brian", 2, false, false);
        let next_driver  = Member::new(3, "Patrick", 3, true, false);

        let members: Vec<Member> = vec![
            current_driver.clone(),
            inactive_driver,
            next_driver.clone()];

        let team = Team {
            id: 1,
            driver: current_driver,
            hostname: "example".into(),
            time: 5.0,
            members: members,
        };

        assert_eq!(team.next_driver(), next_driver);
    }
}
<|endoftext|>


<commit_before>extern crate time;

/// Return current time in microseconds since the UNIX epoch.
pub fn now_microseconds() -> u32 {
    let t = time::get_time();
    (t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32
}

/// Calculate the exponential weighted moving average of a sample vector,
/// with a given alpha parameter.
pub fn ewma(samples: Vec<f64>, alpha: f64) -> Vec<f64> {
    let mut average = Vec::new();

    if samples.is_empty() {
        return average;
    }

    // s_0 = x_0
    average.push(samples[0]);

    for i in range(1u, samples.len()) {
        let prev_sample = samples[i];
        let prev_avg = *average.last().unwrap();
        let curr_avg = alpha * prev_sample + (1.0 - alpha) * prev_avg;

        average.push(curr_avg);
    }

    return average;
}

mod test {
    #[test]
    fn test_exponential_smoothed_moving_average() {
        use super::ewma;
        use std::iter::range_inclusive;
        use std::num::FloatMath;

        let input = range_inclusive(1u, 10).map(|x| x as f64).collect();
        let alpha = 1.0/3.0;
        let expected: Vec<f64> = [1.0, 4.0/3.0, 17.0/9.0,
        70.0/27.0, 275.0/81.0, 1036.0/243.0, 3773.0/729.0, 13378.0/2187.0,
        46439.0/6561.0, 158488.0/19683.0].to_vec();
        let output = ewma(input, alpha);
        let result = expected.iter().zip(output.iter())
            .fold(0.0 as f64, |acc, (&a, &b)| acc + a.abs_sub(b));
        assert!(result == 0.0);
    }
}
<commit_msg>Make EWMA accept a generic vector.<commit_after>extern crate time;

/// Return current time in microseconds since the UNIX epoch.
pub fn now_microseconds() -> u32 {
    let t = time::get_time();
    (t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32
}

/// Calculate the exponential weighted moving average of a sample vector,
/// with a given alpha parameter.
pub fn ewma<T: ToPrimitive>(samples: Vec<T>, alpha: f64) -> Vec<f64> {
    let mut average = Vec::new();

    if samples.is_empty() {
        return average;
    }

    // s_0 = x_0
    average.push(samples[0].to_f64().unwrap());

    for i in range(1u, samples.len()) {
        let prev_sample = samples[i].to_f64().unwrap();
        let prev_avg = *average.last().unwrap();
        let curr_avg = alpha * prev_sample + (1.0 - alpha) * prev_avg;

        average.push(curr_avg);
    }

    return average;
}

mod test {
    #[test]
    fn test_exponential_smoothed_moving_average() {
        use super::ewma;
        use std::iter::range_inclusive;
        use std::num::FloatMath;

        let input = range_inclusive(1u, 10).collect();
        let alpha = 1.0/3.0;
        let expected: Vec<f64> = [1.0, 4.0/3.0, 17.0/9.0,
        70.0/27.0, 275.0/81.0, 1036.0/243.0, 3773.0/729.0, 13378.0/2187.0,
        46439.0/6561.0, 158488.0/19683.0].to_vec();
        let output = ewma(input, alpha);
        let result = expected.iter().zip(output.iter())
            .fold(0.0, |acc, (&a, &b)| acc + a.abs_sub(b));
        assert!(result == 0.0);
    }
}
<|endoftext|>


<commit_before>use super::*;
use serde::{Deserialize, Serialize};

/// Defines the class of geometric shape
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub enum GeoClass {
    /// Lines (segments) class
    Lin,

    /// Triangles class
    Tri,

    /// Quadrilaterals class
    Qua,

    /// Tetrahedra class
    Tet,

    /// Hexahedra class
    Hex,
}

/// Defines the kind of geometric shape
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub enum GeoKind {
    /// Line (segment) with 2 nodes (linear functions)
    Lin2 = 1_002,

    /// Line (segment) with 3 nodes (quadratic functions)
    Lin3 = 1_003,

    /// Line (segment) with 4 nodes (cubic functions)
    Lin4 = 1_004,

    /// Line (segment) with 5 nodes (quartic functions)
    Lin5 = 1_005,

    /// Triangle with 3 nodes (linear edges)
    Tri3 = 2_003,

    /// Triangle with 6 nodes (quadratic edges)
    Tri6 = 2_006,

    /// Triangle with 10 nodes (cubic edges; interior node)
    Tri10 = 2_010,

    /// Triangle with 15 nodes (quartic edges; interior nodes)
    Tri15 = 2_015,

    /// Quadrilateral with 4 nodes (linear edges)
    Qua4 = 2_004,

    /// Quadrilateral with 8 nodes (quadratic edges)
    Qua8 = 2_008,

    /// Quadrilateral with 9 nodes (quadratic edges; interior node)
    Qua9 = 2_009,

    /// Quadrilateral with 12 nodes (cubic edges)
    Qua12 = 2_012,

    /// Quadrilateral with 16 nodes (cubic edges; interior nodes)
    Qua16 = 2_016,

    /// Quadrilateral with 17 nodes (quartic edges; interior node)
    Qua17 = 2_017,

    /// Tetrahedron with 4 nodes (linear faces)
    Tet4 = 3_004,

    /// Tetrahedron with 10 nodes (quadratic faces)
    Tet10 = 3_010,

    /// Hexahedron with 8 nodes (bilinear faces)
    Hex8 = 3_008,

    /// Hexahedron with 20 nodes (quadratic faces)
    Hex20 = 3_020,
}

pub(crate) fn i32_to_fn_interp(kind: i32) -> FnInterp {
    match kind {
        // Lin
        1_002 => FnInterp(GeoKind::Lin2, Lin2::calc_interp),
        1_003 => FnInterp(GeoKind::Lin3, Lin3::calc_interp),
        1_004 => FnInterp(GeoKind::Lin4, Lin4::calc_interp),
        1_005 => FnInterp(GeoKind::Lin5, Lin5::calc_interp),
        // Tri
        2_003 => FnInterp(GeoKind::Tri3, Tri3::calc_interp),
        2_006 => FnInterp(GeoKind::Tri6, Tri6::calc_interp),
        2_010 => FnInterp(GeoKind::Tri10, Tri10::calc_interp),
        2_015 => FnInterp(GeoKind::Tri15, Tri15::calc_interp),
        // Qua
        2_004 => FnInterp(GeoKind::Qua4, Qua4::calc_interp),
        2_008 => FnInterp(GeoKind::Qua8, Qua8::calc_interp),
        2_009 => FnInterp(GeoKind::Qua9, Qua9::calc_interp),
        2_012 => FnInterp(GeoKind::Qua12, Qua12::calc_interp),
        2_016 => FnInterp(GeoKind::Qua16, Qua16::calc_interp),
        2_017 => FnInterp(GeoKind::Qua17, Qua17::calc_interp),
        // Tet
        3_004 => FnInterp(GeoKind::Tet4, Tet4::calc_interp),
        3_010 => FnInterp(GeoKind::Tet10, Tet10::calc_interp),
        // Hex
        3_008 => FnInterp(GeoKind::Hex8, Hex8::calc_interp),
        3_020 => FnInterp(GeoKind::Hex20, Hex20::calc_interp),
        _ => panic!("INTERNAL ERROR: cannot convert i32 to FnInterp"),
    }
}

pub(crate) fn i32_to_fn_deriv(kind: i32) -> FnDeriv {
    match kind {
        // Lin
        1_002 => FnDeriv(GeoKind::Lin2, Lin2::calc_deriv),
        1_003 => FnDeriv(GeoKind::Lin3, Lin3::calc_deriv),
        1_004 => FnDeriv(GeoKind::Lin4, Lin4::calc_deriv),
        1_005 => FnDeriv(GeoKind::Lin5, Lin5::calc_deriv),
        // Tri
        2_003 => FnDeriv(GeoKind::Tri3, Tri3::calc_deriv),
        2_006 => FnDeriv(GeoKind::Tri6, Tri6::calc_deriv),
        2_010 => FnDeriv(GeoKind::Tri10, Tri10::calc_deriv),
        2_015 => FnDeriv(GeoKind::Tri15, Tri15::calc_deriv),
        // Qua
        2_004 => FnDeriv(GeoKind::Qua4, Qua4::calc_deriv),
        2_008 => FnDeriv(GeoKind::Qua8, Qua8::calc_deriv),
        2_009 => FnDeriv(GeoKind::Qua9, Qua9::calc_deriv),
        2_012 => FnDeriv(GeoKind::Qua12, Qua12::calc_deriv),
        2_016 => FnDeriv(GeoKind::Qua16, Qua16::calc_deriv),
        2_017 => FnDeriv(GeoKind::Qua17, Qua17::calc_deriv),
        // Tet
        3_004 => FnDeriv(GeoKind::Tet4, Tet4::calc_deriv),
        3_010 => FnDeriv(GeoKind::Tet10, Tet10::calc_deriv),
        // Hex
        3_008 => FnDeriv(GeoKind::Hex8, Hex8::calc_deriv),
        3_020 => FnDeriv(GeoKind::Hex20, Hex20::calc_deriv),
        _ => panic!("INTERNAL ERROR: cannot convert i32 to FnDeriv"),
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use crate::shapes::{GeoClass, GeoKind};
    use std::collections::HashSet;

    #[test]
    fn derive_works() {
        let class = GeoClass::Tri.clone();
        let kind = GeoKind::Tri6.clone();
        let classes = HashSet::from([GeoClass::Tri, GeoClass::Qua]);
        let kinds = HashSet::from([GeoKind::Tri3, GeoKind::Qua4]);
        assert_eq!(class, GeoClass::Tri);
        assert_eq!(kind, GeoKind::Tri6);
        assert_eq!(format!("{:?}", class), "Tri");
        assert_eq!(format!("{:?}", kind), "Tri6");
        assert_eq!(classes.contains(&GeoClass::Tri), true);
        assert_eq!(kinds.contains(&GeoKind::Tri3), true);
    }

    #[test]
    fn i32_to_fn_interp_works() {
        // todo
    }
}
<commit_msg>Impl VALUES for GeoKind and add tests<commit_after>use super::*;
use serde::{Deserialize, Serialize};

/// Defines the class of geometric shape
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub enum GeoClass {
    /// Lines (segments) class
    Lin,

    /// Triangles class
    Tri,

    /// Quadrilaterals class
    Qua,

    /// Tetrahedra class
    Tet,

    /// Hexahedra class
    Hex,
}

/// Defines the kind of geometric shape
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Deserialize, Serialize)]
pub enum GeoKind {
    /// Line (segment) with 2 nodes (linear functions)
    Lin2 = 1_002,

    /// Line (segment) with 3 nodes (quadratic functions)
    Lin3 = 1_003,

    /// Line (segment) with 4 nodes (cubic functions)
    Lin4 = 1_004,

    /// Line (segment) with 5 nodes (quartic functions)
    Lin5 = 1_005,

    /// Triangle with 3 nodes (linear edges)
    Tri3 = 2_003,

    /// Triangle with 6 nodes (quadratic edges)
    Tri6 = 2_006,

    /// Triangle with 10 nodes (cubic edges; interior node)
    Tri10 = 2_010,

    /// Triangle with 15 nodes (quartic edges; interior nodes)
    Tri15 = 2_015,

    /// Quadrilateral with 4 nodes (linear edges)
    Qua4 = 2_004,

    /// Quadrilateral with 8 nodes (quadratic edges)
    Qua8 = 2_008,

    /// Quadrilateral with 9 nodes (quadratic edges; interior node)
    Qua9 = 2_009,

    /// Quadrilateral with 12 nodes (cubic edges)
    Qua12 = 2_012,

    /// Quadrilateral with 16 nodes (cubic edges; interior nodes)
    Qua16 = 2_016,

    /// Quadrilateral with 17 nodes (quartic edges; interior node)
    Qua17 = 2_017,

    /// Tetrahedron with 4 nodes (linear faces)
    Tet4 = 3_004,

    /// Tetrahedron with 10 nodes (quadratic faces)
    Tet10 = 3_010,

    /// Hexahedron with 8 nodes (bilinear faces)
    Hex8 = 3_008,

    /// Hexahedron with 20 nodes (quadratic faces)
    Hex20 = 3_020,
}

impl GeoKind {
    /// Holds all enum values
    pub const VALUES: [Self; 18] = [
        Self::Lin2,
        Self::Lin3,
        Self::Lin4,
        Self::Lin5,
        Self::Tri3,
        Self::Tri6,
        Self::Tri10,
        Self::Tri15,
        Self::Qua4,
        Self::Qua8,
        Self::Qua9,
        Self::Qua12,
        Self::Qua16,
        Self::Qua17,
        Self::Tet4,
        Self::Tet10,
        Self::Hex8,
        Self::Hex20,
    ];
}

pub(crate) fn i32_to_fn_interp(kind: i32) -> FnInterp {
    match kind {
        // Lin
        1_002 => FnInterp(GeoKind::Lin2, Lin2::calc_interp),
        1_003 => FnInterp(GeoKind::Lin3, Lin3::calc_interp),
        1_004 => FnInterp(GeoKind::Lin4, Lin4::calc_interp),
        1_005 => FnInterp(GeoKind::Lin5, Lin5::calc_interp),
        // Tri
        2_003 => FnInterp(GeoKind::Tri3, Tri3::calc_interp),
        2_006 => FnInterp(GeoKind::Tri6, Tri6::calc_interp),
        2_010 => FnInterp(GeoKind::Tri10, Tri10::calc_interp),
        2_015 => FnInterp(GeoKind::Tri15, Tri15::calc_interp),
        // Qua
        2_004 => FnInterp(GeoKind::Qua4, Qua4::calc_interp),
        2_008 => FnInterp(GeoKind::Qua8, Qua8::calc_interp),
        2_009 => FnInterp(GeoKind::Qua9, Qua9::calc_interp),
        2_012 => FnInterp(GeoKind::Qua12, Qua12::calc_interp),
        2_016 => FnInterp(GeoKind::Qua16, Qua16::calc_interp),
        2_017 => FnInterp(GeoKind::Qua17, Qua17::calc_interp),
        // Tet
        3_004 => FnInterp(GeoKind::Tet4, Tet4::calc_interp),
        3_010 => FnInterp(GeoKind::Tet10, Tet10::calc_interp),
        // Hex
        3_008 => FnInterp(GeoKind::Hex8, Hex8::calc_interp),
        3_020 => FnInterp(GeoKind::Hex20, Hex20::calc_interp),
        _ => panic!("INTERNAL ERROR: cannot convert i32 to FnInterp"),
    }
}

pub(crate) fn i32_to_fn_deriv(kind: i32) -> FnDeriv {
    match kind {
        // Lin
        1_002 => FnDeriv(GeoKind::Lin2, Lin2::calc_deriv),
        1_003 => FnDeriv(GeoKind::Lin3, Lin3::calc_deriv),
        1_004 => FnDeriv(GeoKind::Lin4, Lin4::calc_deriv),
        1_005 => FnDeriv(GeoKind::Lin5, Lin5::calc_deriv),
        // Tri
        2_003 => FnDeriv(GeoKind::Tri3, Tri3::calc_deriv),
        2_006 => FnDeriv(GeoKind::Tri6, Tri6::calc_deriv),
        2_010 => FnDeriv(GeoKind::Tri10, Tri10::calc_deriv),
        2_015 => FnDeriv(GeoKind::Tri15, Tri15::calc_deriv),
        // Qua
        2_004 => FnDeriv(GeoKind::Qua4, Qua4::calc_deriv),
        2_008 => FnDeriv(GeoKind::Qua8, Qua8::calc_deriv),
        2_009 => FnDeriv(GeoKind::Qua9, Qua9::calc_deriv),
        2_012 => FnDeriv(GeoKind::Qua12, Qua12::calc_deriv),
        2_016 => FnDeriv(GeoKind::Qua16, Qua16::calc_deriv),
        2_017 => FnDeriv(GeoKind::Qua17, Qua17::calc_deriv),
        // Tet
        3_004 => FnDeriv(GeoKind::Tet4, Tet4::calc_deriv),
        3_010 => FnDeriv(GeoKind::Tet10, Tet10::calc_deriv),
        // Hex
        3_008 => FnDeriv(GeoKind::Hex8, Hex8::calc_deriv),
        3_020 => FnDeriv(GeoKind::Hex20, Hex20::calc_deriv),
        _ => panic!("INTERNAL ERROR: cannot convert i32 to FnDeriv"),
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::{i32_to_fn_deriv, i32_to_fn_interp};
    use crate::shapes::{GeoClass, GeoKind};
    use std::collections::HashSet;

    #[test]
    fn derive_works() {
        let class = GeoClass::Tri.clone();
        let kind = GeoKind::Tri6.clone();
        let classes = HashSet::from([GeoClass::Tri, GeoClass::Qua]);
        let kinds = HashSet::from([GeoKind::Tri3, GeoKind::Qua4]);
        assert_eq!(class, GeoClass::Tri);
        assert_eq!(kind, GeoKind::Tri6);
        assert_eq!(format!("{:?}", class), "Tri");
        assert_eq!(format!("{:?}", kind), "Tri6");
        assert_eq!(classes.contains(&GeoClass::Tri), true);
        assert_eq!(kinds.contains(&GeoKind::Tri3), true);
    }

    #[test]
    fn data_is_consistent() {
        for kind in GeoKind::VALUES {
            match kind {
                // Lin
                GeoKind::Lin2 => {
                    let k = kind as i32;
                    let nnode = k - 1000;
                    assert_eq!(nnode, 2);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Lin2);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Lin2);
                }
                GeoKind::Lin3 => {
                    let k = kind as i32;
                    let nnode = k - 1000;
                    assert_eq!(nnode, 3);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Lin3);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Lin3);
                }
                GeoKind::Lin4 => {
                    let k = kind as i32;
                    let nnode = k - 1000;
                    assert_eq!(nnode, 4);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Lin4);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Lin4);
                }
                GeoKind::Lin5 => {
                    let k = kind as i32;
                    let nnode = k - 1000;
                    assert_eq!(nnode, 5);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Lin5);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Lin5);
                }

                // Tri
                GeoKind::Tri3 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 3);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Tri3);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Tri3);
                }
                GeoKind::Tri6 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 6);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Tri6);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Tri6);
                }
                GeoKind::Tri10 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 10);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Tri10);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Tri10);
                }
                GeoKind::Tri15 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 15);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Tri15);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Tri15);
                }

                // Qua
                GeoKind::Qua4 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 4);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Qua4);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Qua4);
                }
                GeoKind::Qua8 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 8);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Qua8);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Qua8);
                }
                GeoKind::Qua9 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 9);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Qua9);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Qua9);
                }
                GeoKind::Qua12 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 12);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Qua12);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Qua12);
                }
                GeoKind::Qua16 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 16);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Qua16);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Qua16);
                }
                GeoKind::Qua17 => {
                    let k = kind as i32;
                    let nnode = k - 2000;
                    assert_eq!(nnode, 17);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Qua17);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Qua17);
                }

                // Tet
                GeoKind::Tet4 => {
                    let k = kind as i32;
                    let nnode = k - 3000;
                    assert_eq!(nnode, 4);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Tet4);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Tet4);
                }
                GeoKind::Tet10 => {
                    let k = kind as i32;
                    let nnode = k - 3000;
                    assert_eq!(nnode, 10);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Tet10);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Tet10);
                }

                // Hex
                GeoKind::Hex8 => {
                    let k = kind as i32;
                    let nnode = k - 3000;
                    assert_eq!(nnode, 8);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Hex8);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Hex8);
                }
                GeoKind::Hex20 => {
                    let k = kind as i32;
                    let nnode = k - 3000;
                    assert_eq!(nnode, 20);
                    assert_eq!(i32_to_fn_interp(k).0, GeoKind::Hex20);
                    assert_eq!(i32_to_fn_deriv(k).0, GeoKind::Hex20);
                }
            }
        }
    }
}
<|endoftext|>