<commit_before>extern crate hyper;
extern crate libc;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

use hyper::Client;
use hyper::client::response::Response;
use hyper::header::{ Headers, ContentType };
use hyper::mime::{ Mime, TopLevel, SubLevel };
use hyper::status::StatusCode;
use libc::{ uint8_t, size_t };
use log::LogLevelFilter;
use log4rs::append::file::FileAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{ Appender, Config, Logger, Root };
use serde::Serialize;
use std::collections::HashMap;
use std::env::var;
use std::io::Read;
use std::slice;
use std::sync::{ Once, ONCE_INIT, Mutex };

const BASE_URL: &'static str = "http://localhost:8080/k2/ctapi/";

static OK: i8 = 0;
static ERR_INVALID: i8 = -1;
static ERR_HOST: i8 = -127;

static INIT: Once = ONCE_INIT;

lazy_static! {
    static ref MAP: Mutex<HashMap<u16, u16>> = Mutex::new(HashMap::new());
}

#[derive(Serialize)]
struct Empty();

#[derive(Serialize)]
struct RequestData {
    ctn: u16,
    dad: u8,
    sad: u8,
    lenc: usize,
    command: Vec<u8>,
    lenr: usize
}

#[allow(non_snake_case)]
#[derive(Deserialize)]
struct ResponseData {
    dad: u8,
    sad: u8,
    lenr: usize,
    response: Vec<u8>,
    responseCode: i8
}

macro_rules! post_request {
    ($path:expr) => (post_request($path, &Empty{}));
    ($path:expr, $data:expr) => (post_request($path, $data));
}

#[no_mangle]
#[allow(non_snake_case, unused_must_use)]
pub extern fn CT_init(ctn: u16, pn: u16) -> i8 {
    init_logging();

    debug!("CT_init( ctn: {}; pn: {} )", ctn, pn);

    // Do we know this CTN?
    if MAP.lock().unwrap().contains_key(&ctn) {
        return ERR_INVALID
    }

    // Build the request URL
    let endpoint = "ct_init".to_string();
    let path = endpoint + "/" + &ctn.to_string() + "/" + &pn.to_string();

    debug!("Request path: {}", path);

    // Perform the request
    let mut response = post_request!(&path);

    match response.status {
        StatusCode::Ok => {
            debug!("Response received!");

            // Cast server response
            let mut body = String::new();
            response.read_to_string(&mut body).unwrap();

            let status = body.parse::<i8>().unwrap();
            if status == OK {
                // Store CTN
                MAP.lock().unwrap().insert(ctn, pn);
            }

            debug!("Return status: {}", status);
            status
        },
        _ => {
            error!("Response not OK!");
            debug!("Response: {:?}", response);
            ERR_HOST
        }
    }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn CT_data(ctn: u16, dad: *mut uint8_t, sad: *mut uint8_t, lenc: size_t, command: *const uint8_t, lenr: *mut size_t, response: *mut uint8_t) -> i8 {
    unsafe {
        if !MAP.lock().unwrap().contains_key(&ctn) {
            return ERR_INVALID
        }

        let dad: &mut u8 = &mut *dad;

        let sad: &mut u8 = &mut *sad;

        let lenr: &mut size_t = &mut *lenr;

        let command = slice::from_raw_parts(command, lenc as usize);

        let response = slice::from_raw_parts_mut(response, *lenr);

        let requestData = RequestData {
            ctn: ctn,
            dad: *dad,
            sad: *sad,
            lenc: lenc,
            command: command.to_vec(),
            lenr: *lenr
        };

        let pn = MAP.lock().unwrap();
        let pn = pn.get(&ctn).unwrap();
        let endpoint = "ct_data".to_string();
        let path = endpoint + "/" + &ctn.to_string() + "/" + &pn.to_string();

        let mut http_response = post_request(&path, &requestData);

        match http_response.status {
            StatusCode::Ok => {
                // decode server response
                let mut body = String::new();
                http_response.read_to_string(&mut body).unwrap();
                let responseData: ResponseData = serde_json::from_str(&body).unwrap();

                if responseData.responseCode == OK {

                    *dad = responseData.dad;
                    *sad = responseData.sad;
                    *lenr = responseData.lenr;

                    for (place, element) in response.iter_mut().zip(responseData.response.iter()) {
                        *place = *element;
                    }
                }
                return responseData.responseCode;
            },
            _ => ERR_HOST
        }
    }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn CT_close(ctn: u16) -> i8 {
    // Do we know this CTN?
    if !MAP.lock().unwrap().contains_key(&ctn) {
        return ERR_INVALID
    }

    // Build the request URL
    let pn = MAP.lock().unwrap().get(&ctn).unwrap().clone();
    let endpoint = "ct_close".to_string();
    let path = endpoint + "/" + &ctn.to_string() + "/" + &pn.to_string();

    // Perform the request
    let mut response = post_request!(&path);

    match response.status {
        StatusCode::Ok => {
            // Cast server response
            let mut body = String::new();
            response.read_to_string(&mut body).unwrap();

            let status = body.parse::<i8>().unwrap();
            if status == OK {
                // Remove CTN
                MAP.lock().unwrap().remove(&ctn);
            }

            status
        },
        _ => ERR_HOST
    }
}

fn env_or_default(var_name: &str, default: &str) -> String {
    match var(var_name) {
        Ok(s) => s,
        Err(_) => default.into(),
    }
}

fn init_logging() {
   match var("K2_LOG_PATH") {
        Ok(path) => {
            INIT.call_once(|| {
                let file = FileAppender::builder()
                    .encoder(Box::new(PatternEncoder::new("{d} {l} {M}: {m}{n}")))
                    .build(path + "/" + &"k2_basecamp.log".to_string())
                    .unwrap();

                let config = Config::builder()
                    .appender(Appender::builder().build("file", Box::new(file)))
                    .logger(Logger::builder()
                        .appender("file")
                        .additive(true)
                        .build("k2_basecamp", LogLevelFilter::Debug))
                    .build(Root::builder().appender("file").build(LogLevelFilter::Error))
                    .unwrap();

                log4rs::init_config(config).unwrap();
            })
        },
        _ => ()
    }
}

fn post_request<T>(path: &str, payload: &T) -> Response
    where T: Serialize
{
    // untested
    let base_url = env_or_default("K2_BASE_URL", BASE_URL);
    let url = base_url + path;

    let client = Client::new();

    let mut headers = Headers::new();
    headers.set(
        ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![]))
    );

    let body = serde_json::to_string(&payload).unwrap();

    return client.post(&url)
        .headers(headers)
        .body(&body[..])
        .send()
        .unwrap();
}
<commit_msg>add logging to CT_close and CT_data<commit_after>extern crate hyper;
extern crate libc;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

use hyper::Client;
use hyper::client::response::Response;
use hyper::header::{ Headers, ContentType };
use hyper::mime::{ Mime, TopLevel, SubLevel };
use hyper::status::StatusCode;
use libc::{ uint8_t, size_t };
use log::LogLevelFilter;
use log4rs::append::file::FileAppender;
use log4rs::encode::pattern::PatternEncoder;
use log4rs::config::{ Appender, Config, Logger, Root };
use serde::Serialize;
use std::collections::HashMap;
use std::env::var;
use std::io::Read;
use std::slice;
use std::sync::{ Once, ONCE_INIT, Mutex };

const BASE_URL: &'static str = "http://localhost:8080/k2/ctapi/";

static OK: i8 = 0;
static ERR_INVALID: i8 = -1;
static ERR_HOST: i8 = -127;

static INIT: Once = ONCE_INIT;

lazy_static! {
    static ref MAP: Mutex<HashMap<u16, u16>> = Mutex::new(HashMap::new());
}

#[derive(Serialize)]
struct Empty();

#[derive(Serialize)]
struct RequestData {
    ctn: u16,
    dad: u8,
    sad: u8,
    lenc: usize,
    command: Vec<u8>,
    lenr: usize
}

#[allow(non_snake_case)]
#[derive(Deserialize)]
struct ResponseData {
    dad: u8,
    sad: u8,
    lenr: usize,
    response: Vec<u8>,
    responseCode: i8
}

macro_rules! post_request {
    ($path:expr) => (post_request($path, &Empty{}));
    ($path:expr, $data:expr) => (post_request($path, $data));
}

#[no_mangle]
#[allow(non_snake_case, unused_must_use)]
pub extern fn CT_init(ctn: u16, pn: u16) -> i8 {
    init_logging();

    debug!("CT_init( ctn: {}; pn: {} )", ctn, pn);

    // Do we know this CTN?
    if MAP.lock().unwrap().contains_key(&ctn) {
        return ERR_INVALID
    }

    // Build the request URL
    let endpoint = "ct_init".to_string();
    let path = endpoint + "/" + &ctn.to_string() + "/" + &pn.to_string();

    debug!("Request path: {}", path);

    // Perform the request
    let mut response = post_request!(&path);

    match response.status {
        StatusCode::Ok => {
            debug!("Response received!");

            // Cast server response
            let mut body = String::new();
            response.read_to_string(&mut body).unwrap();

            let status = body.parse::<i8>().unwrap();
            if status == OK {
                // Store CTN
                MAP.lock().unwrap().insert(ctn, pn);
            }

            debug!("Return status: {}", status);
            status
        },
        _ => {
            error!("Response not OK! Returning {}", ERR_HOST);
            debug!("Response: {:?}", response);
            ERR_HOST
        }
    }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn CT_data(ctn: u16, dad: *mut uint8_t, sad: *mut uint8_t, lenc: size_t, command: *const uint8_t, lenr: *mut size_t, response: *mut uint8_t) -> i8 {
    init_logging();

    debug!("CT_data for ctn: {}", ctn);
    unsafe {
        if !MAP.lock().unwrap().contains_key(&ctn) {
            return ERR_INVALID
        }

        let dad: &mut u8 = &mut *dad;

        let sad: &mut u8 = &mut *sad;

        let lenr: &mut size_t = &mut *lenr;

        let command = slice::from_raw_parts(command, lenc as usize);

        let response = slice::from_raw_parts_mut(response, *lenr);

        let requestData = RequestData {
            ctn: ctn,
            dad: *dad,
            sad: *sad,
            lenc: lenc,
            command: command.to_vec(),
            lenr: *lenr
        };

        debug!("Additonal request parameter: dad: {}, sad: {}, lenc: {}, command: {:?}, lenr: {}, response.len(): {}", dad, sad, lenc, command, lenr, response.len());

        let pn = MAP.lock().unwrap();
        let pn = pn.get(&ctn).unwrap();
        let endpoint = "ct_data".to_string();
        let path = endpoint + "/" + &ctn.to_string() + "/" + &pn.to_string();

        debug!("Request path: {}", path);

        let mut http_response = post_request(&path, &requestData);

        match http_response.status {
            StatusCode::Ok => {
                debug!("Response received!");

                // decode server response
                let mut body = String::new();
                http_response.read_to_string(&mut body).unwrap();
                let responseData: ResponseData = serde_json::from_str(&body).unwrap();

                if responseData.responseCode == OK {

                    debug!("Body data from response: dad: {}, sad: {}, lenr: {}", responseData.dad, responseData.sad, responseData.lenr);

                    *dad = responseData.dad;
                    *sad = responseData.sad;
                    *lenr = responseData.lenr;

                    debug!("Content of response array");
                    for (place, element) in response.iter_mut().zip(responseData.response.iter()) {
                        debug!("[{}] {}", place, element);
                        *place = *element;
                    }
                }
                debug!("Return status: {}", responseData.responseCode);
                return responseData.responseCode;
            },
            _ => {
                error!("Response not OK! Returning {}", ERR_HOST);
                debug!("Response: {:?}", response);
                ERR_HOST
            }
        }
    }
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern fn CT_close(ctn: u16) -> i8 {
    init_logging();

    debug!("CT_close( ctn: {} )", ctn);

    // Do we know this CTN?
    if !MAP.lock().unwrap().contains_key(&ctn) {
        return ERR_INVALID
    }

    // Build the request URL
    let pn = MAP.lock().unwrap().get(&ctn).unwrap().clone();
    let endpoint = "ct_close".to_string();
    let path = endpoint + "/" + &ctn.to_string() + "/" + &pn.to_string();

    debug!("Request path: {}", path);

    // Perform the request
    let mut response = post_request!(&path);

    match response.status {
        StatusCode::Ok => {
            debug!("Response received!");

            // Cast server response
            let mut body = String::new();
            response.read_to_string(&mut body).unwrap();

            let status = body.parse::<i8>().unwrap();
            if status == OK {
                // Remove CTN
                MAP.lock().unwrap().remove(&ctn);
            }

            debug!("Return status: {}", status);
            status
        },
        _ => {
            error!("Response not OK! Returning {}", ERR_HOST);
            debug!("Response: {:?}", response);
            ERR_HOST
        }
    }
}

fn env_or_default(var_name: &str, default: &str) -> String {
    match var(var_name) {
        Ok(s) => s,
        Err(_) => default.into(),
    }
}

fn init_logging() {
   match var("K2_LOG_PATH") {
        Ok(path) => {
            INIT.call_once(|| {
                let file = FileAppender::builder()
                    .encoder(Box::new(PatternEncoder::new("{d} {l} {M}: {m}{n}")))
                    .build(path + "/" + &"k2_basecamp.log".to_string())
                    .unwrap();

                let config = Config::builder()
                    .appender(Appender::builder().build("file", Box::new(file)))
                    .logger(Logger::builder()
                        .appender("file")
                        .additive(false)
                        .build("k2_basecamp", LogLevelFilter::Debug))
                    .build(Root::builder().appender("file").build(LogLevelFilter::Error))
                    .unwrap();

                log4rs::init_config(config).unwrap();
            })
        },
        _ => ()
    }
}

fn post_request<T>(path: &str, payload: &T) -> Response
    where T: Serialize
{
    // untested
    let base_url = env_or_default("K2_BASE_URL", BASE_URL);
    let url = base_url + path;

    let client = Client::new();

    let mut headers = Headers::new();
    headers.set(
        ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![]))
    );

    let body = serde_json::to_string(&payload).unwrap();

    return client.post(&url)
        .headers(headers)
        .body(&body[..])
        .send()
        .unwrap();
}
<|endoftext|>


<commit_before>#![feature(associated_consts)]

extern crate uuid;
extern crate jsrs_common;
extern crate js_types;

pub mod alloc;
mod gc_error;
mod test_utils;

use std::cell::RefCell;
use std::mem;
use std::rc::Rc;

use alloc::AllocBox;
use alloc::scope::Scope;
use gc_error::{GcError, Result};
use js_types::js_var::{JsPtrEnum, JsVar};
use js_types::binding::Binding;

pub struct ScopeManager {
    curr_scope: Scope,
    alloc_box: Rc<RefCell<AllocBox>>,
}

impl ScopeManager {
    fn new(alloc_box: Rc<RefCell<AllocBox>>) -> ScopeManager {
        ScopeManager {
            curr_scope: Scope::new(&alloc_box),
            alloc_box: alloc_box,
        }
    }

    pub fn push_scope(&mut self) {
        let parent = mem::replace(&mut self.curr_scope, Scope::new(&self.alloc_box));
        self.curr_scope.set_parent(parent);
    }

    pub fn pop_scope(&mut self, gc_yield: bool) -> Result<()> {
        let parent = self.curr_scope.transfer_stack(gc_yield);
        if let Some(parent) = parent {
            mem::replace(&mut self.curr_scope, *parent);
            Ok(())
        } else {
            Err(GcError::ScopeError)
        }
    }

    pub fn alloc(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<()> {
        self.curr_scope.push(var, ptr)
    }

    pub fn load(&self, bnd: &Binding) -> Result<(JsVar, Option<JsPtrEnum>)> {
        if let (Some(v), ptr) = self.curr_scope.get_var_copy(bnd) {
            Ok((v, ptr))
        } else { Err(GcError::LoadError(bnd.clone())) }
    }

    pub fn store(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<()> {
        self.curr_scope.update_var(var, ptr)
    }
}

pub fn init_gc() -> ScopeManager {
    let alloc_box = Rc::new(RefCell::new(AllocBox::new()));
    ScopeManager::new(alloc_box)
}

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

    use test_utils;
    use js_types::js_var::JsType;
    use js_types::binding::Binding;

    #[test]
    fn test_pop_scope() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.push_scope();
        assert!(mgr.curr_scope.parent.is_some());
        mgr.pop_scope(false).unwrap();
        assert!(mgr.curr_scope.parent.is_none());
    }

    #[test]
    fn test_alloc() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.alloc(test_utils::make_num(1.), None).unwrap();
        mgr.push_scope();
        mgr.alloc(test_utils::make_num(2.), None).unwrap();
        assert_eq!(mgr.alloc_box.borrow().len(), 0);
    }

    #[test]
    fn test_load() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let x = test_utils::make_num(1.);
        let x_bnd = x.binding.clone();
        mgr.alloc(x, None).unwrap();
        let load = mgr.load(&x_bnd);
        assert!(load.is_ok());
        let load = load.unwrap();
        match load.0.t {
            JsType::JsNum(n) => assert_eq!(n, 1.),
            _ => panic!("load result was not equal to value allocated!"),
        }
        assert!(load.1.is_none());
        assert!(mgr.load(&Binding::anon()).is_err());
    }

    #[test]
    fn test_store() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box,);
        mgr.push_scope();
        let x = test_utils::make_num(1.);
        let x_bnd = x.binding.clone();
        mgr.alloc(x, None).unwrap();

        let mut test_num = test_utils::make_num(2.);
        test_num.binding = x_bnd;
        assert!(mgr.store(test_num, None).is_ok());
    }

}
<commit_msg>Add failure tests to ScopeManager<commit_after>#![feature(associated_consts)]

extern crate uuid;
extern crate jsrs_common;
extern crate js_types;

#[cfg(test)]
#[macro_use] extern crate matches;

pub mod alloc;
mod gc_error;
mod test_utils;

use std::cell::RefCell;
use std::mem;
use std::rc::Rc;

use alloc::AllocBox;
use alloc::scope::Scope;
use gc_error::{GcError, Result};
use js_types::js_var::{JsPtrEnum, JsVar};
use js_types::binding::Binding;

pub struct ScopeManager {
    curr_scope: Scope,
    alloc_box: Rc<RefCell<AllocBox>>,
}

impl ScopeManager {
    fn new(alloc_box: Rc<RefCell<AllocBox>>) -> ScopeManager {
        ScopeManager {
            curr_scope: Scope::new(&alloc_box),
            alloc_box: alloc_box,
        }
    }

    pub fn push_scope(&mut self) {
        let parent = mem::replace(&mut self.curr_scope, Scope::new(&self.alloc_box));
        self.curr_scope.set_parent(parent);
    }

    pub fn pop_scope(&mut self, gc_yield: bool) -> Result<()> {
        let parent = self.curr_scope.transfer_stack(gc_yield);
        if let Some(parent) = parent {
            mem::replace(&mut self.curr_scope, *parent);
            Ok(())
        } else {
            Err(GcError::ScopeError)
        }
    }

    pub fn alloc(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<()> {
        self.curr_scope.push(var, ptr)
    }

    pub fn load(&self, bnd: &Binding) -> Result<(JsVar, Option<JsPtrEnum>)> {
        if let (Some(v), ptr) = self.curr_scope.get_var_copy(bnd) {
            Ok((v, ptr))
        } else { Err(GcError::LoadError(bnd.clone())) }
    }

    pub fn store(&mut self, var: JsVar, ptr: Option<JsPtrEnum>) -> Result<()> {
        self.curr_scope.update_var(var, ptr)
    }
}

pub fn init_gc() -> ScopeManager {
    let alloc_box = Rc::new(RefCell::new(AllocBox::new()));
    ScopeManager::new(alloc_box)
}

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

    use gc_error::GcError;
    use js_types::js_var::JsType;
    use js_types::binding::Binding;
    use test_utils;

    #[test]
    fn test_pop_scope() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.push_scope();
        assert!(mgr.curr_scope.parent.is_some());
        mgr.pop_scope(false).unwrap();
        assert!(mgr.curr_scope.parent.is_none());
    }

    #[test]
    fn test_pop_scope_fail() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let res = mgr.pop_scope(false);
        assert!(res.is_err());
        assert!(matches!(res, Err(GcError::ScopeError)));
    }

    #[test]
    fn test_alloc() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        mgr.alloc(test_utils::make_num(1.), None).unwrap();
        mgr.push_scope();
        mgr.alloc(test_utils::make_num(2.), None).unwrap();
        assert_eq!(mgr.alloc_box.borrow().len(), 0);
    }

    #[test]
    fn test_load() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box);
        let x = test_utils::make_num(1.);
        let x_bnd = x.binding.clone();
        mgr.alloc(x, None).unwrap();
        let load = mgr.load(&x_bnd);
        assert!(load.is_ok());
        let load = load.unwrap();
        match load.0.t {
            JsType::JsNum(n) => assert_eq!(n, 1.),
            _ => unreachable!(),
        }
        assert!(load.1.is_none());
    }

    #[test]
    fn test_load_fail() {
        let alloc_box = test_utils::make_alloc_box();
        let mgr = ScopeManager::new(alloc_box);
        let bnd = Binding::anon();
        let res = mgr.load(&bnd);
        assert!(res.is_err());
        assert!(matches!(res, Err(GcError::LoadError(bnd))));
    }

    #[test]
    fn test_store() {
        let alloc_box = test_utils::make_alloc_box();
        let mut mgr = ScopeManager::new(alloc_box,);
        mgr.push_scope();
        let x = test_utils::make_num(1.);
        let x_bnd = x.binding.clone();
        mgr.alloc(x, None).unwrap();

        let mut test_num = test_utils::make_num(2.);
        test_num.binding = x_bnd;
        assert!(mgr.store(test_num, None).is_ok());
    }

}
<|endoftext|>


<commit_before>// Copyright 2014 Carl Lerche, Oliver Mader, Alex Crichton, Thiago Pontes,
//                Yehuda Katz
// Copyright 2015 Carl Lerche, Oliver Mader
// Copyright 2016 Urban Hafner
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "hamcrest"]
#![crate_type = "lib"]

extern crate num;
extern crate regex;

pub use core::{assert_that, expect, success, Matcher, MatchResult};
pub use matchers::is::{is, is_not};
pub use matchers::is::is_not as not;
pub use matchers::is::is_not as does_not;
pub use matchers::none::{none};
pub use matchers::equal_to::equal_to;
pub use matchers::close_to::close_to;
pub use matchers::existing_path::{existing_path, existing_file, existing_dir};
pub use matchers::regex::matches;
pub use matchers::vecs::{of_len, contains};

pub mod core;
pub mod matchers;
pub mod prelude {
    pub use core::assert_that;
    pub use matchers::is::{is, is_not};
    pub use matchers::is::is_not as not;
    pub use matchers::is::is_not as does_not;
    pub use matchers::none::{none};
    pub use matchers::equal_to::equal_to;
    pub use matchers::close_to::close_to;
    pub use matchers::existing_path::{existing_path, existing_file, existing_dir};
    pub use matchers::regex::matches;
    pub use matchers::vecs::{of_len, contains};
}
<commit_msg>DRY up exports<commit_after>// Copyright 2014 Carl Lerche, Oliver Mader, Alex Crichton, Thiago Pontes,
//                Yehuda Katz
// Copyright 2015 Carl Lerche, Oliver Mader
// Copyright 2016 Urban Hafner
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "hamcrest"]
#![crate_type = "lib"]

extern crate num;
extern crate regex;

pub use core::{expect, success, Matcher, MatchResult};
pub use prelude::*;

pub mod core;
pub mod matchers;
pub mod prelude {
    pub use core::assert_that;
    pub use matchers::is::{is, is_not};
    pub use matchers::is::is_not as not;
    pub use matchers::is::is_not as does_not;
    pub use matchers::none::{none};
    pub use matchers::equal_to::equal_to;
    pub use matchers::close_to::close_to;
    pub use matchers::existing_path::{existing_path, existing_file, existing_dir};
    pub use matchers::regex::matches;
    pub use matchers::vecs::{of_len, contains};
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]

#![warn(rust_2018_idioms)]
#![allow(clippy::cast_lossless)]

#[macro_use]
extern crate log;
// From rustc.
extern crate syntax;
extern crate rustc_apfloat;
#[macro_use] extern crate rustc;
extern crate rustc_data_structures;
extern crate rustc_mir;
extern crate rustc_target;

mod shims;
mod operator;
mod helpers;
mod range_map;
mod mono_hash_map;
mod stacked_borrows;
mod intptrcast;
mod machine;
mod eval;

// Make all those symbols available in the same place as our own.
pub use rustc_mir::interpret::*;
// Resolve ambiguity.
pub use rustc_mir::interpret::{self, AllocMap, PlaceTy};

pub use crate::shims::{EvalContextExt as ShimsEvalContextExt};
pub use crate::shims::foreign_items::EvalContextExt as ForeignItemsEvalContextExt;
pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
pub use crate::shims::dlsym::{Dlsym, EvalContextExt as DlsymEvalContextExt};
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
pub use crate::range_map::RangeMap;
pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt, Tag, Permission, Stack, Stacks, Item};
pub use crate::machine::{
    PAGE_SIZE, STACK_ADDR, STACK_SIZE, NUM_CPUS,
    MemoryExtra, AllocExtra, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt,
};
pub use crate::eval::{eval_main, create_ecx, MiriConfig};

/// Insert rustc arguments at the beginning of the argument list that Miri wants to be
/// set per default, for maximal validation power.
pub fn miri_default_args() -> &'static [&'static str] {
    // The flags here should be kept in sync with what bootstrap adds when `test-miri` is
    // set, which happens in `bootstrap/bin/rustc.rs` in the rustc sources.
    &["-Zalways-encode-mir", "-Zmir-emit-retag", "-Zmir-opt-level=0", "--cfg=miri"]
}
<commit_msg>bootstrap no longer carries a copy of these flags<commit_after>#![feature(rustc_private)]

#![warn(rust_2018_idioms)]
#![allow(clippy::cast_lossless)]

#[macro_use]
extern crate log;
// From rustc.
extern crate syntax;
extern crate rustc_apfloat;
#[macro_use] extern crate rustc;
extern crate rustc_data_structures;
extern crate rustc_mir;
extern crate rustc_target;

mod shims;
mod operator;
mod helpers;
mod range_map;
mod mono_hash_map;
mod stacked_borrows;
mod intptrcast;
mod machine;
mod eval;

// Make all those symbols available in the same place as our own.
pub use rustc_mir::interpret::*;
// Resolve ambiguity.
pub use rustc_mir::interpret::{self, AllocMap, PlaceTy};

pub use crate::shims::{EvalContextExt as ShimsEvalContextExt};
pub use crate::shims::foreign_items::EvalContextExt as ForeignItemsEvalContextExt;
pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
pub use crate::shims::dlsym::{Dlsym, EvalContextExt as DlsymEvalContextExt};
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
pub use crate::range_map::RangeMap;
pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt, Tag, Permission, Stack, Stacks, Item};
pub use crate::machine::{
    PAGE_SIZE, STACK_ADDR, STACK_SIZE, NUM_CPUS,
    MemoryExtra, AllocExtra, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt,
};
pub use crate::eval::{eval_main, create_ecx, MiriConfig};

/// Insert rustc arguments at the beginning of the argument list that Miri wants to be
/// set per default, for maximal validation power.
pub fn miri_default_args() -> &'static [&'static str] {
    &["-Zalways-encode-mir", "-Zmir-emit-retag", "-Zmir-opt-level=0", "--cfg=miri"]
}
<|endoftext|>


<commit_before>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A micro-benchmarking library.

#![warn(missing_copy_implementations, missing_debug_implementations, missing_docs)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(clippy))]
<commit_msg>Add retain function<commit_after>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A micro-benchmarking library.

#![feature(test)]

#![warn(missing_copy_implementations, missing_debug_implementations, missing_docs)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(clippy))]

extern crate test;

//================================================
// Functions
//================================================

/// A function that prevents the optimizer from eliminating the supplied value.
pub fn retain<T>(value: T) -> T {
    test::black_box(value)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Jeff Belgum
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software without restriction, including without
// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! A simple statistics library
//!
//! Heavily inspired by the python standard library statistics module.

extern crate rand;
extern crate num;

use num::{FromPrimitive,
          Float,
          Num,
          NumCast,
          One,
          Zero};

/// The mean is the sum of a collection of numbers divided by the number of numbers in the collection.
/// (reference)[http://en.wikipedia.org/wiki/Arithmetic_mean]
pub fn mean<T>(v: &[T]) -> T
    where T: Copy + FromPrimitive + Num + NumCast
{
    let len = FromPrimitive::from_usize(v.len()).unwrap();
    v.iter().fold(Zero::zero(), |acc: T, elem| acc + *elem) / len
}

/// The median is the number separating the higher half of a data sample, a population, or
/// a probability distribution, from the lower half (reference)[http://en.wikipedia.org/wiki/Median)
pub fn median<T>(v: &[T]) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0);
    let mut scratch = Vec::with_capacity(v.len());
    scratch.extend(v.iter());
    quicksort(&mut scratch);

    let mid = scratch.len() / 2;
    if scratch.len() % 2 == 1 {
        *scratch[mid]
    } else {
        (*scratch[mid] + *scratch[mid-1]) / FromPrimitive::from_i32(2).unwrap()
    }
}

fn sum_square_deviations<T>(v: &[T], c: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    let c = match c {
        Some(c) => c,
        None => mean(v),
    };

    let sum = v.iter().map( |x| (*x - c) * (*x - c) ).fold(Zero::zero(), |acc, elem| acc + elem);
    assert!(sum >= Zero::zero(), "negative sum of square root deviations");
    sum
}

/// (Sample variance)[http://en.wikipedia.org/wiki/Variance#Sample_variance]
pub fn variance<T>(v: &[T], xbar: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 1, "variance requires at least two data points");
    let len: T = FromPrimitive::from_usize(v.len()).unwrap();
    let sum = sum_square_deviations(v, xbar);
    sum / (len - One::one())
}

/// (Population variance)[http://en.wikipedia.org/wiki/Variance#Population_variance]
pub fn population_variance<T>(v: &[T], mu: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0, "population variance requires at least one data point");
    let len: T = FromPrimitive::from_usize(v.len()).unwrap();
    let sum = sum_square_deviations(v, mu);
    sum / len
}

///  Standard deviation is a measure that is used to quantify the amount of variation or
///  dispersion of a set of data values. (reference)[http://en.wikipedia.org/wiki/Standard_deviation]
pub fn standard_deviation<T>(v: &[T], xbar: Option<T>) -> T
    where T: Float + FromPrimitive
{
    let var = variance(v, xbar);
    var.sqrt()
}

pub fn population_standard_deviation<T>(v: &[T], mu: Option<T>) -> T
    where T: Float + FromPrimitive
{
    let pvar = population_variance(v, mu);
    pvar.sqrt()
}

#[inline(always)]
fn select_pivot<T>(v: &mut [T]) where T: Copy {
    let idx = rand::random::<usize>() % v.len();
    let tmp = v[0];
    v[0] = v[idx];
    v[idx] = tmp;
}

fn partition<T>(v: &mut [T]) -> usize where T: PartialOrd + Copy {
    select_pivot(v);
    let pivot = v[0];
    let mut i = 0;
    let mut j = 0;
    let end = v.len() - 1;
    while i < end {
        i += 1;
        if v[i] < pivot {
            v[j] = v[i];
            j += 1;
            v[i] = v[j];
        }

    }
    v[j] = pivot;
    j

}

fn quicksort<T>(v: &mut [T]) where T: PartialOrd + Copy {
    if v.len() <= 1 {
        return
    }
    let pivot = partition(v);
    quicksort(&mut v[..pivot]);
    quicksort(&mut v[(pivot+1)..]);
}

// Unit tests for private functions must be in the same module.
#[test]
fn test_qsort_empty() {
    let mut vec: Vec<f64> = vec![];
    quicksort(&mut vec);
    assert_eq!(vec, vec![]);
}

#[test]
fn test_qsort_small() {
    let len = 10;
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len { vec.push(rand::random::<f64>()); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_large() {
    let len = 1_000_000;
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len { vec.push(rand::random::<f64>()); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_sorted() {
    let len = 1_000;
    let mut vec = Vec::with_capacity(len);
    for n in 0..len { vec.push(n); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_reverse_sorted() {
    let len = 1_000;
    let mut vec = Vec::with_capacity(len);
    for n in 0..len { vec.push(len-n); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[cfg(test)]
mod tests {
    extern crate rand;
    extern crate num;

    use super::*;
    use num::Float;

    #[test]
    fn test_mean() {
        let vec = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        assert_eq!(mean(&vec), 1.375);
    }

    #[test]
    fn test_median() {
        let vec = vec![1.0, 3.0];
        assert_eq!(median(&vec), 2.0);
        let vec = vec![1.0, 3.0, 5.0];
        assert_eq!(median(&vec), 3.0);
        let vec = vec![1.0, 3.0, 5.0, 7.0];
        assert_eq!(median(&vec), 4.0);
    }

    #[test]
    fn test_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.428571;
        let epsilon = 1e-6;
        assert!((expected - variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.25;
        let epsilon = 1e-6;
        assert!((expected - population_variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.195229;
        let epsilon = 1e-6;
        assert!((expected - standard_deviation(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.118034;
        let epsilon = 1e-6;
        assert!((expected - population_standard_deviation(&v, None)).abs() < epsilon);
    }
}
<commit_msg>Added a Standard Score method.<commit_after>// Copyright (c) 2015 Jeff Belgum
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software without restriction, including without
// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! A simple statistics library
//!
//! Heavily inspired by the python standard library statistics module.

extern crate rand;
extern crate num;

use num::{FromPrimitive,
          Float,
          Num,
          NumCast,
          One,
          Zero};

/// The mean is the sum of a collection of numbers divided by the number of numbers in the collection.
/// (reference)[http://en.wikipedia.org/wiki/Arithmetic_mean]
pub fn mean<T>(v: &[T]) -> T
    where T: Copy + FromPrimitive + Num + NumCast
{
    let len = FromPrimitive::from_usize(v.len()).unwrap();
    v.iter().fold(Zero::zero(), |acc: T, elem| acc + *elem) / len
}

/// The median is the number separating the higher half of a data sample, a population, or
/// a probability distribution, from the lower half (reference)[http://en.wikipedia.org/wiki/Median)
pub fn median<T>(v: &[T]) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0);
    let mut scratch = Vec::with_capacity(v.len());
    scratch.extend(v.iter());
    quicksort(&mut scratch);

    let mid = scratch.len() / 2;
    if scratch.len() % 2 == 1 {
        *scratch[mid]
    } else {
        (*scratch[mid] + *scratch[mid-1]) / FromPrimitive::from_i32(2).unwrap()
    }
}

fn sum_square_deviations<T>(v: &[T], c: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    let c = match c {
        Some(c) => c,
        None => mean(v),
    };

    let sum = v.iter().map( |x| (*x - c) * (*x - c) ).fold(Zero::zero(), |acc, elem| acc + elem);
    assert!(sum >= Zero::zero(), "negative sum of square root deviations");
    sum
}

/// (Sample variance)[http://en.wikipedia.org/wiki/Variance#Sample_variance]
pub fn variance<T>(v: &[T], xbar: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 1, "variance requires at least two data points");
    let len: T = FromPrimitive::from_usize(v.len()).unwrap();
    let sum = sum_square_deviations(v, xbar);
    sum / (len - One::one())
}

/// (Population variance)[http://en.wikipedia.org/wiki/Variance#Population_variance]
pub fn population_variance<T>(v: &[T], mu: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0, "population variance requires at least one data point");
    let len: T = FromPrimitive::from_usize(v.len()).unwrap();
    let sum = sum_square_deviations(v, mu);
    sum / len
}

///  Standard deviation is a measure that is used to quantify the amount of variation or
///  dispersion of a set of data values. (reference)[http://en.wikipedia.org/wiki/Standard_deviation]
pub fn standard_deviation<T>(v: &[T], xbar: Option<T>) -> T
    where T: Float + FromPrimitive
{
    let var = variance(v, xbar);
    var.sqrt()
}

pub fn population_standard_deviation<T>(v: &[T], mu: Option<T>) -> T
    where T: Float + FromPrimitive
{
    let pvar = population_variance(v, mu);
    pvar.sqrt()
}

/// Standard score is a given datum's (signed) number of standard deviations above the mean.
/// (reference)[http://en.wikipedia.org/wiki/Standard_score]
/// Method returns a vector of scores for a vector of inputs. scores[n] is the score of v[n]
pub fn standard_scores<T>(v: &[T]) -> Vec<T> where T: Float + FromPrimitive {
    let mean = mean(&v);
    let standard_deviation = standard_deviation(&v, None);
    let scores: Vec<T> = v.iter().map(|val| (*val - mean)/standard_deviation).collect();
    return scores;
}

#[inline(always)]
fn select_pivot<T>(v: &mut [T]) where T: Copy {
    let idx = rand::random::<usize>() % v.len();
    let tmp = v[0];
    v[0] = v[idx];
    v[idx] = tmp;
}

fn partition<T>(v: &mut [T]) -> usize where T: PartialOrd + Copy {
    select_pivot(v);
    let pivot = v[0];
    let mut i = 0;
    let mut j = 0;
    let end = v.len() - 1;
    while i < end {
        i += 1;
        if v[i] < pivot {
            v[j] = v[i];
            j += 1;
            v[i] = v[j];
        }

    }
    v[j] = pivot;
    j

}

fn quicksort<T>(v: &mut [T]) where T: PartialOrd + Copy {
    if v.len() <= 1 {
        return
    }
    let pivot = partition(v);
    quicksort(&mut v[..pivot]);
    quicksort(&mut v[(pivot+1)..]);
}

// Unit tests for private functions must be in the same module.
#[test]
fn test_qsort_empty() {
    let mut vec: Vec<f64> = vec![];
    quicksort(&mut vec);
    assert_eq!(vec, vec![]);
}

#[test]
fn test_qsort_small() {
    let len = 10;
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len { vec.push(rand::random::<f64>()); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_large() {
    let len = 1_000_000;
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len { vec.push(rand::random::<f64>()); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_sorted() {
    let len = 1_000;
    let mut vec = Vec::with_capacity(len);
    for n in 0..len { vec.push(n); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_reverse_sorted() {
    let len = 1_000;
    let mut vec = Vec::with_capacity(len);
    for n in 0..len { vec.push(len-n); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[cfg(test)]
mod tests {
    extern crate rand;
    extern crate num;

    use super::*;
    use num::Float;

    #[test]
    fn test_mean() {
        let vec = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        assert_eq!(mean(&vec), 1.375);
    }

    #[test]
    fn test_median() {
        let vec = vec![1.0, 3.0];
        assert_eq!(median(&vec), 2.0);
        let vec = vec![1.0, 3.0, 5.0];
        assert_eq!(median(&vec), 3.0);
        let vec = vec![1.0, 3.0, 5.0, 7.0];
        assert_eq!(median(&vec), 4.0);
    }

    #[test]
    fn test_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.428571;
        let epsilon = 1e-6;
        assert!((expected - variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.25;
        let epsilon = 1e-6;
        assert!((expected - population_variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.195229;
        let epsilon = 1e-6;
        assert!((expected - standard_deviation(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.118034;
        let epsilon = 1e-6;
        assert!((expected - population_standard_deviation(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_standard_scores() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        let expected = vec![-1.150407536484354, -0.941242529850835, -0.941242529850835, -0.10458250331675945, 0.10458250331675945, 0.31374750995027834, 1.150407536484354, 1.5687375497513918];
        assert!(expected == standard_scores(&v));
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc;
use std::collections::HashMap;

/// An ActorAddress structure is used, essentially, just as the identifier of an
/// actor for sending messages to it. ActorAddresses can be cheaply cloned and
/// passed around.
#[derive(Clone, Debug)]
pub struct ActorAddress {
    endpoint: mpsc::Sender<Message>
}

/// A MessageType defines a number of standard messages (such as the one to
/// stop an actor) and a Custom type which can be used to send user-defined
/// messages between actors.
///
/// Custom types contain a static str (so basically they're created from a
/// string literal) which can be matched on.
#[derive(Clone, PartialOrd, PartialEq, Ord, Eq, Debug)]
pub enum MessageType {
    /// A message of this type is automatically sent to any actor upon spawning.
    /// If an actor does not need initialization, it can safely ignore the
    /// message.
    Init,
    /// A message of this type will stop and kill the actor receiving it.
    Stop,
    /// This is a custom message type to use for user-defined messages.
    Custom(&'static str)
}

/// This variant type specifies what kind of data can be passed around in
/// messages; we believe it is better to have a well defined variant type rather
/// than something like a Box<Any>. This makes serialization well defined, and
/// the Map variant can serialize complex data structures.
#[derive(Clone, Debug)]
pub enum MessageVariant {
    Void,
    I64(i64),
    U64(u64),
    F64(f64),
    Str(String),
    Map(HashMap<String, MessageVariant>),
    Act(ActorAddress)
}
impl MessageVariant {
    /// Consumes the MessageVariant and converts it to i64 if possible.
    fn as_i64(self) -> Option<i64> {
        match self {
            MessageVariant::I64(x) => Some(x),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to u64 if possible.
    fn as_u64(self) -> Option<u64> {
        match self {
            MessageVariant::U64(x) => Some(x),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to f64 if possible.
    fn as_f64(self) -> Option<f64> {
        match self {
            MessageVariant::F64(x) => Some(x),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to String if possible.
    fn as_str(self) -> Option<String> {
        match self {
            MessageVariant::Str(x) => Some(x),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to a map if possible.
    fn as_map(self) -> Option<HashMap<String, MessageVariant>> {
        match self {
            MessageVariant::Map(m) => Some(m),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to an ActorAddress if
    /// possible.
    fn as_act(self) -> Option<ActorAddress> {
        match self {
            MessageVariant::Act(a) => Some(a),
            _ => None
        }
    }
}
impl From<i64> for MessageVariant {
    fn from(x: i64) -> MessageVariant { MessageVariant::I64(x) }
}
impl From<u64> for MessageVariant {
    fn from(x: u64) -> MessageVariant { MessageVariant::U64(x) }
}
impl From<f64> for MessageVariant {
    fn from(x: f64) -> MessageVariant { MessageVariant::F64(x) }
}
impl From<String> for MessageVariant {
    fn from(x: String) -> MessageVariant { MessageVariant::Str(x) }
}
impl<'a> From<&'a str> for MessageVariant {
    fn from(x: &'a str) -> MessageVariant { MessageVariant::Str(x.to_string()) }
}
impl From<HashMap<String, MessageVariant>> for MessageVariant {
    fn from(x: HashMap<String, MessageVariant>) -> MessageVariant { MessageVariant::Map(x) }
}
impl From<ActorAddress> for MessageVariant {
    fn from(x: ActorAddress) -> MessageVariant { MessageVariant::Act(x) }
}
impl<'a> From<&'a ActorAddress> for MessageVariant {
    fn from(x: &'a ActorAddress) -> MessageVariant { MessageVariant::Act(x.clone()) }
}

/// A Message contains a type, the actor from whom the message comes, and a
/// datum. A Message can be created and sent using a builder pattern.
#[derive(Clone, Debug)]
pub struct Message {
    mt: MessageType,
    sender: ActorAddress,
    datum: MessageVariant
}

/// The builder struct for a Message.
pub struct MessageBuilder {
    mt: MessageType,
    sender: Option<ActorAddress>,
    datum: Option<MessageVariant>
}

impl Message {
    /// Gets the type of the message.
    pub fn get_type(&self) -> &MessageType { &self.mt }
    /// Gets the sender of the message.
    pub fn get_sender(&self) -> &ActorAddress { &self.sender }
    /// Gets the datum of the message.
    pub fn get_datum(&self) -> &MessageVariant { &self.datum }

    /// Initializes a message builder for an Init typed message.
    pub fn init() -> MessageBuilder {
        MessageBuilder {
            mt: MessageType::Init,
            sender: None,
            datum: None,
        }
    }

    /// Initializes a message builder for a Stop typed message.
    pub fn stop() -> MessageBuilder {
        MessageBuilder {
            mt: MessageType::Stop,
            sender: None,
            datum: None,
        }
    }

    /// Initializes a message builder for a Custom typed message.
    pub fn custom(mt: &'static str) -> MessageBuilder {
        MessageBuilder {
            mt: MessageType::Custom(mt),
            sender: None,
            datum: None,
        }
    }
}

impl MessageBuilder {
    /// Specifies the sender of the message.
    pub fn with_sender<'a>(&'a mut self, f: &ActorAddress) -> &'a mut MessageBuilder {
        self.sender = Some(f.clone());
        self
    }

    /// Specifies the datum of the message.
    pub fn with_datum<'a>(&'a mut self, d: MessageVariant) -> &'a mut MessageBuilder {
        self.datum = Some(d);
        self
    }

    /// Specifies an i64 as the datum of the message.
    pub fn with_i64<'a>(&'a mut self, i: i64) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(i))
    }

    /// Specifies an u64 as the datum of the message.
    pub fn with_u64<'a>(&'a mut self, u: u64) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(u))
    }

    /// Specifies an f64 as the datum of the message.
    pub fn with_f64<'a>(&'a mut self, f: f64) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(f))
    }

    /// Specifies a string as the datum of the message.
    pub fn with_str<'a>(&'a mut self, s: &str) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(s.to_string()))
    }

    /// Specifies a map as the datum of the message.
    pub fn with_map<'a>(&'a mut self, m: HashMap<String, MessageVariant>) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(m))
    }

    /// Specifies an actor as the datum of the message.
    pub fn with_act<'a>(&'a mut self, a: &ActorAddress) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(a))
    }

    fn build(&self) -> Message {
        let (fake_tx, _) = std::sync::mpsc::channel();
        Message {
            mt: self.mt.clone(),
            sender: self.sender.clone().unwrap_or(
                ActorAddress { endpoint: fake_tx }), // TODO: FIX. Leaks a broken channel.
            datum: match self.datum {
                None => MessageVariant::Void,
                Some(ref x) => x.clone(),
            }
        }
    }

    /// Builds the Message and sends it to the specified actor.
    ///
    /// This function is in the builder class for stylistic purposes: this
    /// way, it is possible to have nice one-liners.
    ///
    /// `Message::custom("blah").sender(&some_actor).with_i64(123).send_to(&other_actor);`
    ///
    pub fn send_to(&self, to: &ActorAddress) {
        to.endpoint.send(self.build()).unwrap_or(()); // TODO: Error handling.
    }
}

/// This trait represents the interface of any actor implementation.
///
/// Implementing this trait effectively requires to implement the functionality
/// to act upon one single message. The `mecha` library takes care of handling
/// the mailbox and the loop which receives messages.
pub trait Actor {
    /// This function is the meat of the message processing and must be
    /// implemented to implement this trait.
    fn process_message(&mut self, message: Message, myself: &ActorAddress);
}

/// Spawns an actor based on the provided Actor implementor, whose ownership is
/// acquired by the spawned thread. Returns an ActorAddress identifying the
/// spawned actor.
pub fn spawn<T: Actor + Send + 'static>(mut implementor: T) -> ActorAddress {
    let (tx, rx) = mpsc::channel::<Message>();
    let actor = ActorAddress { endpoint: tx.clone() };
    // Put an Init message on the channel immediately.
    Message::init().send_to(&actor);
    // Then spawn another thread.
    thread::spawn(move || {
        let rx_internal = rx;
        let tx_internal = tx;
        let actor_internal = ActorAddress { endpoint: tx_internal };
        loop {
            let rcvd_msg = rx_internal.recv();
            match rcvd_msg {
                Ok(msg) => {
                    let mt = msg.get_type().clone(); // for later
                    // Consume and process the message
                    implementor.process_message(msg, &actor_internal);
                    // Perform extra standard actions
                    match mt {
                        MessageType::Stop => {
                            // Stop this actor.
                            println!("Exiting upon request.");
                            break;
                        },
                        _ => ()
                    }
                },
                Err(_) => {
                    println!("Exiting upon error receiving message!");
                    break;
                }
            }
        }
    });
    actor
}

#[cfg(test)]
mod tests;
<commit_msg>Conversion functions should be public, d'oh!<commit_after>use std::thread;
use std::sync::mpsc;
use std::collections::HashMap;

/// An ActorAddress structure is used, essentially, just as the identifier of an
/// actor for sending messages to it. ActorAddresses can be cheaply cloned and
/// passed around.
#[derive(Clone, Debug)]
pub struct ActorAddress {
    endpoint: mpsc::Sender<Message>
}

/// A MessageType defines a number of standard messages (such as the one to
/// stop an actor) and a Custom type which can be used to send user-defined
/// messages between actors.
///
/// Custom types contain a static str (so basically they're created from a
/// string literal) which can be matched on.
#[derive(Clone, PartialOrd, PartialEq, Ord, Eq, Debug)]
pub enum MessageType {
    /// A message of this type is automatically sent to any actor upon spawning.
    /// If an actor does not need initialization, it can safely ignore the
    /// message.
    Init,
    /// A message of this type will stop and kill the actor receiving it.
    Stop,
    /// This is a custom message type to use for user-defined messages.
    Custom(&'static str)
}

/// This variant type specifies what kind of data can be passed around in
/// messages; we believe it is better to have a well defined variant type rather
/// than something like a Box<Any>. This makes serialization well defined, and
/// the Map variant can serialize complex data structures.
#[derive(Clone, Debug)]
pub enum MessageVariant {
    Void,
    I64(i64),
    U64(u64),
    F64(f64),
    Str(String),
    Map(HashMap<String, MessageVariant>),
    Act(ActorAddress)
}
impl MessageVariant {
    /// Consumes the MessageVariant and converts it to i64 if possible.
    pub fn as_i64(self) -> Option<i64> {
        match self {
            MessageVariant::I64(x) => Some(x),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to u64 if possible.
    pub fn as_u64(self) -> Option<u64> {
        match self {
            MessageVariant::U64(x) => Some(x),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to f64 if possible.
    pub fn as_f64(self) -> Option<f64> {
        match self {
            MessageVariant::F64(x) => Some(x),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to String if possible.
    pub fn as_str(self) -> Option<String> {
        match self {
            MessageVariant::Str(x) => Some(x),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to a map if possible.
    pub fn as_map(self) -> Option<HashMap<String, MessageVariant>> {
        match self {
            MessageVariant::Map(m) => Some(m),
            _ => None
        }
    }
    /// Consumes the MessageVariant and converts it to an ActorAddress if
    /// possible.
    pub fn as_act(self) -> Option<ActorAddress> {
        match self {
            MessageVariant::Act(a) => Some(a),
            _ => None
        }
    }
}
impl From<i64> for MessageVariant {
    fn from(x: i64) -> MessageVariant { MessageVariant::I64(x) }
}
impl From<u64> for MessageVariant {
    fn from(x: u64) -> MessageVariant { MessageVariant::U64(x) }
}
impl From<f64> for MessageVariant {
    fn from(x: f64) -> MessageVariant { MessageVariant::F64(x) }
}
impl From<String> for MessageVariant {
    fn from(x: String) -> MessageVariant { MessageVariant::Str(x) }
}
impl<'a> From<&'a str> for MessageVariant {
    fn from(x: &'a str) -> MessageVariant { MessageVariant::Str(x.to_string()) }
}
impl From<HashMap<String, MessageVariant>> for MessageVariant {
    fn from(x: HashMap<String, MessageVariant>) -> MessageVariant { MessageVariant::Map(x) }
}
impl From<ActorAddress> for MessageVariant {
    fn from(x: ActorAddress) -> MessageVariant { MessageVariant::Act(x) }
}
impl<'a> From<&'a ActorAddress> for MessageVariant {
    fn from(x: &'a ActorAddress) -> MessageVariant { MessageVariant::Act(x.clone()) }
}

/// A Message contains a type, the actor from whom the message comes, and a
/// datum. A Message can be created and sent using a builder pattern.
#[derive(Clone, Debug)]
pub struct Message {
    mt: MessageType,
    sender: ActorAddress,
    datum: MessageVariant
}

/// The builder struct for a Message.
pub struct MessageBuilder {
    mt: MessageType,
    sender: Option<ActorAddress>,
    datum: Option<MessageVariant>
}

impl Message {
    /// Gets the type of the message.
    pub fn get_type(&self) -> &MessageType { &self.mt }
    /// Gets the sender of the message.
    pub fn get_sender(&self) -> &ActorAddress { &self.sender }
    /// Gets the datum of the message.
    pub fn get_datum(&self) -> &MessageVariant { &self.datum }

    /// Initializes a message builder for an Init typed message.
    pub fn init() -> MessageBuilder {
        MessageBuilder {
            mt: MessageType::Init,
            sender: None,
            datum: None,
        }
    }

    /// Initializes a message builder for a Stop typed message.
    pub fn stop() -> MessageBuilder {
        MessageBuilder {
            mt: MessageType::Stop,
            sender: None,
            datum: None,
        }
    }

    /// Initializes a message builder for a Custom typed message.
    pub fn custom(mt: &'static str) -> MessageBuilder {
        MessageBuilder {
            mt: MessageType::Custom(mt),
            sender: None,
            datum: None,
        }
    }
}

impl MessageBuilder {
    /// Specifies the sender of the message.
    pub fn with_sender<'a>(&'a mut self, f: &ActorAddress) -> &'a mut MessageBuilder {
        self.sender = Some(f.clone());
        self
    }

    /// Specifies the datum of the message.
    pub fn with_datum<'a>(&'a mut self, d: MessageVariant) -> &'a mut MessageBuilder {
        self.datum = Some(d);
        self
    }

    /// Specifies an i64 as the datum of the message.
    pub fn with_i64<'a>(&'a mut self, i: i64) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(i))
    }

    /// Specifies an u64 as the datum of the message.
    pub fn with_u64<'a>(&'a mut self, u: u64) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(u))
    }

    /// Specifies an f64 as the datum of the message.
    pub fn with_f64<'a>(&'a mut self, f: f64) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(f))
    }

    /// Specifies a string as the datum of the message.
    pub fn with_str<'a>(&'a mut self, s: &str) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(s.to_string()))
    }

    /// Specifies a map as the datum of the message.
    pub fn with_map<'a>(&'a mut self, m: HashMap<String, MessageVariant>) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(m))
    }

    /// Specifies an actor as the datum of the message.
    pub fn with_act<'a>(&'a mut self, a: &ActorAddress) -> &'a mut MessageBuilder {
        self.with_datum(MessageVariant::from(a))
    }

    fn build(&self) -> Message {
        let (fake_tx, _) = std::sync::mpsc::channel();
        Message {
            mt: self.mt.clone(),
            sender: self.sender.clone().unwrap_or(
                ActorAddress { endpoint: fake_tx }), // TODO: FIX. Leaks a broken channel.
            datum: match self.datum {
                None => MessageVariant::Void,
                Some(ref x) => x.clone(),
            }
        }
    }

    /// Builds the Message and sends it to the specified actor.
    ///
    /// This function is in the builder class for stylistic purposes: this
    /// way, it is possible to have nice one-liners.
    ///
    /// `Message::custom("blah").sender(&some_actor).with_i64(123).send_to(&other_actor);`
    ///
    pub fn send_to(&self, to: &ActorAddress) {
        to.endpoint.send(self.build()).unwrap_or(()); // TODO: Error handling.
    }
}

/// This trait represents the interface of any actor implementation.
///
/// Implementing this trait effectively requires to implement the functionality
/// to act upon one single message. The `mecha` library takes care of handling
/// the mailbox and the loop which receives messages.
pub trait Actor {
    /// This function is the meat of the message processing and must be
    /// implemented to implement this trait.
    fn process_message(&mut self, message: Message, myself: &ActorAddress);
}

/// Spawns an actor based on the provided Actor implementor, whose ownership is
/// acquired by the spawned thread. Returns an ActorAddress identifying the
/// spawned actor.
pub fn spawn<T: Actor + Send + 'static>(mut implementor: T) -> ActorAddress {
    let (tx, rx) = mpsc::channel::<Message>();
    let actor = ActorAddress { endpoint: tx.clone() };
    // Put an Init message on the channel immediately.
    Message::init().send_to(&actor);
    // Then spawn another thread.
    thread::spawn(move || {
        let rx_internal = rx;
        let tx_internal = tx;
        let actor_internal = ActorAddress { endpoint: tx_internal };
        loop {
            let rcvd_msg = rx_internal.recv();
            match rcvd_msg {
                Ok(msg) => {
                    let mt = msg.get_type().clone(); // for later
                    // Consume and process the message
                    implementor.process_message(msg, &actor_internal);
                    // Perform extra standard actions
                    match mt {
                        MessageType::Stop => {
                            // Stop this actor.
                            println!("Exiting upon request.");
                            break;
                        },
                        _ => ()
                    }
                },
                Err(_) => {
                    println!("Exiting upon error receiving message!");
                    break;
                }
            }
        }
    });
    actor
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>#![feature(collections, core, convert)]
#![allow(dead_code)]

use std::cmp;
use std::fmt;
use std::ops::{Deref};
use std::num::Int;

#[derive(Copy, Clone, Eq, Debug, PartialEq)]
/// Describes relations between two version vectors
enum Ordering {
    Less,
    Equal,
    Greater,
    /// vectors have at least 1 concurrent update
    Concurrent
}

impl Ordering {
    #[inline]
    fn eat(&mut self, order: cmp::Ordering) {
        match (order, *self) {
            (cmp::Ordering::Less, Ordering::Equal) => *self = Ordering::Less,
            (cmp::Ordering::Greater, Ordering::Equal) => *self = Ordering::Greater,
            (cmp::Ordering::Greater, Ordering::Less) |
            (cmp::Ordering::Less, Ordering::Greater) => *self = Ordering::Concurrent,
            _ => ()
        }
    }
}

/// Represents version vector.
///
/// Currently inner implementation is a sorted vector
struct VersionVec<I, T> {
    inner: Vec<(I, T)>
}

impl<I: fmt::Debug, T: fmt::Debug> fmt::Debug for VersionVec<I, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&format!("Versions: {:?}", self.inner))
    }
}

impl<I: Clone, T: Clone> Clone for VersionVec<I, T> {
    fn clone(&self) -> VersionVec<I, T> {
        VersionVec {
            inner: self.inner.clone()
        }
    }
}

impl<I, T> VersionVec<I, T> where I: Ord + Copy + Clone, T: Ord + Copy + Clone + Int {
    /// Creates a new empty version vector
    pub fn new() -> VersionVec<I, T> {
        VersionVec {
            inner: vec![]
        }
    }

    /// Constructs version vector from tuples (id, version)
    pub fn from_vec(v: Vec<(I, T)>) -> VersionVec<I, T> {
        let mut v = v;
        v.sort_by(|a, b| a.0.cmp(&b.0));
        VersionVec {
            inner: v
        }
    }

    /// Creates a new copy of self, merges other into that copy and returns it
    pub fn merged(&self, other: &VersionVec<I, T>) -> VersionVec<I, T> {
        let mut result = self.clone();
        result.merge(other);
        result
    }

    /// Returns the value of counter with id if it exists
    pub fn get(&self, id: I) -> Option<T> {
        for i in &self.inner {
            if i.0 == id {
                return Some(i.1)
            } else if i.0 > id {
                return None
            }
        }

        None
    }

    /// Bump (increase) counter for specified id.
    /// If id is missing, adds a new and sets value to 1
    pub fn bump_for(&mut self, id: I) {
        let idx = self.inner.iter().position(|value| value.0 >= id);
        match idx {
            None => self.inner.push((id, T::one())),
            Some(idx) => {
                if self.inner[idx].0 == id {
                    self.inner[idx].1 = self.inner[idx].1 + T::one()
                } else {
                    self.inner.insert(idx, (id, T::one()))
                }
            }
        }
    }

    /// Merge in-place
    pub fn merge(&mut self, other: &VersionVec<I, T>) {
        let mut self_idx = 0;
        let mut other_idx = 0;

        loop {
            if self_idx >= self.inner.len() {
                self.inner.push_all(&other.inner[other_idx..]);
                break
            }

            if other_idx >= other.inner.len() {
                break
            }

            let left = self.inner[self_idx];
            let right = other.inner[other_idx];

            if left.0 == right.0 {
                self.inner[self_idx].1 = cmp::max(left.1, right.1);
                self_idx += 1;
                other_idx += 1;
            } else {
                if left.0 < right.0 {
                    self_idx += 1
                } else {
                    self.inner.insert(self_idx, right);
                    self_idx += 1;
                    other_idx += 1;
                }
            }
        }
    }

    /// Compares 2 version vectors
    pub fn cmp(&self, other: &VersionVec<I, T>) -> Ordering {
        let mut self_idx = 0;
        let mut other_idx = 0;
        let mut result = Ordering::Equal;

        loop {
            if self_idx >= self.inner.len() {
                if other_idx == other.inner.len() {
                    // both exhausted
                    return result
                } else {
                    // other is not exhausted, so self is less if there is at least 1 non-zero
                    if other.inner[other_idx..].iter().position(|v| v.1 > T::zero()).is_some() {
                        result.eat(cmp::Ordering::Less);
                    }
                    return result
                }
            }

            if other_idx >= other.inner.len() {
                // since we've got here self is not exhausted yet
                // => self is greater if there is at least 1 non-zero
                if self.inner[self_idx..].iter().position(|v| v.1 > T::zero()).is_some() {
                    result.eat(cmp::Ordering::Greater);
                }
                return result
            }

            let left = self.inner[self_idx];
            let right = other.inner[other_idx];

            let id_cmp = left.0.cmp(&right.0);
            let deltas = match id_cmp {
                cmp::Ordering::Less => (1, 0, if left.1 != T::zero() {cmp::Ordering::Greater} else {cmp::Ordering::Equal}),
                cmp::Ordering::Greater => (0, 1, if right.1 != T::zero() {cmp::Ordering::Less} else {cmp::Ordering::Equal}),
                cmp::Ordering::Equal => (1, 1, left.1.cmp(&right.1))
            };

            self_idx += deltas.0;
            other_idx += deltas.1;
            if deltas.2 != cmp::Ordering::Equal {
                result.eat(deltas.2);
            }

            // Ouch, there is a conflict, nothing to catch here
            if result == Ordering::Concurrent {
                return result;
            }
        }
    }
}

/*
impl<I, T> Index<RangeFull> for VersionVec<I, T> {
    type Output = [(I, T)];

    fn index<'a>(&'a self, _index: &RangeFull) -> &'a [(I, T)] {
        &self.inner
    }
}
*/

/*
impl<I, T> AsSlice<(I, T)> for VersionVec<I, T> {
    fn as_slice(&self) -> &[(I, T)] {
        &self.inner
    }
}
*/

// FIXME: it actually should be convert::AsRef but since I'm stick to
// an old version, Deref works much better for now
impl<I, T> Deref for VersionVec<I, T> {
    type Target = [(I, T)];

    fn deref<'a>(&'a self) -> &'a [(I, T)] {
        &self.inner
    }
}

#[cfg(test)]
mod test {
    use super::{Ordering, VersionVec};

    type VecTemplate = Vec<(usize, usize)>;

    #[test]
    fn get_counter() {
        let v = VersionVec::from_vec(vec![(1, 10), (2, 20), (3, 30)]);

        assert_eq!(v.get(1), Some(10));
        assert_eq!(v.get(5), None);
        assert_eq!(v.get(2), Some(20));
        assert_eq!(v.get(3), Some(30));
        assert_eq!(v.get(6), None);
    }

    #[test]
    fn bump() {
        let mut v = VersionVec::from_vec(vec![(1, 10), (2, 20), (3, 30)]);

        v.bump_for(1);
        assert_eq!(&*v, [(1, 11), (2, 20), (3, 30)]);

        v.bump_for(0);
        assert_eq!(&*v, [(0, 1), (1, 11), (2, 20), (3, 30)]);

        v.bump_for(10);
        assert_eq!(&*v, [(0, 1), (1, 11), (2, 20), (3, 30), (10, 1)]);
    }

    #[test]
    fn comparisons() {
        // Taken from synching test cases, except concurrent and nil cases
        // https://github.com/syncthing/protocol/blob/master/vector_compare_test.go
        //
        // Original version vectors do have a single concurrent state
        use Ordering::*;

        let test_cases: Vec<(Ordering, VecTemplate, VecTemplate)> = vec![
            (Equal, vec![], vec![]),
            (Equal, vec![], vec![(10, 0)]),
            (Equal, vec![(10, 0)], vec![]),
            (Equal, vec![(10, 0)], vec![(20, 0)]),
            (Equal, vec![(10, 1), (20, 2)], vec![(10, 1), (20, 2)]),
            (Greater, vec![(1, 10)], vec![]),
            (Greater, vec![(1, 10)], vec![(1, 0)]),
            (Greater, vec![(1, 10)], vec![(1, 8)]),
            (Greater, vec![(1, 20), (20, 50)], vec![(1, 10), (20, 20)]),
            (Greater, vec![(1, 10), (20, 50)], vec![(1, 10), (20, 20)]),
            (Less, vec![], vec![(1, 10)]),
            (Less, vec![(1, 0)], vec![(1, 10)]),
            (Less, vec![(1, 8)], vec![(1, 10)]),
            (Less, vec![(1, 8), (2, 20)], vec![(1, 10), (2, 20)]),
            (Less, vec![(1, 8), (2, 20)], vec![(1, 8), (2, 50)]),
            (Concurrent, vec![(1, 10)], vec![(2, 22)]),
            (Concurrent, vec![(1, 10), (2, 20)], vec![(1, 8), (2, 22)]),
            ];

        for case in test_cases {
            let v1 = VersionVec::from_vec(case.1);
            let v2 = VersionVec::from_vec(case.2);

            let res = v1.cmp(&v2);
            assert!(res == case.0, "expected: {:?}, got {:?}, left {:?}, right {:?}", case.0, res, v1, v2);
        }
    }

    #[test]
    fn merge() {
        let test_cases: Vec<(VecTemplate, VecTemplate, VecTemplate)> = vec![
            (vec![], vec![], vec![]),
            (vec![(1, 10), (2, 20)], vec![(1, 10), (2, 20)], vec![(1, 10), (2, 20)]),
            (vec![], vec![(1, 10)], vec![(1, 10)]),
            (vec![(1, 10)], vec![(1, 10), (2, 20)], vec![(1, 10), (2, 20)]),
            (vec![(1, 10)], vec![(2, 20)], vec![(1, 10), (2, 20)]),
            (vec![(1, 10), (4, 40)], vec![(1, 10), (2, 20), (4, 40)], vec![(1, 10), (2, 20), (4, 40)]),
            (vec![(1, 10), (2, 40)], vec![(1, 20), (2, 20)], vec![(1, 20), (2, 40)]),
            (vec![(10, 1), (20, 2), (30, 1)], vec![(5, 1), (10, 2), (15, 1), (20, 1), (25, 1), (35, 1)],
             vec![(5, 1), (10, 2), (15, 1), (20, 2), (25, 1), (30, 1), (35, 1)])
            ];

        for case in test_cases {
            let v1 = VersionVec::from_vec(case.0);
            let v2 = VersionVec::from_vec(case.1);
            let merged = v1.merged(&v2);

            assert_eq!(&*merged, case.2.as_slice());
        }
    }
}
<commit_msg>Export VersionVec and Ordering<commit_after>#![feature(collections, core, convert)]
#![allow(dead_code)]

use std::cmp;
use std::fmt;
use std::ops::{Deref};
use std::num::Int;

#[derive(Copy, Clone, Eq, Debug, PartialEq)]
/// Describes relations between two version vectors
pub enum Ordering {
    Less,
    Equal,
    Greater,
    /// vectors have at least 1 concurrent update
    Concurrent
}

impl Ordering {
    #[inline]
    fn eat(&mut self, order: cmp::Ordering) {
        match (order, *self) {
            (cmp::Ordering::Less, Ordering::Equal) => *self = Ordering::Less,
            (cmp::Ordering::Greater, Ordering::Equal) => *self = Ordering::Greater,
            (cmp::Ordering::Greater, Ordering::Less) |
            (cmp::Ordering::Less, Ordering::Greater) => *self = Ordering::Concurrent,
            _ => ()
        }
    }
}

/// Represents version vector.
///
/// Currently inner implementation is a sorted vector
pub struct VersionVec<I, T> {
    inner: Vec<(I, T)>
}

impl<I: fmt::Debug, T: fmt::Debug> fmt::Debug for VersionVec<I, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&format!("Versions: {:?}", self.inner))
    }
}

impl<I: Clone, T: Clone> Clone for VersionVec<I, T> {
    fn clone(&self) -> VersionVec<I, T> {
        VersionVec {
            inner: self.inner.clone()
        }
    }
}

impl<I, T> VersionVec<I, T> where I: Ord + Copy + Clone, T: Ord + Copy + Clone + Int {
    /// Creates a new empty version vector
    pub fn new() -> VersionVec<I, T> {
        VersionVec {
            inner: vec![]
        }
    }

    /// Constructs version vector from tuples (id, version)
    pub fn from_vec(v: Vec<(I, T)>) -> VersionVec<I, T> {
        let mut v = v;
        v.sort_by(|a, b| a.0.cmp(&b.0));
        VersionVec {
            inner: v
        }
    }

    /// Creates a new copy of self, merges other into that copy and returns it
    pub fn merged(&self, other: &VersionVec<I, T>) -> VersionVec<I, T> {
        let mut result = self.clone();
        result.merge(other);
        result
    }

    /// Returns the value of counter with id if it exists
    pub fn get(&self, id: I) -> Option<T> {
        for i in &self.inner {
            if i.0 == id {
                return Some(i.1)
            } else if i.0 > id {
                return None
            }
        }

        None
    }

    /// Bump (increase) counter for specified id.
    /// If id is missing, adds a new and sets value to 1
    pub fn bump_for(&mut self, id: I) {
        let idx = self.inner.iter().position(|value| value.0 >= id);
        match idx {
            None => self.inner.push((id, T::one())),
            Some(idx) => {
                if self.inner[idx].0 == id {
                    self.inner[idx].1 = self.inner[idx].1 + T::one()
                } else {
                    self.inner.insert(idx, (id, T::one()))
                }
            }
        }
    }

    /// Merge in-place
    pub fn merge(&mut self, other: &VersionVec<I, T>) {
        let mut self_idx = 0;
        let mut other_idx = 0;

        loop {
            if self_idx >= self.inner.len() {
                self.inner.push_all(&other.inner[other_idx..]);
                break
            }

            if other_idx >= other.inner.len() {
                break
            }

            let left = self.inner[self_idx];
            let right = other.inner[other_idx];

            if left.0 == right.0 {
                self.inner[self_idx].1 = cmp::max(left.1, right.1);
                self_idx += 1;
                other_idx += 1;
            } else {
                if left.0 < right.0 {
                    self_idx += 1
                } else {
                    self.inner.insert(self_idx, right);
                    self_idx += 1;
                    other_idx += 1;
                }
            }
        }
    }

    /// Compares 2 version vectors
    pub fn cmp(&self, other: &VersionVec<I, T>) -> Ordering {
        let mut self_idx = 0;
        let mut other_idx = 0;
        let mut result = Ordering::Equal;

        loop {
            if self_idx >= self.inner.len() {
                if other_idx == other.inner.len() {
                    // both exhausted
                    return result
                } else {
                    // other is not exhausted, so self is less if there is at least 1 non-zero
                    if other.inner[other_idx..].iter().position(|v| v.1 > T::zero()).is_some() {
                        result.eat(cmp::Ordering::Less);
                    }
                    return result
                }
            }

            if other_idx >= other.inner.len() {
                // since we've got here self is not exhausted yet
                // => self is greater if there is at least 1 non-zero
                if self.inner[self_idx..].iter().position(|v| v.1 > T::zero()).is_some() {
                    result.eat(cmp::Ordering::Greater);
                }
                return result
            }

            let left = self.inner[self_idx];
            let right = other.inner[other_idx];

            let id_cmp = left.0.cmp(&right.0);
            let deltas = match id_cmp {
                cmp::Ordering::Less => (1, 0, if left.1 != T::zero() {cmp::Ordering::Greater} else {cmp::Ordering::Equal}),
                cmp::Ordering::Greater => (0, 1, if right.1 != T::zero() {cmp::Ordering::Less} else {cmp::Ordering::Equal}),
                cmp::Ordering::Equal => (1, 1, left.1.cmp(&right.1))
            };

            self_idx += deltas.0;
            other_idx += deltas.1;
            if deltas.2 != cmp::Ordering::Equal {
                result.eat(deltas.2);
            }

            // Ouch, there is a conflict, nothing to catch here
            if result == Ordering::Concurrent {
                return result;
            }
        }
    }
}

/*
impl<I, T> Index<RangeFull> for VersionVec<I, T> {
    type Output = [(I, T)];

    fn index<'a>(&'a self, _index: &RangeFull) -> &'a [(I, T)] {
        &self.inner
    }
}
*/

/*
impl<I, T> AsSlice<(I, T)> for VersionVec<I, T> {
    fn as_slice(&self) -> &[(I, T)] {
        &self.inner
    }
}
*/

// FIXME: it actually should be convert::AsRef but since I'm stick to
// an old version, Deref works much better for now
impl<I, T> Deref for VersionVec<I, T> {
    type Target = [(I, T)];

    fn deref<'a>(&'a self) -> &'a [(I, T)] {
        &self.inner
    }
}

#[cfg(test)]
mod test {
    use super::{Ordering, VersionVec};

    type VecTemplate = Vec<(usize, usize)>;

    #[test]
    fn get_counter() {
        let v = VersionVec::from_vec(vec![(1, 10), (2, 20), (3, 30)]);

        assert_eq!(v.get(1), Some(10));
        assert_eq!(v.get(5), None);
        assert_eq!(v.get(2), Some(20));
        assert_eq!(v.get(3), Some(30));
        assert_eq!(v.get(6), None);
    }

    #[test]
    fn bump() {
        let mut v = VersionVec::from_vec(vec![(1, 10), (2, 20), (3, 30)]);

        v.bump_for(1);
        assert_eq!(&*v, [(1, 11), (2, 20), (3, 30)]);

        v.bump_for(0);
        assert_eq!(&*v, [(0, 1), (1, 11), (2, 20), (3, 30)]);

        v.bump_for(10);
        assert_eq!(&*v, [(0, 1), (1, 11), (2, 20), (3, 30), (10, 1)]);
    }

    #[test]
    fn comparisons() {
        // Taken from synching test cases, except concurrent and nil cases
        // https://github.com/syncthing/protocol/blob/master/vector_compare_test.go
        //
        // Original version vectors do have a single concurrent state
        use Ordering::*;

        let test_cases: Vec<(Ordering, VecTemplate, VecTemplate)> = vec![
            (Equal, vec![], vec![]),
            (Equal, vec![], vec![(10, 0)]),
            (Equal, vec![(10, 0)], vec![]),
            (Equal, vec![(10, 0)], vec![(20, 0)]),
            (Equal, vec![(10, 1), (20, 2)], vec![(10, 1), (20, 2)]),
            (Greater, vec![(1, 10)], vec![]),
            (Greater, vec![(1, 10)], vec![(1, 0)]),
            (Greater, vec![(1, 10)], vec![(1, 8)]),
            (Greater, vec![(1, 20), (20, 50)], vec![(1, 10), (20, 20)]),
            (Greater, vec![(1, 10), (20, 50)], vec![(1, 10), (20, 20)]),
            (Less, vec![], vec![(1, 10)]),
            (Less, vec![(1, 0)], vec![(1, 10)]),
            (Less, vec![(1, 8)], vec![(1, 10)]),
            (Less, vec![(1, 8), (2, 20)], vec![(1, 10), (2, 20)]),
            (Less, vec![(1, 8), (2, 20)], vec![(1, 8), (2, 50)]),
            (Concurrent, vec![(1, 10)], vec![(2, 22)]),
            (Concurrent, vec![(1, 10), (2, 20)], vec![(1, 8), (2, 22)]),
            ];

        for case in test_cases {
            let v1 = VersionVec::from_vec(case.1);
            let v2 = VersionVec::from_vec(case.2);

            let res = v1.cmp(&v2);
            assert!(res == case.0, "expected: {:?}, got {:?}, left {:?}, right {:?}", case.0, res, v1, v2);
        }
    }

    #[test]
    fn merge() {
        let test_cases: Vec<(VecTemplate, VecTemplate, VecTemplate)> = vec![
            (vec![], vec![], vec![]),
            (vec![(1, 10), (2, 20)], vec![(1, 10), (2, 20)], vec![(1, 10), (2, 20)]),
            (vec![], vec![(1, 10)], vec![(1, 10)]),
            (vec![(1, 10)], vec![(1, 10), (2, 20)], vec![(1, 10), (2, 20)]),
            (vec![(1, 10)], vec![(2, 20)], vec![(1, 10), (2, 20)]),
            (vec![(1, 10), (4, 40)], vec![(1, 10), (2, 20), (4, 40)], vec![(1, 10), (2, 20), (4, 40)]),
            (vec![(1, 10), (2, 40)], vec![(1, 20), (2, 20)], vec![(1, 20), (2, 40)]),
            (vec![(10, 1), (20, 2), (30, 1)], vec![(5, 1), (10, 2), (15, 1), (20, 1), (25, 1), (35, 1)],
             vec![(5, 1), (10, 2), (15, 1), (20, 2), (25, 1), (30, 1), (35, 1)])
            ];

        for case in test_cases {
            let v1 = VersionVec::from_vec(case.0);
            let v2 = VersionVec::from_vec(case.1);
            let merged = v1.merged(&v2);

            assert_eq!(&*merged, case.2.as_slice());
        }
    }
}
<|endoftext|>