<commit_before>use chrono::{DateTime, TimeZone, Utc};
use hyper;
use std::error::Error;
use std::fmt;
use std::str::FromStr;

/// A marker trait for all Flows
pub trait Flow {
    fn type_id() -> FlowType;
}

#[derive(Deserialize)]
pub struct JsonError {
    pub error: String,
    pub error_description: Option<String>,
    pub error_uri: Option<String>,
}

/// Encapsulates all possible results of the `request_token(...)` operation
pub enum RequestError {
    /// Indicates connection failure
    ClientError(hyper::Error),
    /// Indicates HTTP status failure
    HttpError(hyper::http::Error),
    /// The OAuth client was not found
    InvalidClient,
    /// Some requested scopes were invalid. String contains the scopes as part of
    /// the server error message
    InvalidScope(String),
    /// A 'catch-all' variant containing the server error and description
    /// First string is the error code, the second may be a more detailed description
    NegativeServerResponse(String, Option<String>),
}

impl From<hyper::Error> for RequestError {
    fn from(error: hyper::Error) -> RequestError {
        RequestError::ClientError(error)
    }
}

impl From<hyper::http::Error> for RequestError {
    fn from(error: hyper::http::Error) -> RequestError {
        RequestError::HttpError(error)
    }
}

impl From<JsonError> for RequestError {
    fn from(value: JsonError) -> RequestError {
        match &*value.error {
            "invalid_client" => RequestError::InvalidClient,
            "invalid_scope" => RequestError::InvalidScope(
                value
                    .error_description
                    .unwrap_or("no description provided".to_string()),
            ),
            _ => RequestError::NegativeServerResponse(value.error, value.error_description),
        }
    }
}

impl fmt::Display for RequestError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            RequestError::ClientError(ref err) => err.fmt(f),
            RequestError::HttpError(ref err) => err.fmt(f),
            RequestError::InvalidClient => "Invalid Client".fmt(f),
            RequestError::InvalidScope(ref scope) => writeln!(f, "Invalid Scope: '{}'", scope),
            RequestError::NegativeServerResponse(ref error, ref desc) => {
                error.fmt(f)?;
                if let &Some(ref desc) = desc {
                    write!(f, ": {}", desc)?;
                }
                "\n".fmt(f)
            }
        }
    }
}

#[derive(Debug)]
pub struct StringError {
    error: String,
}

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

impl StringError {
    pub fn new(error: String, desc: Option<&String>) -> StringError {
        let mut error = error;
        if let Some(d) = desc {
            error.push_str(": ");
            error.push_str(&*d);
        }

        StringError { error: error }
    }
}

impl<'a> From<&'a dyn Error> for StringError {
    fn from(err: &'a dyn Error) -> StringError {
        StringError::new(err.description().to_string(), None)
    }
}

impl From<String> for StringError {
    fn from(value: String) -> StringError {
        StringError::new(value, None)
    }
}

impl Error for StringError {
    fn description(&self) -> &str {
        &self.error
    }
}

/// Represents all implemented token types
#[derive(Clone, PartialEq, Debug)]
pub enum TokenType {
    /// Means that whoever bears the access token will be granted access
    Bearer,
}

impl AsRef<str> for TokenType {
    fn as_ref(&self) -> &'static str {
        match *self {
            TokenType::Bearer => "Bearer",
        }
    }
}

impl FromStr for TokenType {
    type Err = ();
    fn from_str(s: &str) -> Result<TokenType, ()> {
        match s {
            "Bearer" => Ok(TokenType::Bearer),
            _ => Err(()),
        }
    }
}

/// A scheme for use in `hyper::header::Authorization`
#[derive(Clone, PartialEq, Debug)]
pub struct Scheme {
    /// The type of our access token
    pub token_type: TokenType,
    /// The token returned by one of the Authorization Flows
    pub access_token: String,
}

impl std::convert::Into<hyper::header::HeaderValue> for Scheme {
    fn into(self) -> hyper::header::HeaderValue {
        hyper::header::HeaderValue::from_str(&format!(
            "{} {}",
            self.token_type.as_ref(),
            self.access_token
        ))
        .expect("Invalid Scheme header value")
    }
}

impl FromStr for Scheme {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Scheme, &'static str> {
        let parts: Vec<&str> = s.split(' ').collect();
        if parts.len() != 2 {
            return Err("Expected two parts: <token_type> <token>");
        }
        match <TokenType as FromStr>::from_str(parts[0]) {
            Ok(t) => Ok(Scheme {
                token_type: t,
                access_token: parts[1].to_string(),
            }),
            Err(_) => Err("Couldn't parse token type"),
        }
    }
}

/// Represents a token as returned by OAuth2 servers.
///
/// It is produced by all authentication flows.
/// It authenticates certain operations, and must be refreshed once
/// it reached it's expiry date.
///
/// The type is tuned to be suitable for direct de-serialization from server
/// replies, as well as for serialization for later reuse. This is the reason
/// for the two fields dealing with expiry - once in relative in and once in
/// absolute terms.
///
/// Utility methods make common queries easier, see `expired()`.
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct Token {
    /// used when authenticating calls to oauth2 enabled services.
    pub access_token: String,
    /// used to refresh an expired access_token.
    pub refresh_token: String,
    /// The token type as string - usually 'Bearer'.
    pub token_type: String,
    /// access_token will expire after this amount of time.
    /// Prefer using expiry_date()
    pub expires_in: Option<i64>,
    /// timestamp is seconds since epoch indicating when the token will expire in absolute terms.
    /// use expiry_date() to convert to DateTime.
    pub expires_in_timestamp: Option<i64>,
}

impl Token {
    /// Returns true if we are expired.
    ///
    /// # Panics
    /// * if our access_token is unset
    pub fn expired(&self) -> bool {
        if self.access_token.len() == 0 {
            panic!("called expired() on unset token");
        }
        self.expiry_date() <= Utc::now()
    }

    /// Returns a DateTime object representing our expiry date.
    pub fn expiry_date(&self) -> DateTime<Utc> {
        Utc.timestamp(
            self.expires_in_timestamp
                .expect("Tokens without an absolute expiry are invalid"),
            0,
        )
    }

    /// Adjust our stored expiry format to be absolute, using the current time.
    pub fn set_expiry_absolute(&mut self) -> &mut Token {
        if self.expires_in_timestamp.is_some() {
            assert!(self.expires_in.is_none());
            return self;
        }

        self.expires_in_timestamp = Some(Utc::now().timestamp() + self.expires_in.unwrap());
        self.expires_in = None;
        self
    }
}

/// All known authentication types, for suitable constants
#[derive(Clone)]
pub enum FlowType {
    /// [device authentication](https://developers.google.com/youtube/v3/guides/authentication#devices). Only works
    /// for certain scopes.
    /// Contains the device token URL; for google, that is
    /// https://accounts.google.com/o/oauth2/device/code (exported as `GOOGLE_DEVICE_CODE_URL`)
    Device(String),
    /// [installed app flow](https://developers.google.com/identity/protocols/OAuth2InstalledApp). Required
    /// for Drive, Calendar, Gmail...; Requires user to paste a code from the browser.
    InstalledInteractive,
    /// Same as InstalledInteractive, but uses a redirect: The OAuth provider redirects the user's
    /// browser to a web server that is running on localhost. This may not work as well with the
    /// Windows Firewall, but is more comfortable otherwise. The integer describes which port to
    /// bind to (default: 8080)
    InstalledRedirect(u16),
}

/// Represents either 'installed' or 'web' applications in a json secrets file.
/// See `ConsoleApplicationSecret` for more information
#[derive(Deserialize, Serialize, Clone, Default)]
pub struct ApplicationSecret {
    /// The client ID.
    pub client_id: String,
    /// The client secret.
    pub client_secret: String,
    /// The token server endpoint URI.
    pub token_uri: String,
    /// The authorization server endpoint URI.
    pub auth_uri: String,
    pub redirect_uris: Vec<String>,

    /// Name of the google project the credentials are associated with
    pub project_id: Option<String>,
    /// The service account email associated with the client.
    pub client_email: Option<String>,
    /// The URL of the public x509 certificate, used to verify the signature on JWTs, such
    /// as ID tokens, signed by the authentication provider.
    pub auth_provider_x509_cert_url: Option<String>,
    ///  The URL of the public x509 certificate, used to verify JWTs signed by the client.
    pub client_x509_cert_url: Option<String>,
}

/// A type to facilitate reading and writing the json secret file
/// as returned by the [google developer console](https://code.google.com/apis/console)
#[derive(Deserialize, Serialize, Default)]
pub struct ConsoleApplicationSecret {
    pub web: Option<ApplicationSecret>,
    pub installed: Option<ApplicationSecret>,
}

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

    pub const SECRET: &'static str =
        "{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\
         \"client_secret\":\"UqkDJd5RFwnHoiG5x5Rub8SI\",\"token_uri\":\"https://accounts.google.\
         com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:\
         oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\
         \"14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com\",\
         \"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}";

    #[test]
    fn console_secret() {
        use serde_json as json;
        match json::from_str::<ConsoleApplicationSecret>(SECRET) {
            Ok(s) => assert!(s.installed.is_some() && s.web.is_none()),
            Err(err) => panic!(err),
        }
    }

    #[test]
    fn schema() {
        let s = Scheme {
            token_type: TokenType::Bearer,
            access_token: "foo".to_string(),
        };
        let mut headers = hyper::HeaderMap::new();
        headers.insert(hyper::header::AUTHORIZATION, s.into());
        assert_eq!(
            format!("{:?}", headers),
            "{\"authorization\": \"Bearer foo\"}".to_string()
        );
    }

    #[test]
    fn parse_schema() {
        let auth = Scheme::from_str("Bearer foo").unwrap();
        assert_eq!(auth.token_type, TokenType::Bearer);
        assert_eq!(auth.access_token, "foo".to_string());
    }
}
<commit_msg>imp(expiry): Treat tokens with < 1 minute life left as expired.<commit_after>use chrono::{DateTime, TimeZone, Utc};
use hyper;
use std::error::Error;
use std::fmt;
use std::str::FromStr;

/// A marker trait for all Flows
pub trait Flow {
    fn type_id() -> FlowType;
}

#[derive(Deserialize)]
pub struct JsonError {
    pub error: String,
    pub error_description: Option<String>,
    pub error_uri: Option<String>,
}

/// Encapsulates all possible results of the `request_token(...)` operation
pub enum RequestError {
    /// Indicates connection failure
    ClientError(hyper::Error),
    /// Indicates HTTP status failure
    HttpError(hyper::http::Error),
    /// The OAuth client was not found
    InvalidClient,
    /// Some requested scopes were invalid. String contains the scopes as part of
    /// the server error message
    InvalidScope(String),
    /// A 'catch-all' variant containing the server error and description
    /// First string is the error code, the second may be a more detailed description
    NegativeServerResponse(String, Option<String>),
}

impl From<hyper::Error> for RequestError {
    fn from(error: hyper::Error) -> RequestError {
        RequestError::ClientError(error)
    }
}

impl From<hyper::http::Error> for RequestError {
    fn from(error: hyper::http::Error) -> RequestError {
        RequestError::HttpError(error)
    }
}

impl From<JsonError> for RequestError {
    fn from(value: JsonError) -> RequestError {
        match &*value.error {
            "invalid_client" => RequestError::InvalidClient,
            "invalid_scope" => RequestError::InvalidScope(
                value
                    .error_description
                    .unwrap_or("no description provided".to_string()),
            ),
            _ => RequestError::NegativeServerResponse(value.error, value.error_description),
        }
    }
}

impl fmt::Display for RequestError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            RequestError::ClientError(ref err) => err.fmt(f),
            RequestError::HttpError(ref err) => err.fmt(f),
            RequestError::InvalidClient => "Invalid Client".fmt(f),
            RequestError::InvalidScope(ref scope) => writeln!(f, "Invalid Scope: '{}'", scope),
            RequestError::NegativeServerResponse(ref error, ref desc) => {
                error.fmt(f)?;
                if let &Some(ref desc) = desc {
                    write!(f, ": {}", desc)?;
                }
                "\n".fmt(f)
            }
        }
    }
}

#[derive(Debug)]
pub struct StringError {
    error: String,
}

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

impl StringError {
    pub fn new(error: String, desc: Option<&String>) -> StringError {
        let mut error = error;
        if let Some(d) = desc {
            error.push_str(": ");
            error.push_str(&*d);
        }

        StringError { error: error }
    }
}

impl<'a> From<&'a dyn Error> for StringError {
    fn from(err: &'a dyn Error) -> StringError {
        StringError::new(err.description().to_string(), None)
    }
}

impl From<String> for StringError {
    fn from(value: String) -> StringError {
        StringError::new(value, None)
    }
}

impl Error for StringError {
    fn description(&self) -> &str {
        &self.error
    }
}

/// Represents all implemented token types
#[derive(Clone, PartialEq, Debug)]
pub enum TokenType {
    /// Means that whoever bears the access token will be granted access
    Bearer,
}

impl AsRef<str> for TokenType {
    fn as_ref(&self) -> &'static str {
        match *self {
            TokenType::Bearer => "Bearer",
        }
    }
}

impl FromStr for TokenType {
    type Err = ();
    fn from_str(s: &str) -> Result<TokenType, ()> {
        match s {
            "Bearer" => Ok(TokenType::Bearer),
            _ => Err(()),
        }
    }
}

/// A scheme for use in `hyper::header::Authorization`
#[derive(Clone, PartialEq, Debug)]
pub struct Scheme {
    /// The type of our access token
    pub token_type: TokenType,
    /// The token returned by one of the Authorization Flows
    pub access_token: String,
}

impl std::convert::Into<hyper::header::HeaderValue> for Scheme {
    fn into(self) -> hyper::header::HeaderValue {
        hyper::header::HeaderValue::from_str(&format!(
            "{} {}",
            self.token_type.as_ref(),
            self.access_token
        ))
        .expect("Invalid Scheme header value")
    }
}

impl FromStr for Scheme {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Scheme, &'static str> {
        let parts: Vec<&str> = s.split(' ').collect();
        if parts.len() != 2 {
            return Err("Expected two parts: <token_type> <token>");
        }
        match <TokenType as FromStr>::from_str(parts[0]) {
            Ok(t) => Ok(Scheme {
                token_type: t,
                access_token: parts[1].to_string(),
            }),
            Err(_) => Err("Couldn't parse token type"),
        }
    }
}

/// Represents a token as returned by OAuth2 servers.
///
/// It is produced by all authentication flows.
/// It authenticates certain operations, and must be refreshed once
/// it reached it's expiry date.
///
/// The type is tuned to be suitable for direct de-serialization from server
/// replies, as well as for serialization for later reuse. This is the reason
/// for the two fields dealing with expiry - once in relative in and once in
/// absolute terms.
///
/// Utility methods make common queries easier, see `expired()`.
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct Token {
    /// used when authenticating calls to oauth2 enabled services.
    pub access_token: String,
    /// used to refresh an expired access_token.
    pub refresh_token: String,
    /// The token type as string - usually 'Bearer'.
    pub token_type: String,
    /// access_token will expire after this amount of time.
    /// Prefer using expiry_date()
    pub expires_in: Option<i64>,
    /// timestamp is seconds since epoch indicating when the token will expire in absolute terms.
    /// use expiry_date() to convert to DateTime.
    pub expires_in_timestamp: Option<i64>,
}

impl Token {
    /// Returns true if we are expired.
    ///
    /// # Panics
    /// * if our access_token is unset
    pub fn expired(&self) -> bool {
        if self.access_token.len() == 0 {
            panic!("called expired() on unset token");
        }
        self.expiry_date() - chrono::Duration::minutes(1) <= Utc::now()
    }

    /// Returns a DateTime object representing our expiry date.
    pub fn expiry_date(&self) -> DateTime<Utc> {
        Utc.timestamp(
            self.expires_in_timestamp
                .expect("Tokens without an absolute expiry are invalid"),
            0,
        )
    }

    /// Adjust our stored expiry format to be absolute, using the current time.
    pub fn set_expiry_absolute(&mut self) -> &mut Token {
        if self.expires_in_timestamp.is_some() {
            assert!(self.expires_in.is_none());
            return self;
        }

        self.expires_in_timestamp = Some(Utc::now().timestamp() + self.expires_in.unwrap());
        self.expires_in = None;
        self
    }
}

/// All known authentication types, for suitable constants
#[derive(Clone)]
pub enum FlowType {
    /// [device authentication](https://developers.google.com/youtube/v3/guides/authentication#devices). Only works
    /// for certain scopes.
    /// Contains the device token URL; for google, that is
    /// https://accounts.google.com/o/oauth2/device/code (exported as `GOOGLE_DEVICE_CODE_URL`)
    Device(String),
    /// [installed app flow](https://developers.google.com/identity/protocols/OAuth2InstalledApp). Required
    /// for Drive, Calendar, Gmail...; Requires user to paste a code from the browser.
    InstalledInteractive,
    /// Same as InstalledInteractive, but uses a redirect: The OAuth provider redirects the user's
    /// browser to a web server that is running on localhost. This may not work as well with the
    /// Windows Firewall, but is more comfortable otherwise. The integer describes which port to
    /// bind to (default: 8080)
    InstalledRedirect(u16),
}

/// Represents either 'installed' or 'web' applications in a json secrets file.
/// See `ConsoleApplicationSecret` for more information
#[derive(Deserialize, Serialize, Clone, Default)]
pub struct ApplicationSecret {
    /// The client ID.
    pub client_id: String,
    /// The client secret.
    pub client_secret: String,
    /// The token server endpoint URI.
    pub token_uri: String,
    /// The authorization server endpoint URI.
    pub auth_uri: String,
    pub redirect_uris: Vec<String>,

    /// Name of the google project the credentials are associated with
    pub project_id: Option<String>,
    /// The service account email associated with the client.
    pub client_email: Option<String>,
    /// The URL of the public x509 certificate, used to verify the signature on JWTs, such
    /// as ID tokens, signed by the authentication provider.
    pub auth_provider_x509_cert_url: Option<String>,
    ///  The URL of the public x509 certificate, used to verify JWTs signed by the client.
    pub client_x509_cert_url: Option<String>,
}

/// A type to facilitate reading and writing the json secret file
/// as returned by the [google developer console](https://code.google.com/apis/console)
#[derive(Deserialize, Serialize, Default)]
pub struct ConsoleApplicationSecret {
    pub web: Option<ApplicationSecret>,
    pub installed: Option<ApplicationSecret>,
}

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

    pub const SECRET: &'static str =
        "{\"installed\":{\"auth_uri\":\"https://accounts.google.com/o/oauth2/auth\",\
         \"client_secret\":\"UqkDJd5RFwnHoiG5x5Rub8SI\",\"token_uri\":\"https://accounts.google.\
         com/o/oauth2/token\",\"client_email\":\"\",\"redirect_uris\":[\"urn:ietf:wg:oauth:2.0:\
         oob\",\"oob\"],\"client_x509_cert_url\":\"\",\"client_id\":\
         \"14070749909-vgip2f1okm7bkvajhi9jugan6126io9v.apps.googleusercontent.com\",\
         \"auth_provider_x509_cert_url\":\"https://www.googleapis.com/oauth2/v1/certs\"}}";

    #[test]
    fn console_secret() {
        use serde_json as json;
        match json::from_str::<ConsoleApplicationSecret>(SECRET) {
            Ok(s) => assert!(s.installed.is_some() && s.web.is_none()),
            Err(err) => panic!(err),
        }
    }

    #[test]
    fn schema() {
        let s = Scheme {
            token_type: TokenType::Bearer,
            access_token: "foo".to_string(),
        };
        let mut headers = hyper::HeaderMap::new();
        headers.insert(hyper::header::AUTHORIZATION, s.into());
        assert_eq!(
            format!("{:?}", headers),
            "{\"authorization\": \"Bearer foo\"}".to_string()
        );
    }

    #[test]
    fn parse_schema() {
        let auth = Scheme::from_str("Bearer foo").unwrap();
        assert_eq!(auth.token_type, TokenType::Bearer);
        assert_eq!(auth.access_token, "foo".to_string());
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use blas::ddot;
use std::cmp::min;
use std::f64;

pub fn dot(x: &[f64], y: &[f64]) -> f64 {
    let n: i32 = min(x.len() as i32, y.len() as i32);

    unsafe { ddot(n, x, 1, y, 1) }
}

pub fn argmaxima(vals: &[f64]) -> (f64, Vec<usize>) {
    let mut max = f64::MIN;
    let mut ixs = vec![];

    for (i, &v) in vals.iter().enumerate() {
        if (v - max).abs() < 1e-7 {
            ixs.push(i);
        } else if v > max {
            max = v;
            ixs.clear();
            ixs.push(i);
        }
    }

    (max, ixs)
}

// TODO: Pass by iterator so that we don't have to collect before passing.
pub fn sub2ind(dims: &[usize], inds: &[usize]) -> usize {
    let d_it = dims.iter().rev().skip(1);
    let i_it = inds.iter().rev().skip(1);

    d_it.zip(i_it).fold(inds.last().cloned().unwrap(), |acc, (d, i)| i + d * acc)
}

pub fn cartesian_product<T: Clone>(lists: &Vec<Vec<T>>) -> Vec<Vec<T>> {
    fn partial_cartesian<T: Clone>(u: Vec<Vec<T>>, v: &Vec<T>) -> Vec<Vec<T>> {
        u.into_iter()
            .flat_map(|xs| {
                v.iter()
                    .cloned()
                    .map(|y| {
                        let mut vec = xs.clone();
                        vec.push(y);
                        vec
                    })
                    .collect::<Vec<_>>()
            })
            .collect()
    }

    match lists.split_first() {
        Some((head, tail)) => {
            let init: Vec<Vec<T>> = head.iter().cloned().map(|n| vec![n]).collect();

            tail.iter().cloned().fold(init, |vec, list| partial_cartesian(vec, &list))
        }
        None => vec![],
    }
}

#[cfg(test)]
mod tests {
    use super::{sub2ind, cartesian_product};

    #[test]
    fn test_sub2ind() {
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![3, 0, 0]), 3);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 0, 5]), 177);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 5, 5]), 202);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![0, 0, 11]), 385);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![5, 0, 11]), 390);
    }

    #[test]
    #[should_panic]
    fn test_sub2ind_empty() {
        sub2ind(&vec![], &vec![]);
    }

    #[test]
    fn test_cartesian_product() {
        let to_combine = vec![vec![0.0, 1.0, 2.0], vec![7.0, 8.0, 9.0]];

        let combs = cartesian_product(&to_combine);

        assert_eq!(combs[0], vec![0.0, 7.0]);
        assert_eq!(combs[1], vec![0.0, 8.0]);
        assert_eq!(combs[2], vec![0.0, 9.0]);

        assert_eq!(combs[3], vec![1.0, 7.0]);
        assert_eq!(combs[4], vec![1.0, 8.0]);
        assert_eq!(combs[5], vec![1.0, 9.0]);

        assert_eq!(combs[6], vec![2.0, 7.0]);
        assert_eq!(combs[7], vec![2.0, 8.0]);
        assert_eq!(combs[8], vec![2.0, 9.0]);
    }
}
<commit_msg>refactor: clean up `cartesian_product` utility functions<commit_after>#![allow(dead_code)]

use blas::ddot;
use std::cmp::min;
use std::f64;

pub fn dot(x: &[f64], y: &[f64]) -> f64 {
    let n: i32 = min(x.len() as i32, y.len() as i32);

    unsafe { ddot(n, x, 1, y, 1) }
}

pub fn argmaxima(vals: &[f64]) -> (f64, Vec<usize>) {
    let mut max = f64::MIN;
    let mut ixs = vec![];

    for (i, &v) in vals.iter().enumerate() {
        if (v - max).abs() < 1e-7 {
            ixs.push(i);
        } else if v > max {
            max = v;
            ixs.clear();
            ixs.push(i);
        }
    }

    (max, ixs)
}

// TODO: Pass by iterator so that we don't have to collect before passing.
pub fn sub2ind(dims: &[usize], inds: &[usize]) -> usize {
    let d_it = dims.iter().rev().skip(1);
    let i_it = inds.iter().rev().skip(1);

    d_it.zip(i_it).fold(inds.last().cloned().unwrap(), |acc, (d, i)| i + d * acc)
}

/// Given a vector containing a partial Cartesian product, and a list of items,
/// return a vector adding the list of items to the partial Cartesian product.
///
/// # Example
///
/// ```
/// let partial_product = vec![vec![1, 4], vec![1, 5], vec![2, 4], vec![2, 5]];
/// let items = &[6, 7];
/// let next_product = partial_cartesian(partial_product, items);
/// assert_eq!(next_product, vec![vec![1, 4, 6],
///                               vec![1, 4, 7],
///                               vec![1, 5, 6],
///                               vec![1, 5, 7],
///                               vec![2, 4, 6],
///                               vec![2, 4, 7],
///                               vec![2, 5, 6],
///                               vec![2, 5, 7]]);
/// ```
///
/// Pulled from [here](https://gist.github.com/kylewlacy/115965b40e02a3325558).
pub fn partial_cartesian<T: Clone>(a: Vec<Vec<T>>, b: &Vec<T>) -> Vec<Vec<T>> {
    a.into_iter().flat_map(|xs| {
        b.iter().cloned().map(|y| {
            let mut vec = xs.clone();
            vec.push(y);
            vec
        }).collect::<Vec<_>>()
    }).collect()
}

/// Computes the Cartesian product of lists[0] * lists[1] * ... * lists[n].
///
/// # Example
///
/// ```
/// let lists: &[&[_]] = &[&[1, 2], &[4, 5], &[6, 7]];
/// let product = cartesian_product(lists);
/// assert_eq!(product, vec![vec![1, 4, 6],
///                          vec![1, 4, 7],
///                          vec![1, 5, 6],
///                          vec![1, 5, 7],
///                          vec![2, 4, 6],
///                          vec![2, 4, 7],
///                          vec![2, 5, 6],
///                          vec![2, 5, 7]]);
/// ```
///
/// Pulled from [here](https://gist.github.com/kylewlacy/115965b40e02a3325558).
pub fn cartesian_product<T: Clone>(lists: &Vec<Vec<T>>) -> Vec<Vec<T>> {
    match lists.split_first() {
        Some((first, rest)) => {
            let init: Vec<Vec<T>> = first.iter().cloned().map(|n| vec![n]).collect();

            rest.iter().cloned().fold(init, |vec, list| {
                partial_cartesian(vec, &list)
            })
        },
        None => {
            vec![]
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{sub2ind, cartesian_product};

    #[test]
    fn test_sub2ind() {
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![3, 0, 0]), 3);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 0, 5]), 177);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 5, 5]), 202);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![0, 0, 11]), 385);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![5, 0, 11]), 390);
    }

    #[test]
    #[should_panic]
    fn test_sub2ind_empty() {
        sub2ind(&vec![], &vec![]);
    }

    #[test]
    fn test_cartesian_product() {
        let to_combine = vec![vec![0.0, 1.0, 2.0], vec![7.0, 8.0, 9.0]];

        let combs = cartesian_product(&to_combine);

        assert_eq!(combs[0], vec![0.0, 7.0]);
        assert_eq!(combs[1], vec![0.0, 8.0]);
        assert_eq!(combs[2], vec![0.0, 9.0]);

        assert_eq!(combs[3], vec![1.0, 7.0]);
        assert_eq!(combs[4], vec![1.0, 8.0]);
        assert_eq!(combs[5], vec![1.0, 9.0]);

        assert_eq!(combs[6], vec![2.0, 7.0]);
        assert_eq!(combs[7], vec![2.0, 8.0]);
        assert_eq!(combs[8], vec![2.0, 9.0]);
    }
}
<|endoftext|>


<commit_before>extern crate reqwest;

use std::str;
use std::io::{self, Read};

use self::reqwest::Client;
use self::reqwest::header::Connection;

pub fn download(max_kib: usize, url: &str) -> Option<String> {
    let response = Client::new().get(url).header(Connection::close()).send();

    match response {
        Ok(mut response) => {
            let mut body = String::new();

            // 500 kilobyte buffer
            let mut buf = [0; 500 * 1000];
            let mut written = 0;
            // Read until we reach EOF or max_kib KiB
            loop {
                let len = match response.read(&mut buf) {
                    Ok(0) => break,
                    Ok(len) => len,
                    Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                    Err(e) => {
                        debug!("Download from {:?} failed: {}", url, e);
                        return None;
                    }
                };

                let slice = match str::from_utf8(&buf[..len]) {
                    Ok(slice) => slice,
                    Err(e) => {
                        debug!("Failed to read bytes from {:?} as UTF8: {}", url, e);
                        return None;
                    }
                };

                body.push_str(slice);
                written += len;

                // Check if the file is too large to download
                if written > max_kib * 1024 {
                    debug!(
                        "Stopping download - File from {:?} is larger than {} KiB",
                        url, max_kib
                    );
                    return None;
                }
            }
            Some(body)
        }
        Err(e) => {
            debug!("Bad response from {:?}: ({})", url, e);
            None
        }
    }
}
<commit_msg>Fix UTF8 errors in the download function<commit_after>extern crate reqwest;

use std::str;
use std::io::{self, Read};

use self::reqwest::Client;
use self::reqwest::header::Connection;

pub fn download(max_kib: usize, url: &str) -> Option<String> {
    let response = Client::new().get(url).header(Connection::close()).send();

    match response {
        Ok(mut response) => {
            let mut body = String::new();

            // 100 kibibyte buffer
            let mut buf = [0; 100 * 1024];
            let mut written = 0;
            let mut vec = Vec::new();
            let mut end_of_valid = None;

            // Read until we reach EOF or max_kib KiB
            loop {
                if let Some(eov) = end_of_valid {
                    vec = vec[..eov].to_vec();
                }

                let len = match response.read(&mut buf) {
                    Ok(0) => break,
                    Ok(len) => len,
                    Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                    Err(e) => {
                        debug!("Download from {:?} failed: {}", url, e);
                        return None;
                    }
                };
                vec.extend_from_slice(&buf);

                end_of_valid = None;
                let body_slice = match str::from_utf8(&vec[..len]) {
                    Ok(slice) => slice,
                    Err(e) => {
                        let valid = e.valid_up_to();
                        if valid == 0 {
                            error!("Failed to read bytes from {:?} as UTF8: {}", url, e);
                            return None;
                        }
                        end_of_valid = Some(valid);

                        str::from_utf8(&buf[..valid]).unwrap()
                    }
                };

                body.push_str(body_slice);
                written += len;

                // Check if the file is too large to download
                if written > max_kib * 1024 {
                    debug!(
                        "Stopping download - File from {:?} is larger than {} KiB",
                        url, max_kib
                    );
                    return None;
                }
            }
            Some(body)
        }
        Err(e) => {
            debug!("Bad response from {:?}: ({})", url, e);
            None
        }
    }
}
<|endoftext|>


<commit_before>use std::{net, num};

fn parse_ip_v4(raw_addr: &str) -> Result<net::Ipv4Addr, String> {
    let octets: Vec<u8> = raw_addr.splitn(4, '.')
                                  .map(|octet| octet.parse::<u8>())
                                  .filter_map(|octet| {
                                      if octet.is_ok() {
                                          octet.ok()
                                      } else {
                                          None
                                      }
                                  })
                                  .collect();

    if octets.len() < 4 {
        Err(format!("There was an error parsing the IPv4 address: {}", raw_addr))
    } else {
        Ok(net::Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]))
    }
}

fn parse_port(raw_port: &str) -> Result<u16, num::ParseIntError> {
    raw_port.parse()
}

/// Parses a given IPv4 address with `:` seperated port and
/// returns a `Result<(net::Ipv4Addr, u16), String>`
///
/// # Example
///
/// ```
/// use std::net;
/// use rosc::utils;
/// let addr = "127.0.0.1:1234";
/// match utils::parse_ip_and_port(&addr.to_string()) {
///   Ok((ip, port)) => { let sock = net::UdpSocket::bind((ip, port)); },
///   Err(e) => panic!(e),
/// }
/// ```
pub fn parse_ip_and_port(raw_addr: &String) -> Result<(net::Ipv4Addr, u16), String> {
    let parts: Vec<&str> = raw_addr.splitn(2, ':').collect();
    match parts.len() {
        2 => {
            let ip: Result<net::Ipv4Addr, String> = parse_ip_v4(parts[0]);
            let port: Result<u16, num::ParseIntError> = parse_port(parts[1]);
            match ip {
                Ok(ip) => {
                    match port {
                        Ok(port) => Ok((ip, port)),
                        Err(e) => Err(format!("Bad port value: {}", e)),
                    }
                }
                Err(e) => Err(format!("Bad IPv4 address: {}", e)),
            }
        }
        _ => Err(format!("Bad address: {}, Missing port?", raw_addr)),
    }
}
<commit_msg>Extracted four byte padding function to `utils`<commit_after>use std::{net, num};

fn parse_ip_v4(raw_addr: &str) -> Result<net::Ipv4Addr, String> {
    let octets: Vec<u8> = raw_addr.splitn(4, '.')
                                  .map(|octet| octet.parse::<u8>())
                                  .filter_map(|octet| {
                                      if octet.is_ok() {
                                          octet.ok()
                                      } else {
                                          None
                                      }
                                  })
                                  .collect();

    if octets.len() < 4 {
        Err(format!("There was an error parsing the IPv4 address: {}", raw_addr))
    } else {
        Ok(net::Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]))
    }
}

fn parse_port(raw_port: &str) -> Result<u16, num::ParseIntError> {
    raw_port.parse()
}

/// Parses a given IPv4 address with `:` seperated port and
/// returns a `Result<(net::Ipv4Addr, u16), String>`
///
/// # Example
///
/// ```
/// use std::net;
/// use rosc::utils;
/// let addr = "127.0.0.1:1234";
/// match utils::parse_ip_and_port(&addr.to_string()) {
///   Ok((ip, port)) => { let sock = net::UdpSocket::bind((ip, port)); },
///   Err(e) => panic!(e),
/// }
/// ```
pub fn parse_ip_and_port(raw_addr: &String) -> Result<(net::Ipv4Addr, u16), String> {
    let parts: Vec<&str> = raw_addr.splitn(2, ':').collect();
    match parts.len() {
        2 => {
            let ip: Result<net::Ipv4Addr, String> = parse_ip_v4(parts[0]);
            let port: Result<u16, num::ParseIntError> = parse_port(parts[1]);
            match ip {
                Ok(ip) => {
                    match port {
                        Ok(port) => Ok((ip, port)),
                        Err(e) => Err(format!("Bad port value: {}", e)),
                    }
                }
                Err(e) => Err(format!("Bad IPv4 address: {}", e)),
            }
        }
        _ => Err(format!("Bad address: {}, Missing port?", raw_addr)),
    }
}

/// Returns the 4-byte padded position
///
/// # Example
///
/// ```
/// use rosc::utils;
/// let pos: u64 = 10;
/// assert_eq!(12u64, utils::pad(pos))
/// ```
pub fn pad(pos: u64) -> u64 {
    match pos % 4 {
        0 => 0,
        d => pos + (4-d)
    }
}<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::str::Chars;
use unicode_normalization::char::{canonical_combining_class, decompose_compatible};
use unicode_normalization::UnicodeNormalization;
use unidecode::unidecode_char;

const HYPHENS: &str = "-\u{2010}‑‒–—―−－﹘﹣";
const ASCII_UNUSUAL_WHITESPACE: &[char] = &['\t', '\r', '\n'];

pub fn is_mixed_case(s: &str) -> bool {
    let mut has_lowercase = false;
    let mut has_uppercase = false;

    for c in s.chars() {
        if c.is_uppercase() {
            has_uppercase = true;
        };
        if c.is_lowercase() {
            has_lowercase = true;
        };
        if has_lowercase && has_uppercase {
            return true;
        };
    }

    false
}

#[inline]
pub fn is_combining(c: char) -> bool {
    canonical_combining_class(c) > 0
}

#[inline]
pub fn is_ascii_alphabetic(c: char) -> bool {
    match c {
        'a'...'z' => true,
        'A'...'Z' => true,
        _ => false,
    }
}

// Sadly necessary because string split gives "type of this value must be known"
// compilation error when passed a closure in some contexts
#[inline]
pub fn is_nonalphanumeric(c: char) -> bool {
    !c.is_alphanumeric()
}

#[inline]
pub fn lowercase_if_alpha(c: char) -> Option<char> {
    if c.is_uppercase() {
        c.to_lowercase().next()
    } else if c.is_alphabetic() {
        Some(c)
    } else {
        None
    }
}

#[inline]
pub fn uppercase_if_alpha(c: char) -> Option<char> {
    if c.is_lowercase() {
        c.to_uppercase().next()
    } else if c.is_alphabetic() {
        Some(c)
    } else {
        None
    }
}

#[inline]
pub fn transliterate(c: char) -> Chars<'static> {
    unidecode_char(c).chars()
}

#[inline]
pub fn to_ascii_letter(c: char) -> Option<char> {
    debug_assert!(c.is_uppercase(), c.to_string());
    match c {
        'A'...'Z' => Some(c),
        _ => match transliterate(c).next() {
            Some(c) => c.to_uppercase().next(),
            None => None,
        },
    }
}

pub fn to_ascii(s: &str) -> Cow<str> {
    if s.is_ascii() {
        Cow::Borrowed(s)
    } else {
        let mut capitalized_any = false;

        Cow::Owned(
            s.chars()
                .flat_map(transliterate)
                .filter_map(|c| {
                    if !c.is_alphabetic() {
                        None
                    } else if c.is_uppercase() && !capitalized_any {
                        capitalized_any = true;
                        Some(c)
                    } else if c.is_lowercase() && capitalized_any {
                        Some(c)
                    } else {
                        c.to_lowercase().next()
                    }
                })
                .collect(),
        )
    }
}

pub fn capitalize_word(word: &str, simple: bool) -> String {
    debug_assert!(simple == word.chars().all(is_ascii_alphabetic));

    if simple {
        let bytes = word.as_bytes();
        let mut result = String::with_capacity(word.len());
        result.push(bytes[0].to_ascii_uppercase() as char);
        result.extend(bytes[1..].iter().map(|c| c.to_ascii_lowercase() as char));
        result
    } else {
        let mut capitalize_next = true;

        word.chars()
            .map(|c| {
                let result = if capitalize_next {
                    c.to_uppercase().next()
                } else {
                    c.to_lowercase().next()
                }
                .unwrap();

                // If the character doesn't have both uppercase and lowercase versions,
                // it'll be unchanged. That's a prerequisite for it being a separator.
                capitalize_next = result == c && !c.is_alphanumeric() && !is_combining(c);

                result
            })
            .collect()
    }
}

// Ideally we'd use the unicode standard `quick_check` algorithm, but Rust
// doesn't expose that for compatibility forms, and this is simpler to implement,
// though it will have more false negatives.
fn stable_nfkd(c: char) -> bool {
    if is_combining(c) {
        false
    } else {
        let mut stable = true;
        decompose_compatible(c, |d| stable = stable && d == c);
        stable
    }
}

pub fn normalize_nfkd_hyphens_spaces(string: &str) -> Cow<str> {
    if string.is_ascii() && !string.contains(ASCII_UNUSUAL_WHITESPACE) {
        Cow::Borrowed(string)
    } else if string
        .chars()
        .all(|c| stable_nfkd(c) && (c == ' ' || !c.is_whitespace()))
    {
        Cow::Borrowed(string)
    } else {
        let string = string
            .nfkd()
            .map(|c| {
                if HYPHENS.contains(c) {
                    '-'
                } else if c.is_whitespace() {
                    ' '
                } else {
                    c
                }
            })
            .collect();

        Cow::Owned(string)
    }
}

#[derive(Debug, Clone)]
pub struct CharacterCounts {
    pub chars: u8,
    pub alpha: u8,
    pub upper: u8,
    pub ascii_alpha: u8,
    pub ascii_vowels: u8,
}

pub fn categorize_chars(word: &str) -> CharacterCounts {
    debug_assert!(word.len() <= u8::max_value() as usize);

    let mut chars = 0;
    let mut alpha = 0;
    let mut upper = 0;
    let mut ascii_alpha = 0;
    let mut ascii_vowels = 0;

    for c in word.chars() {
        match c {
            'a'...'z' => {
                if "aeiouy".contains(c) {
                    ascii_vowels += 1;
                } else {
                    ascii_alpha += 1;
                }
            }
            'A'...'Z' => {
                if "AEIOUY".contains(c) {
                    ascii_vowels += 1;
                } else {
                    ascii_alpha += 1;
                }
                upper += 1;
            }
            _ if c.is_uppercase() => {
                alpha += 1;
                upper += 1;
            }
            _ if c.is_alphabetic() => {
                alpha += 1;
            }
            _ => {
                chars += 1;
            }
        }
    }

    // Maybe skipping individual increments and doing this instead is
    // premature optimization, but why not
    ascii_alpha += ascii_vowels;
    alpha += ascii_alpha;
    chars += alpha;

    CharacterCounts {
        chars,
        alpha,
        upper,
        ascii_alpha,
        ascii_vowels,
    }
}

pub fn starts_with_consonant(word: &str) -> bool {
    match word.chars().nth(0) {
        Some(c) => is_ascii_alphabetic(c) && !"aeiouAEIOU".contains(c),
        None => false,
    }
}

pub fn starts_with_uppercase(word: &str) -> bool {
    word.chars().take(1).all(char::is_uppercase)
}

pub fn combining_chars(word: &str) -> usize {
    word.chars().filter(|c| is_combining(*c)).count()
}

pub fn has_sequential_alphas(word: &str) -> bool {
    let mut iter = word.chars().peekable();
    while let Some(c) = iter.next() {
        match iter.peek() {
            Some(nc) => {
                if c.is_alphabetic() && nc.is_alphabetic() {
                    return true;
                }
            }
            None => {
                break;
            }
        }
    }

    false
}

#[macro_export]
macro_rules! eq_or_starts_with {
    ($a:expr, $b:expr) => {{
        let mut chars_a = $a.chars().filter_map(lowercase_if_alpha);
        let mut chars_b = $b.chars().filter_map(lowercase_if_alpha);
        let result;

        loop {
            let a = chars_a.next();
            let b = chars_b.next();

            if a.is_none() || b.is_none() {
                result = true;
                break;
            } else if a != b {
                result = false;
                break;
            }
        }

        result
    }};
}

#[macro_export]
macro_rules! eq_or_ends_with {
    ($needle:expr, $haystack:expr) => {{
        let mut n_chars = $needle.chars().rev().filter_map(lowercase_if_alpha);
        let mut h_chars = $haystack.chars().rev().filter_map(lowercase_if_alpha);
        let result;

        loop {
            let n = n_chars.next();
            let h = h_chars.next();

            if n.is_none() {
                result = true;
                break;
            } else if n != h {
                result = false;
                break;
            }
        }

        result
    }};
}

#[cfg(test)]
mod tests {
    use super::*;
    use test::{black_box, Bencher};

    #[test]
    fn sequential_alphas() {
        assert!(has_sequential_alphas("ab"));
        assert!(has_sequential_alphas("abc"));
        assert!(has_sequential_alphas("a.bc"));
        assert!(has_sequential_alphas("鄭a"));
        assert!(!has_sequential_alphas(""));
        assert!(!has_sequential_alphas("a"));
        assert!(!has_sequential_alphas("a.b"));
        assert!(!has_sequential_alphas("鄭.a"));
        assert!(!has_sequential_alphas("ﾟ."));
    }

    #[test]
    fn capitalization() {
        assert_eq!("A", capitalize_word("a", true));
        assert_eq!("Aa", capitalize_word("aa", true));
        assert_eq!("Aa", capitalize_word("AA", true));
    }

    #[bench]
    fn is_mixed_case_false(b: &mut Bencher) {
        b.iter(|| black_box(is_mixed_case("JOHN MACDONALD")))
    }

    #[bench]
    fn is_mixed_case_true(b: &mut Bencher) {
        b.iter(|| black_box(is_mixed_case("J. MacDonald")))
    }

    #[bench]
    fn capitalize_uppercase_word(b: &mut Bencher) {
        b.iter(|| black_box(capitalize_word("JONATHAN", true)))
    }

    #[bench]
    fn capitalize_complex_word(b: &mut Bencher) {
        b.iter(|| black_box(capitalize_word("föö-bar", false)))
    }

    #[bench]
    fn normalize_ascii(b: &mut Bencher) {
        b.iter(|| black_box(normalize_nfkd_hyphens_spaces("James 'J' S. Brown MD").len()))
    }

    #[bench]
    fn normalize_nfkd_stable(b: &mut Bencher) {
        b.iter(|| black_box(normalize_nfkd_hyphens_spaces("James «J» S. Brown MD").len()))
    }

    #[bench]
    fn normalize_needs_fix(b: &mut Bencher) {
        b.iter(|| black_box(normalize_nfkd_hyphens_spaces("James 'J' S. Bröwn MD").len()))
    }
}
<commit_msg>microoptimizations and cleanup in utils<commit_after>use std::borrow::Cow;
use std::str::Chars;
use unicode_normalization::char::{canonical_combining_class, decompose_compatible};
use unicode_normalization::UnicodeNormalization;
use unidecode::unidecode_char;

const HYPHENS: &str = "-\u{2010}‑‒–—―−－﹘﹣";
const ASCII_UNUSUAL_WHITESPACE: &[char] = &['\t', '\r', '\n'];

pub fn is_mixed_case(s: &str) -> bool {
    let mut has_lowercase = false;
    let mut has_uppercase = false;
    let mut iter = s.chars();

    loop {
        match iter.next() {
            Some(c) => {
                if c.is_uppercase() {
                    has_uppercase = true;
                    break;
                } else if c.is_lowercase() {
                    has_lowercase = true;
                    break;
                }
            }
            None => {
                return false;
            }
        }
    }

    if has_lowercase {
        iter.any(|c| c.is_uppercase())
    } else {
        debug_assert!(has_uppercase);
        iter.any(|c| c.is_lowercase())
    }
}

#[inline]
pub fn is_combining(c: char) -> bool {
    canonical_combining_class(c) > 0
}

#[inline]
pub fn is_ascii_alphabetic(c: char) -> bool {
    match c {
        'a'...'z' => true,
        'A'...'Z' => true,
        _ => false,
    }
}

// Sadly necessary because string split gives "type of this value must be known"
// compilation error when passed a closure in some contexts
#[inline]
pub fn is_nonalphanumeric(c: char) -> bool {
    !c.is_alphanumeric()
}

#[inline]
pub fn lowercase_if_alpha(c: char) -> Option<char> {
    if c.is_uppercase() {
        c.to_lowercase().next()
    } else if c.is_alphabetic() {
        Some(c)
    } else {
        None
    }
}

#[inline]
pub fn uppercase_if_alpha(c: char) -> Option<char> {
    if c.is_lowercase() {
        c.to_uppercase().next()
    } else if c.is_alphabetic() {
        Some(c)
    } else {
        None
    }
}

#[inline]
pub fn transliterate(c: char) -> Chars<'static> {
    unidecode_char(c).chars()
}

#[inline]
pub fn to_ascii_letter(c: char) -> Option<char> {
    debug_assert!(c.is_uppercase(), c.to_string());
    match c {
        'A'...'Z' => Some(c),
        _ => transliterate(c)
            .next()
            .and_then(|c| c.to_uppercase().next()),
    }
}

pub fn to_ascii(s: &str) -> Cow<str> {
    if s.is_ascii() {
        Cow::Borrowed(s)
    } else {
        let mut capitalized_any = false;

        // When transliterating, allow the first character to be either
        // capitalized or lowercase, but otherwise enforce lowercase.
        // Also drop any non-alphabetic characters.
        Cow::Owned(
            s.chars()
                .flat_map(transliterate)
                .filter_map(|c| {
                    if c.is_uppercase() {
                        if !capitalized_any {
                            capitalized_any = true;
                            Some(c)
                        } else {
                            c.to_lowercase().next()
                        }
                    } else if c.is_alphabetic() {
                        Some(c)
                    } else {
                        None
                    }
                })
                .collect(),
        )
    }
}

pub fn capitalize_word(word: &str, simple: bool) -> String {
    debug_assert!(simple == word.chars().all(is_ascii_alphabetic));

    if simple {
        let bytes = word.as_bytes();
        let mut result = String::with_capacity(word.len());
        result.push(bytes[0].to_ascii_uppercase() as char);
        result.extend(bytes[1..].iter().map(|c| c.to_ascii_lowercase() as char));
        result
    } else {
        let mut capitalize_next = true;

        word.chars()
            .map(|c| {
                let result = if capitalize_next {
                    c.to_uppercase().next()
                } else {
                    c.to_lowercase().next()
                }
                .unwrap();

                // If the character doesn't have both uppercase and lowercase versions,
                // it'll be unchanged. That's a prerequisite for it being a separator.
                capitalize_next = result == c && !c.is_alphanumeric() && !is_combining(c);

                result
            })
            .collect()
    }
}

// Ideally we'd use the unicode standard `quick_check` algorithm, but Rust
// doesn't expose that for compatibility forms, and this is simpler to implement,
// though it will have more false negatives.
#[inline]
fn stable_nfkd(c: char) -> bool {
    if is_combining(c) {
        false
    } else {
        let mut stable = true;
        decompose_compatible(c, |d| stable = stable && d == c);
        stable
    }
}

pub fn normalize_nfkd_hyphens_spaces(string: &str) -> Cow<str> {
    if string.is_ascii() && !string.contains(ASCII_UNUSUAL_WHITESPACE) {
        Cow::Borrowed(string)
    } else if string
        .chars()
        .all(|c| stable_nfkd(c) && (c == ' ' || !c.is_whitespace()))
    {
        Cow::Borrowed(string)
    } else {
        let string = string
            .nfkd()
            .map(|c| {
                if HYPHENS.contains(c) {
                    '-'
                } else if c.is_whitespace() {
                    ' '
                } else {
                    c
                }
            })
            .collect();

        Cow::Owned(string)
    }
}

#[derive(Debug, Clone)]
pub struct CharacterCounts {
    pub chars: u8,
    pub alpha: u8,
    pub upper: u8,
    pub ascii_alpha: u8,
    pub ascii_vowels: u8,
}

pub fn categorize_chars(word: &str) -> CharacterCounts {
    debug_assert!(word.len() <= u8::max_value() as usize);

    let mut chars = 0;
    let mut alpha = 0;
    let mut upper = 0;
    let mut ascii_alpha = 0;
    let mut ascii_vowels = 0;

    for c in word.chars() {
        match c {
            'a'...'z' => {
                if "aeiouy".contains(c) {
                    ascii_vowels += 1;
                } else {
                    ascii_alpha += 1;
                }
            }
            'A'...'Z' => {
                if "AEIOUY".contains(c) {
                    ascii_vowels += 1;
                } else {
                    ascii_alpha += 1;
                }
                upper += 1;
            }
            _ if c.is_uppercase() => {
                alpha += 1;
                upper += 1;
            }
            _ if c.is_alphabetic() => {
                alpha += 1;
            }
            _ => {
                chars += 1;
            }
        }
    }

    // Maybe skipping individual increments and doing this instead is
    // premature optimization, but why not
    ascii_alpha += ascii_vowels;
    alpha += ascii_alpha;
    chars += alpha;

    CharacterCounts {
        chars,
        alpha,
        upper,
        ascii_alpha,
        ascii_vowels,
    }
}

pub fn starts_with_consonant(word: &str) -> bool {
    word.chars()
        .nth(0)
        .filter(|c| is_ascii_alphabetic(*c) && !"aeiouAEIOU".contains(*c))
        .is_some()
}

pub fn starts_with_uppercase(word: &str) -> bool {
    word.chars().nth(0).filter(|c| c.is_uppercase()).is_some()
}

pub fn combining_chars(word: &str) -> usize {
    word.chars().filter(|c| is_combining(*c)).count()
}

pub fn has_sequential_alphas(word: &str) -> bool {
    let mut prev_alpha = false;
    for c in word.chars() {
        let alpha = c.is_alphabetic();
        if prev_alpha && alpha {
            return true;
        } else {
            prev_alpha = alpha;
        }
    }

    false
}

#[macro_export]
macro_rules! eq_or_starts_with {
    ($a:expr, $b:expr) => {{
        let mut chars_a = $a.chars().filter_map(lowercase_if_alpha);
        let mut chars_b = $b.chars().filter_map(lowercase_if_alpha);
        let result;

        loop {
            let a = chars_a.next();
            let b = chars_b.next();

            if a.is_none() || b.is_none() {
                result = true;
                break;
            } else if a != b {
                result = false;
                break;
            }
        }

        result
    }};
}

#[macro_export]
macro_rules! eq_or_ends_with {
    ($needle:expr, $haystack:expr) => {{
        let mut n_chars = $needle.chars().rev().filter_map(lowercase_if_alpha);
        let mut h_chars = $haystack.chars().rev().filter_map(lowercase_if_alpha);
        let result;

        loop {
            let n = n_chars.next();
            let h = h_chars.next();

            if n.is_none() {
                result = true;
                break;
            } else if n != h {
                result = false;
                break;
            }
        }

        result
    }};
}

#[cfg(test)]
mod tests {
    use super::*;
    use test::{black_box, Bencher};

    #[test]
    fn sequential_alphas() {
        assert!(has_sequential_alphas("ab"));
        assert!(has_sequential_alphas("abc"));
        assert!(has_sequential_alphas("a.bc"));
        assert!(has_sequential_alphas("鄭a"));
        assert!(!has_sequential_alphas(""));
        assert!(!has_sequential_alphas("a"));
        assert!(!has_sequential_alphas("a.b"));
        assert!(!has_sequential_alphas("鄭.a"));
        assert!(!has_sequential_alphas("ﾟ."));
    }

    #[test]
    fn capitalization() {
        assert_eq!("A", capitalize_word("a", true));
        assert_eq!("Aa", capitalize_word("aa", true));
        assert_eq!("Aa", capitalize_word("AA", true));
    }

    #[bench]
    fn is_mixed_case_false(b: &mut Bencher) {
        b.iter(|| black_box(is_mixed_case("JOHN MACDONALD")))
    }

    #[bench]
    fn is_mixed_case_true(b: &mut Bencher) {
        b.iter(|| black_box(is_mixed_case("J. MacDonald")))
    }

    #[bench]
    fn capitalize_uppercase_word(b: &mut Bencher) {
        b.iter(|| black_box(capitalize_word("JONATHAN", true)))
    }

    #[bench]
    fn capitalize_complex_word(b: &mut Bencher) {
        b.iter(|| black_box(capitalize_word("föö-bar", false)))
    }

    #[bench]
    fn normalize_ascii(b: &mut Bencher) {
        b.iter(|| black_box(normalize_nfkd_hyphens_spaces("James 'J' S. Brown MD").len()))
    }

    #[bench]
    fn normalize_nfkd_stable(b: &mut Bencher) {
        b.iter(|| black_box(normalize_nfkd_hyphens_spaces("James «J» S. Brown MD").len()))
    }

    #[bench]
    fn normalize_needs_fix(b: &mut Bencher) {
        b.iter(|| black_box(normalize_nfkd_hyphens_spaces("James 'J' S. Bröwn MD").len()))
    }
}
<|endoftext|>


<commit_before>//! Contains the different types of values understood by XML-RPC.

use utils::{escape_xml, format_datetime};

use base64::encode;
use iso8601::DateTime;

use std::collections::BTreeMap;
use std::io::{self, Write};

/// The possible XML-RPC values.
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// `<i4>` or `<int>`, 32-bit signed integer.
    Int(i32),
    /// `<i8>`, 64-bit signed integer.
    ///
    /// This is an XMLRPC extension and may not be supported by all clients / servers.
    Int64(i64),
    /// `<boolean>`, 0 == `false`, 1 == `true`.
    Bool(bool),
    /// `<string>`
    // FIXME zero-copy? `Cow<'static, ..>`?
    String(String),
    /// `<double>`
    Double(f64),
    /// `<dateTime.iso8601>`, an ISO 8601 formatted date/time value.
    DateTime(DateTime),
    /// `<base64>`, base64-encoded binary data.
    Base64(Vec<u8>),

    /// `<struct>`, a mapping of named values.
    Struct(BTreeMap<String, Value>),
    /// `<array>`, a list of arbitrary (heterogeneous) values.
    Array(Vec<Value>),

    /// `<nil/>`, the empty (Unit) value.
    ///
    /// This is an XMLRPC [extension][ext] and may not be supported by all clients / servers.
    ///
    /// [ext]: https://web.archive.org/web/20050911054235/http://ontosys.com/xml-rpc/extensions.php
    Nil
}

impl Value {
    /// Formats this `Value` as an XML `<value>` element.
    pub fn write_as_xml<W: Write>(&self, fmt: &mut W) -> io::Result<()> {
        writeln!(fmt, "<value>")?;

        match *self {
            Value::Int(i) => {
                writeln!(fmt, "<i4>{}</i4>", i)?;
            }
            Value::Int64(i) => {
                writeln!(fmt, "<i8>{}</i8>", i)?;
            }
            Value::Bool(b) => {
                writeln!(fmt, "<boolean>{}</boolean>", if b { "1" } else { "0" })?;
            }
            Value::String(ref s) => {
                writeln!(fmt, "<string>{}</string>", escape_xml(s))?;
            }
            Value::Double(d) => {
                writeln!(fmt, "<double>{}</double>", d)?;
            }
            Value::DateTime(date_time) => {
                writeln!(fmt, "<dateTime.iso8601>{}</dateTime.iso8601>", format_datetime(&date_time))?;
            }
            Value::Base64(ref data) => {
                writeln!(fmt, "<base64>{}</base64>", encode(data))?;
            }
            Value::Struct(ref map) => {
                writeln!(fmt, "<struct>")?;
                for (ref name, ref value) in map {
                    writeln!(fmt, "<member>")?;
                    writeln!(fmt, "<name>{}</name>", escape_xml(name))?;
                    value.write_as_xml(fmt)?;
                    writeln!(fmt, "</member>")?;
                }
                writeln!(fmt, "</struct>")?;
            }
            Value::Array(ref array) => {
                writeln!(fmt, "<array>")?;
                writeln!(fmt, "<data>")?;
                for value in array {
                    value.write_as_xml(fmt)?;
                }
                writeln!(fmt, "</data>")?;
                writeln!(fmt, "</array>")?;
            }
            Value::Nil => {
                writeln!(fmt, "<nil/>")?;
            }
        }

        writeln!(fmt, "</value>")?;
        Ok(())
    }
}

impl From<i32> for Value {
    fn from(other: i32) -> Self {
        Value::Int(other)
    }
}

impl From<i64> for Value {
    fn from(other: i64) -> Self {
        Value::Int64(other)
    }
}

impl From<bool> for Value {
    fn from(other: bool) -> Self {
        Value::Bool(other)
    }
}

impl From<String> for Value {
    fn from(other: String) -> Self {
        Value::String(other)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(other: &'a str) -> Self {
        Value::String(other.to_string())
    }
}

impl From<f64> for Value {
    fn from(other: f64) -> Self {
        Value::Double(other)
    }
}

impl From<DateTime> for Value {
    fn from(other: DateTime) -> Self {
        Value::DateTime(other)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::str;
    use std::collections::BTreeMap;

    #[test]
    fn escapes_strings() {
        let mut output: Vec<u8> = Vec::new();

        Value::from("<xml> string").write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<string><xml>&nbsp;string</string>\n</value>\n");
    }

    #[test]
    fn escapes_struct_member_names() {
        let mut output: Vec<u8> = Vec::new();
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("x&<x".to_string(), Value::from(true));

        Value::Struct(map).write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<struct>\n<member>\n<name>x&<x</name>\n<value>\n<boolean>1</boolean>\n</value>\n</member>\n</struct>\n</value>\n");
    }
}
<commit_msg>add syntax sugar to access data in a Value<commit_after>//! Contains the different types of values understood by XML-RPC.

use utils::{escape_xml, format_datetime};

use base64::encode;
use iso8601::DateTime;

use std::collections::BTreeMap;
use std::io::{self, Write};

/// The possible XML-RPC values.
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// `<i4>` or `<int>`, 32-bit signed integer.
    Int(i32),
    /// `<i8>`, 64-bit signed integer.
    ///
    /// This is an XMLRPC extension and may not be supported by all clients / servers.
    Int64(i64),
    /// `<boolean>`, 0 == `false`, 1 == `true`.
    Bool(bool),
    /// `<string>`
    // FIXME zero-copy? `Cow<'static, ..>`?
    String(String),
    /// `<double>`
    Double(f64),
    /// `<dateTime.iso8601>`, an ISO 8601 formatted date/time value.
    DateTime(DateTime),
    /// `<base64>`, base64-encoded binary data.
    Base64(Vec<u8>),

    /// `<struct>`, a mapping of named values.
    Struct(BTreeMap<String, Value>),
    /// `<array>`, a list of arbitrary (heterogeneous) values.
    Array(Vec<Value>),

    /// `<nil/>`, the empty (Unit) value.
    ///
    /// This is an XMLRPC [extension][ext] and may not be supported by all clients / servers.
    ///
    /// [ext]: https://web.archive.org/web/20050911054235/http://ontosys.com/xml-rpc/extensions.php
    Nil
}

impl Value {
    /// Formats this `Value` as an XML `<value>` element.
    pub fn write_as_xml<W: Write>(&self, fmt: &mut W) -> io::Result<()> {
        writeln!(fmt, "<value>")?;

        match *self {
            Value::Int(i) => {
                writeln!(fmt, "<i4>{}</i4>", i)?;
            }
            Value::Int64(i) => {
                writeln!(fmt, "<i8>{}</i8>", i)?;
            }
            Value::Bool(b) => {
                writeln!(fmt, "<boolean>{}</boolean>", if b { "1" } else { "0" })?;
            }
            Value::String(ref s) => {
                writeln!(fmt, "<string>{}</string>", escape_xml(s))?;
            }
            Value::Double(d) => {
                writeln!(fmt, "<double>{}</double>", d)?;
            }
            Value::DateTime(date_time) => {
                writeln!(fmt, "<dateTime.iso8601>{}</dateTime.iso8601>", format_datetime(&date_time))?;
            }
            Value::Base64(ref data) => {
                writeln!(fmt, "<base64>{}</base64>", encode(data))?;
            }
            Value::Struct(ref map) => {
                writeln!(fmt, "<struct>")?;
                for (ref name, ref value) in map {
                    writeln!(fmt, "<member>")?;
                    writeln!(fmt, "<name>{}</name>", escape_xml(name))?;
                    value.write_as_xml(fmt)?;
                    writeln!(fmt, "</member>")?;
                }
                writeln!(fmt, "</struct>")?;
            }
            Value::Array(ref array) => {
                writeln!(fmt, "<array>")?;
                writeln!(fmt, "<data>")?;
                for value in array {
                    value.write_as_xml(fmt)?;
                }
                writeln!(fmt, "</data>")?;
                writeln!(fmt, "</array>")?;
            }
            Value::Nil => {
                writeln!(fmt, "<nil/>")?;
            }
        }

        writeln!(fmt, "</value>")?;
        Ok(())
    }

    pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
        index.get(self)
    }

    pub fn as_i32(&self) -> Option<i32> {
        match *self {
            Value::Int(i) => Some(i),
            _ => None
        }
    }

    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Int(i) => Some(i64::from(i)),
            Value::Int64(i) => Some(i),
            _ => None
        }
    }

    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            Value::Bool(b) => Some(b),
            _ => None
        }
    }

    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Value::String(ref s) => Some(s),
            _ => None
        }
    }

    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::Double(d) => Some(d),
            _ => None
        }
    }

    pub fn as_datetime(&self) -> Option<DateTime> {
        match *self {
            Value::DateTime(dt) => Some(dt),
            _ => None
        }
    }

    pub fn as_bytes(&self) -> Option<&[u8]> {
        match *self {
            Value::Base64(ref data) => Some(data),
            _ => None
        }
    }

    pub fn as_struct(&self) -> Option<&BTreeMap<String, Value>> {
        match *self {
            Value::Struct(ref map) => Some(map),
            _ => None
        }
    }

    pub fn as_array(&self) -> Option<&[Value]> {
        match *self {
            Value::Array(ref array) => Some(array),
            _ => None
        }
    }
}

impl From<i32> for Value {
    fn from(other: i32) -> Self {
        Value::Int(other)
    }
}

impl From<i64> for Value {
    fn from(other: i64) -> Self {
        Value::Int64(other)
    }
}

impl From<bool> for Value {
    fn from(other: bool) -> Self {
        Value::Bool(other)
    }
}

impl From<String> for Value {
    fn from(other: String) -> Self {
        Value::String(other)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(other: &'a str) -> Self {
        Value::String(other.to_string())
    }
}

impl From<f64> for Value {
    fn from(other: f64) -> Self {
        Value::Double(other)
    }
}

impl From<DateTime> for Value {
    fn from(other: DateTime) -> Self {
        Value::DateTime(other)
    }
}

pub trait Index {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value>;
}

impl Index for str {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for String {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for usize {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Array(ref array) = *value {
            array.get(*self)
        } else {
            None
        }
    }
}

impl<'a, I> Index for &'a I where I: Index + ?Sized {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        (*self).get(value)
    }
}

impl<I> ::std::ops::Index<I> for Value where I: Index {
    type Output = Value;
    fn index(&self, index: I) -> &Self::Output {
        index.get(self).unwrap_or(&Value::Nil)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::str;
    use std::collections::BTreeMap;

    #[test]
    fn escapes_strings() {
        let mut output: Vec<u8> = Vec::new();

        Value::from("<xml> string").write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<string><xml>&nbsp;string</string>\n</value>\n");
    }

    #[test]
    fn escapes_struct_member_names() {
        let mut output: Vec<u8> = Vec::new();
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("x&<x".to_string(), Value::from(true));

        Value::Struct(map).write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<struct>\n<member>\n<name>x&<x</name>\n<value>\n<boolean>1</boolean>\n</value>\n</member>\n</struct>\n</value>\n");
    }

    #[test]
    fn access_nested_values() {
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("name".to_string(), Value::from("John Doe"));
        map.insert("age".to_string(), Value::from(37));
        map.insert("children".to_string(), Value::Array(vec![Value::from("Mark"), Value::from("Jennyfer")]));
        let value = Value::Struct(map);

        assert_eq!(value.get("name"), Some(&Value::from("John Doe")));
        assert_eq!(value.get("age"), Some(&Value::from(37)));
        assert_eq!(value.get("birthdate"), None);
        assert_eq!(Value::Nil.get("age"), None);
        assert_eq!(value["name"], Value::from("John Doe"));
        assert_eq!(value["age"], Value::from(37));
        assert_eq!(value["birthdate"], Value::Nil);
        assert_eq!(Value::Nil["age"], Value::Nil);
        assert_eq!(value["children"][0], Value::from("Mark"));
        assert_eq!(value["children"][1], Value::from("Jennyfer"));
        assert_eq!(value["children"][2], Value::Nil);

        assert_eq!(value["age"].as_i32(), Some(37));
        assert_eq!(value["children"][0].as_str(), Some("Mark"));
    }
}
<|endoftext|>


<commit_before>use middleware::HandlebarsEngine;

use notify::{RecommendedWatcher, Error, Watcher};
use std::path::Path;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::thread;

fn _watch (p: &Path) -> Result<(), Error>{
    let (tx, rx) = channel();
    let mut watcher: RecommendedWatcher = try!(Watcher::new(tx));
    try!(watcher.watch(p));
    let _ = rx.recv();
    Ok(())
}

pub trait Watchable {
    fn watch(&self, path: &str);
}

impl Watchable for Arc<HandlebarsEngine> {
    fn watch (&self, path: &str) {
        let hbs = self.clone();
        let watch_path = path.to_owned();
        thread::spawn(move || {
            info!("watching path: {}", watch_path);
            let path = Path::new(&watch_path);
            loop {
                match _watch(&path) {
                    Ok(_) => {
                        info!("Template directory changed");
                        if let Err(e) = hbs.reload() {
                            error!("Failed to reload directory: {:?}", e);
                        }
                    },
                    Err(e) => {
                        warn!("Failed to watch directory: {:?}", e);
                        panic!();
                    }
                }
            }
        });
    }
}
<commit_msg>Fix race condition in the watch feature<commit_after>use middleware::HandlebarsEngine;

use notify::{RecommendedWatcher, Error, Watcher};
use std::path::Path;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::thread;

fn _watch (p: &Path, hbs: &Arc<HandlebarsEngine>) -> Result<(), Error>{
    let (tx, rx) = channel();
    let mut watcher: RecommendedWatcher = try!(Watcher::new(tx));
    try!(watcher.watch(p));
    loop {
        let _ = rx.recv();
        info!("Template directory changed");
        if let Err(e) = hbs.reload() {
            error!("Failed to reload directory: {:?}", e);
        }
    }
}

pub trait Watchable {
    fn watch(&self, path: &str);
}

impl Watchable for Arc<HandlebarsEngine> {
    fn watch (&self, path: &str) {
        let hbs = self.clone();
        let watch_path = path.to_owned();
        thread::spawn(move || {
            match _watch(Path::new(&watch_path), &hbs) {
                Ok(_) => (),
                Err(e) => {
                    warn!("Failed to watch directory: {:?}", e);
                    panic!();
                }
            }
        });
    }
}
<|endoftext|>


<commit_before>use anymap::AnyMap;
use std::any::Any;
use std::collections::HashMap;

use Entity;
use EntityIterator;
use components::{ Parent, Children };

/// Keeps track of entities and their components.
pub struct World {
    next_idx: usize,
    next_uuid: usize,
    /// Lists every entity with it's uuid.
    /// A uuid of `0` means an inactive entity.
    active: Vec<usize>,
    reusable_idxs: Vec<usize>,
    /// List of all the components.
    components: Vec<AnyMap>,

    ent_remove: HashMap<usize, usize>,
    ent_changed: HashMap<usize, usize>,
}

impl World {
    pub fn new() -> World {
        World {
            next_idx: 0,
            next_uuid: 1,
            active: Vec::new(),
            reusable_idxs: Vec::new(),
            components: Vec::new(),

            ent_remove: HashMap::new(),
            ent_changed: HashMap::new(),
        }
    }

    /// Adds a new entity.
    /// Will reuse an idx if available, if not it will increment the idx counter and allocate
    /// space for the components.
    pub fn add_entity(&mut self) -> Entity {
        // Get the idx.
        let idx = match self.reusable_idxs.pop() {
            None => {
                // No reusable idxs, so make a new one.
                let idx = self.next_idx;
                self.next_idx += 1;
                // And add a new entry to the components vector.
                self.components.push(AnyMap::new());
                idx
            },
            Some(idx) => idx,
        };

        // Get the uuid.
        let uuid = self.next_uuid;
        self.next_uuid += 1;

        // Register the entity as active.
        if self.active.len() <= uuid {
            self.active.resize(uuid + 1, 0);
        }
        self.active[idx] = uuid;

        // Register the entity as recently changed.
        self.ent_changed.insert(idx, uuid);

        Entity { idx: idx, uuid: uuid }
    }

    /// Slates an entity for removal.
    /// The removal won't actually be done until `confirm_changes()` is called.
    pub fn remove_entity(&mut self, entity: Entity) {
        self.ent_remove.insert(entity.idx, entity.uuid);
    }

    /// Removes all entities currently slated for removal.
    /// Also clears the list of removed and changed entities.
    pub fn confirm_changes(&mut self) {
        // Remove all entities in the `remove` list.
        for (&idx, &uuid) in self.ent_remove.iter() {
            if self.is_valid_entity(&Entity{ idx: idx, uuid: uuid }) {
                self.active[idx] = 0;
                self.reusable_idxs.push(idx);
                // Clear the components associated with the entity.
                self.components[idx].clear();
            }
        }

        self.ent_remove.clear();
        self.ent_changed.clear();
    }

    /// Checks if an `Entity` reference is valid.
    pub fn is_valid_entity(&self, entity: &Entity) -> bool {
        match self.active.get(entity.idx) {
            Some(&uuid) => {
                uuid != 0 && entity.uuid == uuid
            },
            None => false,
        }
    }

    /// Returns the uuid currently associated with an entity index.
    /// Returns 0 for nonexistent entities.
    pub fn get_uuid(&self, idx: usize) -> usize {
        match self.active.get(idx) {
            Some(&uuid) => uuid,
            None => 0,
        }
    }

    /// Adds a new component to an entity.
    /// If the entity already had that component, that component is returned.
    /// Otherwise, `None` is returned.
    pub fn add_component<T: Any>(&mut self, entity: &Entity, component: T) -> Option<T> {
        if self.is_valid_entity(entity) {
            self.ent_changed.insert(entity.idx, entity.uuid);
            return self.components[entity.idx].insert(component);
        }
        None
    }

    /// Returns whether an entity has a specific component or not.
    pub fn has_component<T: Any>(&self, entity: &Entity) -> bool {
        if self.is_valid_entity(entity) {
            return self.components[entity.idx].contains::<T>();
        }
        false
    }

    /// Returns a reference to a component.
    /// If a component does not exist, but it does in the parent,
    /// the parent's component will be returned.
    pub fn get_component<T: Any>(&self, entity: &Entity) -> Option<&T> {
        if self.is_valid_entity(entity) {
            // See if the component is there, if so: return it.
            match self.components[entity.idx].get::<T>() {
                Some(T) => return Some(T),
                None => {
                    // This entity doesn't have the component.
                    // See if has inherited it from a parent.
                    let mut cur_ent = entity;
                    loop  {
                        if self.is_valid_entity(cur_ent) {
                            if let Some(comp) = self.components[cur_ent.idx].get::<T>() {
                                return Some(comp);
                            }
                            if let Some(parent) = self.components[cur_ent.idx].get::<Parent>() {
                                let Parent(cur_ent) = *parent;
                            } else {
                                // No parents left.
                                break;
                            }
                        } else {
                            // Parent not valid.
                            break;
                        }
                    }
                }
            }
        }
        None
    }

    /// Returns a mutable reference to a component, if it exists.
    /// Mutable references won't be retreived from an entities parent,
    /// as this will easily lead to bugs that are very hard to debug.
    pub fn get_mut_component<T: Any>(&mut self, entity: &Entity) -> Option<&mut T> {
        if self.is_valid_entity(entity) {
            let comp = self.components[entity.idx].get_mut::<T>();

            return match comp {
                Some(val) => {
                    self.ent_changed.insert(entity.idx, entity.uuid);
                    Some(val)
                },
                None => None,
            }
        }
        None
    }

    /// Removes a component from an entity.
    /// Returning the component if it existed, or `None` if it didn't.
    pub fn remove_component<T: Any>(&mut self, entity: &Entity) -> Option<T> {
        if self.is_valid_entity(entity) {
            let res = self.components[entity.idx].remove::<T>();

            return match res {
                Some(res) => {
                    self.ent_changed.insert(entity.idx, entity.uuid);
                    Some(res)
                },
                None => None,
            }
        }
        None
    }

    /// Returns a lazy iterator for immutable acces to the entities.
    pub fn iterator(&self) -> EntityIterator {
        EntityIterator {
            active: &self.active,
            curr: 0,
        }
    }

    /// Returns a vector listing all the currently active entities.
    /// Can be used to iterate over all active entities while making changes to the world.
    pub fn list_entities(&self) -> Vec<Entity> {
        self.active.iter().enumerate()
            .filter(|&(_, &uuid)| uuid != 0)
            .map(|(idx, &uuid)| Entity{ idx: idx, uuid: uuid })
            .collect::<Vec<Entity>>()
    }

    /// Returns a vector listing all the entities currently slated for removal.
    pub fn list_removals(&self) -> Vec<Entity> {
        self.ent_remove.iter()
            .map(|(&idx, &uuid)| Entity{ idx: idx, uuid: uuid })
            .collect::<Vec<Entity>>()
    }

    /// Returns a vector listing all the entities that have changed since the last call of.
    /// `confirm_changes`.
    pub fn list_changes(&self) -> Vec<Entity> {
        self.ent_changed.iter()
            .map(|(&idx, &uuid)| Entity{ idx: idx, uuid: uuid })
            .collect::<Vec<Entity>>()
    }
}
<commit_msg>Added debuging println! statements to `get_component`<commit_after>use anymap::AnyMap;
use std::any::Any;
use std::collections::HashMap;

use Entity;
use EntityIterator;
use components::{ Parent, Children };

/// Keeps track of entities and their components.
pub struct World {
    next_idx: usize,
    next_uuid: usize,
    /// Lists every entity with it's uuid.
    /// A uuid of `0` means an inactive entity.
    active: Vec<usize>,
    reusable_idxs: Vec<usize>,
    /// List of all the components.
    components: Vec<AnyMap>,

    ent_remove: HashMap<usize, usize>,
    ent_changed: HashMap<usize, usize>,
}

impl World {
    pub fn new() -> World {
        World {
            next_idx: 0,
            next_uuid: 1,
            active: Vec::new(),
            reusable_idxs: Vec::new(),
            components: Vec::new(),

            ent_remove: HashMap::new(),
            ent_changed: HashMap::new(),
        }
    }

    /// Adds a new entity.
    /// Will reuse an idx if available, if not it will increment the idx counter and allocate
    /// space for the components.
    pub fn add_entity(&mut self) -> Entity {
        // Get the idx.
        let idx = match self.reusable_idxs.pop() {
            None => {
                // No reusable idxs, so make a new one.
                let idx = self.next_idx;
                self.next_idx += 1;
                // And add a new entry to the components vector.
                self.components.push(AnyMap::new());
                idx
            },
            Some(idx) => idx,
        };

        // Get the uuid.
        let uuid = self.next_uuid;
        self.next_uuid += 1;

        // Register the entity as active.
        if self.active.len() <= uuid {
            self.active.resize(uuid + 1, 0);
        }
        self.active[idx] = uuid;

        // Register the entity as recently changed.
        self.ent_changed.insert(idx, uuid);

        Entity { idx: idx, uuid: uuid }
    }

    /// Slates an entity for removal.
    /// The removal won't actually be done until `confirm_changes()` is called.
    pub fn remove_entity(&mut self, entity: Entity) {
        self.ent_remove.insert(entity.idx, entity.uuid);
    }

    /// Removes all entities currently slated for removal.
    /// Also clears the list of removed and changed entities.
    pub fn confirm_changes(&mut self) {
        // Remove all entities in the `remove` list.
        for (&idx, &uuid) in self.ent_remove.iter() {
            if self.is_valid_entity(&Entity{ idx: idx, uuid: uuid }) {
                self.active[idx] = 0;
                self.reusable_idxs.push(idx);
                // Clear the components associated with the entity.
                self.components[idx].clear();
            }
        }

        self.ent_remove.clear();
        self.ent_changed.clear();
    }

    /// Checks if an `Entity` reference is valid.
    pub fn is_valid_entity(&self, entity: &Entity) -> bool {
        match self.active.get(entity.idx) {
            Some(&uuid) => {
                uuid != 0 && entity.uuid == uuid
            },
            None => false,
        }
    }

    /// Returns the uuid currently associated with an entity index.
    /// Returns 0 for nonexistent entities.
    pub fn get_uuid(&self, idx: usize) -> usize {
        match self.active.get(idx) {
            Some(&uuid) => uuid,
            None => 0,
        }
    }

    /// Adds a new component to an entity.
    /// If the entity already had that component, that component is returned.
    /// Otherwise, `None` is returned.
    pub fn add_component<T: Any>(&mut self, entity: &Entity, component: T) -> Option<T> {
        if self.is_valid_entity(entity) {
            self.ent_changed.insert(entity.idx, entity.uuid);
            return self.components[entity.idx].insert(component);
        }
        None
    }

    /// Returns whether an entity has a specific component or not.
    pub fn has_component<T: Any>(&self, entity: &Entity) -> bool {
        if self.is_valid_entity(entity) {
            return self.components[entity.idx].contains::<T>();
        }
        false
    }

    /// Returns a reference to a component.
    /// If a component does not exist, but it does in the parent,
    /// the parent's component will be returned.
    pub fn get_component<T: Any>(&self, entity: &Entity) -> Option<&T> {
        if self.is_valid_entity(entity) {
            // See if the component is there, if so: return it.
            match self.components[entity.idx].get::<T>() {
                Some(T) => return Some(T),
                None => {
                    // This entity doesn't have the component.
                    // See if has inherited it from a parent.
                    let mut cur_ent = entity;
                    println!("start: {}, {}", cur_ent.idx, cur_ent.uuid);
                    loop  {
                        if self.is_valid_entity(cur_ent) {
                            if let Some(comp) = self.components[cur_ent.idx].get::<T>() {
                                return Some(comp);
                            }
                            if let Some(parent) = self.components[cur_ent.idx].get::<Parent>() {
                                let Parent(cur_ent) = *parent;
                                println!("parent: {}, {}", cur_ent.idx, cur_ent.uuid);
                            } else {
                                // No parents left.
                                break;
                            }
                        } else {
                            // Parent not valid.
                            break;
                        }
                    }
                }
            }
        }
        None
    }

    /// Returns a mutable reference to a component, if it exists.
    /// Mutable references won't be retreived from an entities parent,
    /// as this will easily lead to bugs that are very hard to debug.
    pub fn get_mut_component<T: Any>(&mut self, entity: &Entity) -> Option<&mut T> {
        if self.is_valid_entity(entity) {
            let comp = self.components[entity.idx].get_mut::<T>();

            return match comp {
                Some(val) => {
                    self.ent_changed.insert(entity.idx, entity.uuid);
                    Some(val)
                },
                None => None,
            }
        }
        None
    }

    /// Removes a component from an entity.
    /// Returning the component if it existed, or `None` if it didn't.
    pub fn remove_component<T: Any>(&mut self, entity: &Entity) -> Option<T> {
        if self.is_valid_entity(entity) {
            let res = self.components[entity.idx].remove::<T>();

            return match res {
                Some(res) => {
                    self.ent_changed.insert(entity.idx, entity.uuid);
                    Some(res)
                },
                None => None,
            }
        }
        None
    }

    /// Returns a lazy iterator for immutable acces to the entities.
    pub fn iterator(&self) -> EntityIterator {
        EntityIterator {
            active: &self.active,
            curr: 0,
        }
    }

    /// Returns a vector listing all the currently active entities.
    /// Can be used to iterate over all active entities while making changes to the world.
    pub fn list_entities(&self) -> Vec<Entity> {
        self.active.iter().enumerate()
            .filter(|&(_, &uuid)| uuid != 0)
            .map(|(idx, &uuid)| Entity{ idx: idx, uuid: uuid })
            .collect::<Vec<Entity>>()
    }

    /// Returns a vector listing all the entities currently slated for removal.
    pub fn list_removals(&self) -> Vec<Entity> {
        self.ent_remove.iter()
            .map(|(&idx, &uuid)| Entity{ idx: idx, uuid: uuid })
            .collect::<Vec<Entity>>()
    }

    /// Returns a vector listing all the entities that have changed since the last call of.
    /// `confirm_changes`.
    pub fn list_changes(&self) -> Vec<Entity> {
        self.ent_changed.iter()
            .map(|(&idx, &uuid)| Entity{ idx: idx, uuid: uuid })
            .collect::<Vec<Entity>>()
    }
}
<|endoftext|>