<commit_before>//! call rank and take command of slack with rust at your helm

#[macro_use]
extern crate log;
extern crate hyper;
extern crate url;
extern crate regex;
extern crate serde;
extern crate serde_json;

mod rep;

pub use rep::Response;
use regex::{Captures as RegexCaptures, Regex};

use hyper::Client;
use hyper::header::ContentType;
use hyper::server::{Handler as HyperHandler, Request, Response as HyperResponse};
use std::collections::HashMap;
use std::io::Read;

const DEFAULT_RESPONSE: &'static [u8] = b"ok";

fn params<R: Read>(read: &mut R) -> HashMap<String, String> {
    let mut buffer = String::new();
    read.read_to_string(&mut buffer).unwrap();
    let mut params = HashMap::new();
    for (k, v) in url::form_urlencoded::parse(buffer.as_bytes()) {
        params.insert(k, v);
    }
    params
}

/// Capture results for regex matchers that collect captures
pub type Captures<'a> = RegexCaptures<'a>;

/// Allows for responding ot commands after some delayed period of time
pub trait Responder: Sync + Send {
    fn respond(&self, response: Response) -> ();
}

#[doc(hidden)]
pub struct DefaultResponder {
    response_url: String,
}

impl Responder for DefaultResponder {
    fn respond(&self, response: Response) {
        let client = Client::new();
        let _ = client.post(&self.response_url[..])
                      .header(ContentType::json())
                      .body(serde_json::to_string(&response).unwrap().as_bytes())
                      .send();
    }
}

/// Handles matched commands
pub trait Handler: Sync + Send {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response>;
}

impl<F> Handler for F
    where F: Fn(&Command, &Option<Captures>, Box<Responder>) -> Option<Response>,
          F: Send + Sync
{
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        self(cmd, caps, responder)
    }
}

#[doc(hidden)]
pub struct TokenValidator<H: Handler + 'static> {
    handler: H,
    token: String,
}

impl<H: Handler + 'static> Handler for TokenValidator<H> {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        if cmd.token == self.token {
            self.handler.handle(cmd, caps, responder)
        } else {
            None
        }
    }
}

/// A matcher matches commands
pub trait Matcher: Send + Sync {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool);
}

impl<F> Matcher for F
    where F: Fn(&Command) -> (Option<Captures>, bool),
          F: Send + Sync
{
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        self(cmd)
    }
}

/// A direct command matcher
///
pub struct MatchCommand(String);

impl Matcher for MatchCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        (None, cmd.command == self.0)
    }
}

/// A regex pattern matcher
///
pub struct MatchRegex(Regex);

impl Matcher for MatchRegex {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if self.0.is_match(cmd.command.as_ref()) {
            (self.0.captures(cmd.command.as_ref()), true)
        } else {
            (None, false)
        }
    }
}

#[doc(hidden)]
pub struct Route {
    handler: Box<Handler>,
    matcher: Box<Matcher>,
}

/// A command de-multiplexor
#[derive(Default)]
pub struct Mux {
    routes: Vec<Box<Route>>,
}

impl Mux {
    pub fn new() -> Mux {
        Mux { ..Default::default() }
    }

    pub fn command<C, T, H>(&mut self, cmd: C, token: T, handler: H)
        where C: Into<String>,
              T: Into<String>,
              H: Handler + 'static
    {
        self.matching(MatchCommand(cmd.into()),
                      TokenValidator {
                          handler: handler,
                          token: token.into(),
                      })
    }

    pub fn matching<M, H>(&mut self, matcher: M, handler: H)
        where M: Matcher + 'static,
              H: Handler + 'static
    {
        let route = Route {
            handler: Box::new(handler),
            matcher: Box::new(matcher),
        };
        self.route(route)
    }

    ///
    pub fn route(&mut self, route: Route) {
        self.routes.push(Box::new(route));
    }

    pub fn handler<'a>(&self, cmd: &'a Command) -> Option<(Option<Captures<'a>>, &Box<Handler>)> {
        for r in self.routes.iter() {
            if let (captures, true) = r.matcher.matches(cmd) {
                return Some((captures, &r.handler));
            }
        }
        None
    }

    pub fn handle(&self, cmd: &Command) -> Option<Response> {
        // set up responder
        let responder = DefaultResponder { response_url: cmd.response_url.clone() };
        // handle cmd
        if let &Some((ref captures, handler)) = &self.handler(&cmd) {
            info!("attempting to handle cmd ${:?}", cmd);
            handler.handle(&cmd, &captures, Box::new(responder))
        } else {
            None
        }
    }
}

/// A struct representation of a Slack Command and
/// and the context from which it was triggered
#[derive(Default, Debug, PartialEq)]
pub struct Command {
    pub token: String,
    pub team_id: String,
    pub team_domain: String,
    pub channel_id: String,
    pub channel_name: String,
    pub user_id: String,
    pub user_name: String,
    pub command: String,
    pub text: String,
    pub response_url: String,
}

impl Command {
    pub fn from_params(params: HashMap<String, String>) -> Option<Command> {
        if let (Some(token),
                Some(team_id),
                Some(team_domain),
                Some(channel_id),
                Some(channel_name),
                Some(user_id),
                Some(user_name),
                Some(command),
                Some(text),
                Some(response_url)) = (params.get("token"),
                                       params.get("team_id"),
                                       params.get("team_domain"),
                                       params.get("channel_id"),
                                       params.get("channel_name"),
                                       params.get("user_id"),
                                       params.get("user_name"),
                                       params.get("command"),
                                       params.get("text"),
                                       params.get("response_url")) {
            Some(Command {
                token: token.clone(),
                team_id: team_id.clone(),
                team_domain: team_domain.clone(),
                channel_id: channel_id.clone(),
                channel_name: channel_name.clone(),
                user_id: user_id.clone(),
                user_name: user_name.clone(),
                command: command.clone(),
                text: text.clone(),
                response_url: response_url.clone(),
            })
        } else {
            None
        }
    }
}

impl HyperHandler for Mux {
    // https://api.slack.com/slash-commands
    fn handle(&self, req: Request, mut res: HyperResponse) {
        let (_, _, _, _, _, mut body) = req.deconstruct();

        // parse params
        let params = params(&mut body);
        // parse cmd
        if let Some(cmd) = Command::from_params(params) {
            info!("rec cmd {:?}", cmd);
            let write = |bytes: &[u8], content_type: ContentType| {
                res.headers_mut().set(content_type);
                let _ = res.send(bytes);
            };
            if let Some(resp) = self.handle(&cmd) {
                match serde_json::to_string(&resp) {
                    Ok(payload) => write(payload.as_bytes(), ContentType::json()),
                    _ => write(DEFAULT_RESPONSE, ContentType::plaintext()),
                };
            } else {
                write(DEFAULT_RESPONSE, ContentType::plaintext())
            };
        } else {
            error!("rec invalid cmd");
            let _ = res.send(DEFAULT_RESPONSE);
        }
        ()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::regex::Regex;
    use std::collections::HashMap;

    #[test]
    fn matches_commands() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (_, matched) = MatchCommand("/test".to_owned()).matches(&cmd);
        assert!(matched, "cmd did not match")
    }

    #[test]
    fn matches_regexes() {
        let cmd = Command { command: "/test hello world".to_owned(), ..Default::default() };
        let (captures, matched) = MatchRegex(Regex::new(r"(?P<greeting>\S+?) (?P<name>\S+?)$")
                                                 .unwrap())
                                      .matches(&cmd);
        assert!(matched, "cmd did not match");
        match captures {
            Some(caps) => {
                assert_eq!(caps.name("greeting"), Some("hello"));
                assert_eq!(caps.name("name"), Some("world"));
            }
            _ => assert!(false, "expected captures"),
        }
    }

    #[test]
    fn extracts_commands() {
        let mut params = HashMap::new();
        params.insert("token".to_owned(), "test_token".to_owned());
        params.insert("team_id".to_owned(), "test_team".to_owned());
        params.insert("team_domain".to_owned(), "test_team_domain".to_owned());
        params.insert("channel_id".to_owned(), "test_channel_id".to_owned());
        params.insert("channel_name".to_owned(), "test_channel_name".to_owned());
        params.insert("user_id".to_owned(), "test_user_id".to_owned());
        params.insert("user_name".to_owned(), "test_user_name".to_owned());
        params.insert("command".to_owned(), "test_command".to_owned());
        params.insert("text".to_owned(), "test_text".to_owned());
        params.insert("response_url".to_owned(), "test_response_url".to_owned());
        match Command::from_params(params) {
            Some(cmd) => {
                assert_eq!(cmd,
                           Command {
                               token: "test_token".to_owned(),
                               team_id: "test_team".to_owned(),
                               team_domain: "test_team_domain".to_owned(),
                               channel_id: "test_channel_id".to_owned(),
                               channel_name: "test_channel_name".to_owned(),
                               user_id: "test_user_id".to_owned(),
                               user_name: "test_user_name".to_owned(),
                               command: "test_command".to_owned(),
                               text: "test_text".to_owned(),
                               response_url: "test_response_url".to_owned(),
                           })
            }
            _ => assert!(false, "failed to exact command"),
        }
    }
}
<commit_msg>improve docs<commit_after>//! call rank and take command of slack with rust at your helm

#[macro_use]
extern crate log;
extern crate hyper;
extern crate url;
extern crate regex;
extern crate serde;
extern crate serde_json;

mod rep;

pub use rep::Response;
use regex::{Captures as RegexCaptures, Regex};

use hyper::Client;
use hyper::header::ContentType;
use hyper::server::{Handler as HyperHandler, Request, Response as HyperResponse};
use std::collections::HashMap;
use std::io::Read;

const DEFAULT_RESPONSE: &'static [u8] = b"ok";

fn params<R: Read>(read: &mut R) -> HashMap<String, String> {
    let mut buffer = String::new();
    read.read_to_string(&mut buffer).unwrap();
    let mut params = HashMap::new();
    for (k, v) in url::form_urlencoded::parse(buffer.as_bytes()) {
        params.insert(k, v);
    }
    params
}

/// Results for regex matchers that collect captures
pub type Captures<'a> = RegexCaptures<'a>;

/// Deferred response interface
pub trait Responder: Sync + Send {
    fn respond(&self, response: Response) -> ();
}

#[doc(hidden)]
pub struct DefaultResponder {
    response_url: String,
}

impl Responder for DefaultResponder {
    fn respond(&self, response: Response) {
        let client = Client::new();
        let _ = client.post(&self.response_url[..])
                      .header(ContentType::json())
                      .body(serde_json::to_string(&response).unwrap().as_bytes())
                      .send();
    }
}

/// Command handling interface
pub trait Handler: Sync + Send {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response>;
}

impl<F> Handler for F
    where F: Fn(&Command, &Option<Captures>, Box<Responder>) -> Option<Response>,
          F: Send + Sync
{
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        self(cmd, caps, responder)
    }
}

#[doc(hidden)]
pub struct TokenValidator<H: Handler + 'static> {
    handler: H,
    token: String,
}

impl<H: Handler + 'static> Handler for TokenValidator<H> {
    fn handle(&self,
              cmd: &Command,
              caps: &Option<Captures>,
              responder: Box<Responder>)
              -> Option<Response> {
        if cmd.token == self.token {
            self.handler.handle(cmd, caps, responder)
        } else {
            None
        }
    }
}

/// Command matching interface
pub trait Matcher: Send + Sync {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool);
}

impl<F> Matcher for F
    where F: Fn(&Command) -> (Option<Captures>, bool),
          F: Send + Sync
{
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        self(cmd)
    }
}

/// A direct command matcher
///
pub struct MatchCommand(String);

impl Matcher for MatchCommand {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        (None, cmd.command == self.0)
    }
}

/// A regex pattern matcher
///
pub struct MatchRegex(Regex);

impl Matcher for MatchRegex {
    fn matches<'a>(&self, cmd: &'a Command) -> (Option<Captures<'a>>, bool) {
        if self.0.is_match(cmd.command.as_ref()) {
            (self.0.captures(cmd.command.as_ref()), true)
        } else {
            (None, false)
        }
    }
}

#[doc(hidden)]
pub struct Route {
    handler: Box<Handler>,
    matcher: Box<Matcher>,
}

/// A command de-multiplexor
#[derive(Default)]
pub struct Mux {
    routes: Vec<Box<Route>>,
}

impl Mux {
    pub fn new() -> Mux {
        Mux { ..Default::default() }
    }

    pub fn command<C, T, H>(&mut self, cmd: C, token: T, handler: H)
        where C: Into<String>,
              T: Into<String>,
              H: Handler + 'static
    {
        self.matching(MatchCommand(cmd.into()),
                      TokenValidator {
                          handler: handler,
                          token: token.into(),
                      })
    }

    pub fn matching<M, H>(&mut self, matcher: M, handler: H)
        where M: Matcher + 'static,
              H: Handler + 'static
    {
        let route = Route {
            handler: Box::new(handler),
            matcher: Box::new(matcher),
        };
        self.route(route)
    }

    ///
    pub fn route(&mut self, route: Route) {
        self.routes.push(Box::new(route));
    }

    pub fn handler<'a>(&self, cmd: &'a Command) -> Option<(Option<Captures<'a>>, &Box<Handler>)> {
        for r in self.routes.iter() {
            if let (captures, true) = r.matcher.matches(cmd) {
                return Some((captures, &r.handler));
            }
        }
        None
    }

    pub fn handle(&self, cmd: &Command) -> Option<Response> {
        // set up responder
        let responder = DefaultResponder { response_url: cmd.response_url.clone() };
        // handle cmd
        if let &Some((ref captures, handler)) = &self.handler(&cmd) {
            info!("attempting to handle cmd ${:?}", cmd);
            handler.handle(&cmd, &captures, Box::new(responder))
        } else {
            None
        }
    }
}

/// A struct representation of a Slack Command
/// and the context from which it was triggered
#[derive(Default, Debug, PartialEq)]
pub struct Command {
    pub token: String,
    pub team_id: String,
    pub team_domain: String,
    pub channel_id: String,
    pub channel_name: String,
    pub user_id: String,
    pub user_name: String,
    pub command: String,
    pub text: String,
    pub response_url: String,
}

impl Command {
    pub fn from_params(params: HashMap<String, String>) -> Option<Command> {
        if let (Some(token),
                Some(team_id),
                Some(team_domain),
                Some(channel_id),
                Some(channel_name),
                Some(user_id),
                Some(user_name),
                Some(command),
                Some(text),
                Some(response_url)) = (params.get("token"),
                                       params.get("team_id"),
                                       params.get("team_domain"),
                                       params.get("channel_id"),
                                       params.get("channel_name"),
                                       params.get("user_id"),
                                       params.get("user_name"),
                                       params.get("command"),
                                       params.get("text"),
                                       params.get("response_url")) {
            Some(Command {
                token: token.clone(),
                team_id: team_id.clone(),
                team_domain: team_domain.clone(),
                channel_id: channel_id.clone(),
                channel_name: channel_name.clone(),
                user_id: user_id.clone(),
                user_name: user_name.clone(),
                command: command.clone(),
                text: text.clone(),
                response_url: response_url.clone(),
            })
        } else {
            None
        }
    }
}

impl HyperHandler for Mux {
    // https://api.slack.com/slash-commands
    fn handle(&self, req: Request, mut res: HyperResponse) {
        let (_, _, _, _, _, mut body) = req.deconstruct();

        // parse params
        let params = params(&mut body);
        // parse cmd
        if let Some(cmd) = Command::from_params(params) {
            info!("rec cmd {:?}", cmd);
            let write = |bytes: &[u8], content_type: ContentType| {
                res.headers_mut().set(content_type);
                let _ = res.send(bytes);
            };
            if let Some(resp) = self.handle(&cmd) {
                match serde_json::to_string(&resp) {
                    Ok(payload) => write(payload.as_bytes(), ContentType::json()),
                    _ => write(DEFAULT_RESPONSE, ContentType::plaintext()),
                };
            } else {
                write(DEFAULT_RESPONSE, ContentType::plaintext())
            };
        } else {
            error!("rec invalid cmd");
            let _ = res.send(DEFAULT_RESPONSE);
        }
        ()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::regex::Regex;
    use std::collections::HashMap;

    #[test]
    fn matches_commands() {
        let cmd = Command { command: "/test".to_owned(), ..Default::default() };
        let (_, matched) = MatchCommand("/test".to_owned()).matches(&cmd);
        assert!(matched, "cmd did not match")
    }

    #[test]
    fn matches_regexes() {
        let cmd = Command { command: "/test hello world".to_owned(), ..Default::default() };
        let (captures, matched) = MatchRegex(Regex::new(r"(?P<greeting>\S+?) (?P<name>\S+?)$")
                                                 .unwrap())
                                      .matches(&cmd);
        assert!(matched, "cmd did not match");
        match captures {
            Some(caps) => {
                assert_eq!(caps.name("greeting"), Some("hello"));
                assert_eq!(caps.name("name"), Some("world"));
            }
            _ => assert!(false, "expected captures"),
        }
    }

    #[test]
    fn extracts_commands() {
        let mut params = HashMap::new();
        params.insert("token".to_owned(), "test_token".to_owned());
        params.insert("team_id".to_owned(), "test_team".to_owned());
        params.insert("team_domain".to_owned(), "test_team_domain".to_owned());
        params.insert("channel_id".to_owned(), "test_channel_id".to_owned());
        params.insert("channel_name".to_owned(), "test_channel_name".to_owned());
        params.insert("user_id".to_owned(), "test_user_id".to_owned());
        params.insert("user_name".to_owned(), "test_user_name".to_owned());
        params.insert("command".to_owned(), "test_command".to_owned());
        params.insert("text".to_owned(), "test_text".to_owned());
        params.insert("response_url".to_owned(), "test_response_url".to_owned());
        match Command::from_params(params) {
            Some(cmd) => {
                assert_eq!(cmd,
                           Command {
                               token: "test_token".to_owned(),
                               team_id: "test_team".to_owned(),
                               team_domain: "test_team_domain".to_owned(),
                               channel_id: "test_channel_id".to_owned(),
                               channel_name: "test_channel_name".to_owned(),
                               user_id: "test_user_id".to_owned(),
                               user_name: "test_user_name".to_owned(),
                               command: "test_command".to_owned(),
                               text: "test_text".to_owned(),
                               response_url: "test_response_url".to_owned(),
                           })
            }
            _ => assert!(false, "failed to exact command"),
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::fmt;
use std::iter::FromIterator;

#[derive(Clone, PartialEq, Eq)]
pub enum Token {
    Output,
    Input,
    Loop(Vec<Token>),
    Move(i32),
    Add(i32, i32),
    Set(i32, i32),
    MulCopy(i32, i32, i32),
    Scan(i32),
    LoadOut(i32, i32),
    LoadOutSet(i32),
    If(i32, Vec<Token>),
}

impl fmt::Debug for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Output => write!(f, "Output"),
            Input => write!(f, "Input"),
            Move(offset) => write!(f, "Move(offset={})", offset),
            Add(offset, value) => write!(f, "Add(offset={}, value={})", offset, value),
            Set(offset, value) => write!(f, "Set(offset={}, value={})", offset, value),
            MulCopy(src, dest, mul) => {
                write!(f, "MulCopy(src={}, dest={}, mul={})", src, dest, mul)
            }
            Scan(offset) => write!(f, "Scan(offset={})", offset),
            LoadOut(offset, add) => write!(f, "LoadOut(offset={}, add={})", offset, add),
            LoadOutSet(value) => write!(f, "LoadOutSet(value={})", value),
            Loop(ref content) => write!(f, "Loop(content={:?})", content),
            If(offset, ref content) => write!(f, "If(offset={}, content={:?})", offset, content),
        }
    }
}

use Token::*;

struct OptimizeState {
    tokens: Vec<Token>,
    // With HashMap, the order sometimes switches
    // in recursion, and the optimizer never exits.
    adds: BTreeMap<i32, i32>,
    sets: BTreeMap<i32, i32>,
    shift: i32,
}

impl OptimizeState {
    fn new() -> OptimizeState {
        OptimizeState {
            tokens: Vec::new(),
            adds: BTreeMap::new(),
            sets: BTreeMap::new(),
            shift: 0,
        }
    }

    fn apply_shift(&mut self) {
        if self.shift != 0 {
            self.tokens.push(Move(self.shift));
            self.shift = 0;
        }
    }

    fn apply_adds_sets(&mut self) {
        for (offset, value) in self.sets.iter() {
            self.tokens.push(Set(*offset, *value));
        }
        for (offset, value) in self.adds.iter() {
            self.tokens.push(Add(*offset, *value));
        }
        self.sets.clear();
        self.adds.clear();
    }
}

pub fn parse(code: &str) -> Vec<Token> {
    _parse(&mut code.chars())
}

fn _parse(chars: &mut std::str::Chars) -> Vec<Token> {
    let mut tokens = Vec::new();
    while let Some(i) = chars.next() {
        match i {
            '+' => tokens.push(Add(0, 1)),
            '-' => tokens.push(Add(0, -1)),
            '>' => tokens.push(Move(1)),
            '<' => tokens.push(Move(-1)),
            '[' => tokens.push(Loop(_parse(chars))),
            ']' => {
                break;
            }
            ',' => tokens.push(Input),
            '.' => {
                tokens.push(LoadOut(0, 0));
                tokens.push(Output);
            }
            _ => (),
        };
    }

    tokens
}

fn _optimize(tokens: &Vec<Token>) -> OptimizeState {
    let mut do_output = false;
    let mut state = OptimizeState::new();

    for token in tokens.iter() {
        match *token {
            Set(..) | Add(..) | Move(_) | LoadOut(..) | LoadOutSet(_) | Output => {}
            _ => {
                if do_output {
                    state.tokens.push(Output);
                    do_output = false;
                }

                state.apply_adds_sets();
            }
        }

        match *token {
            Loop(_) | Input | Scan(_) => {
                state.apply_shift();
            }
            _ => {}
        }

        match *token {
            Set(mut offset, val) => {
                offset += state.shift;
                // Add before Set does nothing; remove it
                state.adds.remove(&offset);
                state.sets.insert(offset, val);
            }
            Add(mut offset, mut val) => {
                offset += state.shift;
                if state.sets.contains_key(&offset) {
                    val = state.sets.get(&offset).unwrap() + val;
                    state.sets.insert(offset, val);
                } else {
                    val = state.adds.get(&offset).unwrap_or(&0) + val;
                    state.adds.insert(offset, val);
                }
            }
            MulCopy(src, dest, mul) => {
                state.tokens.push(MulCopy(src + state.shift, dest + state.shift, mul))
            }
            If(offset, ref contents) => {
                let mut newcontents = Vec::new();
                for i in contents.iter() {
                    newcontents.push(match *i {
                        Set(offset, value) => Set(offset + state.shift, value),
                        MulCopy(src, dest, mul) => {
                            MulCopy(src + state.shift, dest + state.shift, mul)
                        }
                        _ => unreachable!(),
                    });
                }
                state.tokens.push(If(offset + state.shift, newcontents));
            }
            Move(offset) => state.shift += offset,
            Output => do_output = true,
            LoadOut(mut offset, add) => {
                offset += state.shift;
                if state.sets.contains_key(&offset) {
                    state.tokens.push(LoadOutSet(state.sets.get(&offset).unwrap() + add));
                } else {
                    state.tokens.push(LoadOut(offset, state.adds.get(&offset).unwrap_or(&0) + add));
                }
            }
            Loop(ref contents) => _optimize_loop(contents, &mut state),
            LoadOutSet(value) => state.tokens.push(LoadOutSet(value)),
            Input => state.tokens.push(Input),
            Scan(offset) => state.tokens.push(Scan(offset + state.shift)),
        }
    }

    if do_output {
        state.tokens.push(Output);
    }

    state
}

fn _optimize_loop(tokens: &Vec<Token>, outer: &mut OptimizeState) {
    let mut inner = _optimize(tokens);

    if inner.shift != 0 && inner.sets.is_empty() && inner.adds.is_empty() &&
       inner.tokens.is_empty() {
        outer.tokens.push(Scan(inner.shift));
    } else if inner.shift == 0 && inner.tokens.is_empty() && inner.adds.contains_key(&0) &&
              inner.adds.len() == 1 {
        if !inner.sets.is_empty() {
            let mut iftokens = Vec::new();
            for (offset, value) in inner.sets.iter() {
                iftokens.push(Set(*offset, *value));
            }
            iftokens.push(Set(0, 0));
            outer.tokens.push(If(0, iftokens));
        } else {
            outer.sets.insert(0, 0);
        }
    } else if inner.shift == 0 && inner.tokens.is_empty() && inner.adds.get(&0) == Some(&-1) {
        let contents = inner.adds.iter().filter_map(|(offset, value)| {
            if *offset != 0 {
                let src = 0;
                let dest = *offset;
                let mul = *value;
                Some(MulCopy(src, dest, mul))
            } else {
                None
            }
        });

        if !inner.sets.is_empty() {
            let iftokens = Vec::from_iter(inner.sets
                .iter()
                .map(|(offset, value)| Set(*offset, *value))
                .chain(contents));
            outer.tokens.push(If(0, iftokens));
        } else {
            outer.tokens.extend(contents);
        }

        outer.sets.insert(0, 0);
    } else {
        inner.apply_adds_sets();
        inner.apply_shift();

        outer.tokens.push(Loop(inner.tokens));
    }
}

pub fn optimize(tokens: Vec<Token>) -> Vec<Token> {
    let mut oldtokens = tokens;
    // Ignore sets/adds/shifts at end of file
    let mut newtokens = _optimize(&oldtokens).tokens;
    while newtokens != oldtokens {
        oldtokens = newtokens;
        newtokens = _optimize(&oldtokens).tokens;
    }
    newtokens
}
<commit_msg>Use #[derive(Default)] instead of having a ::new() method<commit_after>use std::collections::BTreeMap;
use std::fmt;
use std::iter::FromIterator;

#[derive(Clone, PartialEq, Eq)]
pub enum Token {
    Output,
    Input,
    Loop(Vec<Token>),
    Move(i32),
    Add(i32, i32),
    Set(i32, i32),
    MulCopy(i32, i32, i32),
    Scan(i32),
    LoadOut(i32, i32),
    LoadOutSet(i32),
    If(i32, Vec<Token>),
}

impl fmt::Debug for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Output => write!(f, "Output"),
            Input => write!(f, "Input"),
            Move(offset) => write!(f, "Move(offset={})", offset),
            Add(offset, value) => write!(f, "Add(offset={}, value={})", offset, value),
            Set(offset, value) => write!(f, "Set(offset={}, value={})", offset, value),
            MulCopy(src, dest, mul) => {
                write!(f, "MulCopy(src={}, dest={}, mul={})", src, dest, mul)
            }
            Scan(offset) => write!(f, "Scan(offset={})", offset),
            LoadOut(offset, add) => write!(f, "LoadOut(offset={}, add={})", offset, add),
            LoadOutSet(value) => write!(f, "LoadOutSet(value={})", value),
            Loop(ref content) => write!(f, "Loop(content={:?})", content),
            If(offset, ref content) => write!(f, "If(offset={}, content={:?})", offset, content),
        }
    }
}

use Token::*;

#[derive(Default)]
struct OptimizeState {
    tokens: Vec<Token>,
    // With HashMap, the order sometimes switches
    // in recursion, and the optimizer never exits.
    adds: BTreeMap<i32, i32>,
    sets: BTreeMap<i32, i32>,
    shift: i32,
}

impl OptimizeState {
    fn apply_shift(&mut self) {
        if self.shift != 0 {
            self.tokens.push(Move(self.shift));
            self.shift = 0;
        }
    }

    fn apply_adds_sets(&mut self) {
        for (offset, value) in self.sets.iter() {
            self.tokens.push(Set(*offset, *value));
        }
        for (offset, value) in self.adds.iter() {
            self.tokens.push(Add(*offset, *value));
        }
        self.sets.clear();
        self.adds.clear();
    }
}

pub fn parse(code: &str) -> Vec<Token> {
    _parse(&mut code.chars())
}

fn _parse(chars: &mut std::str::Chars) -> Vec<Token> {
    let mut tokens = Vec::new();
    while let Some(i) = chars.next() {
        match i {
            '+' => tokens.push(Add(0, 1)),
            '-' => tokens.push(Add(0, -1)),
            '>' => tokens.push(Move(1)),
            '<' => tokens.push(Move(-1)),
            '[' => tokens.push(Loop(_parse(chars))),
            ']' => {
                break;
            }
            ',' => tokens.push(Input),
            '.' => {
                tokens.push(LoadOut(0, 0));
                tokens.push(Output);
            }
            _ => (),
        };
    }

    tokens
}

fn _optimize(tokens: &Vec<Token>) -> OptimizeState {
    let mut do_output = false;
    let mut state = OptimizeState::default();

    for token in tokens.iter() {
        match *token {
            Set(..) | Add(..) | Move(_) | LoadOut(..) | LoadOutSet(_) | Output => {}
            _ => {
                if do_output {
                    state.tokens.push(Output);
                    do_output = false;
                }

                state.apply_adds_sets();
            }
        }

        match *token {
            Loop(_) | Input | Scan(_) => {
                state.apply_shift();
            }
            _ => {}
        }

        match *token {
            Set(mut offset, val) => {
                offset += state.shift;
                // Add before Set does nothing; remove it
                state.adds.remove(&offset);
                state.sets.insert(offset, val);
            }
            Add(mut offset, mut val) => {
                offset += state.shift;
                if state.sets.contains_key(&offset) {
                    val = state.sets.get(&offset).unwrap() + val;
                    state.sets.insert(offset, val);
                } else {
                    val = state.adds.get(&offset).unwrap_or(&0) + val;
                    state.adds.insert(offset, val);
                }
            }
            MulCopy(src, dest, mul) => {
                state.tokens.push(MulCopy(src + state.shift, dest + state.shift, mul))
            }
            If(offset, ref contents) => {
                let mut newcontents = Vec::new();
                for i in contents.iter() {
                    newcontents.push(match *i {
                        Set(offset, value) => Set(offset + state.shift, value),
                        MulCopy(src, dest, mul) => {
                            MulCopy(src + state.shift, dest + state.shift, mul)
                        }
                        _ => unreachable!(),
                    });
                }
                state.tokens.push(If(offset + state.shift, newcontents));
            }
            Move(offset) => state.shift += offset,
            Output => do_output = true,
            LoadOut(mut offset, add) => {
                offset += state.shift;
                if state.sets.contains_key(&offset) {
                    state.tokens.push(LoadOutSet(state.sets.get(&offset).unwrap() + add));
                } else {
                    state.tokens.push(LoadOut(offset, state.adds.get(&offset).unwrap_or(&0) + add));
                }
            }
            Loop(ref contents) => _optimize_loop(contents, &mut state),
            LoadOutSet(value) => state.tokens.push(LoadOutSet(value)),
            Input => state.tokens.push(Input),
            Scan(offset) => state.tokens.push(Scan(offset + state.shift)),
        }
    }

    if do_output {
        state.tokens.push(Output);
    }

    state
}

fn _optimize_loop(tokens: &Vec<Token>, outer: &mut OptimizeState) {
    let mut inner = _optimize(tokens);

    if inner.shift != 0 && inner.sets.is_empty() && inner.adds.is_empty() &&
       inner.tokens.is_empty() {
        outer.tokens.push(Scan(inner.shift));
    } else if inner.shift == 0 && inner.tokens.is_empty() && inner.adds.contains_key(&0) &&
              inner.adds.len() == 1 {
        if !inner.sets.is_empty() {
            let mut iftokens = Vec::new();
            for (offset, value) in inner.sets.iter() {
                iftokens.push(Set(*offset, *value));
            }
            iftokens.push(Set(0, 0));
            outer.tokens.push(If(0, iftokens));
        } else {
            outer.sets.insert(0, 0);
        }
    } else if inner.shift == 0 && inner.tokens.is_empty() && inner.adds.get(&0) == Some(&-1) {
        let contents = inner.adds.iter().filter_map(|(offset, value)| {
            if *offset != 0 {
                let src = 0;
                let dest = *offset;
                let mul = *value;
                Some(MulCopy(src, dest, mul))
            } else {
                None
            }
        });

        if !inner.sets.is_empty() {
            let iftokens = Vec::from_iter(inner.sets
                .iter()
                .map(|(offset, value)| Set(*offset, *value))
                .chain(contents));
            outer.tokens.push(If(0, iftokens));
        } else {
            outer.tokens.extend(contents);
        }

        outer.sets.insert(0, 0);
    } else {
        inner.apply_adds_sets();
        inner.apply_shift();

        outer.tokens.push(Loop(inner.tokens));
    }
}

pub fn optimize(tokens: Vec<Token>) -> Vec<Token> {
    let mut oldtokens = tokens;
    // Ignore sets/adds/shifts at end of file
    let mut newtokens = _optimize(&oldtokens).tokens;
    while newtokens != oldtokens {
        oldtokens = newtokens;
        newtokens = _optimize(&oldtokens).tokens;
    }
    newtokens
}
<|endoftext|>


<commit_before>extern mod extra;
use std::rand;
use std::vec;
use std::num;
use extra::sort;

/**
 * Arbitrary is a trait for types that you can generate arbitrary
 * instances of. You should also be able to ask for their size, so
 * you can report small failing examples instead of large ones.
 *
 */
trait Arbitrary : Clone {
    fn gen() -> Self;
    fn size(&self) -> uint;
}

impl Arbitrary for uint {
    fn gen() -> uint {
        let n : uint = rand::random();
         n % num::pow_with_uint(2,10)
    }
    fn size(&self) -> uint {
        self.clone()
    }
}

impl Arbitrary for int {
    fn gen() -> int {
        let n : int = rand::random();
        n % num::pow_with_uint(2,10)
    }

    fn size(&self) -> uint {
        self.clone().to_uint()
    }
}

impl<T:Arbitrary> Arbitrary for ~[T] {
    fn gen() -> ~[T] {
        let _n : uint = rand::random();
        let n = _n % 100;
        vec::build_sized(n, |p| {
            for n.times {
                p(Arbitrary::gen());
            }
        })
    }

    fn size(&self) -> uint {
        self.len()
    }
}

/**
 * quick_check
 *   description: a string describing what the property being tested is
 *   f: function that takes arbitrary input and returns whether
 *      the invariant held.
 *
 *   returns whether all the tests passed.
 */
fn quick_check<T:Arbitrary>(description : &str,
                            f : extern fn(T) -> bool) -> bool {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        let t : T = Arbitrary::gen();
        if f(t.clone()) {
            passing += 1;
        } else {
            failed.push(t);
        }
    }
    if passing == num_tests {
        println(fmt!("+++ OK, passed 100 tests for %s", description));
        return true;
    } else {
        println(fmt!("*** Failed '%s' on:", description));
        if failed.len() < 5 {
            // is this really the best way? can't be...
            let mut i = 0;
            for failed.len().times {
                println(fmt!("%?", failed[i]));
                i += 1;
            }
        } else {
            let mut failed_with_sizes : ~[(uint, T)] =
                failed.iter().transform(|x| (x.size(), x.clone()))
                .collect();
            sort::quick_sort(failed_with_sizes, |e1, e2| {
                e1.first() <= e2.first()
            });
            let mut i = 0;
            for 5.times {
                println(fmt!("%?", failed_with_sizes[i].second()));
                i += 1;
            }
            println("...and more");
        }
        return false;
    }
}

#[test]
fn reverse_uint_vecs() {
    fn reverse<A:Clone>(v : ~[A]) -> ~[A] {
        let mut newvec = ~[];
        for v.iter().advance |e| {
            // NOTE(dbp 2013-07-25): This is intentionally buggy.
            newvec.push(e.clone());
        }
        return newvec;
    }

    fn prop_reverse_reverse_uints(v : ~[uint]) -> bool {
        reverse(reverse(v.clone())) == v
    }

    fn prop_reverse_moves_first_to_last(v : ~[uint]) -> bool {
        if v.len() > 0 {
            reverse(v.clone())[v.len() - 1] == v[0]
        } else {
            true // trivially
        }
    }

    assert!(
        quick_check("reversing a list twice yields the same list",
                    prop_reverse_reverse_uints));
    assert!(
        !quick_check("reversing a list moves first to last",
                     prop_reverse_moves_first_to_last));
}
<commit_msg>added 2-arrity version of QC - code copying is bad! and another test<commit_after>extern mod extra;
use std::rand;
use std::vec;
use std::num;
use extra::sort;

/**
 * Arbitrary is a trait for types that you can generate arbitrary
 * instances of. You should also be able to ask for their size, so
 * you can report small failing examples instead of large ones.
 *
 */
trait Arbitrary : Clone {
    fn gen() -> Self;
    fn size(&self) -> uint;
}

impl Arbitrary for uint {
    fn gen() -> uint {
        let n : uint = rand::random();
         n % num::pow_with_uint(2,10)
    }
    fn size(&self) -> uint {
        self.clone()
    }
}

impl Arbitrary for int {
    fn gen() -> int {
        let n : int = rand::random();
        n % num::pow_with_uint(2,10)
    }

    fn size(&self) -> uint {
        self.clone().to_uint()
    }
}

impl<T:Arbitrary> Arbitrary for ~[T] {
    fn gen() -> ~[T] {
        let _n : uint = rand::random();
        let n = _n % 100;
        vec::build_sized(n, |p| {
            for n.times {
                p(Arbitrary::gen());
            }
        })
    }

    fn size(&self) -> uint {
        self.len()
    }
}

/**
 * quick_check
 *   description: a string describing what the property being tested is
 *   f: function that takes arbitrary input and returns whether
 *      the invariant held.
 *
 *   returns whether all the tests passed.
 */
fn quick_check<T:Arbitrary>(description : &str,
                            f : extern fn(T) -> bool) -> bool {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        let t : T = Arbitrary::gen();
        if f(t.clone()) {
            passing += 1;
        } else {
            failed.push(t);
        }
    }
    if passing == num_tests {
        println(fmt!("+++ OK, passed 100 tests for %s", description));
        return true;
    } else {
        println(fmt!("*** Failed '%s' on:", description));
        if failed.len() < 5 {
            // is this really the best way? can't be...
            let mut i = 0;
            for failed.len().times {
                println(fmt!("%?", failed[i]));
                i += 1;
            }
        } else {
            let mut failed_with_sizes : ~[(uint, T)] =
                failed.iter().transform(|x| (x.size(), x.clone()))
                .collect();
            sort::quick_sort(failed_with_sizes, |e1, e2| {
                e1.first() <= e2.first()
            });
            let mut i = 0;
            for 5.times {
                println(fmt!("%?", failed_with_sizes[i].second()));
                i += 1;
            }
            println("...and more");
        }
        return false;
    }
}

fn quick_check2<T:Arbitrary>(description : &str,
                             f : extern fn(T,T) -> bool) -> bool {
    let num_tests = 100;
    let mut passing = 0;
    let mut failed = ~[];
    for num_tests.times {
        let t1 : T = Arbitrary::gen();
        let t2 : T = Arbitrary::gen();
        if f(t1.clone(), t2.clone()) {
            passing += 1;
        } else {
            failed.push((t1, t2));
        }
    }
    if passing == num_tests {
        println(fmt!("+++ OK, passed 100 tests for %s", description));
        return true;
    } else {
        println(fmt!("*** Failed '%s' on:", description));
        if failed.len() < 5 {
            // is this really the best way? can't be...
            let mut i = 0;
            for failed.len().times {
                println(fmt!("%?", failed[i]));
                i += 1;
            }
        } else {
            let mut failed_with_sizes : ~[(uint, (T,T))] =
                failed.iter().transform(|x| (x.first().size() + x.second().size(),
                                             x.clone()))
                .collect();
            sort::quick_sort(failed_with_sizes, |e1, e2| {
                e1.first() <= e2.first()
            });
            let mut i = 0;
            for 5.times {
                println(fmt!("%?", failed_with_sizes[i].second()));
                i += 1;
            }
            println("...and more");
        }
        return false;
    }
}

#[test]
fn reverse_uint_vecs() {
    fn reverse<A:Clone>(v : ~[A]) -> ~[A] {
        let mut newvec = ~[];
        for v.iter().advance |e| {
            // NOTE(dbp 2013-07-25): This is intentionally buggy.
            newvec.push(e.clone());
        }
        return newvec;
    }

    fn prop_reverse_reverse_uints(v : ~[uint]) -> bool {
        reverse(reverse(v.clone())) == v
    }

    fn prop_reverse_moves_first_to_last(v : ~[uint]) -> bool {
        if v.len() > 0 {
            reverse(v.clone())[v.len() - 1] == v[0]
        } else {
            true // trivially
        }
    }

    assert!(
        quick_check("reversing a list twice yields the same list",
                    prop_reverse_reverse_uints));
    assert!(
        !quick_check("reversing a list moves first to last",
                     prop_reverse_moves_first_to_last));
}

#[test]
fn struct_gen() {

    #[deriving(Clone, Eq)]
    struct Foo { n: uint, xs: ~[int] }

    impl Arbitrary for Foo {
        fn gen() -> Foo {
            Foo { n: Arbitrary::gen(), xs: Arbitrary::gen() }
        }
        fn size(&self) -> uint {
            self.xs.len()
        }
    }
    // NOTE(dbp 2013-07-27): Not sure why this isn't covered by `deriving`,
    // is in a not-yet-implemented feature?
    impl Clone for Foo {
        fn clone(&self) -> Foo {
            Foo { n: self.n, xs: self.xs.clone() }
        }
    }
    impl Eq for Foo {
        fn eq(&self, other: &Foo) -> bool {
            self.n == other.n && self.xs == other.xs
        }
    }

    fn add_foos(a1: &Foo, a2: &Foo) -> Foo {
        let mut new_xs = ~[];
        new_xs = vec::append(new_xs, a1.xs);
        new_xs = vec::append(new_xs, a2.xs);
        Foo {n: a1.n + a2.n, xs: new_xs}
    }

    // NOTE(dbp 2013-07-27): This is obviously not true.
    fn prop_add_foos_commutes(a1: Foo, a2: Foo) -> bool {
        add_foos(&a1, &a2) == add_foos(&a2, &a1)
    }

    fn prop_add_zero_foo_identity(a: Foo) -> bool {
        add_foos(&a, &Foo {n: 0, xs: ~[]}) == a
    }

    assert!(
        !quick_check2("add_foos is commutative",
                    prop_add_foos_commutes));

    assert!(
        quick_check("add_foos with a zero Foo is an identity",
                    prop_add_zero_foo_identity));
}<|endoftext|>


<commit_before>mod stats;

#[no_mangle]
pub extern "C" fn nse_c(obs_pointer: *const f64, sim_pointer: *const f64, arr_size: usize) -> f64 {

    let obs_arr =
        unsafe { std::slice::from_raw_parts(obs_pointer as *const f64, arr_size as usize) };
    let sim_arr =
        unsafe { std::slice::from_raw_parts(sim_pointer as *const f64, arr_size as usize) };

    return nse(obs_arr, sim_arr);
}

#[no_mangle]
pub extern "C" fn mse_c(obs_pointer: *const f64, sim_pointer: *const f64, arr_size: usize) -> f64 {

    let obs_arr =
        unsafe { std::slice::from_raw_parts(obs_pointer as *const f64, arr_size as usize) };
    let sim_arr =
        unsafe { std::slice::from_raw_parts(sim_pointer as *const f64, arr_size as usize) };

    return mse(obs_arr, sim_arr);
}

#[no_mangle]
pub extern "C" fn rmse_c(obs_pointer: *const f64, sim_pointer: *const f64, arr_size: usize) -> f64 {

    let obs_arr =
        unsafe { std::slice::from_raw_parts(obs_pointer as *const f64, arr_size as usize) };
    let sim_arr =
        unsafe { std::slice::from_raw_parts(sim_pointer as *const f64, arr_size as usize) };

    return rmse(obs_arr, sim_arr);
}

#[no_mangle]
pub extern "C" fn kge_c(obs_pointer: *const f64, sim_pointer: *const f64, arr_size: usize) -> f64 {

    let obs_arr =
        unsafe { std::slice::from_raw_parts(obs_pointer as *const f64, arr_size as usize) };
    let sim_arr =
        unsafe { std::slice::from_raw_parts(sim_pointer as *const f64, arr_size as usize) };

    return kge(obs_arr, sim_arr);
}

pub fn mse(obs: &[f64], sim: &[f64]) -> f64 {
    let mut sum_y: f64 = 0.0;

    for (o, s) in obs.iter().zip(sim.iter()) {
        let delta = s - o;
        sum_y += delta.powf(2.0);
    }
    let len: f64 = obs.len() as f64;
    return sum_y / len;
}

pub fn rmse(obs: &[f64], sim: &[f64]) -> f64 {
    return mse(obs, sim).sqrt();
}

/*
    Nash-Sutcliffe efficiency.

    References:
        * Nash, Jea, and J. V. Sutcliffe. 1970. "River Flow Forecasting through
             Conceptual Models Part I-A Discussion of Principles." Journal of
             Hydrology 10 (3): 282-90.
*/
pub fn nse(obs: &[f64], sim: &[f64]) -> f64 {

    let m: f64 = obs.iter().fold(0f64, std::ops::Add::add) / (obs.len() as f64);

    //int t;
    let mut e1: f64 = 0.0;
    let mut e2: f64 = 0.0;

    for (o, s) in obs.iter().zip(sim.iter()) {
        let delta = o - s;
        e1 += delta.powf(2.0);

        let bias = o - m;
        e2 += bias.powf(2.0);
    }

    if e1 == 0.0f64 {
        return 1.0f64;
    } else {
        return 1.0f64 - e1 / e2;
    }
}

/*
    Kling-Gupta efficiency.

    References:
        * Gupta, Hoshin V., Harald Kling, Koray K. Yilmaz, and Guillermo F.
            Martinez. "Decomposition of the Mean Squared Error and NSE
            Performance Criteria: Implications for Improving Hydrological
            Modelling." Journal of Hydrology 377, no. 1–2 (October 20, 2009):
            80–91. doi:10.1016/j.jhydrol.2009.08.003.
*/
pub fn kge(obs: &[f64], sim: &[f64]) -> f64 {

    let obs_mean: f64 = stats::mean(obs);
    let sim_mean: f64 = stats::mean(sim);
    let obs_std: f64 = stats::standard_dev_mean(obs, obs_mean);
    let sim_std: f64 = stats::standard_dev_mean(sim, sim_mean);

    let beta: f64 = sim_mean / obs_mean;
    let cov_so: f64 = stats::covariance(sim, obs);

    // Default to zero, we set later if sim_std != 0
    let mut alpha: f64 = 0.0;
    let mut r: f64 = 0.0;
    if sim_std != 0.0 {
        alpha = sim_std / obs_std;
        r = cov_so / (sim_std * obs_std);
    }

    return 1.0 - ((r - 1.0).powf(2.0) + (alpha - 1.0).powf(2.0) + (beta - 1.0).powf(2.0)).sqrt();
}
<commit_msg>Remove unnecessary casts in C interface methods<commit_after>mod stats;

#[no_mangle]
pub extern "C" fn nse_c(obs_pointer: *const f64, sim_pointer: *const f64, arr_size: usize) -> f64 {

    let obs_arr =
        unsafe { std::slice::from_raw_parts(obs_pointer, arr_size) };
    let sim_arr =
        unsafe { std::slice::from_raw_parts(sim_pointer, arr_size) };

    return nse(obs_arr, sim_arr);
}

#[no_mangle]
pub extern "C" fn mse_c(obs_pointer: *const f64, sim_pointer: *const f64, arr_size: usize) -> f64 {

    let obs_arr =
        unsafe { std::slice::from_raw_parts(obs_pointer, arr_size) };
    let sim_arr =
        unsafe { std::slice::from_raw_parts(sim_pointer, arr_size) };

    return mse(obs_arr, sim_arr);
}

#[no_mangle]
pub extern "C" fn rmse_c(obs_pointer: *const f64, sim_pointer: *const f64, arr_size: usize) -> f64 {

    let obs_arr =
        unsafe { std::slice::from_raw_parts(obs_pointer, arr_size) };
    let sim_arr =
        unsafe { std::slice::from_raw_parts(sim_pointer, arr_size) };

    return rmse(obs_arr, sim_arr);
}

#[no_mangle]
pub extern "C" fn kge_c(obs_pointer: *const f64, sim_pointer: *const f64, arr_size: usize) -> f64 {

    let obs_arr =
        unsafe { std::slice::from_raw_parts(obs_pointer, arr_size) };
    let sim_arr =
        unsafe { std::slice::from_raw_parts(sim_pointer, arr_size) };

    return kge(obs_arr, sim_arr);
}

pub fn mse(obs: &[f64], sim: &[f64]) -> f64 {
    let mut sum_y: f64 = 0.0;

    for (o, s) in obs.iter().zip(sim.iter()) {
        let delta = s - o;
        sum_y += delta.powf(2.0);
    }
    let len: f64 = obs.len() as f64;
    return sum_y / len;
}

pub fn rmse(obs: &[f64], sim: &[f64]) -> f64 {
    return mse(obs, sim).sqrt();
}

/*
    Nash-Sutcliffe efficiency.

    References:
        * Nash, Jea, and J. V. Sutcliffe. 1970. "River Flow Forecasting through
             Conceptual Models Part I-A Discussion of Principles." Journal of
             Hydrology 10 (3): 282-90.
*/
pub fn nse(obs: &[f64], sim: &[f64]) -> f64 {

    let m: f64 = obs.iter().fold(0f64, std::ops::Add::add) / (obs.len() as f64);

    //int t;
    let mut e1: f64 = 0.0;
    let mut e2: f64 = 0.0;

    for (o, s) in obs.iter().zip(sim.iter()) {
        let delta = o - s;
        e1 += delta.powf(2.0);

        let bias = o - m;
        e2 += bias.powf(2.0);
    }

    if e1 == 0.0f64 {
        return 1.0f64;
    } else {
        return 1.0f64 - e1 / e2;
    }
}

/*
    Kling-Gupta efficiency.

    References:
        * Gupta, Hoshin V., Harald Kling, Koray K. Yilmaz, and Guillermo F.
            Martinez. "Decomposition of the Mean Squared Error and NSE
            Performance Criteria: Implications for Improving Hydrological
            Modelling." Journal of Hydrology 377, no. 1–2 (October 20, 2009):
            80–91. doi:10.1016/j.jhydrol.2009.08.003.
*/
pub fn kge(obs: &[f64], sim: &[f64]) -> f64 {

    let obs_mean: f64 = stats::mean(obs);
    let sim_mean: f64 = stats::mean(sim);
    let obs_std: f64 = stats::standard_dev_mean(obs, obs_mean);
    let sim_std: f64 = stats::standard_dev_mean(sim, sim_mean);

    let beta: f64 = sim_mean / obs_mean;
    let cov_so: f64 = stats::covariance(sim, obs);

    // Default to zero, we set later if sim_std != 0
    let mut alpha: f64 = 0.0;
    let mut r: f64 = 0.0;
    if sim_std != 0.0 {
        alpha = sim_std / obs_std;
        r = cov_so / (sim_std * obs_std);
    }

    return 1.0 - ((r - 1.0).powf(2.0) + (alpha - 1.0).powf(2.0) + (beta - 1.0).powf(2.0)).sqrt();
}
<|endoftext|>


<commit_before>//! OpenCC binding for Rust
//!
//! You should install [OpenCC 1.0.x](https://github.com/BYVoid/OpenCC) library first.
//!
//! Supported configurations:
//!
//! * `s2t.json` Simplified Chinese to Traditional Chinese
//! * `t2s.json` Traditional Chinese to Simplified Chinese
//! * `s2tw.json` Simplified Chinese to Traditional Chinese (Taiwan Standard)
//! * `tw2s.json` Traditional Chinese (Taiwan Standard) to Simplified Chinese
//! * `s2hk.json` Simplified Chinese to Traditional Chinese (Hong Kong Standard)
//! * `hk2s.json` Traditional Chinese (Hong Kong Standard) to Simplified Chinese
//! * `s2twp.json` Simplified Chinese to Traditional Chinese (Taiwan Standard) with Taiwanese idiom
//! * `tw2sp.json` Traditional Chinese (Taiwan Standard) to Simplified Chinese with Mainland Chinese idiom
//! * `t2tw.json` Traditional Chinese (OpenCC Standard) to Taiwan Standard
//! * `t2hk.json` Traditional Chinese (OpenCC Standard) to Hong Kong Standard
//!
//! # Examples
//! ```
//! extern crate opencc;
//!
//! use opencc::OpenCC;
//!
//! fn main() {
//!     let cc = OpenCC::new("t2s.json");
//!     println!("{}", cc.convert("乾坤一擲").unwrap());
//!     println!("{}", cc.convert("開放中文轉換").unwrap());
//! }
//! ```
extern crate libc;
use libc::{size_t, c_void, c_char};

use std::ffi::CStr;
use std::str;

#[link(name = "opencc")]
extern {
    fn opencc_open(config: *const c_char) -> *mut c_void;
    fn opencc_close(opencc: *mut c_void);
    fn opencc_convert_utf8(opencc: *mut c_void, text: *const c_char, length: size_t) -> *mut c_char;
    fn opencc_convert_utf8_free(text: *mut c_char);
}

pub struct OpenCC {
    /// Configuration file
    pub config: String,
    _is_closed: bool,
    libopencc: *mut c_void,
}

impl OpenCC {
    /// Constructs a new `OpenCC`
    ///
    /// # Examples
    /// ```
    /// let cc = opencc::OpenCC::new("t2s.json");
    /// ```
    pub fn new(config: &str) -> OpenCC {
        let _config = config.to_string();
        let config_ptr = _config.as_ptr();
        unsafe {
            OpenCC {
                config: _config,
                _is_closed: false,
                libopencc: opencc_open(config_ptr as *const c_char),
            }
        }
    }

    /// Convert a text
    ///
    /// # Examples
    /// ```
    /// let cc = opencc::OpenCC::new("t2s.json");
    /// cc.convert("乾坤一擲").unwrap();
    /// cc.convert("開放中文轉換").unwrap();
    /// ```
    pub fn convert(&self, text: &str) -> Option<String> {
        if self._is_closed {
            None
        } else {
            unsafe {
                let text_ptr = text.as_ptr();
                let c_ptr = opencc_convert_utf8(self.libopencc, text_ptr as *const c_char, text.len() as size_t);
                if c_ptr.is_null() {
                    None
                } else {
                    let c_str = CStr::from_ptr(c_ptr);
                    let str_buf: String = str::from_utf8(c_str.to_bytes()).unwrap().to_owned();
                    opencc_convert_utf8_free(c_ptr);
                    Some(str_buf)
                }
            }
        }
    }

    /// Close the underlying libopencc.
    /// Will be called automatically when the variable gets out of scope.
    pub fn close(&mut self) {
        if !self._is_closed {
            unsafe {
                opencc_close(self.libopencc);
            }
            self._is_closed = true;
        }
    }

    /// Is the underlying libopencc closed
    pub fn is_closed(&self) -> bool {
        self._is_closed
    }
}

impl Drop for OpenCC {
    /// Close the underlying libopencc when it been droped
    fn drop(&mut self) {
        self.close();
    }
}

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

    #[test]
    fn test_simple_convert() {
        let cc = OpenCC::new("t2s.json");
        assert_eq!("乾坤一掷".to_string(), cc.convert("乾坤一擲").unwrap());
        assert_eq!("开放中文转换".to_string(), cc.convert("開放中文轉換").unwrap());
    }

    #[test]
    fn test_opencc_close() {
        let mut cc = OpenCC::new("t2s.json");
        assert_eq!("乾坤一掷".to_string(), cc.convert("乾坤一擲").unwrap());
        assert_eq!(false, cc.is_closed());
        cc.close();
        assert_eq!(true, cc.convert("開放中文轉換").is_none());
        assert_eq!(true, cc.is_closed());
    }
}
<commit_msg>Add opencc_error API<commit_after>//! OpenCC binding for Rust
//!
//! You should install [OpenCC 1.0.x](https://github.com/BYVoid/OpenCC) library first.
//!
//! Supported configurations:
//!
//! * `s2t.json` Simplified Chinese to Traditional Chinese
//! * `t2s.json` Traditional Chinese to Simplified Chinese
//! * `s2tw.json` Simplified Chinese to Traditional Chinese (Taiwan Standard)
//! * `tw2s.json` Traditional Chinese (Taiwan Standard) to Simplified Chinese
//! * `s2hk.json` Simplified Chinese to Traditional Chinese (Hong Kong Standard)
//! * `hk2s.json` Traditional Chinese (Hong Kong Standard) to Simplified Chinese
//! * `s2twp.json` Simplified Chinese to Traditional Chinese (Taiwan Standard) with Taiwanese idiom
//! * `tw2sp.json` Traditional Chinese (Taiwan Standard) to Simplified Chinese with Mainland Chinese idiom
//! * `t2tw.json` Traditional Chinese (OpenCC Standard) to Taiwan Standard
//! * `t2hk.json` Traditional Chinese (OpenCC Standard) to Hong Kong Standard
//!
//! # Examples
//! ```
//! extern crate opencc;
//!
//! use opencc::OpenCC;
//!
//! fn main() {
//!     let cc = OpenCC::new("t2s.json");
//!     println!("{}", cc.convert("乾坤一擲").unwrap());
//!     println!("{}", cc.convert("開放中文轉換").unwrap());
//! }
//! ```
extern crate libc;
use libc::{size_t, c_void, c_char};

use std::ffi::CStr;
use std::str;

#[link(name = "opencc")]
extern {
    fn opencc_open(config: *const c_char) -> *mut c_void;
    fn opencc_close(opencc: *mut c_void);
    fn opencc_convert_utf8(opencc: *mut c_void, text: *const c_char, length: size_t) -> *mut c_char;
    fn opencc_convert_utf8_free(text: *mut c_char);
    fn opencc_error() -> *const c_char;
}

pub struct OpenCC {
    /// Configuration file
    pub config: String,
    _is_closed: bool,
    libopencc: *mut c_void,
}

impl OpenCC {
    /// Constructs a new `OpenCC`
    ///
    /// # Examples
    /// ```
    /// let cc = opencc::OpenCC::new("t2s.json");
    /// ```
    pub fn new(config: &str) -> OpenCC {
        let _config = config.to_string();
        let config_ptr = _config.as_ptr();
        unsafe {
            OpenCC {
                config: _config,
                _is_closed: false,
                libopencc: opencc_open(config_ptr as *const c_char),
            }
        }
    }

    /// Convert a text
    ///
    /// # Examples
    /// ```
    /// let cc = opencc::OpenCC::new("t2s.json");
    /// cc.convert("乾坤一擲").unwrap();
    /// cc.convert("開放中文轉換").unwrap();
    /// ```
    pub fn convert(&self, text: &str) -> Option<String> {
        if self._is_closed {
            None
        } else {
            unsafe {
                let text_ptr = text.as_ptr();
                let c_ptr = opencc_convert_utf8(self.libopencc, text_ptr as *const c_char, text.len() as size_t);
                if c_ptr.is_null() {
                    None
                } else {
                    let c_str = CStr::from_ptr(c_ptr);
                    let str_buf: String = str::from_utf8(c_str.to_bytes()).unwrap().to_owned();
                    opencc_convert_utf8_free(c_ptr);
                    Some(str_buf)
                }
            }
        }
    }

    /// Close the underlying libopencc.
    /// Will be called automatically when the variable gets out of scope.
    pub fn close(&mut self) {
        if !self._is_closed {
            unsafe {
                opencc_close(self.libopencc);
            }
            self._is_closed = true;
        }
    }

    /// Is the underlying libopencc closed
    pub fn is_closed(&self) -> bool {
        self._is_closed
    }

    /// Returns the last error message
    ///
    /// # Safety
    ///
    /// Note that this function is the only one which is NOT thread-safe.
    pub fn last_error() -> Option<String> {
        unsafe {
            let error_ptr = opencc_error();
            if error_ptr.is_null() {
                None
            } else {
                let c_str = CStr::from_ptr(error_ptr);
                let str_buf: String = str::from_utf8(c_str.to_bytes()).unwrap().to_owned();
                Some(str_buf)
            }
        }
    }
}

impl Drop for OpenCC {
    /// Close the underlying libopencc when it been droped
    fn drop(&mut self) {
        self.close();
    }
}

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

    #[test]
    fn test_simple_convert() {
        let cc = OpenCC::new("t2s.json");
        assert_eq!("乾坤一掷".to_string(), cc.convert("乾坤一擲").unwrap());
        assert_eq!("开放中文转换".to_string(), cc.convert("開放中文轉換").unwrap());
    }

    #[test]
    fn test_opencc_close() {
        let mut cc = OpenCC::new("t2s.json");
        assert_eq!("乾坤一掷".to_string(), cc.convert("乾坤一擲").unwrap());
        assert_eq!(false, cc.is_closed());
        cc.close();
        assert_eq!(true, cc.convert("開放中文轉換").is_none());
        assert_eq!(true, cc.is_closed());
    }

    #[test]
    fn test_opencc_last_error() {
        println!("{}", OpenCC::last_error().unwrap());
    }
}
<|endoftext|>


<commit_before>#![feature(asm)]
#![crate_id="sha"]

use std::slice::bytes::copy_memory;

static MAGIC_VALUES_SHA256: [u32, ..8] = [
    0x6a09e667,
    0xbb67ae85,
    0x3c6ef372,
    0xa54ff53a,
    0x510e527f,
    0x9b05688c,
    0x1f83d9ab,
    0x5be0cd19
];

static ROUND_CONSTANTS: [u32, ..64] = [
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];

pub struct Sha256<'a> {
    state: &'a [u32],
    position: uint,
    buffer: Vec<u8>
}

impl<'a> Sha256<'a> {
    pub fn new() -> Sha256<'a> {
        let mut buffer = Vec::with_capacity(64);
        unsafe { buffer.set_len(64); }
        Sha256 {
            state: MAGIC_VALUES_SHA256.clone(),
            buffer: buffer,
            position: 0,
        }
    }

    //
    // Adds the message to the buffer and hashes when the
    // buffer is full
    // TODO: refactor
    //
    pub fn update(&mut self, message: &[u8]) {

        let mut position: uint = 0;

        if self.position > 0 {
            let space = 64 - self.position;
            if space > message.len() {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    copy_memory(destination, message);
                }
                self.position += message.len();
                return;
            } else if space == message.len() {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    copy_memory(destination, message);
                }
                self.hash();
                return;
            } else {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    let source = message.slice_to(space);
                    copy_memory(destination, source);
                }
                self.hash();
                position += space;
            }
        }

        while position < message.len() {
            let end = position + 64;
            if end <= message.len() {
                {
                    let destination = self.buffer.as_mut_slice();
                    let source = message.slice(position, end);
                    copy_memory(destination, source);
                }
                self.hash();
                position = end;

            // final iteration
            } else {
                {
                    let destination = self.buffer.as_mut_slice();
                    let source = message.slice_from(position);
                    copy_memory(destination, source);
                }
                self.position = message.len() - position;
                break;
            }
        }

    }

    fn hash(&mut self) {
        //TODO: inline assembly?
        //

        let mut first: u32;
        unsafe {
            asm!(
                "movl $a, $b"
                :"=r"(first)
                :"a"(self.state),
                :
            )
        }
    }

}

#[cfg(test)]
mod test {
    #![feature(phase)]

    use super::Sha256;
    use std::string::String;

    macro_rules! rotate_right_32 (
        ($value:expr, $shift:expr) => (
            ($value >> $shift) | ($value << (32 - $shift))
        )
    )

    #[test]
    fn test_sha256() {
        let mut hasher = Sha256::new();
        let message = String::from_str("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ");

        hasher.update(message.as_bytes());

        assert!(hasher.position == 63 && message.len() == 63);
        hasher.update("a".as_bytes());
        assert!(hasher.position == 0);
    }

    #[test]
    fn test_right_rotate() {
        let five: u32 = 5;

        let shifted: u32 = 2147483650;

        assert_eq!(shifted, rotate_right_32!(five, 1));

    }
}

<commit_msg>inline x86 for hash functions<commit_after>#![feature(asm)]
#![crate_id="sha"]

use std::slice::bytes::copy_memory;

static MAGIC_VALUES_SHA256: [u32, ..8] = [
    0x6a09e667,
    0xbb67ae85,
    0x3c6ef372,
    0xa54ff53a,
    0x510e527f,
    0x9b05688c,
    0x1f83d9ab,
    0x5be0cd19
];

static ROUND_CONSTANTS: [u32, ..64] = [
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];

pub struct Sha256<'a> {
    state: &'a [u32],
    position: uint,
    buffer: Vec<u8>
}

impl<'a> Sha256<'a> {
    pub fn new() -> Sha256<'a> {
        let mut buffer = Vec::with_capacity(64);
        unsafe { buffer.set_len(64); }
        Sha256 {
            state: MAGIC_VALUES_SHA256.clone(),
            buffer: buffer,
            position: 0,
        }
    }

    //
    // Adds the message to the buffer and hashes when the
    // buffer is full
    // TODO: refactor
    //
    pub fn update(&mut self, message: &[u8]) {

        let mut position: uint = 0;

        if self.position > 0 {
            let space = 64 - self.position;
            if space > message.len() {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    copy_memory(destination, message);
                }
                self.position += message.len();
                return;
            } else if space == message.len() {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    copy_memory(destination, message);
                }
                self.hash();
                return;
            } else {
                {
                    let destination = self.buffer.mut_slice_from(self.position);
                    let source = message.slice_to(space);
                    copy_memory(destination, source);
                }
                self.hash();
                position += space;
            }
        }

        while position < message.len() {
            let end = position + 64;
            if end <= message.len() {
                {
                    let destination = self.buffer.as_mut_slice();
                    let source = message.slice(position, end);
                    copy_memory(destination, source);
                }
                self.hash();
                position = end;

            // final iteration
            } else {
                {
                    let destination = self.buffer.as_mut_slice();
                    let source = message.slice_from(position);
                    copy_memory(destination, source);
                }
                self.position = message.len() - position;
                break;
            }
        }

    }

    #[cfg(target_arch = "x86_64")]
    fn hash(chunk: &Vec<u8>, state: &Vec<u32>) {

        let mut schedule: Vec<u32> = Vec::with_capacity(64);

        unsafe {
            schedule.set_len(64);

        }
        let mut ptr = schedule.as_mut_ptr();
        unsafe {
            asm!(
                // Move chunk into schedule array
                "
                movq ($1), %rax
                movq 8($1), %rcx
                movq %rax, ($0)
                movq %rcx, 8($0)

                movq 16($1), %rax
                movq 24($1), %rcx
                movq %rax, 16($0)
                movq %rcx, 24($0)

                movq 32($1), %rax
                movq 40($1), %rcx
                movq %rax, 32($0)
                movq %rcx, 40($0)

                movq 48($1), %rax
                movq 56($1), %rcx
                movq %rax, 48($0)
                movq %rcx, 56($0)
                "
                :"+r"(ptr)
                :"r"(chunk.as_ptr())
                : "rax", "rcx"
            );

        }

        println!("{}", schedule[0]);
        println!("{}", schedule[1]);
        println!("{}", schedule[2]);
        println!("{}", schedule[3]);
        println!("{}", schedule[4]);
        println!("{}", schedule[5]);
    }

    #[cfg(target_arch = "x86")]
    fn hash(chunk: &Vec<u8>, state: &Vec<u32>) {

        let mut schedule: Vec<u32> = Vec::with_capacity(64);

        unsafe {
            schedule.set_len(64);

        }
        let mut ptr = schedule.as_mut_ptr();
        unsafe {
            asm!(
                // Move chunk into schedule array
                "
                movl ($1), %eax
                movl 4($1), %ecx
                movl %eax, ($0)
                movl %ecx, 4($0)

                movl 8($1), %eax
                movl 12($1), %ecx
                movl %eax, 8($0)
                movl %ecx, 12($0)

                movl 16($1), %eax
                movl 20($1), %ecx
                movl %eax, 16($0)
                movl %ecx, 20($0)

                movl 24($1), %eax
                movl 28($1), %ecx
                movl %eax, 24($0)
                movl %ecx, 28($0)

                movl 32($1), %eax
                movl 36($1), %ecx
                movl %eax, 32($0)
                movl %ecx, 36($0)

                movl 40($1), %eax
                movl 44($1), %ecx
                movl %eax, 40($0)
                movl %ecx, 44($0)

                movl 48($1), %eax
                movl 52($1), %ecx
                movl %eax, 48($0)
                movl %ecx, 52($0)

                movl 56($1), %eax
                movl 60($1), %ecx
                movl %eax, 56($0)
                movl %ecx, 60($0)
                "
                :"+r"(ptr)
                :"r"(chunk.as_ptr())
                : "eax", "ecx"
            );

        }
    }
}

#[cfg(test)]
mod test {
    #![feature(phase)]

    use super::Sha256;
    use std::string::String;

    macro_rules! rotate_right_32 (
        ($value:expr, $shift:expr) => (
            ($value >> $shift) | ($value << (32 - $shift))
        )
    )

    #[test]
    fn test_sha256() {
        let mut hasher = Sha256::new();
        let message = String::from_str("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ");

        hasher.update(message.as_bytes());

        assert!(hasher.position == 63 && message.len() == 63);
        hasher.update("a".as_bytes());
        assert!(hasher.position == 0);
    }

    #[test]
    fn test_right_rotate() {
        let five: u32 = 5;

        let shifted: u32 = 2147483650;

        assert_eq!(shifted, rotate_right_32!(five, 1));

    }
}

<|endoftext|>


<commit_before>use std::marker::PhantomData;

pub struct Lock<'a, T: 'a> {
    opt_val: Option<T>,
    phantom_lock: PhantomData<&'a mut ()>
}

impl<'a, T: 'a> Lock<'a, T> {
    /// Creates a Lock<T> container, which should never be directly visible
    ///
    /// Should not be called directly. Only public so that `noleak!()` can call it
    pub fn new() -> Self {
        Lock { opt_val: None, phantom_lock: PhantomData }
    }

    pub fn lock<R, F: FnOnce(Acceptor<'a, T>) -> R>(&'a mut self, f: F) -> R {
        let acc = Acceptor::new(self);
        f(acc)
    }
}

pub struct Acceptor<'a, T: 'a> {
    mut_lock: &'a mut Lock<'a, T>
}

impl<'a, T: 'a> Acceptor<'a, T> {
    fn new(lock: &'a mut Lock<'a, T>) -> Self {
        Acceptor { mut_lock: lock }
    }

    pub fn fill(self, t: T) -> Handle<'a, T> {
        self.mut_lock.opt_val = Some(t);
        Handle { mut_lock: self.mut_lock }
    }

    pub fn fill_from<'b>(self, handle_t: Handle<'b, T>) -> Handle<'a, T> {
        let new = handle_t.mut_lock.opt_val.take().expect("Attempting to .fill_from() an emptied Handle!");
        self.fill(new)
    }
}

pub struct Handle<'a, T: 'a> {
    mut_lock: &'a mut Lock<'a, T>
}

impl<'a, T: 'a> std::ops::Deref for Handle<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.mut_lock.opt_val.as_ref().expect("Tried to deref() an emptied Handle!")
    }
}

impl <'a, T: 'a> std::ops::DerefMut for Handle<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.mut_lock.opt_val.as_mut().expect("Tried to deref_mut() an emptied Handle!")
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Test, and doc change<commit_after>use std::marker::PhantomData;

pub struct Lock<'a, T: 'a> {
    opt_val: Option<T>,
    phantom_lock: PhantomData<&'a mut ()>
}

impl<'a, T: 'a> Lock<'a, T> {
    /// Creates an empty Lock<T> container.
    ///
    /// Needs to be stored in a binding (e.g. `let lock = Lock::new();`) to be useful.
    pub fn new() -> Self {
        Lock { opt_val: None, phantom_lock: PhantomData }
    }

    pub fn lock<R, F: FnOnce(Acceptor<'a, T>) -> R>(&'a mut self, f: F) -> R {
        let acc = Acceptor::new(self);
        f(acc)
    }
}

pub struct Acceptor<'a, T: 'a> {
    mut_lock: &'a mut Lock<'a, T>
}

impl<'a, T: 'a> Acceptor<'a, T> {
    fn new(lock: &'a mut Lock<'a, T>) -> Self {
        Acceptor { mut_lock: lock }
    }

    pub fn fill(self, t: T) -> Handle<'a, T> {
        self.mut_lock.opt_val = Some(t);
        Handle { mut_lock: self.mut_lock }
    }

    pub fn fill_from<'b>(self, handle_t: Handle<'b, T>) -> Handle<'a, T> {
        let new = handle_t.mut_lock.opt_val.take().expect("Attempting to .fill_from() an emptied Handle!");
        self.fill(new)
    }
}

pub struct Handle<'a, T: 'a> {
    mut_lock: &'a mut Lock<'a, T>
}

impl<'a, T: 'a> std::ops::Deref for Handle<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.mut_lock.opt_val.as_ref().expect("Tried to deref() an emptied Handle!")
    }
}

impl <'a, T: 'a> std::ops::DerefMut for Handle<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.mut_lock.opt_val.as_mut().expect("Tried to deref_mut() an emptied Handle!")
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn it_works() {
        use super::*;
        let mut lock = Lock::new();
        let mut handle = lock.lock(|acc| acc.fill(0i32));
        assert_eq!(*handle, 0i32);
    }
}
<|endoftext|>


<commit_before>#![feature(slice_patterns)]
extern crate byteorder;
extern crate rand;

use std::io::Read;
use std::ffi::CString;

pub mod lev;
pub mod rec;

/// Position struct.
#[derive(Debug, PartialEq)]
pub struct Position<T> {
    /// X-position.
    pub x: T,
    /// Y-position.
    pub y: T
}

/// Read n bytes function.
fn read_n<R> (reader: R, bytes: u64) -> Vec<u8>
    where R: Read {
        let mut buffer = vec![];
        let mut chunk = reader.take(bytes);
        chunk.read_to_end(&mut buffer).unwrap();
        buffer
}

/// Read CString data from byte vector and stop at null byte.
fn cstring_read (buffer: Vec<u8>) -> CString {
    let mut name :Vec<u8> = vec![];
    for n in 0..buffer.len() {
        if buffer[n] != 0 { name.push(buffer[n]); }
        else { break };
    }
    CString::new(name).unwrap()
}
<commit_msg>Fix gh-pages base-url<commit_after>#![doc(html_root_url = "https://hexjelly.github.io/elma-rust/")]
#![feature(slice_patterns)]
extern crate byteorder;
extern crate rand;

use std::io::Read;
use std::ffi::CString;

pub mod lev;
pub mod rec;

/// Position struct.
#[derive(Debug, PartialEq)]
pub struct Position<T> {
    /// X-position.
    pub x: T,
    /// Y-position.
    pub y: T
}

/// Read n bytes function.
fn read_n<R> (reader: R, bytes: u64) -> Vec<u8>
    where R: Read {
        let mut buffer = vec![];
        let mut chunk = reader.take(bytes);
        chunk.read_to_end(&mut buffer).unwrap();
        buffer
}

/// Read CString data from byte vector and stop at null byte.
fn cstring_read (buffer: Vec<u8>) -> CString {
    let mut name :Vec<u8> = vec![];
    for n in 0..buffer.len() {
        if buffer[n] != 0 { name.push(buffer[n]); }
        else { break };
    }
    CString::new(name).unwrap()
}
<|endoftext|>