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

macro_rules! define_set {
    ($name:ident, $builder_mod:ident, $text_ty:ty, $as_bytes:expr,
     $(#[$doc_regexset_example:meta])* ) => {
        pub mod $name {
            use std::fmt;
            use std::iter;
            use std::slice;
            use std::vec;

            use error::Error;
            use exec::Exec;
            use re_builder::$builder_mod::RegexSetBuilder;
            use re_trait::RegularExpression;

/// Match multiple (possibly overlapping) regular expressions in a single scan.
///
/// A regex set corresponds to the union of two or more regular expressions.
/// That is, a regex set will match text where at least one of its
/// constituent regular expressions matches. A regex set as its formulated here
/// provides a touch more power: it will also report *which* regular
/// expressions in the set match. Indeed, this is the key difference between
/// regex sets and a single `Regex` with many alternates, since only one
/// alternate can match at a time.
///
/// For example, consider regular expressions to match email addresses and
/// domains: `[a-z]+@[a-z]+\.(com|org|net)` and `[a-z]+\.(com|org|net)`. If a
/// regex set is constructed from those regexes, then searching the text
/// `foo@example.com` will report both regexes as matching. Of course, one
/// could accomplish this by compiling each regex on its own and doing two
/// searches over the text. The key advantage of using a regex set is that it
/// will report the matching regexes using a *single pass through the text*.
/// If one has hundreds or thousands of regexes to match repeatedly (like a URL
/// router for a complex web application or a user agent matcher), then a regex
/// set can realize huge performance gains.
///
/// # Example
///
/// This shows how the above two regexes (for matching email addresses and
/// domains) might work:
///
$(#[$doc_regexset_example])*
///
/// Note that it would be possible to adapt the above example to using `Regex`
/// with an expression like:
///
/// ```ignore
/// (?P<email>[a-z]+@(?P<email_domain>[a-z]+[.](com|org|net)))|(?P<domain>[a-z]+[.](com|org|net))
/// ```
///
/// After a match, one could then inspect the capture groups to figure out
/// which alternates matched. The problem is that it is hard to make this
/// approach scale when there are many regexes since the overlap between each
/// alternate isn't always obvious to reason about.
///
/// # Limitations
///
/// Regex sets are limited to answering the following two questions:
///
/// 1. Does any regex in the set match?
/// 2. If so, which regexes in the set match?
///
/// As with the main `Regex` type, it is cheaper to ask (1) instead of (2)
/// since the matching engines can stop after the first match is found.
///
/// Other features like finding the location of successive matches or their
/// sub-captures aren't supported. If you need this functionality, the
/// recommended approach is to compile each regex in the set independently and
/// selectively match them based on which regexes in the set matched.
///
/// # Performance
///
/// A `RegexSet` has the same performance characteristics as `Regex`. Namely,
/// search takes `O(mn)` time, where `m` is proportional to the size of the
/// regex set and `n` is proportional to the length of the search text.
#[derive(Clone)]
pub struct RegexSet(Exec);

impl RegexSet {
    /// Create a new regex set with the given regular expressions.
    ///
    /// This takes an iterator of `S`, where `S` is something that can produce
    /// a `&str`. If any of the strings in the iterator are not valid regular
    /// expressions, then an error is returned.
    ///
    /// # Example
    ///
    /// Create a new regex set from an iterator of strings:
    ///
    /// ```rust
    /// # use regex::RegexSet;
    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
    /// assert!(set.is_match("foo"));
    /// ```
    pub fn new<I, S>(exprs: I) -> Result<RegexSet, Error>
            where S: AsRef<str>, I: IntoIterator<Item=S> {
        RegexSetBuilder::new(exprs).build()
    }

    /// Returns true if and only if one of the regexes in this set matches
    /// the text given.
    ///
    /// This method should be preferred if you only need to test whether any
    /// of the regexes in the set should match, but don't care about *which*
    /// regexes matched. This is because the underlying matching engine will
    /// quit immediately after seeing the first match instead of continuing to
    /// find all matches.
    ///
    /// Note that as with searches using `Regex`, the expression is unanchored
    /// by default. That is, if the regex does not start with `^` or `\A`, or
    /// end with `$` or `\z`, then it is permitted to match anywhere in the
    /// text.
    ///
    /// # Example
    ///
    /// Tests whether a set matches some text:
    ///
    /// ```rust
    /// # use regex::RegexSet;
    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
    /// assert!(set.is_match("foo"));
    /// assert!(!set.is_match("☃"));
    /// ```
    pub fn is_match(&self, text: $text_ty) -> bool {
        self.is_match_at(text, 0)
    }

    /// Returns the same as is_match, but starts the search at the given
    /// offset.
    ///
    /// The significance of the starting point is that it takes the surrounding
    /// context into consideration. For example, the `\A` anchor can only
    /// match when `start == 0`.
    #[doc(hidden)]
    pub fn is_match_at(&self, text: $text_ty, start: usize) -> bool {
        self.0.searcher().is_match_at($as_bytes(text), start)
    }

    /// Returns the set of regular expressions that match in the given text.
    ///
    /// The set returned contains the index of each regular expression that
    /// matches in the given text. The index is in correspondence with the
    /// order of regular expressions given to `RegexSet`'s constructor.
    ///
    /// The set can also be used to iterate over the matched indices.
    ///
    /// Note that as with searches using `Regex`, the expression is unanchored
    /// by default. That is, if the regex does not start with `^` or `\A`, or
    /// end with `$` or `\z`, then it is permitted to match anywhere in the
    /// text.
    ///
    /// # Example
    ///
    /// Tests which regular expressions match the given text:
    ///
    /// ```rust
    /// # use regex::RegexSet;
    /// let set = RegexSet::new(&[
    ///     r"\w+",
    ///     r"\d+",
    ///     r"\pL+",
    ///     r"foo",
    ///     r"bar",
    ///     r"barfoo",
    ///     r"foobar",
    /// ]).unwrap();
    /// let matches: Vec<_> = set.matches("foobar").into_iter().collect();
    /// assert_eq!(matches, vec![0, 2, 3, 4, 6]);
    ///
    /// // You can also test whether a particular regex matched:
    /// let matches = set.matches("foobar");
    /// assert!(!matches.matched(5));
    /// assert!(matches.matched(6));
    /// ```
    pub fn matches(&self, text: $text_ty) -> SetMatches {
        let mut matches = vec![false; self.0.regex_strings().len()];
        let any = self.read_matches_at(&mut matches, text, 0);
        SetMatches {
            matched_any: any,
            matches: matches,
        }
    }

    /// Returns the same as matches, but starts the search at the given
    /// offset and stores the matches into the slice given.
    ///
    /// The significance of the starting point is that it takes the surrounding
    /// context into consideration. For example, the `\A` anchor can only
    /// match when `start == 0`.
    ///
    /// `matches` must have a length that is at least the number of regexes
    /// in this set.
    ///
    /// This method returns true if and only if at least one member of
    /// `matches` is true after executing the set against `text`.
    #[doc(hidden)]
    pub fn read_matches_at(
        &self,
        matches: &mut [bool],
        text: $text_ty,
        start: usize,
    ) -> bool {
        self.0.searcher().many_matches_at(matches, $as_bytes(text), start)
    }

    /// Returns the total number of regular expressions in this set.
    pub fn len(&self) -> usize {
        self.0.regex_strings().len()
    }
}

/// A set of matches returned by a regex set.
#[derive(Clone, Debug)]
pub struct SetMatches {
    matched_any: bool,
    matches: Vec<bool>,
}

impl SetMatches {
    /// Whether this set contains any matches.
    pub fn matched_any(&self) -> bool {
        self.matched_any
    }

    /// Whether the regex at the given index matched.
    ///
    /// The index for a regex is determined by its insertion order upon the
    /// initial construction of a `RegexSet`, starting at `0`.
    ///
    /// # Panics
    ///
    /// If `regex_index` is greater than or equal to `self.len()`.
    pub fn matched(&self, regex_index: usize) -> bool {
        self.matches[regex_index]
    }

    /// The total number of regexes in the set that created these matches.
    pub fn len(&self) -> usize {
        self.matches.len()
    }

    /// Returns an iterator over indexes in the regex that matched.
    pub fn iter(&self) -> SetMatchesIter {
        SetMatchesIter((&*self.matches).into_iter().enumerate())
    }
}

impl IntoIterator for SetMatches {
    type IntoIter = SetMatchesIntoIter;
    type Item = usize;

    fn into_iter(self) -> Self::IntoIter {
        SetMatchesIntoIter(self.matches.into_iter().enumerate())
    }
}

impl<'a> IntoIterator for &'a SetMatches {
    type IntoIter = SetMatchesIter<'a>;
    type Item = usize;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

/// An owned iterator over the set of matches from a regex set.
pub struct SetMatchesIntoIter(iter::Enumerate<vec::IntoIter<bool>>);

impl Iterator for SetMatchesIntoIter {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        loop {
            match self.0.next() {
                None => return None,
                Some((_, false)) => {}
                Some((i, true)) => return Some(i),
            }
        }
    }
}

impl DoubleEndedIterator for SetMatchesIntoIter {
    fn next_back(&mut self) -> Option<usize> {
        loop {
            match self.0.next_back() {
                None => return None,
                Some((_, false)) => {}
                Some((i, true)) => return Some(i),
            }
        }
    }
}

/// A borrowed iterator over the set of matches from a regex set.
///
/// The lifetime `'a` refers to the lifetime of a `SetMatches` value.
#[derive(Clone)]
pub struct SetMatchesIter<'a>(iter::Enumerate<slice::Iter<'a, bool>>);

impl<'a> Iterator for SetMatchesIter<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        loop {
            match self.0.next() {
                None => return None,
                Some((_, &false)) => {}
                Some((i, &true)) => return Some(i),
            }
        }
    }
}

impl<'a> DoubleEndedIterator for SetMatchesIter<'a> {
    fn next_back(&mut self) -> Option<usize> {
        loop {
            match self.0.next_back() {
                None => return None,
                Some((_, &false)) => {}
                Some((i, &true)) => return Some(i),
            }
        }
    }
}

#[doc(hidden)]
impl From<Exec> for RegexSet {
    fn from(exec: Exec) -> Self {
        RegexSet(exec)
    }
}

impl fmt::Debug for RegexSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RegexSet({:?})", self.0.regex_strings())
    }
}

#[allow(dead_code)] fn as_bytes_str(text: &str) -> &[u8] { text.as_bytes() }
#[allow(dead_code)] fn as_bytes_bytes(text: &[u8]) -> &[u8] { text }
        }
    }
}

define_set! {
    unicode,
    set_unicode,
    &str,
    as_bytes_str,
/// ```rust
/// # use regex::RegexSet;
/// let set = RegexSet::new(&[
///     r"[a-z]+@[a-z]+\.(com|org|net)",
///     r"[a-z]+\.(com|org|net)",
/// ]).unwrap();
///
/// // Ask whether any regexes in the set match.
/// assert!(set.is_match("foo@example.com"));
///
/// // Identify which regexes in the set match.
/// let matches: Vec<_> = set.matches("foo@example.com").into_iter().collect();
/// assert_eq!(vec![0, 1], matches);
///
/// // Try again, but with text that only matches one of the regexes.
/// let matches: Vec<_> = set.matches("example.com").into_iter().collect();
/// assert_eq!(vec![1], matches);
///
/// // Try again, but with text that doesn't match any regex in the set.
/// let matches: Vec<_> = set.matches("example").into_iter().collect();
/// assert!(matches.is_empty());
/// ```
}

define_set! {
    bytes,
    set_bytes,
    &[u8],
    as_bytes_bytes,
/// ```rust
/// # use regex::bytes::RegexSet;
/// let set = RegexSet::new(&[
///     r"[a-z]+@[a-z]+\.(com|org|net)",
///     r"[a-z]+\.(com|org|net)",
/// ]).unwrap();
///
/// // Ask whether any regexes in the set match.
/// assert!(set.is_match(b"foo@example.com"));
///
/// // Identify which regexes in the set match.
/// let matches: Vec<_> = set.matches(b"foo@example.com").into_iter().collect();
/// assert_eq!(vec![0, 1], matches);
///
/// // Try again, but with text that only matches one of the regexes.
/// let matches: Vec<_> = set.matches(b"example.com").into_iter().collect();
/// assert_eq!(vec![1], matches);
///
/// // Try again, but with text that doesn't match any regex in the set.
/// let matches: Vec<_> = set.matches(b"example").into_iter().collect();
/// assert!(matches.is_empty());
/// ```
}
<commit_msg>doc: clarify order of match iterator<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

macro_rules! define_set {
    ($name:ident, $builder_mod:ident, $text_ty:ty, $as_bytes:expr,
     $(#[$doc_regexset_example:meta])* ) => {
        pub mod $name {
            use std::fmt;
            use std::iter;
            use std::slice;
            use std::vec;

            use error::Error;
            use exec::Exec;
            use re_builder::$builder_mod::RegexSetBuilder;
            use re_trait::RegularExpression;

/// Match multiple (possibly overlapping) regular expressions in a single scan.
///
/// A regex set corresponds to the union of two or more regular expressions.
/// That is, a regex set will match text where at least one of its
/// constituent regular expressions matches. A regex set as its formulated here
/// provides a touch more power: it will also report *which* regular
/// expressions in the set match. Indeed, this is the key difference between
/// regex sets and a single `Regex` with many alternates, since only one
/// alternate can match at a time.
///
/// For example, consider regular expressions to match email addresses and
/// domains: `[a-z]+@[a-z]+\.(com|org|net)` and `[a-z]+\.(com|org|net)`. If a
/// regex set is constructed from those regexes, then searching the text
/// `foo@example.com` will report both regexes as matching. Of course, one
/// could accomplish this by compiling each regex on its own and doing two
/// searches over the text. The key advantage of using a regex set is that it
/// will report the matching regexes using a *single pass through the text*.
/// If one has hundreds or thousands of regexes to match repeatedly (like a URL
/// router for a complex web application or a user agent matcher), then a regex
/// set can realize huge performance gains.
///
/// # Example
///
/// This shows how the above two regexes (for matching email addresses and
/// domains) might work:
///
$(#[$doc_regexset_example])*
///
/// Note that it would be possible to adapt the above example to using `Regex`
/// with an expression like:
///
/// ```ignore
/// (?P<email>[a-z]+@(?P<email_domain>[a-z]+[.](com|org|net)))|(?P<domain>[a-z]+[.](com|org|net))
/// ```
///
/// After a match, one could then inspect the capture groups to figure out
/// which alternates matched. The problem is that it is hard to make this
/// approach scale when there are many regexes since the overlap between each
/// alternate isn't always obvious to reason about.
///
/// # Limitations
///
/// Regex sets are limited to answering the following two questions:
///
/// 1. Does any regex in the set match?
/// 2. If so, which regexes in the set match?
///
/// As with the main `Regex` type, it is cheaper to ask (1) instead of (2)
/// since the matching engines can stop after the first match is found.
///
/// Other features like finding the location of successive matches or their
/// sub-captures aren't supported. If you need this functionality, the
/// recommended approach is to compile each regex in the set independently and
/// selectively match them based on which regexes in the set matched.
///
/// # Performance
///
/// A `RegexSet` has the same performance characteristics as `Regex`. Namely,
/// search takes `O(mn)` time, where `m` is proportional to the size of the
/// regex set and `n` is proportional to the length of the search text.
#[derive(Clone)]
pub struct RegexSet(Exec);

impl RegexSet {
    /// Create a new regex set with the given regular expressions.
    ///
    /// This takes an iterator of `S`, where `S` is something that can produce
    /// a `&str`. If any of the strings in the iterator are not valid regular
    /// expressions, then an error is returned.
    ///
    /// # Example
    ///
    /// Create a new regex set from an iterator of strings:
    ///
    /// ```rust
    /// # use regex::RegexSet;
    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
    /// assert!(set.is_match("foo"));
    /// ```
    pub fn new<I, S>(exprs: I) -> Result<RegexSet, Error>
            where S: AsRef<str>, I: IntoIterator<Item=S> {
        RegexSetBuilder::new(exprs).build()
    }

    /// Returns true if and only if one of the regexes in this set matches
    /// the text given.
    ///
    /// This method should be preferred if you only need to test whether any
    /// of the regexes in the set should match, but don't care about *which*
    /// regexes matched. This is because the underlying matching engine will
    /// quit immediately after seeing the first match instead of continuing to
    /// find all matches.
    ///
    /// Note that as with searches using `Regex`, the expression is unanchored
    /// by default. That is, if the regex does not start with `^` or `\A`, or
    /// end with `$` or `\z`, then it is permitted to match anywhere in the
    /// text.
    ///
    /// # Example
    ///
    /// Tests whether a set matches some text:
    ///
    /// ```rust
    /// # use regex::RegexSet;
    /// let set = RegexSet::new(&[r"\w+", r"\d+"]).unwrap();
    /// assert!(set.is_match("foo"));
    /// assert!(!set.is_match("☃"));
    /// ```
    pub fn is_match(&self, text: $text_ty) -> bool {
        self.is_match_at(text, 0)
    }

    /// Returns the same as is_match, but starts the search at the given
    /// offset.
    ///
    /// The significance of the starting point is that it takes the surrounding
    /// context into consideration. For example, the `\A` anchor can only
    /// match when `start == 0`.
    #[doc(hidden)]
    pub fn is_match_at(&self, text: $text_ty, start: usize) -> bool {
        self.0.searcher().is_match_at($as_bytes(text), start)
    }

    /// Returns the set of regular expressions that match in the given text.
    ///
    /// The set returned contains the index of each regular expression that
    /// matches in the given text. The index is in correspondence with the
    /// order of regular expressions given to `RegexSet`'s constructor.
    ///
    /// The set can also be used to iterate over the matched indices.
    ///
    /// Note that as with searches using `Regex`, the expression is unanchored
    /// by default. That is, if the regex does not start with `^` or `\A`, or
    /// end with `$` or `\z`, then it is permitted to match anywhere in the
    /// text.
    ///
    /// # Example
    ///
    /// Tests which regular expressions match the given text:
    ///
    /// ```rust
    /// # use regex::RegexSet;
    /// let set = RegexSet::new(&[
    ///     r"\w+",
    ///     r"\d+",
    ///     r"\pL+",
    ///     r"foo",
    ///     r"bar",
    ///     r"barfoo",
    ///     r"foobar",
    /// ]).unwrap();
    /// let matches: Vec<_> = set.matches("foobar").into_iter().collect();
    /// assert_eq!(matches, vec![0, 2, 3, 4, 6]);
    ///
    /// // You can also test whether a particular regex matched:
    /// let matches = set.matches("foobar");
    /// assert!(!matches.matched(5));
    /// assert!(matches.matched(6));
    /// ```
    pub fn matches(&self, text: $text_ty) -> SetMatches {
        let mut matches = vec![false; self.0.regex_strings().len()];
        let any = self.read_matches_at(&mut matches, text, 0);
        SetMatches {
            matched_any: any,
            matches: matches,
        }
    }

    /// Returns the same as matches, but starts the search at the given
    /// offset and stores the matches into the slice given.
    ///
    /// The significance of the starting point is that it takes the surrounding
    /// context into consideration. For example, the `\A` anchor can only
    /// match when `start == 0`.
    ///
    /// `matches` must have a length that is at least the number of regexes
    /// in this set.
    ///
    /// This method returns true if and only if at least one member of
    /// `matches` is true after executing the set against `text`.
    #[doc(hidden)]
    pub fn read_matches_at(
        &self,
        matches: &mut [bool],
        text: $text_ty,
        start: usize,
    ) -> bool {
        self.0.searcher().many_matches_at(matches, $as_bytes(text), start)
    }

    /// Returns the total number of regular expressions in this set.
    pub fn len(&self) -> usize {
        self.0.regex_strings().len()
    }
}

/// A set of matches returned by a regex set.
#[derive(Clone, Debug)]
pub struct SetMatches {
    matched_any: bool,
    matches: Vec<bool>,
}

impl SetMatches {
    /// Whether this set contains any matches.
    pub fn matched_any(&self) -> bool {
        self.matched_any
    }

    /// Whether the regex at the given index matched.
    ///
    /// The index for a regex is determined by its insertion order upon the
    /// initial construction of a `RegexSet`, starting at `0`.
    ///
    /// # Panics
    ///
    /// If `regex_index` is greater than or equal to `self.len()`.
    pub fn matched(&self, regex_index: usize) -> bool {
        self.matches[regex_index]
    }

    /// The total number of regexes in the set that created these matches.
    pub fn len(&self) -> usize {
        self.matches.len()
    }

    /// Returns an iterator over indexes in the regex that matched.
    ///
    /// This will always produces matches in ascending order of index, where
    /// the index corresponds to the index of the regex that matched with
    /// respect to its position when initially building the set.
    pub fn iter(&self) -> SetMatchesIter {
        SetMatchesIter((&*self.matches).into_iter().enumerate())
    }
}

impl IntoIterator for SetMatches {
    type IntoIter = SetMatchesIntoIter;
    type Item = usize;

    fn into_iter(self) -> Self::IntoIter {
        SetMatchesIntoIter(self.matches.into_iter().enumerate())
    }
}

impl<'a> IntoIterator for &'a SetMatches {
    type IntoIter = SetMatchesIter<'a>;
    type Item = usize;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

/// An owned iterator over the set of matches from a regex set.
///
/// This will always produces matches in ascending order of index, where the
/// index corresponds to the index of the regex that matched with respect to
/// its position when initially building the set.
pub struct SetMatchesIntoIter(iter::Enumerate<vec::IntoIter<bool>>);

impl Iterator for SetMatchesIntoIter {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        loop {
            match self.0.next() {
                None => return None,
                Some((_, false)) => {}
                Some((i, true)) => return Some(i),
            }
        }
    }
}

impl DoubleEndedIterator for SetMatchesIntoIter {
    fn next_back(&mut self) -> Option<usize> {
        loop {
            match self.0.next_back() {
                None => return None,
                Some((_, false)) => {}
                Some((i, true)) => return Some(i),
            }
        }
    }
}

/// A borrowed iterator over the set of matches from a regex set.
///
/// The lifetime `'a` refers to the lifetime of a `SetMatches` value.
///
/// This will always produces matches in ascending order of index, where the
/// index corresponds to the index of the regex that matched with respect to
/// its position when initially building the set.
#[derive(Clone)]
pub struct SetMatchesIter<'a>(iter::Enumerate<slice::Iter<'a, bool>>);

impl<'a> Iterator for SetMatchesIter<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        loop {
            match self.0.next() {
                None => return None,
                Some((_, &false)) => {}
                Some((i, &true)) => return Some(i),
            }
        }
    }
}

impl<'a> DoubleEndedIterator for SetMatchesIter<'a> {
    fn next_back(&mut self) -> Option<usize> {
        loop {
            match self.0.next_back() {
                None => return None,
                Some((_, &false)) => {}
                Some((i, &true)) => return Some(i),
            }
        }
    }
}

#[doc(hidden)]
impl From<Exec> for RegexSet {
    fn from(exec: Exec) -> Self {
        RegexSet(exec)
    }
}

impl fmt::Debug for RegexSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RegexSet({:?})", self.0.regex_strings())
    }
}

#[allow(dead_code)] fn as_bytes_str(text: &str) -> &[u8] { text.as_bytes() }
#[allow(dead_code)] fn as_bytes_bytes(text: &[u8]) -> &[u8] { text }
        }
    }
}

define_set! {
    unicode,
    set_unicode,
    &str,
    as_bytes_str,
/// ```rust
/// # use regex::RegexSet;
/// let set = RegexSet::new(&[
///     r"[a-z]+@[a-z]+\.(com|org|net)",
///     r"[a-z]+\.(com|org|net)",
/// ]).unwrap();
///
/// // Ask whether any regexes in the set match.
/// assert!(set.is_match("foo@example.com"));
///
/// // Identify which regexes in the set match.
/// let matches: Vec<_> = set.matches("foo@example.com").into_iter().collect();
/// assert_eq!(vec![0, 1], matches);
///
/// // Try again, but with text that only matches one of the regexes.
/// let matches: Vec<_> = set.matches("example.com").into_iter().collect();
/// assert_eq!(vec![1], matches);
///
/// // Try again, but with text that doesn't match any regex in the set.
/// let matches: Vec<_> = set.matches("example").into_iter().collect();
/// assert!(matches.is_empty());
/// ```
}

define_set! {
    bytes,
    set_bytes,
    &[u8],
    as_bytes_bytes,
/// ```rust
/// # use regex::bytes::RegexSet;
/// let set = RegexSet::new(&[
///     r"[a-z]+@[a-z]+\.(com|org|net)",
///     r"[a-z]+\.(com|org|net)",
/// ]).unwrap();
///
/// // Ask whether any regexes in the set match.
/// assert!(set.is_match(b"foo@example.com"));
///
/// // Identify which regexes in the set match.
/// let matches: Vec<_> = set.matches(b"foo@example.com").into_iter().collect();
/// assert_eq!(vec![0, 1], matches);
///
/// // Try again, but with text that only matches one of the regexes.
/// let matches: Vec<_> = set.matches(b"example.com").into_iter().collect();
/// assert_eq!(vec![1], matches);
///
/// // Try again, but with text that doesn't match any regex in the set.
/// let matches: Vec<_> = set.matches(b"example").into_iter().collect();
/// assert!(matches.is_empty());
/// ```
}
<|endoftext|>


<commit_before>#![warn(clippy::all, rust_2018_idioms)]

use chrono::prelude::Utc;
use hmac::{Hmac, Mac, NewMac};
use reqwest::{
    blocking::{Body, Client, Response},
    header,
};
use sha1::Sha1;

pub use reqwest::Error;

#[derive(Clone, Debug)]
pub struct Bucket {
    name: String,
    region: Option<String>,
    access_key: String,
    secret_key: String,
    proto: String,
}

impl Bucket {
    pub fn new(
        name: String,
        region: Option<String>,
        access_key: String,
        secret_key: String,
        proto: &str,
    ) -> Bucket {
        Bucket {
            name,
            region,
            access_key,
            secret_key,
            proto: proto.to_string(),
        }
    }

    pub fn put<R: std::io::Read + Send + 'static>(
        &self,
        client: &Client,
        path: &str,
        content: R,
        content_length: u64,
        content_type: &str,
        extra_headers: header::HeaderMap,
    ) -> Result<Response, Error> {
        let path = path.strip_prefix("/").unwrap_or(path);
        let date = Utc::now().to_rfc2822();
        let auth = self.auth("PUT", &date, path, "", content_type);
        let url = self.url(path);

        client
            .put(&url)
            .header(header::AUTHORIZATION, auth)
            .header(header::CONTENT_TYPE, content_type)
            .header(header::DATE, date)
            .header(header::USER_AGENT, "crates.io (https://crates.io)")
            .headers(extra_headers)
            .body(Body::sized(content, content_length))
            .send()?
            .error_for_status()
            .map_err(Into::into)
    }

    pub fn delete(&self, client: &Client, path: &str) -> Result<Response, Error> {
        let path = path.strip_prefix("/").unwrap_or(path);
        let date = Utc::now().to_rfc2822();
        let auth = self.auth("DELETE", &date, path, "", "");
        let url = self.url(path);

        client
            .delete(&url)
            .header(header::DATE, date)
            .header(header::AUTHORIZATION, auth)
            .send()?
            .error_for_status()
            .map_err(Into::into)
    }

    pub fn host(&self) -> String {
        format!(
            "{}.s3{}.amazonaws.com",
            self.name,
            match self.region {
                Some(ref r) if !r.is_empty() => format!("-{}", r),
                Some(_) => String::new(),
                None => String::new(),
            }
        )
    }

    fn auth(&self, verb: &str, date: &str, path: &str, md5: &str, content_type: &str) -> String {
        let string = format!(
            "{verb}\n{md5}\n{ty}\n{date}\n{headers}{resource}",
            verb = verb,
            md5 = md5,
            ty = content_type,
            date = date,
            headers = "",
            resource = format!("/{}/{}", self.name, path)
        );
        let signature = {
            let key = self.secret_key.as_bytes();
            let mut h = Hmac::<Sha1>::new_varkey(key).expect("HMAC can take key of any size");
            h.update(string.as_bytes());
            let res = h.finalize().into_bytes();
            base64::encode(&res)
        };
        format!("AWS {}:{}", self.access_key, signature)
    }

    fn url(&self, path: &str) -> String {
        format!("{}://{}/{}", self.proto, self.host(), path)
    }
}
<commit_msg>Auto merge of #3495 - Turbo87:s3-timeout, r=jtgeibel<commit_after>#![warn(clippy::all, rust_2018_idioms)]

use chrono::prelude::Utc;
use hmac::{Hmac, Mac, NewMac};
use reqwest::{
    blocking::{Body, Client, Response},
    header,
};
use sha1::Sha1;
use std::time::Duration;

pub use reqwest::Error;

#[derive(Clone, Debug)]
pub struct Bucket {
    name: String,
    region: Option<String>,
    access_key: String,
    secret_key: String,
    proto: String,
}

impl Bucket {
    pub fn new(
        name: String,
        region: Option<String>,
        access_key: String,
        secret_key: String,
        proto: &str,
    ) -> Bucket {
        Bucket {
            name,
            region,
            access_key,
            secret_key,
            proto: proto.to_string(),
        }
    }

    pub fn put<R: std::io::Read + Send + 'static>(
        &self,
        client: &Client,
        path: &str,
        content: R,
        content_length: u64,
        content_type: &str,
        extra_headers: header::HeaderMap,
    ) -> Result<Response, Error> {
        let path = path.strip_prefix("/").unwrap_or(path);
        let date = Utc::now().to_rfc2822();
        let auth = self.auth("PUT", &date, path, "", content_type);
        let url = self.url(path);

        client
            .put(&url)
            .header(header::AUTHORIZATION, auth)
            .header(header::CONTENT_TYPE, content_type)
            .header(header::DATE, date)
            .header(header::USER_AGENT, "crates.io (https://crates.io)")
            .headers(extra_headers)
            .body(Body::sized(content, content_length))
            .timeout(Duration::from_secs(60))
            .send()?
            .error_for_status()
            .map_err(Into::into)
    }

    pub fn delete(&self, client: &Client, path: &str) -> Result<Response, Error> {
        let path = path.strip_prefix("/").unwrap_or(path);
        let date = Utc::now().to_rfc2822();
        let auth = self.auth("DELETE", &date, path, "", "");
        let url = self.url(path);

        client
            .delete(&url)
            .header(header::DATE, date)
            .header(header::AUTHORIZATION, auth)
            .send()?
            .error_for_status()
            .map_err(Into::into)
    }

    pub fn host(&self) -> String {
        format!(
            "{}.s3{}.amazonaws.com",
            self.name,
            match self.region {
                Some(ref r) if !r.is_empty() => format!("-{}", r),
                Some(_) => String::new(),
                None => String::new(),
            }
        )
    }

    fn auth(&self, verb: &str, date: &str, path: &str, md5: &str, content_type: &str) -> String {
        let string = format!(
            "{verb}\n{md5}\n{ty}\n{date}\n{headers}{resource}",
            verb = verb,
            md5 = md5,
            ty = content_type,
            date = date,
            headers = "",
            resource = format!("/{}/{}", self.name, path)
        );
        let signature = {
            let key = self.secret_key.as_bytes();
            let mut h = Hmac::<Sha1>::new_varkey(key).expect("HMAC can take key of any size");
            h.update(string.as_bytes());
            let res = h.finalize().into_bytes();
            base64::encode(&res)
        };
        format!("AWS {}:{}", self.access_key, signature)
    }

    fn url(&self, path: &str) -> String {
        format!("{}://{}/{}", self.proto, self.host(), path)
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate libc;
extern crate num;

use self::num::complex::Complex;
use self::libc::{
    c_double,
    c_float,
    c_int,
    c_void,
};

pub trait Scalar<T, S> {
    fn as_const(self) -> T;
    fn as_mut(self) -> S;
}

macro_rules! scalar_impl(
    ($t: ty, $c_type: ty) => (
        impl<'a> Scalar<*const $t, *mut $t> for &'a $t {
            #[inline]
            fn as_const(self) -> *const $t {
                self as *const $c_type
            }

            #[inline]
            fn as_mut(self) -> *mut $t {
                &self as *const _ as *mut $c_type
            }
        }

        impl<'a> Scalar<*const c_void, *mut c_void> for &'a Complex<$t> {
            #[inline]
            fn as_const(self) -> *const c_void {
                self as *const _ as *const c_void
            }

            #[inline]
            fn as_mut(self) -> *mut c_void {
                self as *const _ as *mut c_void
            }
        }
    );
)

scalar_impl!(i32, c_int)
scalar_impl!(f32, c_float)
scalar_impl!(f64, c_double)
<commit_msg>Add char as scalar<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate libc;
extern crate num;

use self::num::complex::Complex;
use self::libc::{
    c_char,
    c_double,
    c_float,
    c_int,
    c_void,
};

pub trait Scalar<T, S> {
    fn as_const(self) -> T;
    fn as_mut(self) -> S;
}

macro_rules! scalar_impl(
    ($t: ty, $c_type: ty) => (
        impl<'a> Scalar<*const $t, *mut $t> for &'a $t {
            #[inline]
            fn as_const(self) -> *const $t {
                self as *const $c_type
            }

            #[inline]
            fn as_mut(self) -> *mut $t {
                &self as *const _ as *mut $c_type
            }
        }

        impl<'a> Scalar<*const c_void, *mut c_void> for &'a Complex<$t> {
            #[inline]
            fn as_const(self) -> *const c_void {
                self as *const _ as *const c_void
            }

            #[inline]
            fn as_mut(self) -> *mut c_void {
                self as *const _ as *mut c_void
            }
        }
    );
)

scalar_impl!(i8, c_char)
scalar_impl!(i32, c_int)
scalar_impl!(f32, c_float)
scalar_impl!(f64, c_double)
<|endoftext|>


<commit_before>use gl;
use gl::types::*;
use gl_context::GLContext;
use std::collections::HashMap;
use std::ptr;
use std::str;

pub struct ProgramHandle<'a> {
  pub gl_id: GLuint,
}

impl<'a> ProgramHandle<'a> {
  pub fn new<'b: 'a>(_gl: &'b GLContext) -> ProgramHandle<'a> {
    let gl_id = unsafe {
      gl::CreateProgram()
    };

    ProgramHandle {
      gl_id: gl_id,
    }
  }
}

#[unsafe_destructor]
impl<'a> Drop for ProgramHandle<'a> {
  fn drop(&mut self) {
    unsafe {
      gl::DeleteProgram(self.gl_id);
    }
  }
}

pub struct ShaderHandle<'a> {
  pub gl_id: GLuint,
}

impl<'a> ShaderHandle<'a> {
  pub fn compile_from<'b: 'a>(
    _gl: &'b GLContext,
    shader_source: String,
    typ: GLenum
  ) -> ShaderHandle<'a> {
    let gl_id = unsafe {
      gl::CreateShader(typ)
    };
    // Attempt to compile the shader
    shader_source.with_c_str(|ptr| unsafe { gl::ShaderSource(gl_id, 1, &ptr, ptr::null()) });
    unsafe {
      gl::CompileShader(gl_id);
    }

    // Get the compile status
    let mut status = gl::FALSE as GLint;
    unsafe {
      gl::GetShaderiv(gl_id, gl::COMPILE_STATUS, &mut status);
    }

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      unsafe {
        gl::GetShaderiv(gl_id, gl::INFO_LOG_LENGTH, &mut len);
      }
      let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
      unsafe {
        gl::GetShaderInfoLog(gl_id, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
      }
      panic!("error compiling 0x{:x} shader: {}", typ, str::from_utf8(buf.as_slice()).expect("ShaderInfoLog not valid utf8"));
    }

    ShaderHandle {
      gl_id: gl_id,
    }
  }
}

#[unsafe_destructor]
impl<'a> Drop for ShaderHandle<'a> {
  fn drop(&mut self) {
    unsafe {
      gl::DeleteShader(self.gl_id);
    }
  }
}

pub struct Shader<'a> {
  pub handle: ProgramHandle<'a>,
  pub components: Vec<ShaderHandle<'a>>,
  pub uniforms: HashMap<String, GLint>,
}

impl<'a> Shader<'a> {
  pub fn new<'b: 'a, T: Iterator<(String, GLenum)>>(
    gl: &'b GLContext,
    shader_components: T,
  ) -> Shader<'a> {
    let mut shader_components = shader_components;
    let handle = ProgramHandle::new(gl);

    let mut components = Vec::new();
    for (content, component) in shader_components {
      let s = ShaderHandle::compile_from(gl, content, component);
      unsafe { gl::AttachShader(handle.gl_id, s.gl_id) };
      components.push(s);
    }

    unsafe {
      gl::LinkProgram(handle.gl_id);
    }

    // Get the link status
    let mut status = gl::FALSE as GLint;
    unsafe {
      gl::GetProgramiv(handle.gl_id, gl::LINK_STATUS, &mut status);
    }

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len: GLint = 0;
      unsafe {
        gl::GetProgramiv(handle.gl_id, gl::INFO_LOG_LENGTH, &mut len);
      }
      let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
      unsafe {
        gl::GetProgramInfoLog(handle.gl_id, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
      }
      panic!("{}", str::from_utf8(buf.as_slice()).expect("ProgramInfoLog not valid utf8"));
    }

    Shader {
      handle: handle,
      components: components,
      uniforms: HashMap::new(),
    }
  }

  pub fn use_shader(&self, _gl: &mut GLContext) {
    unsafe {
      gl::UseProgram(self.handle.gl_id)
    }
  }

  pub fn with_uniform_location<T>(
    &mut self,
    gl: &mut GLContext,
    name: &'static str,
    f: |GLint| -> T,
  ) -> T {
    let s_name = String::from_str(name);
    let name = name.to_c_str().as_ptr();
    let t = match self.uniforms.get(&s_name) {
      None => {
        self.use_shader(gl);
        let loc = unsafe { gl::GetUniformLocation(self.handle.gl_id, name) };
        assert!(loc != -1, "couldn't find shader uniform: {}", s_name);

        self.uniforms.insert(s_name, loc);
        f(loc)
      },
      Some(&loc) => {
        self.use_shader(gl);
        f(loc)
      }
    };

    t
  }
}
<commit_msg>change with_uniform_location to get_uniform_location<commit_after>use gl;
use gl::types::*;
use gl_context::GLContext;
use std::collections::HashMap;
use std::ptr;
use std::str;

pub struct ProgramHandle<'a> {
  pub gl_id: GLuint,
}

impl<'a> ProgramHandle<'a> {
  pub fn new<'b: 'a>(_gl: &'b GLContext) -> ProgramHandle<'a> {
    let gl_id = unsafe {
      gl::CreateProgram()
    };

    ProgramHandle {
      gl_id: gl_id,
    }
  }
}

#[unsafe_destructor]
impl<'a> Drop for ProgramHandle<'a> {
  fn drop(&mut self) {
    unsafe {
      gl::DeleteProgram(self.gl_id);
    }
  }
}

pub struct ShaderHandle<'a> {
  pub gl_id: GLuint,
}

impl<'a> ShaderHandle<'a> {
  pub fn compile_from<'b: 'a>(
    _gl: &'b GLContext,
    shader_source: String,
    typ: GLenum
  ) -> ShaderHandle<'a> {
    let gl_id = unsafe {
      gl::CreateShader(typ)
    };
    // Attempt to compile the shader
    shader_source.with_c_str(|ptr| unsafe { gl::ShaderSource(gl_id, 1, &ptr, ptr::null()) });
    unsafe {
      gl::CompileShader(gl_id);
    }

    // Get the compile status
    let mut status = gl::FALSE as GLint;
    unsafe {
      gl::GetShaderiv(gl_id, gl::COMPILE_STATUS, &mut status);
    }

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      unsafe {
        gl::GetShaderiv(gl_id, gl::INFO_LOG_LENGTH, &mut len);
      }
      let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
      unsafe {
        gl::GetShaderInfoLog(gl_id, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
      }
      panic!("error compiling 0x{:x} shader: {}", typ, str::from_utf8(buf.as_slice()).expect("ShaderInfoLog not valid utf8"));
    }

    ShaderHandle {
      gl_id: gl_id,
    }
  }
}

#[unsafe_destructor]
impl<'a> Drop for ShaderHandle<'a> {
  fn drop(&mut self) {
    unsafe {
      gl::DeleteShader(self.gl_id);
    }
  }
}

pub struct Shader<'a> {
  pub handle: ProgramHandle<'a>,
  pub components: Vec<ShaderHandle<'a>>,
  pub uniforms: HashMap<String, GLint>,
}

impl<'a> Shader<'a> {
  pub fn new<'b: 'a, T: Iterator<(String, GLenum)>>(
    gl: &'b GLContext,
    shader_components: T,
  ) -> Shader<'a> {
    let mut shader_components = shader_components;
    let handle = ProgramHandle::new(gl);

    let mut components = Vec::new();
    for (content, component) in shader_components {
      let s = ShaderHandle::compile_from(gl, content, component);
      unsafe { gl::AttachShader(handle.gl_id, s.gl_id) };
      components.push(s);
    }

    unsafe {
      gl::LinkProgram(handle.gl_id);
    }

    // Get the link status
    let mut status = gl::FALSE as GLint;
    unsafe {
      gl::GetProgramiv(handle.gl_id, gl::LINK_STATUS, &mut status);
    }

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len: GLint = 0;
      unsafe {
        gl::GetProgramiv(handle.gl_id, gl::INFO_LOG_LENGTH, &mut len);
      }
      let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
      unsafe {
        gl::GetProgramInfoLog(handle.gl_id, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
      }
      panic!("{}", str::from_utf8(buf.as_slice()).expect("ProgramInfoLog not valid utf8"));
    }

    Shader {
      handle: handle,
      components: components,
      uniforms: HashMap::new(),
    }
  }

  pub fn use_shader(&self, _gl: &mut GLContext) {
    unsafe {
      gl::UseProgram(self.handle.gl_id)
    }
  }

  pub fn get_uniform_location<T>(
    &mut self,
    gl: &mut GLContext,
    name: &'static str,
  ) -> GLint {
    let s_name = String::from_str(name);
    let name = name.to_c_str().as_ptr();
    match self.uniforms.get(&s_name) {
      None => {
        self.use_shader(gl);
        let loc = unsafe { gl::GetUniformLocation(self.handle.gl_id, name) };
        assert!(loc != -1, "couldn't find shader uniform: {}", s_name);

        self.uniforms.insert(s_name, loc);
        loc
      },
      Some(&loc) => loc,
    }
  }
}
<|endoftext|>


<commit_before>use super::{MaxPQ, MinPQ};

const INITIAL_PRIORITY_QUEUE_CAPACITY: usize = 1;

pub struct BinaryHeapMaxPQ<Key> {
    pq: Vec<Option<Key>>,
    n: usize
}

impl<Key: PartialOrd> BinaryHeapMaxPQ<Key> {
    fn with_capacity(capacity: usize) -> BinaryHeapMaxPQ<Key> {
        let mut pq = Vec::with_capacity(capacity + 1);
        for _ in 0 .. capacity + 1 {
            pq.push(None);
        }
        BinaryHeapMaxPQ {
            pq: pq,
            n: 0
        }
    }

    fn resize(&mut self, capacity: usize) {
        assert!(capacity > self.n);
        let mut temp = Vec::with_capacity(capacity);
        for i in 0 .. capacity {
            if i >= 1 && i <= self.n {
                temp.push(self.pq[i].take());
            } else {
                temp.push(None);
            }
        }
        self.pq = temp;
    }

    fn swim(&mut self, k: usize) {
        let mut k = k;
        while k > 1 && self.pq[k/2] < self.pq[k] {
            self.pq.swap(k, k/2);
            k = k/2;
        }
    }

    fn sink(&mut self, k: usize) {
        let mut k = k;
        while 2*k <= self.n {
            let mut j = 2*k;
            if j < self.n && self.pq[j] < self.pq[j+1] {
                j += 1;
            }
            if self.pq[k] >= self.pq[j] {
                break;
            }
            self.pq.swap(k, j);
            k = j;
        }
    }
}

impl<Key: PartialOrd>  MaxPQ<Key> for BinaryHeapMaxPQ<Key> {
    /// create an empty priority queue
    fn new() -> Self {
        BinaryHeapMaxPQ::with_capacity(INITIAL_PRIORITY_QUEUE_CAPACITY)
    }
    /// create a priority queue with given keys
    fn from_vec(a: Vec<Key>) -> Self {
        let mut pq = Self::new();
        let len = a.len();
        pq.pq.move_from(a.map_in_place(Some), 0, len);
        pq
    }
    /// insert a key into the priority queue
    fn insert(&mut self, x: Key) {
        let len = self.pq.len();
        if self.n == len - 1 {
            self.resize(2 * len);
        }
        self.n += 1;
        let n = self.n;
        self.pq[n] = Some(x);
        self.swim(n);
    }
    /// return and remove the largest key
    fn del_max(&mut self) -> Option<Key> {
        let max = self.pq[1].take();
        self.pq.swap(1, self.n);
        self.n -= 1;
        self.sink(1);
        let len = self.pq.len();
        if self.n > 0 && self.n == (len - 1) / 4 {
            self.resize(len / 2);
        }
        max
    }
    /// is the priority queue empty?
    #[inline]
    fn is_empty(&self) -> bool {
        self.n == 0
    }
    /// return the largest key
    fn max(&self) -> Option<&Key> {
        self.pq[1].as_ref()
    }
    /// number of entries in the priority queue
    fn size(&self) -> usize {
        self.n
    }
}

pub struct BinaryHeapMinPQ<Key> {
    pq: Vec<Option<Key>>,
    n: usize
}

impl<Key: PartialOrd> BinaryHeapMinPQ<Key> {
    fn with_capacity(capacity: usize) -> BinaryHeapMinPQ<Key> {
        let mut pq = Vec::with_capacity(capacity + 1);
        for _ in 0 .. capacity + 1 {
            pq.push(None);
        }
        BinaryHeapMinPQ {
            pq: pq,
            n: 0
        }
    }

    fn resize(&mut self, capacity: usize) {
        assert!(capacity > self.n);
        let mut temp = Vec::with_capacity(capacity);
        for i in 0 .. capacity {
            if i >= 1 && i <= self.n {
                temp.push(self.pq[i].take());
            } else {
                temp.push(None);
            }
        }
        self.pq = temp;
    }

    fn swim(&mut self, k: usize) {
        let mut k = k;
        while k > 1 && self.pq[k/2] > self.pq[k] {
            self.pq.swap(k, k/2);
            k = k/2;
        }
    }

    fn sink(&mut self, k: usize) {
        let mut k = k;
        while 2*k <= self.n {
            let mut j = 2*k;
            if j < self.n && self.pq[j] > self.pq[j+1] {
                j += 1;
            }
            if self.pq[k] <= self.pq[j] {
                break;
            }
            self.pq.swap(k, j);
            k = j;
        }
    }
}

impl<Key: PartialOrd>  MinPQ<Key> for BinaryHeapMinPQ<Key> {
    /// create an empty priority queue
    fn new() -> Self {
        BinaryHeapMinPQ::with_capacity(INITIAL_PRIORITY_QUEUE_CAPACITY)
    }
    /// create a priority queue with given keys
    fn from_vec(a: Vec<Key>) -> Self {
        let mut pq = Self::new();
        let len = a.len();
        pq.pq.move_from(a.map_in_place(Some), 0, len);
        pq
    }
    /// insert a key into the priority queue
    fn insert(&mut self, x: Key) {
        let len = self.pq.len();
        if self.n == len - 1 {
            self.resize(2 * len);
        }
        self.n += 1;
        let n = self.n;
        self.pq[n] = Some(x);
        self.swim(n);
    }
    /// return and remove the largest key
    fn del_min(&mut self) -> Option<Key> {
        let min = self.pq[1].take();
        self.pq.swap(1, self.n);
        self.n -= 1;
        self.sink(1);
        let len = self.pq.len();
        if self.n > 0 && self.n == (len - 1) / 4 {
            self.resize(len / 2);
        }
        min
    }
    /// is the priority queue empty?
    #[inline]
    fn is_empty(&self) -> bool {
        self.n == 0
    }
    /// return the smallest key
    fn min(&self) -> Option<&Key> {
        self.pq[1].as_ref()
    }
    /// number of entries in the priority queue
    fn size(&self) -> usize {
        self.n
    }
}

#[test]
fn test_binary_heap_min_priority_queue() {
    let mut pq: BinaryHeapMinPQ<char> = MinPQ::new();

    pq.insert('P');
    pq.insert('Q');
    pq.insert('E');

    assert_eq!(pq.size(), 3);
    assert_eq!(pq.del_min().unwrap(), 'E');
    assert_eq!(pq.size(), 2);

    pq.insert('X');
    pq.insert('A');
    pq.insert('M');

    assert_eq!(pq.del_min().unwrap(), 'A');

    pq.insert('P');
    pq.insert('L');
    pq.insert('B');

    assert_eq!(pq.del_min().unwrap(), 'B');

    assert_eq!(pq.size(), 6);
}

#[test]
fn test_binary_heap_max_priority_queue() {
    let mut pq: BinaryHeapMaxPQ<char> = MaxPQ::new();

    pq.insert('P');
    pq.insert('Q');
    pq.insert('E');

    assert_eq!(pq.size(), 3);
    assert_eq!(pq.del_max().unwrap(), 'Q');
    assert_eq!(pq.size(), 2);

    pq.insert('X');
    pq.insert('A');
    pq.insert('M');

    assert_eq!(pq.del_max().unwrap(), 'X');

    pq.insert('P');
    pq.insert('L');
    pq.insert('E');

    assert_eq!(pq.del_max().unwrap(), 'P');

    assert_eq!(pq.size(), 6);
}

#[test]
fn test_empty_binary_heap() {
    let mut pq: BinaryHeapMaxPQ<char> = MaxPQ::new();
    pq.insert('P');
    assert_eq!(pq.is_empty(), false);
    assert_eq!(pq.size(), 1);
    pq.del_max();
    assert_eq!(pq.size(), 0);
    assert_eq!(pq.is_empty(), true);
}
<commit_msg>priority_queues/binary_heaps: fix BinaryHeapMax/MinPQ::from_vec()<commit_after>use super::{MaxPQ, MinPQ};

const INIT_SIZE: usize = 1;

/// Generic max priority queue implementation with a binary heap
pub struct BinaryHeapMaxPQ<Key> {
    pq: Vec<Option<Key>>,
    n: usize
}

impl<Key: PartialOrd> BinaryHeapMaxPQ<Key> {
    fn with_capacity(capacity: usize) -> BinaryHeapMaxPQ<Key> {
        let mut pq = Vec::with_capacity(capacity + 1);
        for _ in 0 .. capacity + 1 {
            pq.push(None);
        }
        BinaryHeapMaxPQ {
            pq: pq,
            n: 0
        }
    }

    fn resize(&mut self, capacity: usize) {
        assert!(capacity > self.n);
        let mut temp = Vec::with_capacity(capacity);
        for i in 0 .. capacity {
            if i >= 1 && i <= self.n {
                temp.push(self.pq[i].take());
            } else {
                temp.push(None);
            }
        }
        self.pq = temp;
    }

    fn swim(&mut self, k: usize) {
        let mut k = k;
        while k > 1 && self.pq[k/2] < self.pq[k] {
            self.pq.swap(k, k/2);
            k = k/2;
        }
    }

    fn sink(&mut self, k: usize) {
        let mut k = k;
        while 2*k <= self.n {
            let mut j = 2*k;
            if j < self.n && self.pq[j] < self.pq[j+1] {
                j += 1;
            }
            if self.pq[k] >= self.pq[j] {
                break;
            }
            self.pq.swap(k, j);
            k = j;
        }
    }
}

impl<Key: PartialOrd>  MaxPQ<Key> for BinaryHeapMaxPQ<Key> {
    /// create an empty priority queue
    fn new() -> Self {
        BinaryHeapMaxPQ::with_capacity(INIT_SIZE)
    }

    /// create a priority queue with given keys
    fn from_vec(a: Vec<Key>) -> Self {
        let len = a.len();
        let mut pq = Self::new();
        pq.pq.move_from(a.map_in_place(Some), 0, len);
        for k in 1 .. len / 2 + 1 {
            pq.sink(k);
        }
        pq.n = len;
        pq
    }

    /// insert a key into the priority queue
    fn insert(&mut self, x: Key) {
        let len = self.pq.len();
        if self.n == len - 1 {
            self.resize(2 * len);
        }
        self.n += 1;
        let n = self.n;
        self.pq[n] = Some(x);
        self.swim(n);
    }

    /// return and remove the largest key
    fn del_max(&mut self) -> Option<Key> {
        let max = self.pq[1].take();
        self.pq.swap(1, self.n);
        self.n -= 1;
        self.sink(1);
        let len = self.pq.len();
        if self.n > 0 && self.n == (len - 1) / 4 {
            self.resize(len / 2);
        }
        max
    }

    /// is the priority queue empty?
    #[inline]
    fn is_empty(&self) -> bool {
        self.n == 0
    }

    /// return the largest key
    fn max(&self) -> Option<&Key> {
        self.pq[1].as_ref()
    }

    /// number of entries in the priority queue
    #[inline]
    fn size(&self) -> usize {
        self.n
    }
}

/// Generic min priority queue implementation with a binary heap
pub struct BinaryHeapMinPQ<Key> {
    pq: Vec<Option<Key>>,
    n: usize
}

impl<Key: PartialOrd> BinaryHeapMinPQ<Key> {
    fn with_capacity(capacity: usize) -> BinaryHeapMinPQ<Key> {
        let mut pq = Vec::with_capacity(capacity + 1);
        for _ in 0 .. capacity + 1 {
            pq.push(None);
        }
        BinaryHeapMinPQ {
            pq: pq,
            n: 0
        }
    }

    fn resize(&mut self, capacity: usize) {
        assert!(capacity > self.n);
        let mut temp = Vec::with_capacity(capacity);
        for i in 0 .. capacity {
            if i >= 1 && i <= self.n {
                temp.push(self.pq[i].take());
            } else {
                temp.push(None);
            }
        }
        self.pq = temp;
    }

    fn swim(&mut self, k: usize) {
        let mut k = k;
        while k > 1 && self.pq[k/2] > self.pq[k] {
            self.pq.swap(k, k/2);
            k = k/2;
        }
    }

    fn sink(&mut self, k: usize) {
        let mut k = k;
        while 2*k <= self.n {
            let mut j = 2*k;
            if j < self.n && self.pq[j] > self.pq[j+1] {
                j += 1;
            }
            if self.pq[k] <= self.pq[j] {
                break;
            }
            self.pq.swap(k, j);
            k = j;
        }
    }
}

impl<Key: PartialOrd>  MinPQ<Key> for BinaryHeapMinPQ<Key> {
    /// create an empty priority queue
    fn new() -> Self {
        BinaryHeapMinPQ::with_capacity(INIT_SIZE)
    }

    /// create a priority queue with given keys
    fn from_vec(a: Vec<Key>) -> Self {
        let len = a.len();
        let mut pq = Self::new();
        pq.pq.move_from(a.map_in_place(Some), 0, len);
        for k in 1 .. len / 2 + 1 {
            pq.sink(k);
        }
        pq.n = len;
        pq
    }

    /// insert a key into the priority queue
    fn insert(&mut self, x: Key) {
        let len = self.pq.len();
        if self.n == len - 1 {
            self.resize(2 * len);
        }
        self.n += 1;
        let n = self.n;
        self.pq[n] = Some(x);
        self.swim(n);
    }

    /// return and remove the smallest key
    fn del_min(&mut self) -> Option<Key> {
        let min = self.pq[1].take();
        self.pq.swap(1, self.n);
        self.n -= 1;
        self.sink(1);
        let len = self.pq.len();
        if self.n > 0 && self.n == (len - 1) / 4 {
            self.resize(len / 2);
        }
        min
    }

    /// is the priority queue empty?
    #[inline]
    fn is_empty(&self) -> bool {
        self.n == 0
    }

    /// return the smallest key
    fn min(&self) -> Option<&Key> {
        self.pq[1].as_ref()
    }

    /// number of entries in the priority queue
    fn size(&self) -> usize {
        self.n
    }
}

#[test]
fn test_binary_heap_min_priority_queue() {
    let mut pq: BinaryHeapMinPQ<char> = MinPQ::new();

    pq.insert('P');
    pq.insert('Q');
    pq.insert('E');

    assert_eq!(pq.size(), 3);
    assert_eq!(pq.del_min().unwrap(), 'E');
    assert_eq!(pq.size(), 2);

    pq.insert('X');
    pq.insert('A');
    pq.insert('M');

    assert_eq!(pq.del_min().unwrap(), 'A');

    pq.insert('P');
    pq.insert('L');
    pq.insert('B');

    assert_eq!(pq.del_min().unwrap(), 'B');

    assert_eq!(pq.size(), 6);
}

#[test]
fn test_binary_heap_max_priority_queue() {
    let mut pq: BinaryHeapMaxPQ<char> = MaxPQ::new();

    pq.insert('P');
    pq.insert('Q');
    pq.insert('E');

    assert_eq!(pq.size(), 3);
    assert_eq!(pq.del_max().unwrap(), 'Q');
    assert_eq!(pq.size(), 2);

    pq.insert('X');
    pq.insert('A');
    pq.insert('M');

    assert_eq!(pq.del_max().unwrap(), 'X');

    pq.insert('P');
    pq.insert('L');
    pq.insert('E');

    assert_eq!(pq.del_max().unwrap(), 'P');

    assert_eq!(pq.size(), 6);
}

#[test]
fn test_empty_binary_heap() {
    let mut pq: BinaryHeapMaxPQ<char> = MaxPQ::new();
    pq.insert('P');
    assert_eq!(pq.is_empty(), false);
    assert_eq!(pq.size(), 1);
    pq.del_max();
    assert_eq!(pq.size(), 0);
    assert_eq!(pq.is_empty(), true);
}
<|endoftext|>


<commit_before>use super::rk4;
use traits::*;

pub enum Method {
    //RK2,
    RK4,
}

/**
# Default values

When creating a new `Solver` with `Solver::new()`, this is the default
configuration:

- [method](struct.Solver.html#method.method): `Method::RK4`

- [weights](struct.Solver.html#method.weights) for the intermediate points:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

(Note that each internal value of the vector will be converted to `T` via
[T::from_str_radix()](../num_traits/trait.Num.html#tymethod.from_str_radix).)

# Example

```
use ode::{Method, Solver};

let time_interval: [f32; 2] = [0., 100.];
let ini_cond: Vec<f32> = vec![0.];

// simple config
Solver::new(&time_interval, &ini_cond)
    .method(Method::RK4)
    .solve(|t: &f32, _: &Vec<f32>| vec![2.*t]);

// complex config
let mut s = Solver::new(&time_interval, &ini_cond);
s.method(Method::RK4);

// run the solver
let (times, pos) = s.solve(|t: &f32, _: &Vec<f32>| vec![2.*t]);
```
*/
pub struct Solver<T> where T: Number {
    method: Method,
    weights: Vec<T>,
    weight_sum: T,
    time_begin: T,
    time_end: T,
    step: T,
    initial_conditions: Vec<T>,
}

impl<T> Solver<T> where T: Number {
    /*
    Re-calculate the sum of the registered weights.
    */
    fn sum_weights(weights: &Vec<T>) -> T {
        weights
            .iter()
            .fold(T::zero(), |sum, i| sum + i.clone())
    }

    /*
    Return the default weights for the intermidiate points of a given method.

    Return values are:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

    (Note that each internal value of the vector will be converted to `T` via
    `T::from_str_radix()`.)
    */
    fn get_default_weights_for(method: &Method) -> Vec<T> {
        let weights = match method {
            //&Method::RK2 => vec!["1", "1"],
            &Method::RK4 => vec!["1", "2", "2", "1"],
        };

        weights
            .iter()
            .map(|el| T::from_str_radix(el, 10).ok().unwrap())
            .collect()
    }

    /**
    Start building a new Solver.

    Default values are:

    - method: `Method::RK4`,
    - intermidiate point weights: `vec![1, 2, 2, 1]`
    - step size: `10e-3`

    (Note that these values will be converted to `T` via `T::from_str_radix()`.)
    */
    pub fn new(time_interval: &[T; 2],
               initial_conditions: &Vec<T>) -> Solver<T> {
        let weights = Self::get_default_weights_for(&Method::RK4);
        let sum_of_weights = Self::sum_weights(&weights);
        let default_step = T::from_str_radix("10e-3", 10).ok().unwrap();

        Solver {
            method:             Method::RK4,
            weights:            weights,
            weight_sum:         sum_of_weights,
            time_begin:         time_interval[0].clone(),
            time_end:           time_interval[1].clone(),
            step:               default_step,
            initial_conditions: initial_conditions.clone(),
        }
    }

    /**
    Select the desired algorithm to solve the givem problem, also updating the
    weights based on default values. To manually alter these values, please
    check `Self::change_weight()`.
    */
    pub fn method(&mut self, new_method: Method) -> &mut Solver<T> {
        self.weights = Self::get_default_weights_for(&new_method);
        self.method = new_method;
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Modify the default weighting applyed to each intermidiate point.
    */
    pub fn weights(&mut self, new_weights: Vec<T>) -> &mut Solver<T> {
        self.weights = new_weights.clone();
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Validates the data passed to the solver.

    This is tipically called by `run()` before attempting to solve the passed
    function, but was made public so the data can be verified and corrected
    without a panic.

    Data checks are:

    - `Self::weights.len()` should match the selected method:

        - `Method::RK2` requires 2 weights;
        - `Method::RK4` requires 4 weights;
    */
    pub fn validate(&self) -> bool {
        self.weights.len() == match self.method {
            //Method::RK2 => 2,
            Method::RK4 => 4,
        }
    }

    /**
    Check and run the solver, returning the results of the calculation.

    Notice that, before the solver actually runs, it validates its data by
    calling `Self::validate()` within an `assert!`. See that function for more
    details.
    */
    pub fn solve<F>(&self, function: F) -> (Vec<T>, Vec<Vec<T>>)
        where F: Function<T> {
        assert!(self.validate());

        match self.method {
            //Method::RK2 => {}
            Method::RK4 => rk4::solver(function,
                                       self.initial_conditions.clone(),
                                       &[self.time_begin, self.time_end],
                                       self.step,
                                       &self.weights,
                                       self.weight_sum)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = Solver::new(&[0., 100.],
                            &vec![0., 0.]);
    }
}
<commit_msg>Return Self instead of Solver<commit_after>use super::rk4;
use traits::*;

pub enum Method {
    //RK2,
    RK4,
}

/**
# Default values

When creating a new `Solver` with `Solver::new()`, this is the default
configuration:

- [method](struct.Solver.html#method.method): `Method::RK4`

- [weights](struct.Solver.html#method.weights) for the intermediate points:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

(Note that each internal value of the vector will be converted to `T` via
[T::from_str_radix()](../num_traits/trait.Num.html#tymethod.from_str_radix).)

# Example

```
use ode::{Method, Solver};

let time_interval: [f32; 2] = [0., 100.];
let ini_cond: Vec<f32> = vec![0.];

// simple config
Solver::new(&time_interval, &ini_cond)
    .method(Method::RK4)
    .solve(|t: &f32, _: &Vec<f32>| vec![2.*t]);

// complex config
let mut s = Solver::new(&time_interval, &ini_cond);
s.method(Method::RK4);

// run the solver
let (times, pos) = s.solve(|t: &f32, _: &Vec<f32>| vec![2.*t]);
```
*/
pub struct Solver<T> where T: Number {
    method: Method,
    weights: Vec<T>,
    weight_sum: T,
    time_begin: T,
    time_end: T,
    step: T,
    initial_conditions: Vec<T>,
}

impl<T> Solver<T> where T: Number {
    /*
    Re-calculate the sum of the registered weights.
    */
    fn sum_weights(weights: &Vec<T>) -> T {
        weights
            .iter()
            .fold(T::zero(), |sum, i| sum + i.clone())
    }

    /*
    Return the default weights for the intermidiate points of a given method.

    Return values are:

    - `Method::RK2`: `vec![1, 1],`
    - `Method::RK4`: `vec![1, 2, 2, 1],`

    (Note that each internal value of the vector will be converted to `T` via
    `T::from_str_radix()`.)
    */
    fn get_default_weights_for(method: &Method) -> Vec<T> {
        let weights = match method {
            //&Method::RK2 => vec!["1", "1"],
            &Method::RK4 => vec!["1", "2", "2", "1"],
        };

        weights
            .iter()
            .map(|el| T::from_str_radix(el, 10).ok().unwrap())
            .collect()
    }

    /**
    Start building a new Solver.

    Default values are:

    - method: `Method::RK4`,
    - intermidiate point weights: `vec![1, 2, 2, 1]`
    - step size: `10e-3`

    (Note that these values will be converted to `T` via `T::from_str_radix()`.)
    */
    pub fn new(time_interval: &[T; 2],
               initial_conditions: &Vec<T>) -> Solver<T> {
        let weights = Self::get_default_weights_for(&Method::RK4);
        let sum_of_weights = Self::sum_weights(&weights);
        let default_step = T::from_str_radix("10e-3", 10).ok().unwrap();

        Self {
            method:             Method::RK4,
            weights:            weights,
            weight_sum:         sum_of_weights,
            time_begin:         time_interval[0].clone(),
            time_end:           time_interval[1].clone(),
            step:               default_step,
            initial_conditions: initial_conditions.clone(),
        }
    }

    /**
    Select the desired algorithm to solve the givem problem, also updating the
    weights based on default values. To manually alter these values, please
    check `Self::change_weight()`.
    */
    pub fn method(&mut self, new_method: Method) -> &mut Solver<T> {
        self.weights = Self::get_default_weights_for(&new_method);
        self.method = new_method;
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Modify the default weighting applyed to each intermidiate point.
    */
    pub fn weights(&mut self, new_weights: Vec<T>) -> &mut Solver<T> {
        self.weights = new_weights.clone();
        self.weight_sum = Self::sum_weights(&self.weights);

        self
    }

    /**
    Validates the data passed to the solver.

    This is tipically called by `run()` before attempting to solve the passed
    function, but was made public so the data can be verified and corrected
    without a panic.

    Data checks are:

    - `Self::weights.len()` should match the selected method:

        - `Method::RK2` requires 2 weights;
        - `Method::RK4` requires 4 weights;
    */
    pub fn validate(&self) -> bool {
        self.weights.len() == match self.method {
            //Method::RK2 => 2,
            Method::RK4 => 4,
        }
    }

    /**
    Check and run the solver, returning the results of the calculation.

    Notice that, before the solver actually runs, it validates its data by
    calling `Self::validate()` within an `assert!`. See that function for more
    details.
    */
    pub fn solve<F>(&self, function: F) -> (Vec<T>, Vec<Vec<T>>)
        where F: Function<T> {
        assert!(self.validate());

        match self.method {
            //Method::RK2 => {}
            Method::RK4 => rk4::solver(function,
                                       self.initial_conditions.clone(),
                                       &[self.time_begin, self.time_end],
                                       self.step,
                                       &self.weights,
                                       self.weight_sum)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn it_works() {
        let _ = Solver::new(&[0., 100.],
                            &vec![0., 0.]);
    }
}
<|endoftext|>


<commit_before>use color::Color4;
use common::*;
use gl::types::*;
use light::{Light, set_point_light};
use mob;
use nalgebra::Vec3;
use physics::Physics;
use state::App;
use std::f32::consts::PI;
use std::ops::{Deref, DerefMut};
use std::num::Float;
use terrain_block::BlockPosition;
use time;
use yaglw::gl_context::GLContext;

macro_rules! translate_mob(
  ($world:expr, $mob:expr, $v:expr) => (
    translate_mob(
      $world.gl_context,
      &mut $world.physics,
      &mut $world.mob_buffers,
      $mob,
      $v
    );
  );
);

pub fn update<'a>(app: &mut App) {
  app.timers.time("update", || {
    app.timers.time("update.player", || {
      app.player.update(
        app.timers,
        app.gl_context,
        &mut app.terrain_game_loader,
        &mut app.id_allocator,
        &mut app.physics,
      );
    });

    app.timers.time("update.mobs", || {
      for (_, mob) in app.mobs.iter() {
        let mut mob_cell = mob.deref().borrow_mut();
        let mob = mob_cell.deref_mut();

        let block_position = BlockPosition::from_world_position(&mob.position);

        mob.solid_boundary.update(
          app.timers,
          app.gl_context,
          &mut app.terrain_game_loader,
          &mut app.id_allocator,
          &mut app.physics,
          block_position,
        );

        {
          let behavior = mob.behavior;
          (behavior)(app, mob);
        }

        mob.speed = mob.speed - Vec3::new(0.0, 0.1, 0.0 as GLfloat);

        let delta_p = mob.speed;
        if delta_p.x != 0.0 {
          translate_mob!(app, mob, Vec3::new(delta_p.x, 0.0, 0.0));
        }
        if delta_p.y != 0.0 {
          translate_mob!(app, mob, Vec3::new(0.0, delta_p.y, 0.0));
        }
        if delta_p.z != 0.0 {
          translate_mob!(app, mob, Vec3::new(0.0, 0.0, delta_p.z));
        }
      }
    });

    app.timers.time("update.sun", || {
      let ticks = app.sun_timer.update(time::precise_time_ns());
      app.sun += ticks as u16;

      let radius = 1024.0;
      // Convert the sun angle to radians.
      let sun_f = (app.sun as f32) * 2.0 * PI / 256.0;
      // position relative to player
      let sun_x = radius * sun_f.cos();
      let sun_y = radius * sun_f.sin();
      // "absolute" position
      let sun_position = app.player.camera.position + Vec3::new(sun_x, sun_y, 0.0);

      set_point_light(
        &mut app.terrain_shader,
        app.gl_context,
        &Light {
          position: sun_position,
          intensity: Vec3::new(0.6, 0.6, 0.2),
        }
      );
    });
  })
}

fn translate_mob(
  gl: &mut GLContext,
  physics: &mut Physics,
  mob_buffers: &mut mob::MobBuffers,
  mob: &mut mob::Mob,
  delta_p: Vec3<GLfloat>,
) {
  if physics.translate_misc(mob.id, delta_p).is_some() {
    mob.speed = mob.speed - delta_p;
  } else {
    let bounds = physics.get_bounds(mob.id).unwrap();
    mob.position = mob.position + delta_p;
    mob_buffers.update(
      gl,
      mob.id,
      &to_triangles(bounds, &Color4::of_rgba(1.0, 0.0, 0.0, 1.0))
    );
  }
}
<commit_msg>Ambient light changes over time too.<commit_after>use color::Color4;
use common::*;
use gl::types::*;
use light::{Light, set_point_light, set_ambient_light};
use mob;
use nalgebra::Vec3;
use physics::Physics;
use state::App;
use std::cmp::partial_min;
use std::f32::consts::PI;
use std::ops::{Deref, DerefMut};
use std::num::Float;
use terrain_block::BlockPosition;
use time;
use yaglw::gl_context::GLContext;

macro_rules! translate_mob(
  ($world:expr, $mob:expr, $v:expr) => (
    translate_mob(
      $world.gl_context,
      &mut $world.physics,
      &mut $world.mob_buffers,
      $mob,
      $v
    );
  );
);

pub fn update<'a>(app: &mut App) {
  app.timers.time("update", || {
    app.timers.time("update.player", || {
      app.player.update(
        app.timers,
        app.gl_context,
        &mut app.terrain_game_loader,
        &mut app.id_allocator,
        &mut app.physics,
      );
    });

    app.timers.time("update.mobs", || {
      for (_, mob) in app.mobs.iter() {
        let mut mob_cell = mob.deref().borrow_mut();
        let mob = mob_cell.deref_mut();

        let block_position = BlockPosition::from_world_position(&mob.position);

        mob.solid_boundary.update(
          app.timers,
          app.gl_context,
          &mut app.terrain_game_loader,
          &mut app.id_allocator,
          &mut app.physics,
          block_position,
        );

        {
          let behavior = mob.behavior;
          (behavior)(app, mob);
        }

        mob.speed = mob.speed - Vec3::new(0.0, 0.1, 0.0 as GLfloat);

        let delta_p = mob.speed;
        if delta_p.x != 0.0 {
          translate_mob!(app, mob, Vec3::new(delta_p.x, 0.0, 0.0));
        }
        if delta_p.y != 0.0 {
          translate_mob!(app, mob, Vec3::new(0.0, delta_p.y, 0.0));
        }
        if delta_p.z != 0.0 {
          translate_mob!(app, mob, Vec3::new(0.0, 0.0, delta_p.z));
        }
      }
    });

    app.timers.time("update.sun", || {
      let ticks = app.sun_timer.update(time::precise_time_ns());
      app.sun += ticks as u16;

      let radius = 1024.0;
      // Convert the sun angle to radians.
      let sun_f = (app.sun as f32) * 2.0 * PI / 256.0;
      let (s, c) = sun_f.sin_cos();
      let sun_position = app.player.camera.position + Vec3::new(c, s, 0.0) * radius;

      let sun_color = Vec3::new(0.6, 0.6, 0.2);

      set_point_light(
        &mut app.terrain_shader,
        app.gl_context,
        &Light {
          position: sun_position,
          intensity: sun_color,
        }
      );

      let ambient_light = partial_min(0.2, s / 2.0).unwrap();

      set_ambient_light(
        &mut app.terrain_shader,
        app.gl_context,
        sun_color * ambient_light,
      );
    });
  })
}

fn translate_mob(
  gl: &mut GLContext,
  physics: &mut Physics,
  mob_buffers: &mut mob::MobBuffers,
  mob: &mut mob::Mob,
  delta_p: Vec3<GLfloat>,
) {
  if physics.translate_misc(mob.id, delta_p).is_some() {
    mob.speed = mob.speed - delta_p;
  } else {
    let bounds = physics.get_bounds(mob.id).unwrap();
    mob.position = mob.position + delta_p;
    mob_buffers.update(
      gl,
      mob.id,
      &to_triangles(bounds, &Color4::of_rgba(1.0, 0.0, 0.0, 1.0))
    );
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use model::{Color, FieldCoord, HexCoord, Model, Move};
use view::Event;

pub fn update(model: &mut Model, event: Option<Event>) {
    if let Some(event) = event {
        use view::Event::*;
        match event {
            Click(field) => if model.turn == field.color() {
                if model.board.is_piece_on_field(&field) {
                    if model.selected_piece.as_ref() == Some(&field) {
                        clear_selection(model);
                    } else {
                        model.available_moves = Some(model.board.get_available_moves(&field));
                        model.selected_piece = Some(field);
                    }
                } else if let Some(selected) = model.selected_piece.take() {
                    if model.board.can_move_piece(&selected, &field) {
                        model.board.move_piece(&selected, &field);

                        let (capture_count, mut fields_to_check) =
                            check_hexes(model, &selected.to_hex());
                        fields_to_check.append(&mut model.board.get_field_edge_neighbors(&field));
                        check_captures(model, &fields_to_check);

                        match model.turn {
                            Color::White => model.white_hexes += capture_count,
                            Color::Black => model.black_hexes += capture_count,
                        }

                        model.last_move = Move::Move(selected, field);
                        model.switch_turns();
                    }
                    clear_selection(model);
                }
            } else if model.exchanging && model.board.is_piece_on_field(&field) {
                model.exchanging = false;
                model.board.remove_piece(&field);
                match model.turn {
                    Color::White => {
                        model.white_hexes -= 2;
                        model.black_pieces -= 1;
                    },
                    Color::Black => {
                        model.black_hexes -= 2;
                        model.white_pieces -= 1;
                    },
                }

                // Players don't collect hexes removed due to an exchange
                let (_, fields_to_check) = check_hexes(model, &field.to_hex());
                check_captures(model, &fields_to_check);

                model.last_move = Move::Exchange(field);
                model.switch_turns();
            } else {
                clear_selection(model);
            },
            Exchange => {
                if model.can_exchange() {
                    model.exchanging = !model.exchanging;
                    clear_selection(model);
                }
            }
            NewGame => *model = Model::new(),
        }
    }
}

fn clear_selection(model: &mut Model) {
    model.selected_piece = None;
    model.available_moves = None;
}

fn check_captures(model: &mut Model, fields_to_check: &[FieldCoord]) {
    for field in fields_to_check {
        if field.color() != model.turn && model.board.is_piece_on_field(field)
            && model
                .board
                .get_field_edge_neighbors(field)
                .into_iter()
                .all(|coord| model.board.is_piece_on_field(&coord))
        {
            model.board.remove_piece(field);
            match model.turn {
                Color::White => model.black_pieces -= 1,
                Color::Black => model.white_pieces -= 1,
            }
        }
    }
}

fn check_hexes(model: &mut Model, coord: &HexCoord) -> (u32, Vec<FieldCoord>) {
    if model.board.is_hex_removable(coord) {
        remove_hex(model, coord)
    } else {
        (0, vec![])
    }
}

fn remove_hex(model: &mut Model, coord: &HexCoord) -> (u32, Vec<FieldCoord>) {
    let mut remove_count = 1;
    model.board.remove_hex(coord);

    let mut fields = vec![];

    for i in 0..6 {
        if let Some(neighbor) = model.board.get_hex_neighbor(coord, i) {
            if model.board.is_hex_removable(&neighbor) {
                let (removed, mut new_fields) = remove_hex(model, &neighbor);
                remove_count += removed;
                fields.append(&mut new_fields);
            } else {
                let field = neighbor.to_field((i + 3) % 6);
                if field.color() != model.turn {
                    fields.push(field);
                }
            }
        }
    }
    (remove_count, fields)
}
<commit_msg>Rename field to clicked<commit_after>/*
 * Copyright (C) 2017-2018 Ryan Huang
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

use model::{Color, FieldCoord, HexCoord, Model, Move};
use view::Event;

pub fn update(model: &mut Model, event: Option<Event>) {
    if let Some(event) = event {
        use view::Event::*;
        match event {
            Click(clicked) => if model.turn == clicked.color() {
                if model.board.is_piece_on_field(&clicked) {
                    if model.selected_piece.as_ref() == Some(&clicked) {
                        clear_selection(model);
                    } else {
                        model.available_moves = Some(model.board.get_available_moves(&clicked));
                        model.selected_piece = Some(clicked);
                    }
                } else if let Some(selected) = model.selected_piece.take() {
                    if model.board.can_move_piece(&selected, &clicked) {
                        model.board.move_piece(&selected, &clicked);

                        let (capture_count, mut fields_to_check) =
                            check_hexes(model, &selected.to_hex());
                        fields_to_check.append(&mut model.board.get_field_edge_neighbors(&clicked));
                        check_captures(model, &fields_to_check);

                        match model.turn {
                            Color::White => model.white_hexes += capture_count,
                            Color::Black => model.black_hexes += capture_count,
                        }

                        model.last_move = Move::Move(selected, clicked);
                        model.switch_turns();
                    }
                    clear_selection(model);
                }
            } else if model.exchanging && model.board.is_piece_on_field(&clicked) {
                model.exchanging = false;
                model.board.remove_piece(&clicked);
                match model.turn {
                    Color::White => {
                        model.white_hexes -= 2;
                        model.black_pieces -= 1;
                    },
                    Color::Black => {
                        model.black_hexes -= 2;
                        model.white_pieces -= 1;
                    },
                }

                // Players don't collect hexes removed due to an exchange
                let (_, fields_to_check) = check_hexes(model, &clicked.to_hex());
                check_captures(model, &fields_to_check);

                model.last_move = Move::Exchange(clicked);
                model.switch_turns();
            } else {
                clear_selection(model);
            },
            Exchange => {
                if model.can_exchange() {
                    model.exchanging = !model.exchanging;
                    clear_selection(model);
                }
            }
            NewGame => *model = Model::new(),
        }
    }
}

fn clear_selection(model: &mut Model) {
    model.selected_piece = None;
    model.available_moves = None;
}

fn check_captures(model: &mut Model, fields_to_check: &[FieldCoord]) {
    for field in fields_to_check {
        if field.color() != model.turn && model.board.is_piece_on_field(field)
            && model
                .board
                .get_field_edge_neighbors(field)
                .into_iter()
                .all(|coord| model.board.is_piece_on_field(&coord))
        {
            model.board.remove_piece(field);
            match model.turn {
                Color::White => model.black_pieces -= 1,
                Color::Black => model.white_pieces -= 1,
            }
        }
    }
}

fn check_hexes(model: &mut Model, coord: &HexCoord) -> (u32, Vec<FieldCoord>) {
    if model.board.is_hex_removable(coord) {
        remove_hex(model, coord)
    } else {
        (0, vec![])
    }
}

fn remove_hex(model: &mut Model, coord: &HexCoord) -> (u32, Vec<FieldCoord>) {
    let mut remove_count = 1;
    model.board.remove_hex(coord);

    let mut fields = vec![];

    for i in 0..6 {
        if let Some(neighbor) = model.board.get_hex_neighbor(coord, i) {
            if model.board.is_hex_removable(&neighbor) {
                let (removed, mut new_fields) = remove_hex(model, &neighbor);
                remove_count += removed;
                fields.append(&mut new_fields);
            } else {
                let field = neighbor.to_field((i + 3) % 6);
                if field.color() != model.turn {
                    fields.push(field);
                }
            }
        }
    }
    (remove_count, fields)
}
<|endoftext|>