<commit_before>use std::sync::{Arc, Mutex};

use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use chrono::{DateTime, UTC};
use serde::Deserialize;
use serde_json;

use super::super::config::Config;
use super::super::memdbstash::MemDbStash;
use super::super::Result;
use super::handlers::{healthcheck_handler, lookup_symbol_handler};
use super::types::{ApiResponse, ApiError};

#[derive(Serialize, Clone)]
pub struct HealthCheckResponse {
    pub is_healthy: bool,
    pub sync_lag: u32,
}

pub struct ServerContext {
    pub config: Config,
    pub stash: MemDbStash,
    cached_memdb_status: Mutex<Option<(DateTime<UTC>, HealthCheckResponse)>>,
}

pub struct ApiServer {
    ctx: Arc<ServerContext>,
}

impl ServerContext {
    pub fn check_health(&self) -> Result<HealthCheckResponse> {
        let mut cache_value = self.cached_memdb_status.lock().unwrap();
        if_chain! {
            if let Some((ts, ref rv)) = *cache_value;
            if UTC::now() - self.config.get_server_healthcheck_ttl()? < ts;
            then { return Ok(rv.clone()); }
        }
        let state = self.stash.get_sync_status()?;
        let rv = HealthCheckResponse {
            is_healthy: state.is_healthy(),
            sync_lag: state.lag(),
        };
        *cache_value = Some((UTC::now(), rv.clone()));
        Ok(rv)
    }
}

impl ApiServer {
    pub fn new(config: &Config) -> Result<ApiServer> {
        Ok(ApiServer {
            ctx: Arc::new(ServerContext {
                config: config.clone(),
                stash: MemDbStash::new(config)?,
                cached_memdb_status: Mutex::new(None),
            }),
        })
    }

    pub fn run(&self) -> Result<()> {
        let ctx = self.ctx.clone();
        Server::http(self.ctx.config.get_server_socket_addr()?)?
            .handle(move |req: Request, resp: Response|
        {
            let handler = match req.uri {
                RequestUri::AbsolutePath(ref path) => {
                    match path.as_str() {
                        "/health" => healthcheck_handler,
                        "/lookup" => lookup_symbol_handler,
                        _ => not_found,
                    }
                }
                _ => bad_request,
            };
            match handler(&*ctx.clone(), req) {
                Ok(result) => result,
                Err(err) => ApiResponse::from_error(err).unwrap(),
            }.write_to_response(resp).unwrap();
        })?;
        Ok(())
    }
}

pub fn load_request_data<D: Deserialize>(req: &mut Request) -> Result<D> {
    Ok(match serde_json::from_reader(req) {
        Ok(data) => data,
        Err(err) => { return Err(ApiError::BadJson(Box::new(err)).into()); }
    })
}

fn bad_request(_: &ServerContext, _: Request) -> Result<ApiResponse>
{
    Err(ApiError::BadRequest.into())
}

fn not_found(_: &ServerContext, _: Request) -> Result<ApiResponse>
{
    Err(ApiError::NotFound.into())
}
<commit_msg>Log when the server is up<commit_after>use std::sync::{Arc, Mutex};

use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use chrono::{DateTime, UTC};
use serde::Deserialize;
use serde_json;

use super::super::config::Config;
use super::super::memdbstash::MemDbStash;
use super::super::Result;
use super::handlers::{healthcheck_handler, lookup_symbol_handler};
use super::types::{ApiResponse, ApiError};

#[derive(Serialize, Clone)]
pub struct HealthCheckResponse {
    pub is_healthy: bool,
    pub sync_lag: u32,
}

pub struct ServerContext {
    pub config: Config,
    pub stash: MemDbStash,
    cached_memdb_status: Mutex<Option<(DateTime<UTC>, HealthCheckResponse)>>,
}

pub struct ApiServer {
    ctx: Arc<ServerContext>,
}

impl ServerContext {
    pub fn check_health(&self) -> Result<HealthCheckResponse> {
        let mut cache_value = self.cached_memdb_status.lock().unwrap();
        if_chain! {
            if let Some((ts, ref rv)) = *cache_value;
            if UTC::now() - self.config.get_server_healthcheck_ttl()? < ts;
            then { return Ok(rv.clone()); }
        }
        let state = self.stash.get_sync_status()?;
        let rv = HealthCheckResponse {
            is_healthy: state.is_healthy(),
            sync_lag: state.lag(),
        };
        *cache_value = Some((UTC::now(), rv.clone()));
        Ok(rv)
    }
}

impl ApiServer {
    pub fn new(config: &Config) -> Result<ApiServer> {
        Ok(ApiServer {
            ctx: Arc::new(ServerContext {
                config: config.clone(),
                stash: MemDbStash::new(config)?,
                cached_memdb_status: Mutex::new(None),
            }),
        })
    }

    pub fn run(&self) -> Result<()> {
        let addr = self.ctx.config.get_server_socket_addr()?;
        let (ref host, port) = addr;
        info!("Listening on http://{}:{}/", host, port);

        let ctx = self.ctx.clone();
        Server::http(addr)?
            .handle(move |req: Request, resp: Response|
        {
            let handler = match req.uri {
                RequestUri::AbsolutePath(ref path) => {
                    match path.as_str() {
                        "/health" => healthcheck_handler,
                        "/lookup" => lookup_symbol_handler,
                        _ => not_found,
                    }
                }
                _ => bad_request,
            };
            match handler(&*ctx.clone(), req) {
                Ok(result) => result,
                Err(err) => ApiResponse::from_error(err).unwrap(),
            }.write_to_response(resp).unwrap();
        })?;
        Ok(())
    }
}

pub fn load_request_data<D: Deserialize>(req: &mut Request) -> Result<D> {
    Ok(match serde_json::from_reader(req) {
        Ok(data) => data,
        Err(err) => { return Err(ApiError::BadJson(Box::new(err)).into()); }
    })
}

fn bad_request(_: &ServerContext, _: Request) -> Result<ApiResponse>
{
    Err(ApiError::BadRequest.into())
}

fn not_found(_: &ServerContext, _: Request) -> Result<ApiResponse>
{
    Err(ApiError::NotFound.into())
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;

/// Command line argument parser error types
#[derive(PartialEq, Debug)]
pub enum ClapErrorType {
    /// Error occurs when some possible values were set, but clap found unexpected value
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug").index(1)
    /// .possible_value("fast")
    /// .possible_value("slow")
    /// # ).get_matches_from_safe(vec!["", "other"]);
    InvalidValue,
    /// Error occurs when clap found unexpected flag or option
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::from_usage("-f, --flag 'some flag'")
    /// # ).get_matches_from_safe(vec!["", "--other"]);
    InvalidArgument,
    /// Error occurs when clap found unexpected subcommand
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg, SubCommand};
    /// # let result = App::new("myprog")
    /// #                    .subcommand(
    /// SubCommand::with_name("conifg")
    ///                .about("Used for configuration")
    ///                .arg(Arg::with_name("config_file")
    ///                           .help("The configuration file to use")
    ///                           .index(1))
    /// # ).get_matches_from_safe(vec!["", "other"]);
    InvalidSubcommand,
    /// Error occurs when option does not allow empty values but some was found
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug")
    /// .empty_values(false))
    /// #                 .arg(
    /// # Arg::with_name("color")
    /// # ).get_matches_from_safe(vec!["", "--debug", "--color"]);
    EmptyValue,
    /// Parser inner error
    OptionError,
    /// Parser inner error
    ArgumentError,
    /// Parser inner error
    ValueError,
    /// Error occurs when argument got more values then were expected
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug").index(1)
    /// .max_values(2)
    /// # ).get_matches_from_safe(vec!["", "too", "much", "values"]);
    TooMuchValues,
    /// Error occurs when argument got less values then were expected
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug").index(1)
    /// .min_values(3)
    /// # ).get_matches_from_safe(vec!["", "too", "few"]);
    TooFewValues,
    /// Error occurs when clap find two ore more conflicting arguments
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug")
    /// .conflicts_with("color")
    /// # ).get_matches_from_safe(vec!["", "--debug", "--color"]);
    ArgumentConflict,
    /// Error occurs when one or more required arguments missing
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug")
    /// .required(true)
    /// # ).get_matches_from_safe(vec![""]);
    MissingRequiredArgument,
    /// Error occurs when required subcommand missing
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg, AppSettings, SubCommand};
    /// # let result = App::new("myprog")
    /// #                    .setting(AppSettings::SubcommandRequired)
    /// #                    .subcommand(
    /// SubCommand::with_name("conifg")
    ///                .about("Used for configuration")
    ///                .arg(Arg::with_name("config_file")
    ///                           .help("The configuration file to use")
    ///                           .index(1))
    /// # ).get_matches_from_safe(vec![""]);
    MissingSubcommand,
    /// Error occurs when clap find argument while is was not expecting any
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App};
    /// # let result = App::new("myprog").get_matches_from_safe(vec!["", "--arg"]);
    UnexpectedArgument,
    /// Error occurs when argument was used multiple times and was not set as multiple.
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug")
    /// .multiple(false)
    /// # ).get_matches_from_safe(vec!["", "--debug", "--debug"]);
    UnexpectedMultipleUsage
}

/// Command line argument parser error
#[derive(Debug)]
pub struct ClapError {
    /// Formated error message
    pub error: String,
    /// Command line argument parser error type
    pub error_type: ClapErrorType
}

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

impl fmt::Display for ClapError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.error)
    }
}<commit_msg>docs: fixed ClapErrorType docs<commit_after>use std::error::Error;
use std::fmt;

/// Command line argument parser error types
#[derive(PartialEq, Debug)]
pub enum ClapErrorType {
    /// Error occurs when some possible values were set, but clap found unexpected value
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug").index(1)
    /// .possible_value("fast")
    /// .possible_value("slow")
    /// # ).get_matches_from_safe(vec!["", "other"]);
    /// ```
    InvalidValue,
    /// Error occurs when clap found unexpected flag or option
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::from_usage("-f, --flag 'some flag'")
    /// # ).get_matches_from_safe(vec!["", "--other"]);
    /// ```
    InvalidArgument,
    /// Error occurs when clap found unexpected subcommand
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg, SubCommand};
    /// # let result = App::new("myprog")
    /// #                    .subcommand(
    /// SubCommand::with_name("conifg")
    ///                .about("Used for configuration")
    ///                .arg(Arg::with_name("config_file")
    ///                           .help("The configuration file to use")
    ///                           .index(1))
    /// # ).get_matches_from_safe(vec!["", "other"]);
    /// ```
    InvalidSubcommand,
    /// Error occurs when option does not allow empty values but some was found
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug")
    /// .empty_values(false))
    /// #                 .arg(
    /// # Arg::with_name("color")
    /// # ).get_matches_from_safe(vec!["", "--debug", "--color"]);
    /// ```
    EmptyValue,
    /// Parser inner error
    OptionError,
    /// Parser inner error
    ArgumentError,
    /// Parser inner error
    ValueError,
    /// Error occurs when argument got more values then were expected
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug").index(1)
    /// .max_values(2)
    /// # ).get_matches_from_safe(vec!["", "too", "much", "values"]);
    /// ```
    TooMuchValues,
    /// Error occurs when argument got less values then were expected
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug").index(1)
    /// .min_values(3)
    /// # ).get_matches_from_safe(vec!["", "too", "few"]);
    /// ```
    TooFewValues,
    /// Error occurs when clap find two ore more conflicting arguments
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug")
    /// .conflicts_with("color")
    /// # ).get_matches_from_safe(vec!["", "--debug", "--color"]);
    /// ```
    ArgumentConflict,
    /// Error occurs when one or more required arguments missing
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug")
    /// .required(true)
    /// # ).get_matches_from_safe(vec![""]);
    /// ```
    MissingRequiredArgument,
    /// Error occurs when required subcommand missing
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg, AppSettings, SubCommand};
    /// # let result = App::new("myprog")
    /// #                    .setting(AppSettings::SubcommandRequired)
    /// #                    .subcommand(
    /// SubCommand::with_name("conifg")
    ///                .about("Used for configuration")
    ///                .arg(Arg::with_name("config_file")
    ///                           .help("The configuration file to use")
    ///                           .index(1))
    /// # ).get_matches_from_safe(vec![""]);
    /// ```
    MissingSubcommand,
    /// Error occurs when clap find argument while is was not expecting any
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App};
    /// # let result = App::new("myprog").get_matches_from_safe(vec!["", "--arg"]);
    /// ```
    UnexpectedArgument,
    /// Error occurs when argument was used multiple times and was not set as multiple.
    ///
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use clap::{App, Arg};
    /// # let result = App::new("myprog")
    /// #                 .arg(
    /// # Arg::with_name("debug")
    /// .multiple(false)
    /// # ).get_matches_from_safe(vec!["", "--debug", "--debug"]);
    /// ```
    UnexpectedMultipleUsage
}

/// Command line argument parser error
#[derive(Debug)]
pub struct ClapError {
    /// Formated error message
    pub error: String,
    /// Command line argument parser error type
    pub error_type: ClapErrorType
}

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

impl fmt::Display for ClapError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.error)
    }
}<|endoftext|>


<commit_before>use std::fmt::{Display, Debug, Formatter, Result as FmtResult};
use std::str::FromStr;
use url::Host;
use serde::{Deserialize, Deserializer};
use serde::{Serialize, Serializer};

#[derive(Clone,PartialEq,Eq)]
pub struct EmailAddress {
    serialization: String,
    local_end: usize,
}

impl FromStr for EmailAddress {
    type Err = ();

    fn from_str(input: &str) -> Result<EmailAddress, ()> {
        let local_end = input.find('@').ok_or(())?;
        // Transform local part to lowercase, according to unicode
        let local = input[..local_end].to_lowercase();
        // Verify and normalize domain to lowercase ASCII, according to WHATWG
        let host = Host::parse(&input[local_end + 1..]).map_err(|_| ())?;
        if let Host::Domain(domain) = host {
            Ok(EmailAddress::from_parts(&local, &domain))
        } else {
            Err(())
        }
    }
}

impl AsRef<str> for EmailAddress {
    /// Return the serialization of this email address.
    fn as_ref(&self) -> &str {
        &self.serialization
    }
}

impl Serialize for EmailAddress {
    /// Serialize this email address as a string.
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where S: Serializer {
        self.as_str().serialize(serializer)
    }
}

impl EmailAddress {
    /// Create an email address from trusted local and domain parts.
    fn from_parts(local: &str, domain: &str) -> EmailAddress {
        EmailAddress {
            serialization: format!("{}@{}", local, domain),
            local_end: local.len(),
        }
    }

    /// Create an EmailAddress from trusted input.
    ///
    /// The input is the already serialized form, preferably extracted from an
    /// EmailAddress parsed earlier.
    pub fn from_trusted(input: &str) -> EmailAddress {
        EmailAddress {
            serialization: input.to_owned(),
            local_end: input.find('@').expect("no @ found in input"),
        }
    }

    /// Deserialize implementation for trusted input.
    ///
    /// Because this assumes input is valid, it must be explicitely selected using
    /// `#[serde(deserialize_with = "EmailAddress::deserialize_trusted")]`
    pub fn deserialize_trusted<'de, D>(deserializer: D) -> Result<EmailAddress, D::Error>
            where D: Deserializer<'de> {
        <&str>::deserialize(deserializer).map(|s| EmailAddress::from_trusted(s))
    }

    /// Return the serialization.
    pub fn as_str(&self) -> &str {
        &self.serialization
    }

    /// Return the normalized local part.
    pub fn local(&self) -> &str {
        &self.serialization[..self.local_end]
    }

    /// Return the ASCII normalized domain.
    pub fn domain(&self) -> &str {
        &self.serialization[self.local_end + 1..]
    }

    /// Return the normalized local and domain parts as a tuple.
    pub fn parts(&self) -> (&str, &str) {
        (self.local(), self.domain())
    }

    /// Normalize a Google email address.
    ///
    /// This method can also be used to normalize G Suite addresses.
    pub fn normalize_google(&self) -> EmailAddress {
        let (local, domain) = self.parts();

        // Normalize googlemail.com to gmail.com
        let domain = match domain {
            "googlemail.com" => "gmail.com",
            domain => domain,
        };

        // Trim plus addresses
        let local = match self.local().find('+') {
            Some(pos) => &local[..pos],
            None => local,
        };

        // Ignore dots
        let local = local.replace(".", "");

        EmailAddress::from_parts(&local, domain)
    }
}

/// Display the serialization of this email address.
impl Display for EmailAddress {
    fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
        Display::fmt(&self.serialization, formatter)
    }
}

/// Debug the serialization of this email address.
impl Debug for EmailAddress {
    fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
        Debug::fmt(&self.serialization, formatter)
    }
}

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

    #[test]
    fn test_normal() {
        fn parse(input: &str, output: &str) {
            assert_eq!(
                input.parse::<EmailAddress>().unwrap(),
                EmailAddress::from_trusted(output)
            )
        }
        parse("example.foo+bar@example.com",
              "example.foo+bar@example.com");
        parse("EXAMPLE.FOO+BAR@EXAMPLE.COM",
              "example.foo+bar@example.com");
        parse("BJÖRN@göteborg.test",
              "björn@xn--gteborg-90a.test");
        parse("İⅢ@İⅢ.example",
              "i̇ⅲ@xn--iiii-qwc.example");
    }

    #[test]
    fn test_google() {
        fn parse(input: &str, output: &str) {
            assert_eq!(
                input.parse::<EmailAddress>().unwrap().normalize_google(),
                EmailAddress::from_trusted(output)
            )
        }
        parse("example@gmail.com",
              "example@gmail.com");
        parse("example@googlemail.com",
              "example@gmail.com");
        parse("example.foo@gmail.com",
              "examplefoo@gmail.com");
        parse("example+bar@gmail.com",
              "example@gmail.com");
        parse("example.foo+bar@googlemail.com",
              "examplefoo@gmail.com");
        parse("EXAMPLE@GOOGLEMAIL.COM",
              "example@gmail.com");
        parse("EXAMPLE.FOO+BAR@GOOGLEMAIL.COM",
              "examplefoo@gmail.com");
    }
}
<commit_msg>Add tests for invalid emails, and handle empty parts<commit_after>use std::fmt::{Display, Debug, Formatter, Result as FmtResult};
use std::str::FromStr;
use url::Host;
use serde::{Deserialize, Deserializer};
use serde::{Serialize, Serializer};

#[derive(Clone,PartialEq,Eq)]
pub struct EmailAddress {
    serialization: String,
    local_end: usize,
}

impl FromStr for EmailAddress {
    type Err = ();

    fn from_str(input: &str) -> Result<EmailAddress, ()> {
        let local_end = input.find('@').ok_or(())?;
        // Transform local part to lowercase, according to unicode
        let local = input[..local_end].to_lowercase();
        if local == "" { return Err(()); }
        // Verify and normalize domain to lowercase ASCII, according to WHATWG
        let host = Host::parse(&input[local_end + 1..]).map_err(|_| ())?;
        if let Host::Domain(domain) = host {
            if domain == "" {
                Err(())
            } else {
                Ok(EmailAddress::from_parts(&local, &domain))
            }
        } else {
            Err(())
        }
    }
}

impl AsRef<str> for EmailAddress {
    /// Return the serialization of this email address.
    fn as_ref(&self) -> &str {
        &self.serialization
    }
}

impl Serialize for EmailAddress {
    /// Serialize this email address as a string.
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where S: Serializer {
        self.as_str().serialize(serializer)
    }
}

impl EmailAddress {
    /// Create an email address from trusted local and domain parts.
    fn from_parts(local: &str, domain: &str) -> EmailAddress {
        EmailAddress {
            serialization: format!("{}@{}", local, domain),
            local_end: local.len(),
        }
    }

    /// Create an EmailAddress from trusted input.
    ///
    /// The input is the already serialized form, preferably extracted from an
    /// EmailAddress parsed earlier.
    pub fn from_trusted(input: &str) -> EmailAddress {
        EmailAddress {
            serialization: input.to_owned(),
            local_end: input.find('@').expect("no @ found in input"),
        }
    }

    /// Deserialize implementation for trusted input.
    ///
    /// Because this assumes input is valid, it must be explicitely selected using
    /// `#[serde(deserialize_with = "EmailAddress::deserialize_trusted")]`
    pub fn deserialize_trusted<'de, D>(deserializer: D) -> Result<EmailAddress, D::Error>
            where D: Deserializer<'de> {
        <&str>::deserialize(deserializer).map(|s| EmailAddress::from_trusted(s))
    }

    /// Return the serialization.
    pub fn as_str(&self) -> &str {
        &self.serialization
    }

    /// Return the normalized local part.
    pub fn local(&self) -> &str {
        &self.serialization[..self.local_end]
    }

    /// Return the ASCII normalized domain.
    pub fn domain(&self) -> &str {
        &self.serialization[self.local_end + 1..]
    }

    /// Return the normalized local and domain parts as a tuple.
    pub fn parts(&self) -> (&str, &str) {
        (self.local(), self.domain())
    }

    /// Normalize a Google email address.
    ///
    /// This method can also be used to normalize G Suite addresses.
    pub fn normalize_google(&self) -> EmailAddress {
        let (local, domain) = self.parts();

        // Normalize googlemail.com to gmail.com
        let domain = match domain {
            "googlemail.com" => "gmail.com",
            domain => domain,
        };

        // Trim plus addresses
        let local = match self.local().find('+') {
            Some(pos) => &local[..pos],
            None => local,
        };

        // Ignore dots
        let local = local.replace(".", "");

        EmailAddress::from_parts(&local, domain)
    }
}

/// Display the serialization of this email address.
impl Display for EmailAddress {
    fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
        Display::fmt(&self.serialization, formatter)
    }
}

/// Debug the serialization of this email address.
impl Debug for EmailAddress {
    fn fmt(&self, formatter: &mut Formatter) -> FmtResult {
        Debug::fmt(&self.serialization, formatter)
    }
}

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

    #[test]
    fn test_valid() {
        fn parse(input: &str, output: &str) {
            assert_eq!(
                input.parse::<EmailAddress>().unwrap(),
                EmailAddress::from_trusted(output)
            );
        }
        parse("example.foo+bar@example.com",
              "example.foo+bar@example.com");
        parse("EXAMPLE.FOO+BAR@EXAMPLE.COM",
              "example.foo+bar@example.com");
        parse("BJÖRN@göteborg.test",
              "björn@xn--gteborg-90a.test");
        parse("İⅢ@İⅢ.example",
              "i̇ⅲ@xn--iiii-qwc.example");
    }

    #[test]
    fn test_invalid() {
        fn parse(input: &str) {
            assert!(input.parse::<EmailAddress>().is_err());
        }
        parse("foo");
        parse("foo@");
        parse("@foo.example");
        parse("foo@127.0.0.1");
        parse("foo@[::1]");
    }

    #[test]
    fn test_google() {
        fn parse(input: &str, output: &str) {
            assert_eq!(
                input.parse::<EmailAddress>().unwrap().normalize_google(),
                EmailAddress::from_trusted(output)
            );
        }
        parse("example@gmail.com",
              "example@gmail.com");
        parse("example@googlemail.com",
              "example@gmail.com");
        parse("example.foo@gmail.com",
              "examplefoo@gmail.com");
        parse("example+bar@gmail.com",
              "example@gmail.com");
        parse("example.foo+bar@googlemail.com",
              "examplefoo@gmail.com");
        parse("EXAMPLE@GOOGLEMAIL.COM",
              "example@gmail.com");
        parse("EXAMPLE.FOO+BAR@GOOGLEMAIL.COM",
              "examplefoo@gmail.com");
    }
}
<|endoftext|>


<commit_before>use crate::convert::*;
use crate::operations::folded_multiply;
use crate::operations::read_small;
use crate::random_state::PI;
use crate::RandomState;
use core::hash::Hasher;

///This constant come from Kunth's prng (Empirically it works better than those from splitmix32).
pub(crate) const MULTIPLE: u64 = 6364136223846793005;
const ROT: u32 = 23; //17

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [`AHasher`] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: u64,
    pad: u64,
    extra_keys: [u64; 2],
}

impl AHasher {
    /// Creates a new hasher keyed to the provided key.
    #[inline]
    #[allow(dead_code)] // Is not called if non-fallback hash is used.
    pub fn new_with_keys(key1: u128, key2: u128) -> AHasher {
        let pi: [u128; 2] = PI.convert();
        let key1: [u64; 2] = (key1 ^ pi[0]).convert();
        let key2: [u64; 2] = (key2 ^ pi[1]).convert();
        AHasher {
            buffer: key1[0],
            pad: key1[1],
            extra_keys: key2,
        }
    }

    #[allow(unused)] // False positive
    pub(crate) fn test_with_keys(key1: u128, key2: u128) -> Self {
        let key1: [u64; 2] = key1.convert();
        let key2: [u64; 2] = key2.convert();
        Self {
            buffer: key1[0],
            pad: key1[1],
            extra_keys: key2,
        }
    }

    #[inline]
    #[allow(dead_code)] // Is not called if non-fallback hash is used.
    pub(crate) fn from_random_state(rand_state: &RandomState) -> AHasher {
        AHasher {
            buffer: rand_state.k0,
            pad: rand_state.k1,
            extra_keys: [rand_state.k2, rand_state.k3],
        }
    }

    /// This update function has the goal of updating the buffer with a single multiply
    /// FxHash does this but is vulnerable to attack. To avoid this input needs to be masked to with an
    /// unpredictable value. Other hashes such as murmurhash have taken this approach but were found vulnerable
    /// to attack. The attack was based on the idea of reversing the pre-mixing (Which is necessarily
    /// reversible otherwise bits would be lost) then placing a difference in the highest bit before the
    /// multiply used to mix the data. Because a multiply can never affect the bits to the right of it, a
    /// subsequent update that also differed in this bit could result in a predictable collision.
    ///
    /// This version avoids this vulnerability while still only using a single multiply. It takes advantage
    /// of the fact that when a 64 bit multiply is performed the upper 64 bits are usually computed and thrown
    /// away. Instead it creates two 128 bit values where the upper 64 bits are zeros and multiplies them.
    /// (The compiler is smart enough to turn this into a 64 bit multiplication in the assembly)
    /// Then the upper bits are xored with the lower bits to produce a single 64 bit result.
    ///
    /// To understand why this is a good scrambling function it helps to understand multiply-with-carry PRNGs:
    /// https://en.wikipedia.org/wiki/Multiply-with-carry_pseudorandom_number_generator
    /// If the multiple is chosen well, this creates a long period, decent quality PRNG.
    /// Notice that this function is equivalent to this except the `buffer`/`state` is being xored with each
    /// new block of data. In the event that data is all zeros, it is exactly equivalent to a MWC PRNG.
    ///
    /// This is impervious to attack because every bit buffer at the end is dependent on every bit in
    /// `new_data ^ buffer`. For example suppose two inputs differed in only the 5th bit. Then when the
    /// multiplication is performed the `result` will differ in bits 5-69. More specifically it will differ by
    /// 2^5 * MULTIPLE. However in the next step bits 65-128 are turned into a separate 64 bit value. So the
    /// differing bits will be in the lower 6 bits of this value. The two intermediate values that differ in
    /// bits 5-63 and in bits 0-5 respectively get added together. Producing an output that differs in every
    /// bit. The addition carries in the multiplication and at the end additionally mean that the even if an
    /// attacker somehow knew part of (but not all) the contents of the buffer before hand,
    /// they would not be able to predict any of the bits in the buffer at the end.
    #[inline(always)]
    #[cfg(feature = "folded_multiply")]
    fn update(&mut self, new_data: u64) {
        self.buffer = folded_multiply(new_data ^ self.buffer, MULTIPLE);
    }

    #[inline(always)]
    #[cfg(not(feature = "folded_multiply"))]
    fn update(&mut self, new_data: u64) {
        let d1 = (new_data ^ self.buffer).wrapping_mul(MULTIPLE);
        self.pad = (self.pad ^ d1).rotate_left(8).wrapping_mul(MULTIPLE);
        self.buffer = (self.buffer ^ self.pad).rotate_left(24);
    }

    /// Similar to the above this function performs an update using a "folded multiply".
    /// However it takes in 128 bits of data instead of 64. Both halves must be masked.
    ///
    /// This makes it impossible for an attacker to place a single bit difference between
    /// two blocks so as to cancel each other.
    ///
    /// However this is not sufficient. to prevent (a,b) from hashing the same as (b,a) the buffer itself must
    /// be updated between calls in a way that does not commute. To achieve this XOR and Rotate are used.
    /// Add followed by xor is not the same as xor followed by add, and rotate ensures that the same out bits
    /// can't be changed by the same set of input bits. To cancel this sequence with subsequent input would require
    /// knowing the keys.
    #[inline(always)]
    #[cfg(feature = "folded_multiply")]
    fn large_update(&mut self, new_data: u128) {
        let block: [u64; 2] = new_data.convert();
        let combined = folded_multiply(block[0] ^ self.extra_keys[0], block[1] ^ self.extra_keys[1]);
        self.buffer = (self.buffer.wrapping_add(self.pad) ^ combined).rotate_left(ROT);
    }

    #[inline(always)]
    #[cfg(not(feature = "folded_multiply"))]
    fn large_update(&mut self, new_data: u128) {
        let block: [u64; 2] = new_data.convert();
        self.update(block[0]);
        self.update(block[1]);
    }

    #[inline]
    #[cfg(feature = "specialize")]
    fn short_finish(&self) -> u64 {
        self.buffer.wrapping_add(self.pad)
    }
}

/// Provides [Hasher] methods to hash all of the primitive types.
///
/// [Hasher]: core::hash::Hasher
impl Hasher for AHasher {
    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.large_update(i);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    #[allow(clippy::collapsible_if)]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //Needs to be an add rather than an xor because otherwise it could be canceled with carefully formed input.
        self.buffer = self.buffer.wrapping_add(length).wrapping_mul(MULTIPLE);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() > 8 {
            if data.len() > 16 {
                let tail = data.read_last_u128();
                self.large_update(tail);
                while data.len() > 16 {
                    let (block, rest) = data.read_u128();
                    self.large_update(block);
                    data = rest;
                }
            } else {
                self.large_update([data.read_u64().0, data.read_last_u64()].convert());
            }
        } else {
            let value = read_small(data);
            self.large_update(value.convert());
        }
    }

    #[inline]
    #[cfg(feature = "folded_multiply")]
    fn finish(&self) -> u64 {
        let rot = (self.buffer & 63) as u32;
        folded_multiply(self.buffer, self.pad).rotate_left(rot)
    }

    #[inline]
    #[cfg(not(feature = "folded_multiply"))]
    fn finish(&self) -> u64 {
        let rot = (self.buffer & 63) as u32;
        (self.buffer ^ self.pad).rotate_left(24).wrapping_mul(MULTIPLE).rotate_left(rot)
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherU64 {
    pub(crate) buffer: u64,
    pub(crate) pad: u64,
}

/// A specialized hasher for only primitives under 64 bits.
#[cfg(feature = "specialize")]
impl Hasher for AHasherU64 {
    #[inline]
    fn finish(&self) -> u64 {
        let rot = (self.pad & 64) as u32;
        self.buffer.rotate_left(rot)
    }

    #[inline]
    fn write(&mut self, _bytes: &[u8]) {
        unreachable!("This should never be called")
    }

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.buffer = folded_multiply(i ^ self.buffer, MULTIPLE);
    }

    #[inline]
    fn write_u128(&mut self, _i: u128) {
        unreachable!("This should never be called")
    }

    #[inline]
    fn write_usize(&mut self, _i: usize) {
        unimplemented!()
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherFixed(pub AHasher);

/// A specialized hasher for fixed size primitives larger than 64 bits.
#[cfg(feature = "specialize")]
impl Hasher for AHasherFixed {
    #[inline]
    fn finish(&self) -> u64 {
        self.0.short_finish()
    }

    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        self.0.write(bytes)
    }

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.0.write_u64(i);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.0.write_u128(i);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.0.write_usize(i);
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherStr(pub AHasher);

/// A specialized hasher for a single string
/// Note that the other types don't panic because the hash impl for String tacks on an unneeded call. (As does vec)
#[cfg(feature = "specialize")]
impl Hasher for AHasherStr {
    #[inline]
    fn finish(&self) -> u64 {
        self.0.finish()
    }

    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        if bytes.len() > 8 {
            self.0.write(bytes)
        } else {
            let value = read_small(bytes);
            self.0.buffer = folded_multiply(value[0] ^ self.0.buffer,
                                           value[1] ^ self.0.extra_keys[1]);
            self.0.pad = self.0.pad.wrapping_add(bytes.len() as u64);
        }
    }

    #[inline]
    fn write_u8(&mut self, _i: u8) {}

    #[inline]
    fn write_u16(&mut self, _i: u16) {}

    #[inline]
    fn write_u32(&mut self, _i: u32) {}

    #[inline]
    fn write_u64(&mut self, _i: u64) {}

    #[inline]
    fn write_u128(&mut self, _i: u128) {}

    #[inline]
    fn write_usize(&mut self, _i: usize) {}
}

#[cfg(test)]
mod tests {
    use crate::convert::Convert;
    use crate::fallback_hash::*;

    #[test]
    fn test_hash() {
        let mut hasher = AHasher::new_with_keys(0, 0);
        let value: u64 = 1 << 32;
        hasher.update(value);
        let result = hasher.buffer;
        let mut hasher = AHasher::new_with_keys(0, 0);
        let value2: u64 = 1;
        hasher.update(value2);
        let result2 = hasher.buffer;
        let result: [u8; 8] = result.convert();
        let result2: [u8; 8] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<commit_msg>Further speed up slow path<commit_after>use crate::convert::*;
use crate::operations::folded_multiply;
use crate::operations::read_small;
use crate::random_state::PI;
use crate::RandomState;
use core::hash::Hasher;

///This constant come from Kunth's prng (Empirically it works better than those from splitmix32).
pub(crate) const MULTIPLE: u64 = 6364136223846793005;
const ROT: u32 = 23; //17

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [`AHasher`] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: u64,
    pad: u64,
    extra_keys: [u64; 2],
}

impl AHasher {
    /// Creates a new hasher keyed to the provided key.
    #[inline]
    #[allow(dead_code)] // Is not called if non-fallback hash is used.
    pub fn new_with_keys(key1: u128, key2: u128) -> AHasher {
        let pi: [u128; 2] = PI.convert();
        let key1: [u64; 2] = (key1 ^ pi[0]).convert();
        let key2: [u64; 2] = (key2 ^ pi[1]).convert();
        AHasher {
            buffer: key1[0],
            pad: key1[1],
            extra_keys: key2,
        }
    }

    #[allow(unused)] // False positive
    pub(crate) fn test_with_keys(key1: u128, key2: u128) -> Self {
        let key1: [u64; 2] = key1.convert();
        let key2: [u64; 2] = key2.convert();
        Self {
            buffer: key1[0],
            pad: key1[1],
            extra_keys: key2,
        }
    }

    #[inline]
    #[allow(dead_code)] // Is not called if non-fallback hash is used.
    pub(crate) fn from_random_state(rand_state: &RandomState) -> AHasher {
        AHasher {
            buffer: rand_state.k0,
            pad: rand_state.k1,
            extra_keys: [rand_state.k2, rand_state.k3],
        }
    }

    /// This update function has the goal of updating the buffer with a single multiply
    /// FxHash does this but is vulnerable to attack. To avoid this input needs to be masked to with an
    /// unpredictable value. Other hashes such as murmurhash have taken this approach but were found vulnerable
    /// to attack. The attack was based on the idea of reversing the pre-mixing (Which is necessarily
    /// reversible otherwise bits would be lost) then placing a difference in the highest bit before the
    /// multiply used to mix the data. Because a multiply can never affect the bits to the right of it, a
    /// subsequent update that also differed in this bit could result in a predictable collision.
    ///
    /// This version avoids this vulnerability while still only using a single multiply. It takes advantage
    /// of the fact that when a 64 bit multiply is performed the upper 64 bits are usually computed and thrown
    /// away. Instead it creates two 128 bit values where the upper 64 bits are zeros and multiplies them.
    /// (The compiler is smart enough to turn this into a 64 bit multiplication in the assembly)
    /// Then the upper bits are xored with the lower bits to produce a single 64 bit result.
    ///
    /// To understand why this is a good scrambling function it helps to understand multiply-with-carry PRNGs:
    /// https://en.wikipedia.org/wiki/Multiply-with-carry_pseudorandom_number_generator
    /// If the multiple is chosen well, this creates a long period, decent quality PRNG.
    /// Notice that this function is equivalent to this except the `buffer`/`state` is being xored with each
    /// new block of data. In the event that data is all zeros, it is exactly equivalent to a MWC PRNG.
    ///
    /// This is impervious to attack because every bit buffer at the end is dependent on every bit in
    /// `new_data ^ buffer`. For example suppose two inputs differed in only the 5th bit. Then when the
    /// multiplication is performed the `result` will differ in bits 5-69. More specifically it will differ by
    /// 2^5 * MULTIPLE. However in the next step bits 65-128 are turned into a separate 64 bit value. So the
    /// differing bits will be in the lower 6 bits of this value. The two intermediate values that differ in
    /// bits 5-63 and in bits 0-5 respectively get added together. Producing an output that differs in every
    /// bit. The addition carries in the multiplication and at the end additionally mean that the even if an
    /// attacker somehow knew part of (but not all) the contents of the buffer before hand,
    /// they would not be able to predict any of the bits in the buffer at the end.
    #[inline(always)]
    #[cfg(feature = "folded_multiply")]
    fn update(&mut self, new_data: u64) {
        self.buffer = folded_multiply(new_data ^ self.buffer, MULTIPLE);
    }

    #[inline(always)]
    #[cfg(not(feature = "folded_multiply"))]
    fn update(&mut self, new_data: u64) {
        let d1 = (new_data ^ self.buffer).wrapping_mul(MULTIPLE);
        self.pad = (self.pad ^ d1).rotate_left(8).wrapping_mul(MULTIPLE);
        self.buffer = (self.buffer ^ self.pad).rotate_left(24);
    }

    /// Similar to the above this function performs an update using a "folded multiply".
    /// However it takes in 128 bits of data instead of 64. Both halves must be masked.
    ///
    /// This makes it impossible for an attacker to place a single bit difference between
    /// two blocks so as to cancel each other.
    ///
    /// However this is not sufficient. to prevent (a,b) from hashing the same as (b,a) the buffer itself must
    /// be updated between calls in a way that does not commute. To achieve this XOR and Rotate are used.
    /// Add followed by xor is not the same as xor followed by add, and rotate ensures that the same out bits
    /// can't be changed by the same set of input bits. To cancel this sequence with subsequent input would require
    /// knowing the keys.
    #[inline(always)]
    #[cfg(feature = "folded_multiply")]
    fn large_update(&mut self, new_data: u128) {
        let block: [u64; 2] = new_data.convert();
        let combined = folded_multiply(block[0] ^ self.extra_keys[0], block[1] ^ self.extra_keys[1]);
        self.buffer = (self.buffer.wrapping_add(self.pad) ^ combined).rotate_left(ROT);
    }

    #[inline(always)]
    #[cfg(not(feature = "folded_multiply"))]
    fn large_update(&mut self, new_data: u128) {
        let block: [u64; 2] = new_data.convert();
        self.update(block[0]);
        self.update(block[1]);
    }

    #[inline]
    #[cfg(feature = "specialize")]
    fn short_finish(&self) -> u64 {
        self.buffer.wrapping_add(self.pad)
    }
}

/// Provides [Hasher] methods to hash all of the primitive types.
///
/// [Hasher]: core::hash::Hasher
impl Hasher for AHasher {
    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.large_update(i);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    #[allow(clippy::collapsible_if)]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //Needs to be an add rather than an xor because otherwise it could be canceled with carefully formed input.
        self.buffer = self.buffer.wrapping_add(length).wrapping_mul(MULTIPLE);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() > 8 {
            if data.len() > 16 {
                let tail = data.read_last_u128();
                self.large_update(tail);
                while data.len() > 16 {
                    let (block, rest) = data.read_u128();
                    self.large_update(block);
                    data = rest;
                }
            } else {
                self.large_update([data.read_u64().0, data.read_last_u64()].convert());
            }
        } else {
            let value = read_small(data);
            self.large_update(value.convert());
        }
    }

    #[inline]
    #[cfg(feature = "folded_multiply")]
    fn finish(&self) -> u64 {
        let rot = (self.buffer & 63) as u32;
        folded_multiply(self.buffer, self.pad).rotate_left(rot)
    }

    #[inline]
    #[cfg(not(feature = "folded_multiply"))]
    fn finish(&self) -> u64 {
        let rot = (self.buffer & 63) as u32;
        (self.buffer.wrapping_mul(MULTIPLE) ^ self.pad).rotate_left(rot)
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherU64 {
    pub(crate) buffer: u64,
    pub(crate) pad: u64,
}

/// A specialized hasher for only primitives under 64 bits.
#[cfg(feature = "specialize")]
impl Hasher for AHasherU64 {
    #[inline]
    fn finish(&self) -> u64 {
        let rot = (self.pad & 64) as u32;
        self.buffer.rotate_left(rot)
    }

    #[inline]
    fn write(&mut self, _bytes: &[u8]) {
        unreachable!("This should never be called")
    }

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.buffer = folded_multiply(i ^ self.buffer, MULTIPLE);
    }

    #[inline]
    fn write_u128(&mut self, _i: u128) {
        unreachable!("This should never be called")
    }

    #[inline]
    fn write_usize(&mut self, _i: usize) {
        unimplemented!()
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherFixed(pub AHasher);

/// A specialized hasher for fixed size primitives larger than 64 bits.
#[cfg(feature = "specialize")]
impl Hasher for AHasherFixed {
    #[inline]
    fn finish(&self) -> u64 {
        self.0.short_finish()
    }

    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        self.0.write(bytes)
    }

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.0.write_u64(i);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.0.write_u128(i);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.0.write_usize(i);
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherStr(pub AHasher);

/// A specialized hasher for a single string
/// Note that the other types don't panic because the hash impl for String tacks on an unneeded call. (As does vec)
#[cfg(feature = "specialize")]
impl Hasher for AHasherStr {
    #[inline]
    fn finish(&self) -> u64 {
        self.0.finish()
    }

    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        if bytes.len() > 8 {
            self.0.write(bytes)
        } else {
            let value = read_small(bytes);
            self.0.buffer = folded_multiply(value[0] ^ self.0.buffer,
                                           value[1] ^ self.0.extra_keys[1]);
            self.0.pad = self.0.pad.wrapping_add(bytes.len() as u64);
        }
    }

    #[inline]
    fn write_u8(&mut self, _i: u8) {}

    #[inline]
    fn write_u16(&mut self, _i: u16) {}

    #[inline]
    fn write_u32(&mut self, _i: u32) {}

    #[inline]
    fn write_u64(&mut self, _i: u64) {}

    #[inline]
    fn write_u128(&mut self, _i: u128) {}

    #[inline]
    fn write_usize(&mut self, _i: usize) {}
}

#[cfg(test)]
mod tests {
    use crate::convert::Convert;
    use crate::fallback_hash::*;

    #[test]
    fn test_hash() {
        let mut hasher = AHasher::new_with_keys(0, 0);
        let value: u64 = 1 << 32;
        hasher.update(value);
        let result = hasher.buffer;
        let mut hasher = AHasher::new_with_keys(0, 0);
        let value2: u64 = 1;
        hasher.update(value2);
        let result2 = hasher.buffer;
        let result: [u8; 8] = result.convert();
        let result2: [u8; 8] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<|endoftext|>


<commit_before>//! Functions for computing [integral images](https://en.wikipedia.org/wiki/Summed_area_table)
//! and running sums of rows and columns.

extern crate image;

use image::{
    Luma,
    GenericImage,
    ImageBuffer
};

use definitions::{
    VecBuffer
};

/// Computes the integral image of an 8bpp grayscale image.
/// I is the integral image of an image F if I(x, y) is the
/// sum of F(x', y') for x' <= x, y' <= y. i.e. each pixel
/// in the integral image contains the sum of the pixel intensities
/// of all input pixels that are above it and to its left.
/// The integral image has the helpful property that it lets us
/// compute the sum of pixel intensities from any rectangular region
/// in the input image in constant time.
/// Specifically, given a rectangle in F with clockwise corners
/// A, B, C, D, with A at the upper left, the total pixel intensity
/// of this rectangle is I(C) - I(B) - I(D) + I(A).
// TODO: Support more formats.
// TODO: This is extremely slow. Fix that!
pub fn integral_image<I>(image: &I) -> VecBuffer<Luma<u32>>
    where I: GenericImage<Pixel=Luma<u8>> {
    padded_integral_image(image, 0, 0)
}

/// Computes the integral image of the result of padding image
/// with its boundary pixels for x_padding columns on either
/// side and y_padding rows at its top and bottom.
/// Returned image has width image.width() + 2 * x_padding
/// and height image.height() + 2 * y_padding.
pub fn padded_integral_image<I>(image: &I, x_padding: u32, y_padding: u32) -> VecBuffer<Luma<u32>>
    where I: GenericImage<Pixel=Luma<u8>>
{
    let (in_width, in_height) = image.dimensions();
    let out_width = in_width + 2 * x_padding;
    let out_height = in_height + 2 * y_padding;

    let mut out: ImageBuffer<Luma<u32>, Vec<u32>> = ImageBuffer::new(out_width, out_height);

    if in_width == 0 || in_height == 0 {
        return out;
    }

    for y in 0..out_height {
        let y_in: u32;
        if y < y_padding {
            y_in = 0;
        }
        else if y >= in_height + y_padding {
            y_in = in_height - 1;
        }
        else {
            y_in = y - y_padding;
        }

        for x in 0..out_width {
            let x_in: u32;
            if x < x_padding {
                x_in = 0;
            }
            else if x >= in_width + x_padding {
                x_in = in_width - 1;
            }
            else {
                x_in = x - x_padding;
            }

            unsafe {
                let p = image.unsafe_get_pixel(x_in, y_in);
                out.unsafe_put_pixel(x, y, Luma([p[0] as u32]));
            }
        }
    }

    for x in 1..out_width {
        (*out.get_pixel_mut(x, 0))[0] += unsafe { out.unsafe_get_pixel(x - 1, 0)[0] };
    }

    for y in 1..out_height {
        (*out.get_pixel_mut(0, y))[0] += unsafe { out.unsafe_get_pixel(0, y - 1)[0] };

        for x in 1..out_width {
            (*out.get_pixel_mut(x, y))[0] += unsafe { out.unsafe_get_pixel(x, y - 1)[0] };
            (*out.get_pixel_mut(x, y))[0] += unsafe { out.unsafe_get_pixel(x - 1, y)[0] };
            (*out.get_pixel_mut(x, y))[0] -= unsafe { out.unsafe_get_pixel(x - 1, y - 1)[0] };
        }
    }

    out
}

/// Computes the running sum of one row of image, padded
/// at the beginning and end. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all rows in an image.
// TODO: faster, more formats
pub fn row_running_sum<I>(image: &I, row: u32, buffer: &mut [u32], padding: u32)
    where I: GenericImage<Pixel=Luma<u8>> {

    let width = image.width();
    assert!(buffer.len() >= (width + 2 * padding) as usize,
        format!("Buffer length {} is less than {} + 2 * {}", buffer.len(), width, padding));
    assert!(row < image.height(),
        format!("row out of bound: {} >= {}", row, image.height()));

    for x in 0..padding {
        buffer[x as usize] = unsafe { image.unsafe_get_pixel(0, row)[0] as u32 };
    }

    for x in 0..width {
        let idx = (x + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(x, row)[0] as u32 };
    }

    for x in 0..padding {
        let idx = (x + width + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(width - 1, row)[0] as u32 };
    }

    for x in 1..width + 2 * padding {
        buffer[x as usize] += buffer[(x - 1) as usize] as u32;
    }
}

/// Computes the running sum of one column of image, padded
/// at the top and bottom. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all columns in an image.
// TODO: faster, more formats
pub fn column_running_sum<I>(image: &I, column: u32, buffer: &mut [u32], padding: u32)
    where I: GenericImage<Pixel=Luma<u8>> {

    let height = image.height();
    assert!(buffer.len() >= (height + 2 * padding) as usize,
        format!("Buffer length {} is less than {} + 2 * {}", buffer.len(), height, padding));
    assert!(column < image.width(),
        format!("column out of bound: {} >= {}", column, image.width()));

    for y in 0..padding {
        buffer[y as usize] = unsafe { image.unsafe_get_pixel(column, 0)[0] as u32 };
    }

    for y in 0..height {
        let idx = (y + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(column, y)[0] as u32 };
    }

    for y in 0..padding {
        let idx = (y + height + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(column, height - 1)[0] as u32 };
    }

    for y in 1..height + 2 * padding {
        buffer[y as usize] += buffer[(y - 1) as usize] as u32;
    }
}

#[cfg(test)]
mod test {

    use super::{
        column_running_sum,
        integral_image,
        padded_integral_image,
        row_running_sum
    };
    use utils::{
        gray_bench_image,
        GrayTestImage
    };
    use image::{
        GenericImage,
        GrayImage,
        ImageBuffer,
        Luma
    };
    use quickcheck::{
        quickcheck
    };
    use definitions::{
        VecBuffer
    };
    use test;

    #[test]
    fn test_integral_image() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected: ImageBuffer<Luma<u32>, Vec<u32>>
            = ImageBuffer::from_raw(3, 2, vec![
            1,  3,  6,
            5, 12, 21]).unwrap();

        assert_pixels_eq!(integral_image(&image), expected);
    }

    #[bench]
    fn bench_integral_image(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let integral = integral_image(&image);
            test::black_box(integral);
            });
    }

    #[test]
    fn test_padded_integral_image() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected: ImageBuffer<Luma<u32>, Vec<u32>>
            = ImageBuffer::from_raw(5, 4, vec![
              1,  2,   4,   7,  10,
              2,  4,   8,  14,  20,
              6, 12,  21,  33,  45,
             10, 20,  34,  52,  70]).unwrap();

        assert_pixels_eq!(padded_integral_image(&image, 1, 1), expected);
    }

    #[test]
    fn test_row_running_sum() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        row_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_row_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(1000, 1);
        let mut buffer = [0; 1010];
        b.iter(|| {
            row_running_sum(&image, 0, &mut buffer, 5);
            });
    }

    #[test]
    fn test_column_running_sum() {
        let image: GrayImage = ImageBuffer::from_raw(2, 3, vec![
            1, 4,
            2, 5,
            3, 6]).unwrap();

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        column_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_column_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(100, 1000);
        let mut buffer = [0; 1010];
        b.iter(|| {
            column_running_sum(&image, 0, &mut buffer, 5);
            });
    }

    /// Simple implementation of integral_image to validate faster versions against.
    fn integral_image_ref<I>(image: &I) -> VecBuffer<Luma<u32>>
        where I: GenericImage<Pixel=Luma<u8>>
    {
        let (width, height) = image.dimensions();
        let mut out = ImageBuffer::new(width, height);

        for y in 0..height {
            for x in 0..width {
                let mut sum = 0u32;

                for iy in 0..(y + 1) {
                    for ix in 0..(x + 1) {
                        sum += image.get_pixel(ix, iy)[0] as u32;
                    }
                }

                out.put_pixel(x, y, Luma([sum]));
            }
        }

        out
    }

    #[test]
    fn test_integral_image_matches_reference_implementation() {
        fn prop(image: GrayTestImage) -> bool {
            let expected = integral_image_ref(&image.0);
            let actual = integral_image(&image.0);
            actual.pixels().eq(expected.pixels())
        }
        quickcheck(prop as fn(GrayTestImage) -> bool);
    }
}
<commit_msg>Less terrible implementation of integral_image<commit_after>//! Functions for computing [integral images](https://en.wikipedia.org/wiki/Summed_area_table)
//! and running sums of rows and columns.

extern crate image;

use image::{
    Luma,
    GenericImage,
    ImageBuffer
};

use definitions::{
    VecBuffer
};

use std::cmp;

/// Computes the integral image of an 8bpp grayscale image.
/// I is the integral image of an image F if I(x, y) is the
/// sum of F(x', y') for x' <= x, y' <= y. i.e. each pixel
/// in the integral image contains the sum of the pixel intensities
/// of all input pixels that are above it and to its left.
/// The integral image has the helpful property that it lets us
/// compute the sum of pixel intensities from any rectangular region
/// in the input image in constant time.
/// Specifically, given a rectangle in F with clockwise corners
/// A, B, C, D, with A at the upper left, the total pixel intensity
/// of this rectangle is I(C) - I(B) - I(D) + I(A).
// TODO: Support more formats.
// TODO: This is extremely slow. Fix that!
pub fn integral_image<I>(image: &I) -> VecBuffer<Luma<u32>>
    where I: GenericImage<Pixel=Luma<u8>> {
    padded_integral_image(image, 0, 0)
}

/// Computes the integral image of the result of padding image with
/// its boundary pixels for x_padding columns on either side and y_padding
/// rows at its top and bottom. Returned image has width image.width() + 2 * x_padding
/// and height image.height() + 2 * y_padding.
pub fn padded_integral_image<I>(image: &I, x_padding: u32, y_padding: u32) -> VecBuffer<Luma<u32>>
    where I: GenericImage<Pixel=Luma<u8>>
{
    let (in_width, in_height) = image.dimensions();
    let out_width = in_width + 2 * x_padding;
    let out_height = in_height + 2 * y_padding;

    let mut out: ImageBuffer<Luma<u32>, Vec<u32>> = ImageBuffer::new(out_width, out_height);

    if in_width == 0 || in_height == 0 {
        return out;
    }

    let mut top_sum = 0u32;
    for x in 0..out_width {
        let x_in = adjust_for_padding(x, x_padding, in_width);
        unsafe {
            top_sum += image.unsafe_get_pixel(x_in, 0)[0] as u32;
            out.unsafe_put_pixel(x, 0, Luma([top_sum]));
        }
    }

    for y in 1..out_height {
        let y_in = adjust_for_padding(y, y_padding, in_height);
        let mut sum = 0;

        for x in 0..out_width {
            let x_in = adjust_for_padding(x, x_padding, in_width);

            unsafe {
                sum += image.unsafe_get_pixel(x_in, y_in)[0] as u32;
                let above = out.unsafe_get_pixel(x, y - 1)[0];
                out.unsafe_put_pixel(x, y, Luma([above + sum]))
            }
        }
    }

    out
}

#[inline(always)]
fn adjust_for_padding(out_index: u32, padding: u32, upper: u32) -> u32 {
    if out_index < padding {
        return 0;
    } else if out_index >= upper + padding {
        return upper - 1;
    }
    return out_index - padding;
}

/// Computes the running sum of one row of image, padded
/// at the beginning and end. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all rows in an image.
// TODO: faster, more formats
pub fn row_running_sum<I>(image: &I, row: u32, buffer: &mut [u32], padding: u32)
    where I: GenericImage<Pixel=Luma<u8>> {

    let width = image.width();
    assert!(buffer.len() >= (width + 2 * padding) as usize,
        format!("Buffer length {} is less than {} + 2 * {}", buffer.len(), width, padding));
    assert!(row < image.height(),
        format!("row out of bound: {} >= {}", row, image.height()));

    for x in 0..padding {
        buffer[x as usize] = unsafe { image.unsafe_get_pixel(0, row)[0] as u32 };
    }

    for x in 0..width {
        let idx = (x + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(x, row)[0] as u32 };
    }

    for x in 0..padding {
        let idx = (x + width + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(width - 1, row)[0] as u32 };
    }

    for x in 1..width + 2 * padding {
        buffer[x as usize] += buffer[(x - 1) as usize] as u32;
    }
}

/// Computes the running sum of one column of image, padded
/// at the top and bottom. The padding is by continuity.
/// Takes a reference to buffer so that this can be reused
/// for all columns in an image.
// TODO: faster, more formats
pub fn column_running_sum<I>(image: &I, column: u32, buffer: &mut [u32], padding: u32)
    where I: GenericImage<Pixel=Luma<u8>> {

    let height = image.height();
    assert!(buffer.len() >= (height + 2 * padding) as usize,
        format!("Buffer length {} is less than {} + 2 * {}", buffer.len(), height, padding));
    assert!(column < image.width(),
        format!("column out of bound: {} >= {}", column, image.width()));

    for y in 0..padding {
        buffer[y as usize] = unsafe { image.unsafe_get_pixel(column, 0)[0] as u32 };
    }

    for y in 0..height {
        let idx = (y + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(column, y)[0] as u32 };
    }

    for y in 0..padding {
        let idx = (y + height + padding) as usize;
        buffer[idx] = unsafe { image.unsafe_get_pixel(column, height - 1)[0] as u32 };
    }

    for y in 1..height + 2 * padding {
        buffer[y as usize] += buffer[(y - 1) as usize] as u32;
    }
}

#[cfg(test)]
mod test {

    use super::{
        column_running_sum,
        integral_image,
        padded_integral_image,
        row_running_sum
    };
    use utils::{
        gray_bench_image,
        GrayTestImage
    };
    use image::{
        GenericImage,
        GrayImage,
        ImageBuffer,
        Luma
    };
    use quickcheck::{
        quickcheck
    };
    use definitions::{
        VecBuffer
    };
    use test;

    #[test]
    fn test_integral_image() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected: ImageBuffer<Luma<u32>, Vec<u32>>
            = ImageBuffer::from_raw(3, 2, vec![
            1,  3,  6,
            5, 12, 21]).unwrap();

        assert_pixels_eq!(integral_image(&image), expected);
    }

    #[bench]
    fn bench_integral_image(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let integral = integral_image(&image);
            test::black_box(integral);
            });
    }

    #[test]
    fn test_padded_integral_image() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected: ImageBuffer<Luma<u32>, Vec<u32>>
            = ImageBuffer::from_raw(5, 4, vec![
              1,  2,   4,   7,  10,
              2,  4,   8,  14,  20,
              6, 12,  21,  33,  45,
             10, 20,  34,  52,  70]).unwrap();

        assert_pixels_eq!(padded_integral_image(&image, 1, 1), expected);
    }

    #[test]
    fn test_row_running_sum() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            1, 2, 3,
            4, 5, 6]).unwrap();

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        row_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_row_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(1000, 1);
        let mut buffer = [0; 1010];
        b.iter(|| {
            row_running_sum(&image, 0, &mut buffer, 5);
            });
    }

    #[test]
    fn test_column_running_sum() {
        let image: GrayImage = ImageBuffer::from_raw(2, 3, vec![
            1, 4,
            2, 5,
            3, 6]).unwrap();

        let expected = [1, 2, 4, 7, 10];

        let mut buffer = [0; 5];
        column_running_sum(&image, 0, &mut buffer, 1);

        assert_eq!(buffer, expected);
    }

    #[bench]
    fn bench_column_running_sum(b: &mut test::Bencher) {
        let image = gray_bench_image(100, 1000);
        let mut buffer = [0; 1010];
        b.iter(|| {
            column_running_sum(&image, 0, &mut buffer, 5);
            });
    }

    /// Simple implementation of integral_image to validate faster versions against.
    fn integral_image_ref<I>(image: &I) -> VecBuffer<Luma<u32>>
        where I: GenericImage<Pixel=Luma<u8>>
    {
        let (width, height) = image.dimensions();
        let mut out = ImageBuffer::new(width, height);

        for y in 0..height {
            for x in 0..width {
                let mut sum = 0u32;

                for iy in 0..(y + 1) {
                    for ix in 0..(x + 1) {
                        sum += image.get_pixel(ix, iy)[0] as u32;
                    }
                }

                out.put_pixel(x, y, Luma([sum]));
            }
        }

        out
    }

    #[test]
    fn test_integral_image_matches_reference_implementation() {
        fn prop(image: GrayTestImage) -> bool {
            let expected = integral_image_ref(&image.0);
            let actual = integral_image(&image.0);
            actual.pixels().eq(expected.pixels())
        }
        quickcheck(prop as fn(GrayTestImage) -> bool);
    }
}
<|endoftext|>


<commit_before>use std::time::{Duration, SystemTime, UNIX_EPOCH};

// ========================================================================= //

/// Converts a `SystemTime` to a Windows `FILETIME`.
pub fn filetime_from_system_time(timestamp: SystemTime) -> u64 {
    match timestamp.duration_since(filetime_epoch()) {
        Ok(delta) => {
            delta.as_secs() * 10_000_000 + (delta.subsec_nanos() / 100) as u64
        }
        Err(_) => 0,
    }
}

/// Converts a Windows `FILETIME` to a `SystemTime`.
pub fn system_time_from_filetime(timestamp: u64) -> SystemTime {
    let delta = Duration::new(
        timestamp / 10_000_000,
        (timestamp % 10_000_000) as u32 * 100,
    );
    filetime_epoch() + delta
}

/// Returns the epoch used for Windows `FILETIME` values.
fn filetime_epoch() -> SystemTime {
    // The epoch used by CFB files is Jan 1, 1601 UTC, which we can calculate
    // from the Unix epoch constant, which is Jan 1, 1970 UTC.
    UNIX_EPOCH - Duration::from_secs(11644473600)
}

// ========================================================================= //

#[cfg(test)]
mod tests {
    use super::{filetime_from_system_time, system_time_from_filetime};
    use std::time::{Duration, UNIX_EPOCH};

    #[test]
    fn to_system_time() {
        let sat_2017_mar_18_at_18_46_36_gmt =
            UNIX_EPOCH + Duration::from_secs(1489862796);
        assert_eq!(
            system_time_from_filetime(131343363960000000),
            sat_2017_mar_18_at_18_46_36_gmt
        );
    }

    #[test]
    fn from_system_time() {
        let sat_2017_mar_18_at_18_46_36_gmt =
            UNIX_EPOCH + Duration::from_secs(1489862796);
        assert_eq!(
            filetime_from_system_time(sat_2017_mar_18_at_18_46_36_gmt),
            131343363960000000
        );
    }
}

// ========================================================================= //
<commit_msg>Fix work with time<commit_after>use std::time::{Duration, SystemTime, UNIX_EPOCH};

// ========================================================================= //

/// Converts a `SystemTime` to a Windows `FILETIME`.
pub fn filetime_from_system_time(timestamp: SystemTime) -> u64 {
    match timestamp.duration_since(filetime_epoch()) {
        Ok(delta) => {
            delta.as_secs() * 1_000_000_000 + delta.subsec_nanos() as u64
        }
        Err(_) => 0,
    }
}

/// Converts a Windows `FILETIME` to a `SystemTime`.
pub fn system_time_from_filetime(timestamp: u64) -> SystemTime {
    let delta = Duration::new(
        timestamp / 1_000_000_000,
        (timestamp % 1_000_000_000) as u32,
    );
    filetime_epoch() + delta
}

/// Returns the epoch used for Windows `FILETIME` values.
fn filetime_epoch() -> SystemTime {
    // The epoch used by CFB files is Jan 1, 1601 UTC, which we can calculate
    // from the Unix epoch constant, which is Jan 1, 1970 UTC.
    UNIX_EPOCH - Duration::from_secs(11644473600)
}

// ========================================================================= //

#[cfg(test)]
mod tests {
    use super::{filetime_from_system_time, system_time_from_filetime};
    use std::time::{Duration, UNIX_EPOCH};

    #[test]
    fn to_system_time() {
        let sat_2017_mar_18_at_18_46_36_gmt =
            UNIX_EPOCH + Duration::from_secs(1489862796);
        assert_eq!(
            system_time_from_filetime(131343363960000000),
            sat_2017_mar_18_at_18_46_36_gmt
        );
    }

    #[test]
    fn from_system_time() {
        let sat_2017_mar_18_at_18_46_36_gmt =
            UNIX_EPOCH + Duration::from_secs(1489862796);
        assert_eq!(
            filetime_from_system_time(sat_2017_mar_18_at_18_46_36_gmt),
            131343363960000000
        );
    }
}

// ========================================================================= //
<|endoftext|>


<commit_before>use crate::core::*;
use crate::geometry::Space;
use crate::policies::{FinitePolicy, Policy};
use rand::{
    distributions::{Distribution, Normal},
    rngs::ThreadRng,
    Rng,
    thread_rng,
};
use std::ops::Add;

pub struct PerturbedPolicy<P, D, R = ThreadRng> {
    pub base_policy: Shared<P>,
    pub noise_dist: D,

    rng: R,
}

impl<P, D> PerturbedPolicy<P, D> {
    pub fn new(base_policy: Shared<P>, noise_dist: D) -> Self {
        PerturbedPolicy::with_rng(base_policy, noise_dist, thread_rng())
    }
}

impl<P> PerturbedPolicy<P, Normal> {
    pub fn normal(base_policy: Shared<P>, std_dev: f64) -> Self {
        PerturbedPolicy::with_rng(base_policy, Normal::new(0.0, std_dev), thread_rng())
    }
}

impl<P, D, R> PerturbedPolicy<P, D, R> {
    pub fn with_rng(base_policy: Shared<P>, noise_dist: D, rng: R) -> Self {
        PerturbedPolicy {
            base_policy,
            noise_dist,
            rng,
        }
    }
}

impl<P, D, R> Algorithm for PerturbedPolicy<P, D, R> {}

impl<S, P, D, R> Policy<S> for PerturbedPolicy<P, D, R>
where
    P: Policy<S>,
    D: Distribution<P::Action>,
    R: Rng,
    P::Action: Add<P::Action, Output = P::Action>,
{
    type Action = P::Action;

    fn sample(&mut self, s: &S) -> P::Action {
        let base_action = self.base_policy.borrow_mut().sample(s);
        let perturbation = self.noise_dist.sample(&mut self.rng);

        base_action + perturbation
    }

    fn probability(&mut self, _: &S, _: P::Action) -> f64 {
        unimplemented!()
    }
}

impl<S, P, D, R> FinitePolicy<S> for PerturbedPolicy<P, D, R>
where
    P: FinitePolicy<S>,
    D: Distribution<P::Action>,
    R: Rng,
{
    fn n_actions(&self) -> P::Action {
        self.base_policy.n_actions()
    }

    fn probabilities(&mut self, _: &S) -> Vector<f64> {
        unimplemented!()
    }
}
<commit_msg>feat(policies): implement handle_terminal for PerturbedPolicy<commit_after>use crate::core::*;
use crate::geometry::Space;
use crate::policies::{FinitePolicy, Policy};
use rand::{
    distributions::{Distribution, Normal},
    rngs::ThreadRng,
    Rng,
    thread_rng,
};
use std::ops::Add;

pub struct PerturbedPolicy<P, D, R = ThreadRng> {
    pub base_policy: Shared<P>,
    pub noise_dist: D,

    rng: R,
}

impl<P, D> PerturbedPolicy<P, D> {
    pub fn new(base_policy: Shared<P>, noise_dist: D) -> Self {
        PerturbedPolicy::with_rng(base_policy, noise_dist, thread_rng())
    }
}

impl<P> PerturbedPolicy<P, Normal> {
    pub fn normal(base_policy: Shared<P>, std_dev: f64) -> Self {
        PerturbedPolicy::with_rng(base_policy, Normal::new(0.0, std_dev), thread_rng())
    }
}

impl<P, D, R> PerturbedPolicy<P, D, R> {
    pub fn with_rng(base_policy: Shared<P>, noise_dist: D, rng: R) -> Self {
        PerturbedPolicy {
            base_policy,
            noise_dist,
            rng,
        }
    }
}

impl<P: Algorithm, D, R> Algorithm for PerturbedPolicy<P, D, R> {
    fn handle_terminal(&mut self) {
        self.base_policy.borrow_mut().handle_terminal();
    }
}

impl<S, P, D, R> Policy<S> for PerturbedPolicy<P, D, R>
where
    P: Policy<S>,
    D: Distribution<P::Action>,
    R: Rng,
    P::Action: Add<P::Action, Output = P::Action>,
{
    type Action = P::Action;

    fn sample(&mut self, s: &S) -> P::Action {
        let base_action = self.base_policy.borrow_mut().sample(s);
        let perturbation = self.noise_dist.sample(&mut self.rng);

        base_action + perturbation
    }

    fn probability(&mut self, _: &S, _: P::Action) -> f64 {
        unimplemented!()
    }
}

impl<S, P, D, R> FinitePolicy<S> for PerturbedPolicy<P, D, R>
where
    P: FinitePolicy<S>,
    D: Distribution<P::Action>,
    R: Rng,
{
    fn n_actions(&self) -> P::Action {
        self.base_policy.n_actions()
    }

    fn probabilities(&mut self, _: &S) -> Vector<f64> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>
pub enum YSONValue<'a> {
    Map{values: Vec<(YSONValue<'a>, YSONValue<'a>)>},
    Array{values: Vec<YSONValue<'a>>},
    Scalar{value: &'a str}
}

impl<'a> YSONValue<'a> {
    fn require(tok: &str, mut src: &'a str) -> &'a str {
        src = src.trim_left();
        if src.starts_with(tok) {
            src.split_at(tok.len()).1.trim_left()
        }
        else {
            panic!("Expected token {} not found.", tok)
        }
    }

    fn allow(tok: &str, mut src: &'a str) -> &'a str {
        src = src.trim_left();
        if src.starts_with(tok) {
            src.split_at(tok.len()).1.trim_left()
        }
        else {
            src
        }
    }

    pub fn parse_map(mut src: &str) -> (YSONValue, &str) {
        let mut values = Vec::new();
        src = YSONValue::require("{", src);
        while !src.starts_with('}') {
            let (key, src2) = YSONValue::parse_scalar(src);
            src = YSONValue::require(":", src2);
            let (value, src2) = YSONValue::parse(src);
            src = YSONValue::allow(",", src2);
            values.push((key, value));
        }
        YSONValue::require("}", src);
        println!("parsed map");
        (YSONValue::Map{values: values}, src)
    }

    pub fn parse_array(mut src: &str) -> (YSONValue, &str) {
        let mut values = Vec::new();
        src = YSONValue::require("[", src);
        while !src.starts_with(']') {
            let (value, src2) = YSONValue::parse(src);
            src = YSONValue::allow(",", src2);
            values.push(value);
        }
        YSONValue::require("]", src);
        println!("parsed array");
        (YSONValue::Array{values: values}, src)
    }

    pub fn parse_quoted_string(src: &str) -> (YSONValue, &str) {
        // Parse series of characters starting and ending with '"', including whitespace and
        // newlines.
        let mut chars = src.char_indices();
        let mut prev_char = '\\';
        loop {
            let (idx, this_char) = match chars.next() {
                None => panic!("Expected terminating \" not found."),
                Some((idx, ch)) => ((idx, ch))
            };
            if this_char == '"' && prev_char != '\\' {
                let (s, src) = src.split_at(idx + 1);
                println!("parsed quoted string: {}", s);
                return (YSONValue::Scalar{value: s}, src);
            }
            else {
                prev_char = this_char;
            }
        }
    }

    pub fn parse_literal(src: &str) -> (YSONValue, &str) {
        // Parse series of characters consisting of any character but: ":,]}", or
        // whitespace.
        match src.find(|ch| char::is_whitespace(ch) || ":,]}".contains(ch)) {
            None => panic!("End of input reached while parsing literal."),
            Some(idx) => {
                let (s, src) = src.split_at(idx);
                println!("parsed literal: {}", s);
                return (YSONValue::Scalar{value: s}, src);
            }
        }
    }

    pub fn parse_scalar(src: &str) -> (YSONValue, &str) {
        if src.starts_with('"') {
            return YSONValue::parse_quoted_string(src);
        }
        else {
            return YSONValue::parse_literal(src);
        };
    }

    pub fn parse(src: &str) -> (YSONValue, &str) {
        let src = src.trim_left();// strip leading whitespace
        if src.starts_with('{') {
            return YSONValue::parse_map(src);
        }
        else if src.starts_with('[') {
            return YSONValue::parse_array(src);
        }
        else {
            return YSONValue::parse_scalar(src);
        };
    }

    pub fn display(&self) {
        match *self {
            YSONValue::Map{ref values} => {
                print!("{{\n");
                for x in values {
                    x.0.display();
                    print!(":");
                    x.1.display();
                    print!(",\n");
                }
                print!("}}\n");
            },
            YSONValue::Array{ref values} => {
                print!("[\n");
                for x in values {
                    x.display();
                    print!(",\n");
                }
                print!("]\n");
            },
            YSONValue::Scalar{ref value} => print!("{}", value)
        }
    }
}
<commit_msg>Split off parsing code into YSONParser, a start at some accessors for YSONValues<commit_after>
use std::num;

#[derive(Debug)]
pub enum YSONError {
    ParseFloatError(num::ParseFloatError),
    ScalarNotFloatError
}

pub enum YSONValue<'a> {
    Map{values: Vec<(YSONValue<'a>, YSONValue<'a>)>},
    Array{values: Vec<YSONValue<'a>>},
    RawScalar{value: &'a str},
    String{value: String}
}

struct YSONParser<'a> {
    src: &'a str
}

impl<'a> YSONParser<'a> {
    fn eat_white(&mut self) {
        self.src = self.src.trim_left();
    }

    fn require(&mut self, tok: &str) {
        self.eat_white();
        if self.src.starts_with(tok) {
            self.src = self.src.split_at(tok.len()).1;
            self.eat_white();
        }
        else {
            panic!("Expected token {} not found.", tok)
        }
    }

    fn allow(&mut self, tok: &str) {
        self.eat_white();
        if self.src.starts_with(tok) {
            self.src = self.src.split_at(tok.len()).1;
            self.eat_white();
        }
    }

    pub fn parse_map(&mut self) -> YSONValue<'a> {
        let mut values = Vec::new();
        self.require("{");
        while !self.src.starts_with('}') {
            let key = self.parse_scalar();
            self.require(":");
            let value = self.parse_value();
            self.allow(",");
            values.push((key, value));
        }
        self.require("}");
        println!("parsed map");
        YSONValue::Map{values: values}
    }

    pub fn parse_array(&mut self) -> YSONValue<'a> {
        let mut values = Vec::new();
        self.require("[");
        while !self.src.starts_with(']') {
            values.push(self.parse_value());
            self.allow(",");
        }
        self.require("]");
        println!("parsed array");
        YSONValue::Array{values: values}
    }

    pub fn parse_quoted_string(&mut self) -> YSONValue<'a> {
        // Parse series of characters starting and ending with '"', including whitespace and
        // newlines.
        let mut chars = self.src.char_indices();
        let mut prev_char = '\\';
        loop {
            let (idx, this_char) = match chars.next() {
                None => panic!("Expected terminating \" not found."),
                Some((idx, ch)) => ((idx, ch))
            };
            if this_char == '"' && prev_char != '\\' {
                let (s, src2) = self.src.split_at(idx + 1);
                self.src = src2;
                println!("parsed quoted string: {}", s);
                return YSONValue::RawScalar{value: s};
            }
            else {
                prev_char = this_char;
            }
        }
    }

    pub fn parse_literal(&mut self) -> YSONValue<'a> {
        // Parse series of characters consisting of any character but: ":,]}", or
        // whitespace.
        match self.src.find(|ch| char::is_whitespace(ch) || ":,]}".contains(ch)) {
            None => panic!("End of input reached while parsing literal."),
            Some(idx) => {
                let (s, src2) = self.src.split_at(idx);
                self.src = src2;
                println!("parsed literal: {}", s);
                return YSONValue::RawScalar{value: s};
            }
        }
    }

    pub fn parse_scalar(&mut self) -> YSONValue<'a> {
        if self.src.starts_with('"') {
            return self.parse_quoted_string();
        }
        else {
            return self.parse_literal();
        };
    }

    pub fn parse_value(&mut self) -> YSONValue<'a> {
        self.eat_white();
        if self.src.starts_with('{') {
            return self.parse_map();
        }
        else if self.src.starts_with('[') {
            return self.parse_array();
        }
        else {
            return self.parse_scalar();
        };
    }
}

impl<'a> YSONValue<'a> {
    pub fn parse(src: &'a str) -> YSONValue<'a> {
        let mut parser = YSONParser{src: src};
        parser.parse_value()
    }

    pub fn map_values(&self) -> Option<&Vec<(YSONValue<'a>, YSONValue<'a>)>> {
        match *self {
            YSONValue::Map{ref values} => Some(values),
            _ => None
        }
    }

    pub fn map_value(&self, key: &str) -> Option<&YSONValue<'a>> {
        for x in self.map_values().unwrap() {
            if x.0.scalar_value().unwrap() == key {
                return Some(&(x.1));
            }
        }
        return None;
    }

    pub fn array_values(&self) -> Option<&Vec<YSONValue<'a>>> {
        match *self {
            YSONValue::Array{ref values} => Some(values),
            _ => None
        }
    }

    pub fn scalar_value(&self) -> Option<&str> {
        match *self {
            YSONValue::RawScalar{ref value} => Some(value),
            YSONValue::String{ref value} => Some(&value),
            _ => None
        }
    }

    pub fn f64_value(&self) -> Result<f64, YSONError> {
        let scal_val = match self.scalar_value() {
            Some(scalar) => scalar,
            _ => return Err(YSONError::ScalarNotFloatError)
        };
        scal_val.parse::<f64>().map_err(YSONError::ParseFloatError)
    }

    pub fn display(&self) {
        match *self {
            YSONValue::Map{ref values} => {
                print!("{{\n");
                for x in values {
                    x.0.display();
                    print!(":");
                    x.1.display();
                    print!(",\n");
                }
                print!("}}\n");
            },
            YSONValue::Array{ref values} => {
                print!("[\n");
                for x in values {
                    x.display();
                    print!(",\n");
                }
                print!("]\n");
            },
            YSONValue::RawScalar{ref value} => {
                print!("{}", value);
            },
            YSONValue::String{ref value} => {
                print!("{}", value);
            }
        }
    }
}
<|endoftext|>