<commit_before>use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::{Machine, Log, Context,
                    Account, Storage, AccountCommitment,
                    BlockHeader};

use serde_json::Value;
use std::collections::HashMap;
use std::str::FromStr;

pub struct JSONBlock {
    codes: HashMap<Address, Vec<u8>>,
    balances: HashMap<Address, U256>,
    storages: HashMap<Address, HashMap<M256, M256>>,
    nonces: HashMap<Address, M256>,

    coinbase: Address,
    timestamp: M256,
    number: M256,
    difficulty: M256,
    gas_limit: Gas,

    logs: Vec<Log>,
}

static EMPTY: [u8; 0] = [];

impl JSONBlock {
    pub fn block_header(&self) -> BlockHeader {
        BlockHeader {
            coinbase: self.coinbase,
            timestamp: self.timestamp,
            number: self.number,
            difficulty: self.difficulty,
            gas_limit: self.gas_limit,
        }
    }

    pub fn request_account(&self, address: Address) -> AccountCommitment {
        let balance = self.balance(address);
        let code = self.account_code(address);
        let nonce = self.account_nonce(address);

        AccountCommitment::Full {
            address: address,
            balance: balance,
            code: code.into(),
            nonce: nonce
        }
    }

    pub fn request_account_storage(&self, address: Address, index: M256) -> AccountCommitment {
        let hashmap_default = HashMap::new();
        let storage = self.storages.get(&address).unwrap_or(&hashmap_default);
        let value = match storage.get(&index) {
            Some(val) => *val,
            None => M256::zero(),
        };

        AccountCommitment::Storage {
            address: address,
            index: index,
            value: value,
        }
    }

    pub fn request_account_code(&self, address: Address) -> AccountCommitment {
        let default = Vec::new();
        let code = self.codes.get(&address).unwrap_or(&default);

        AccountCommitment::Code {
            address: address,
            code: code.clone(),
        }
    }

    pub fn apply_account(&mut self, account: Account) {
        match account {
            Account::Full {
                address: address,
                balance: balance,
                changing_storage: changing_storage,
                code: code,
                nonce: nonce,
            } => {
                self.set_balance(address, balance);
                self.set_account_code(address, code.as_slice());
                if !self.storages.contains_key(&address) {
                    self.storages.insert(address, HashMap::new());
                }
                let changing_storage: HashMap<M256, M256> = changing_storage.into();
                for (key, value) in changing_storage {
                    self.storages.get_mut(&address).unwrap().insert(key, value);
                }
                self.set_account_nonce(address, nonce);
            },
            Account::Create {
                address: address,
                balance: balance,
                storage: storage,
                code: code,
                nonce: nonce,
            } => {
                self.set_balance(address, balance);
                self.set_account_code(address, code.as_slice());
                self.storages.insert(address, storage.into());
                self.set_account_nonce(address, nonce);
            },
            Account::Remove(address) => {
                self.set_balance(address, U256::zero());
                self.set_account_code(address, Vec::new().as_slice());
                self.storages.insert(address, HashMap::new());
                self.set_account_nonce(address, M256::zero());
            },
            Account::IncreaseBalance(address, topup) => {
                let balance = self.balance(address);
                self.set_balance(address, balance + topup);
            },
            Account::DecreaseBalance(address, withdraw) => {
                let balance = self.balance(address);
                self.set_balance(address, balance - withdraw);
            },
        }
    }

    pub fn apply_log(&mut self, log: Log) {
        self.logs.push(log);
    }

    pub fn coinbase(&self) -> Address {
        self.coinbase
    }

    pub fn timestamp(&self) -> M256 {
        self.timestamp
    }

    pub fn number(&self) -> M256 {
        self.number
    }

    pub fn difficulty(&self) -> M256 {
        self.difficulty
    }

    pub fn gas_limit(&self) -> Gas {
        self.gas_limit
    }

    pub fn account_nonce(&self, address: Address) -> M256 {
        self.nonces.get(&address).map_or(M256::zero(), |s| (*s).into())
    }

    pub fn set_account_nonce(&mut self, address: Address, nonce: M256) {
        self.nonces.insert(address, nonce);
    }

    pub fn account_code(&self, address: Address) -> &[u8] {
        self.codes.get(&address).map_or(EMPTY.as_ref(), |s| s.as_ref())
    }

    pub fn set_account_code(&mut self, address: Address, code: &[u8]) {
        self.codes.insert(address, code.into());
    }

    pub fn balance(&self, address: Address) -> U256 {
        self.balances.get(&address).map_or(U256::zero(), |s| (*s).into())
    }

    pub fn set_balance(&mut self, address: Address, balance: U256) {
        self.balances.insert(address, balance);
    }

    pub fn account_storage(&self, address: Address, index: M256) -> M256 {
        match self.storages.get(&address) {
            None => M256::zero(),
            Some(ref ve) => {
                match ve.get(&index) {
                    Some(&v) => v,
                    None => M256::zero()
                }
            }
        }
    }

    pub fn set_account_storage(&mut self, address: Address, index: M256, val: M256) {
        if self.storages.get(&address).is_none() {
            self.storages.insert(address, HashMap::new());
        }

        let v = self.storages.get_mut(&address).unwrap();
        v.insert(index, val);
    }

    pub fn find_log(&self, address: Address, data: &[u8], topics: &[M256]) -> bool {
        for log in &self.logs {
            if log.address == address && log.data.as_slice() == data && log.topics.as_slice() == topics {
                return true;
            }
        }
        return false;
    }
}

pub fn create_block(v: &Value) -> JSONBlock {
    let mut block = {
        let env = &v["env"];

        let current_coinbase = env["currentCoinbase"].as_str().unwrap();
        let current_difficulty = env["currentDifficulty"].as_str().unwrap();
        let current_gas_limit = env["currentGasLimit"].as_str().unwrap();
        let current_number = env["currentNumber"].as_str().unwrap();
        let current_timestamp = env["currentTimestamp"].as_str().unwrap();

        JSONBlock {
            balances: HashMap::new(),
            storages: HashMap::new(),
            codes: HashMap::new(),
            nonces: HashMap::new(),

            coinbase: Address::from_str(current_coinbase).unwrap(),
            difficulty: M256::from_str(current_difficulty).unwrap(),
            gas_limit: Gas::from_str(current_gas_limit).unwrap(),
            number: M256::from_str(current_number).unwrap(),
            timestamp: M256::from_str(current_timestamp).unwrap(),

            logs: Vec::new(),
        }
    };

    let ref pre_addresses = v["pre"];

    for (address, data) in pre_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();

        block.set_account_code(address, code.as_ref());
        block.set_balance(address, balance);

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            block.set_account_storage(address, index, value);
        }
    }

    block
}

pub fn create_context(v: &Value) -> Context {
    let address = Address::from_str(v["exec"]["address"].as_str().unwrap()).unwrap();
    let caller = Address::from_str(v["exec"]["caller"].as_str().unwrap()).unwrap();
    let code = read_hex(v["exec"]["code"].as_str().unwrap()).unwrap();
    let data = read_hex(v["exec"]["data"].as_str().unwrap()).unwrap();
    let gas = Gas::from_str(v["exec"]["gas"].as_str().unwrap()).unwrap();
    let gas_price = Gas::from_str(v["exec"]["gasPrice"].as_str().unwrap()).unwrap();
    let origin = Address::from_str(v["exec"]["origin"].as_str().unwrap()).unwrap();
    let value = U256::from_str(v["exec"]["value"].as_str().unwrap()).unwrap();

    Context {
        address: address,
        caller: caller,
        code: code,
        data: data,
        gas_limit: gas,
        gas_price: gas_price,
        origin: origin,
        value: value,
    }
}
<commit_msg>Problem: cargo test failed<commit_after>use sputnikvm::{Gas, M256, U256, Address, read_hex};
use sputnikvm::vm::{Machine, Log, Context,
                    Account, Storage, AccountCommitment,
                    BlockHeader};

use serde_json::Value;
use std::collections::HashMap;
use std::str::FromStr;

pub struct JSONBlock {
    codes: HashMap<Address, Vec<u8>>,
    balances: HashMap<Address, U256>,
    storages: HashMap<Address, HashMap<M256, M256>>,
    nonces: HashMap<Address, M256>,

    coinbase: Address,
    timestamp: M256,
    number: M256,
    difficulty: M256,
    gas_limit: Gas,

    logs: Vec<Log>,
}

static EMPTY: [u8; 0] = [];

impl JSONBlock {
    pub fn block_header(&self) -> BlockHeader {
        BlockHeader {
            coinbase: self.coinbase,
            timestamp: self.timestamp,
            number: self.number,
            difficulty: self.difficulty,
            gas_limit: self.gas_limit,
        }
    }

    pub fn request_account(&self, address: Address) -> AccountCommitment {
        let balance = self.balance(address);
        let code = self.account_code(address);
        let nonce = self.account_nonce(address);

        AccountCommitment::Full {
            address: address,
            balance: balance,
            code: code.into(),
            nonce: nonce
        }
    }

    pub fn request_account_storage(&self, address: Address, index: M256) -> AccountCommitment {
        let hashmap_default = HashMap::new();
        let storage = self.storages.get(&address).unwrap_or(&hashmap_default);
        let value = match storage.get(&index) {
            Some(val) => *val,
            None => M256::zero(),
        };

        AccountCommitment::Storage {
            address: address,
            index: index,
            value: value,
        }
    }

    pub fn request_account_code(&self, address: Address) -> AccountCommitment {
        let default = Vec::new();
        let code = self.codes.get(&address).unwrap_or(&default);

        AccountCommitment::Code {
            address: address,
            code: code.clone(),
        }
    }

    pub fn apply_account(&mut self, account: Account) {
        match account {
            Account::Full {
                address: address,
                balance: balance,
                changing_storage: changing_storage,
                code: code,
                nonce: nonce,
            } => {
                self.set_balance(address, balance);
                self.set_account_code(address, code.as_slice());
                if !self.storages.contains_key(&address) {
                    self.storages.insert(address, HashMap::new());
                }
                let changing_storage: HashMap<M256, M256> = changing_storage.into();
                for (key, value) in changing_storage {
                    self.storages.get_mut(&address).unwrap().insert(key, value);
                }
                self.set_account_nonce(address, nonce);
            },
            Account::Create {
                address: address,
                balance: balance,
                storage: storage,
                code: code,
                nonce: nonce,
            } => {
                self.set_balance(address, balance);
                self.set_account_code(address, code.as_slice());
                self.storages.insert(address, storage.into());
                self.set_account_nonce(address, nonce);
            },
            Account::Remove(address) => {
                self.set_balance(address, U256::zero());
                self.set_account_code(address, Vec::new().as_slice());
                self.storages.insert(address, HashMap::new());
                self.set_account_nonce(address, M256::zero());
            },
            Account::IncreaseBalance(address, topup) => {
                let balance = self.balance(address);
                self.set_balance(address, balance + topup);
            },
            Account::DecreaseBalance(address, withdraw) => {
                let balance = self.balance(address);
                self.set_balance(address, balance - withdraw);
            },
        }
    }

    pub fn apply_log(&mut self, log: Log) {
        self.logs.push(log);
    }

    pub fn coinbase(&self) -> Address {
        self.coinbase
    }

    pub fn timestamp(&self) -> M256 {
        self.timestamp
    }

    pub fn number(&self) -> M256 {
        self.number
    }

    pub fn difficulty(&self) -> M256 {
        self.difficulty
    }

    pub fn gas_limit(&self) -> Gas {
        self.gas_limit
    }

    pub fn account_nonce(&self, address: Address) -> M256 {
        self.nonces.get(&address).map_or(M256::zero(), |s| (*s).into())
    }

    pub fn set_account_nonce(&mut self, address: Address, nonce: M256) {
        self.nonces.insert(address, nonce);
    }

    pub fn account_code(&self, address: Address) -> &[u8] {
        self.codes.get(&address).map_or(EMPTY.as_ref(), |s| s.as_ref())
    }

    pub fn set_account_code(&mut self, address: Address, code: &[u8]) {
        self.codes.insert(address, code.into());
    }

    pub fn balance(&self, address: Address) -> U256 {
        self.balances.get(&address).map_or(U256::zero(), |s| (*s).into())
    }

    pub fn set_balance(&mut self, address: Address, balance: U256) {
        self.balances.insert(address, balance);
    }

    pub fn account_storage(&self, address: Address, index: M256) -> M256 {
        match self.storages.get(&address) {
            None => M256::zero(),
            Some(ref ve) => {
                match ve.get(&index) {
                    Some(&v) => v,
                    None => M256::zero()
                }
            }
        }
    }

    pub fn set_account_storage(&mut self, address: Address, index: M256, val: M256) {
        if self.storages.get(&address).is_none() {
            self.storages.insert(address, HashMap::new());
        }

        let v = self.storages.get_mut(&address).unwrap();
        v.insert(index, val);
    }

    pub fn find_log(&self, address: Address, data: &[u8], topics: &[M256]) -> bool {
        for log in &self.logs {
            if log.address == address && log.data.as_slice() == data && log.topics.as_slice() == topics {
                return true;
            }
        }
        return false;
    }
}

pub fn create_block(v: &Value) -> JSONBlock {
    let mut block = {
        let env = &v["env"];

        let current_coinbase = env["currentCoinbase"].as_str().unwrap();
        let current_difficulty = env["currentDifficulty"].as_str().unwrap();
        let current_gas_limit = env["currentGasLimit"].as_str().unwrap();
        let current_number = env["currentNumber"].as_str().unwrap();
        let current_timestamp = env["currentTimestamp"].as_str().unwrap();

        JSONBlock {
            balances: HashMap::new(),
            storages: HashMap::new(),
            codes: HashMap::new(),
            nonces: HashMap::new(),

            coinbase: Address::from_str(current_coinbase).unwrap(),
            difficulty: M256::from_str(current_difficulty).unwrap(),
            gas_limit: Gas::from_str(current_gas_limit).unwrap(),
            number: M256::from_str(current_number).unwrap(),
            timestamp: M256::from_str(current_timestamp).unwrap(),

            logs: Vec::new(),
        }
    };

    let ref pre_addresses = v["pre"];

    for (address, data) in pre_addresses.as_object().unwrap() {
        let address = Address::from_str(address.as_str()).unwrap();
        let balance = U256::from_str(data["balance"].as_str().unwrap()).unwrap();
        let code = read_hex(data["code"].as_str().unwrap()).unwrap();

        block.set_account_code(address, code.as_ref());
        block.set_balance(address, balance);

        let storage = data["storage"].as_object().unwrap();
        for (index, value) in storage {
            let index = M256::from_str(index.as_str()).unwrap();
            let value = M256::from_str(value.as_str().unwrap()).unwrap();
            block.set_account_storage(address, index, value);
        }
    }

    block
}

pub fn create_context(v: &Value) -> Context {
    let address = Address::from_str(v["exec"]["address"].as_str().unwrap()).unwrap();
    let caller = Address::from_str(v["exec"]["caller"].as_str().unwrap()).unwrap();
    let code = read_hex(v["exec"]["code"].as_str().unwrap()).unwrap();
    let data = read_hex(v["exec"]["data"].as_str().unwrap()).unwrap();
    let gas = Gas::from_str(v["exec"]["gas"].as_str().unwrap()).unwrap();
    let gas_price = Gas::from_str(v["exec"]["gasPrice"].as_str().unwrap()).unwrap();
    let origin = Address::from_str(v["exec"]["origin"].as_str().unwrap()).unwrap();
    let value = U256::from_str(v["exec"]["value"].as_str().unwrap()).unwrap();

    Context {
        address: address,
        caller: caller,
        code: code,
        data: data,
        gas_limit: gas,
        gas_price: gas_price,
        origin: origin,
        value: value,
        create: false,
    }
}
<|endoftext|>


<commit_before>use super::theme::Theme;
use super::settings::*;
use super::super::LoadingError;
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::io::BufReader;
use walkdir::WalkDir;
use std::fs::File;

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct ThemeSet {
    pub themes: BTreeMap<String, Theme>,
}

/// A set of themes, includes convenient methods for loading and discovering themes.
impl ThemeSet {
    /// Returns all the themes found in a folder, good for enumerating before loading one with get_theme
    pub fn discover_theme_paths<P: AsRef<Path>>(folder: P) -> Result<Vec<PathBuf>, LoadingError> {
        let mut themes = Vec::new();
        for entry in WalkDir::new(folder) {
            let entry = try!(entry.map_err(LoadingError::WalkDir));
            if entry.path().extension().map(|e| e == "tmTheme").unwrap_or(false) {
                themes.push(entry.path().to_owned());
            }
        }
        Ok(themes)
    }

    fn read_file(path: &Path) -> Result<BufReader<File>, LoadingError> {
        let reader = try!(File::open(path));
        Ok(BufReader::new(reader))
    }

    fn read_plist(path: &Path) -> Result<Settings, LoadingError> {
        Ok(try!(read_plist(try!(Self::read_file(path)))))
    }

    /// Loads a theme given a path to a .tmTheme file
    pub fn get_theme<P: AsRef<Path>>(path: P) -> Result<Theme, LoadingError> {
        Ok(try!(Theme::parse_settings(try!(Self::read_plist(path.as_ref())))))
    }

    /// Loads all the themes in a folder
    pub fn load_from_folder<P: AsRef<Path>>(folder: P) -> Result<ThemeSet, LoadingError> {
        let paths = try!(Self::discover_theme_paths(folder));
        let mut map = BTreeMap::new();
        for p in &paths {
            let theme = try!(Self::get_theme(p));
            let basename =
                try!(p.file_stem().and_then(|x| x.to_str()).ok_or(LoadingError::BadPath));
            map.insert(basename.to_owned(), theme);
        }
        Ok(ThemeSet { themes: map })
    }
}

#[cfg(test)]
mod tests {
    use highlighting::{ThemeSet, Color};
    #[test]
    fn can_parse_common_themes() {
        let themes = ThemeSet::load_from_folder("testdata").unwrap();
        let all_themes: Vec<&str> = themes.themes.keys().map(|x| &**x).collect();
        println!("{:?}", all_themes);

        let theme = ThemeSet::get_theme("testdata/spacegray/base16-ocean.dark.tmTheme").unwrap();
        assert_eq!(theme.name.unwrap(), "Base16 Ocean Dark");
        assert_eq!(theme.settings.selection.unwrap(),
                   Color {
                       r: 0x4f,
                       g: 0x5b,
                       b: 0x66,
                       a: 0xff,
                   });
        assert_eq!(theme.scopes[0].style.foreground.unwrap(),
                   Color {
                       r: 0xc0,
                       g: 0xc5,
                       b: 0xce,
                       a: 0xFF,
                   });
        // assert!(false);
    }
}
<commit_msg>load theme from streams<commit_after>use super::theme::Theme;
use super::settings::*;
use super::super::LoadingError;
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::io::{BufReader, BufRead, Seek};
use walkdir::WalkDir;
use std::fs::File;

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct ThemeSet {
    pub themes: BTreeMap<String, Theme>,
}

/// A set of themes, includes convenient methods for loading and discovering themes.
impl ThemeSet {
    /// Returns all the themes found in a folder, good for enumerating before loading one with get_theme
    pub fn discover_theme_paths<P: AsRef<Path>>(folder: P) -> Result<Vec<PathBuf>, LoadingError> {
        let mut themes = Vec::new();
        for entry in WalkDir::new(folder) {
            let entry = try!(entry.map_err(LoadingError::WalkDir));
            if entry.path().extension().map(|e| e == "tmTheme").unwrap_or(false) {
                themes.push(entry.path().to_owned());
            }
        }
        Ok(themes)
    }

    /// Loads a theme given a path to a .tmTheme file
    pub fn get_theme<P: AsRef<Path>>(path: P) -> Result<Theme, LoadingError> {
        let file = try!(File::open(path));
        let mut file = BufReader::new(file);
        Self::load_from_reader(&mut file)
    }

    /// Loads a theme given a readable stream
    pub fn load_from_reader<R: BufRead + Seek>(r: &mut R) -> Result<Theme, LoadingError> {
        Ok(try!(Theme::parse_settings(try!(read_plist(r)))))
    }

    /// Loads all the themes in a folder
    pub fn load_from_folder<P: AsRef<Path>>(folder: P) -> Result<ThemeSet, LoadingError> {
        let paths = try!(Self::discover_theme_paths(folder));
        let mut map = BTreeMap::new();
        for p in &paths {
            let theme = try!(Self::get_theme(p));
            let basename =
                try!(p.file_stem().and_then(|x| x.to_str()).ok_or(LoadingError::BadPath));
            map.insert(basename.to_owned(), theme);
        }
        Ok(ThemeSet { themes: map })
    }
}

#[cfg(test)]
mod tests {
    use highlighting::{ThemeSet, Color};
    #[test]
    fn can_parse_common_themes() {
        let themes = ThemeSet::load_from_folder("testdata").unwrap();
        let all_themes: Vec<&str> = themes.themes.keys().map(|x| &**x).collect();
        println!("{:?}", all_themes);

        let theme = ThemeSet::get_theme("testdata/spacegray/base16-ocean.dark.tmTheme").unwrap();
        assert_eq!(theme.name.unwrap(), "Base16 Ocean Dark");
        assert_eq!(theme.settings.selection.unwrap(),
                   Color {
                       r: 0x4f,
                       g: 0x5b,
                       b: 0x66,
                       a: 0xff,
                   });
        assert_eq!(theme.scopes[0].style.foreground.unwrap(),
                   Color {
                       r: 0xc0,
                       g: 0xc5,
                       b: 0xce,
                       a: 0xFF,
                   });
        // assert!(false);
    }
}
<|endoftext|>


<commit_before>extern crate rocket;

use rocket::{Request, Data, Outcome};
use rocket::data::{self, FromData};
use rocket::Outcome::*;
use std::collections::HashMap;

pub struct WhereStructResult {
    sql: String, values: Vec<String>,
}

// My Results
type QueryOpResult = Result<String, String>;
type WhereResult = Result<WhereStructResult, String>;

// implement QueryString
pub struct QueryString {
    query: HashMap<String, String>
}

impl FromData for QueryString {
    type Error = String;

    fn from_data(req: &Request, _: Data) -> data::Outcome<Self, String> {
        let querystring: Vec<&str> = req.uri().query()
            .unwrap().split("&").collect();
        let mut result: QueryString = QueryString{query: HashMap::new()};

        for qs in querystring {
            let kv: Vec<&str> = qs.split("=").collect();
            // [0] is key, [1] is value
            result.query.insert(kv[0].to_string(), kv[1].to_string());
        }
        Success(result)
    }
}

pub fn query_operator(qop: &String) -> QueryOpResult {
    match &qop[..] {
        "$eq" => Ok("=".to_string()),
        "$ne" => Ok("!=".to_string()),
        "$gt" => Ok(">".to_string()),
        "$lt" => Ok("<".to_string()),
        "$gte" => Ok(">=".to_string()),
        "$lte" => Ok("<=".to_string()),
        "$in" => Ok("IN".to_string()),
        "$nin" => Ok("NOT IN".to_string()),
        "$notnull" => Ok("IS NOT NULL".to_string()),
        "$null" => Ok("IS NULL".to_string()),
         _ => Err(format!("operator {} not found", qop)),
    }
}

// Get request and return chuck WHERE statement with values
pub fn ext_where(_: &Request) -> WhereResult {
    Ok(WhereStructResult {
        sql: "WHERE user_id=$1".to_string(),
        values: vec!["5".to_string()],
    })
}

#[cfg(test)]
mod tests {
    use super::{rocket};
    use rocket::local::Client;
    use rocket::http::ContentType;
    use postgres::commands::*;

    #[test]
    fn get_opetators() {
        use std::collections::HashMap;

        let mut test_cases = HashMap::new();
        test_cases.insert("$eq", "=");
        test_cases.insert("$ne", "!=");
        test_cases.insert("$gt", ">");
        test_cases.insert("$gte", ">=");
        test_cases.insert("$lt", "<");
        test_cases.insert("$lte", "<=");
        test_cases.insert("$in", "IN");
        test_cases.insert("$nin", "NOT IN");
        test_cases.insert("$notnull", "IS NOT NULL");
        test_cases.insert("$null", "IS NULL");

        for (op, expected) in &test_cases {
            match query_operator(&op.to_string()) {
                Ok(x) => assert_eq!(expected.to_string(), x),
                Err(e) => assert_eq!("", e)
            }
        }
    }

    #[test]
    fn get_opetators_error() {
        let invalid = "!tn".to_string();
        match query_operator(&invalid) {
            Ok(_) => println!("no result"),
            Err(e) => assert_eq!(format!("operator {} not found", invalid), e)
        }
    }

    #[test]
    fn where_by_request() {
        let client = Client::new(rocket::ignite())
            .expect("valid rocket");
        let req = client.get("/db/sch/tbl?user_id=5&name=cool")
            .header(ContentType::JSON);
        let result = ext_where(req.inner())
            .unwrap();

        assert_eq!(result.sql, "WHERE user_id=$1".to_string());
        assert_eq!(result.values, vec!["5".to_string()])
    }
}
<commit_msg>Add two more tests to ext_where<commit_after>extern crate rocket;

use rocket::{Request, Data};
use rocket::data::{self, FromData};
use rocket::Outcome::*;
use std::collections::HashMap;

pub struct WhereStructResult {
    sql: String, values: Vec<String>,
}

// My Results
type QueryOpResult = Result<String, String>;
type WhereResult = Result<WhereStructResult, String>;

// TODO: Move there later!
// implement QueryString
pub struct QueryString {
    query: HashMap<String, String>
}

// TODO: Use FromForm instead FromData
impl FromData for QueryString {
    type Error = String;

    fn from_data(req: &Request, _: Data) -> data::Outcome<Self, String> {
        let querystring: Vec<&str> = req.uri().query()
            .unwrap().split("&").collect();
        let mut result: QueryString = QueryString{query: HashMap::new()};

        for qs in querystring {
            let kv: Vec<&str> = qs.split("=").collect();
            // [0] is key, [1] is value
            result.query.insert(kv[0].to_string(), kv[1].to_string());
        }
        Success(result)
    }
}

pub fn query_operator(qop: &String) -> QueryOpResult {
    match &qop[..] {
        "$eq" => Ok("=".to_string()),
        "$ne" => Ok("!=".to_string()),
        "$gt" => Ok(">".to_string()),
        "$lt" => Ok("<".to_string()),
        "$gte" => Ok(">=".to_string()),
        "$lte" => Ok("<=".to_string()),
        "$in" => Ok("IN".to_string()),
        "$nin" => Ok("NOT IN".to_string()),
        "$notnull" => Ok("IS NOT NULL".to_string()),
        "$null" => Ok("IS NULL".to_string()),
         _ => Err(format!("operator {} not found", qop)),
    }
}

// Get QueryString and return chunck WHERE statement with values
pub fn ext_where(qs: QueryString) -> WhereResult {
    let where_syntax: String;
    let mut pid: u32 = 0;
    let mut where_values: Vec<String> = Vec::new();
    let mut where_fields: Vec<String> = Vec::new();

    for (k, v) in qs.query.iter() {
        pid = pid + 1;
        where_fields.push(format!("{}=${}", k, pid));
        where_values.push(v.to_string());
    }

    if pid > 1 {
        where_syntax = format!("WHERE {}", where_fields.join(" AND "));
    } else {
        where_syntax = format!("WHERE {}", where_fields.join(" "));
    }

    Ok(WhereStructResult {
        sql: where_syntax,
        values: where_values
    })
}

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

    #[test]
    fn get_opetators() {
        use std::collections::HashMap;

        let mut test_cases = HashMap::new();
        test_cases.insert("$eq", "=");
        test_cases.insert("$ne", "!=");
        test_cases.insert("$gt", ">");
        test_cases.insert("$gte", ">=");
        test_cases.insert("$lt", "<");
        test_cases.insert("$lte", "<=");
        test_cases.insert("$in", "IN");
        test_cases.insert("$nin", "NOT IN");
        test_cases.insert("$notnull", "IS NOT NULL");
        test_cases.insert("$null", "IS NULL");

        for (op, expected) in &test_cases {
            match query_operator(&op.to_string()) {
                Ok(x) => assert_eq!(expected.to_string(), x),
                Err(e) => assert_eq!("", e)
            }
        }
    }

    #[test]
    fn get_opetators_error() {
        let invalid = "!tn".to_string();
        match query_operator(&invalid) {
            Ok(_) => println!("no result"),
            Err(e) => assert_eq!(format!("operator {} not found", invalid), e)
        }
    }

    #[test]
    fn where_by_request_one_querystring() {
        let mut hm = HashMap::new();
        hm.insert("user_id".to_string(), "5".to_string());

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1".to_string());
        assert_eq!(result.values, vec!["5".to_string()])
    }

    #[test]
    fn where_by_request_n_querystring() {
        let mut hm = HashMap::new();
        hm.insert("user_id".to_string(), "5".to_string());
        hm.insert("name".to_string(), "goga".to_string());

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1 AND name=$2".to_string());
        assert_eq!(result.values, vec!["5".to_string(), "goga".to_string()])
    }
}
<|endoftext|>


<commit_before>// xfail-boot
// based on:
// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java

fn main() {

    let vec[int] inputs = vec(
        50000
        //these segfault :(
        //500000,
        //5000000,
        //50000000
        );

    let vec[Body.props] bodies = NBodySystem.MakeNBodySystem();

    for (int n in inputs) {
        log NBodySystem.energy(bodies);

        let int i = 0;
        while (i < n) {
            NBodySystem.advance(bodies, 0.01);
            i += 1;
        }
        log NBodySystem.energy(bodies);
    }
}

// making a native call to sqrt
native "rust" mod rustrt {
    fn squareroot(&float input, &mutable float output);
}

// Body.props is a record of floats, so
// vec[Body.props] is a vector of records of floats

mod NBodySystem {

    fn MakeNBodySystem() -> vec[Body.props] {
        let vec[Body.props] bodies = vec(
            // these each return a Body.props
            Body.sun(),
            Body.jupiter(),
            Body.saturn(),
            Body.uranus(),
            Body.neptune());

        let float px = 0.0;
        let float py = 0.0;
        let float pz = 0.0;

        let int i = 0;
        while (i < 5) {
            px += bodies.(i).vx * bodies.(i).mass;
            py += bodies.(i).vy * bodies.(i).mass;
            pz += bodies.(i).vz * bodies.(i).mass;

            i += 1;
        }

        // side-effecting
        Body.offsetMomentum(bodies.(0), px, py, pz);

        ret bodies;
    }

    fn advance(vec[Body.props] bodies, float dt) -> () {

        let int i = 0;
        while (i < 5) {
            let int j = i+1;
            while (j < 5) {
                let float dx = bodies.(i).x - bodies.(j).x;
                let float dy = bodies.(i).y - bodies.(j).y;
                let float dz = bodies.(i).z - bodies.(j).z;

                let float dSquared = dx * dx + dy * dy + dz * dz;

                let float distance;
                rustrt.squareroot(dSquared, distance);
                let float mag = dt / (dSquared * distance);

                bodies.(i).vx -= dx * bodies.(j).mass * mag;
                bodies.(i).vy -= dy * bodies.(j).mass * mag;
                bodies.(i).vz -= dz * bodies.(j).mass * mag;

                bodies.(j).vx += dx * bodies.(i).mass * mag;
                bodies.(j).vy += dy * bodies.(i).mass * mag;
                bodies.(j).vz += dz * bodies.(i).mass * mag;

                j += 1;

            }

            i += 1;
        }

        i = 0;
        while (i < 5) {

            bodies.(i).x += dt * bodies.(i).vx;
            bodies.(i).y += dt * bodies.(i).vy;
            bodies.(i).z += dt * bodies.(i).vz;

            i += 1;
        }
    }

    fn energy(vec[Body.props] bodies) -> float {
        let float dx;
        let float dy;
        let float dz;
        let float distance;
        let float e = 0.0;

        let int i = 0;
        while (i < 5) {
            e += 0.5 * bodies.(i).mass *
                (  bodies.(i).vx * bodies.(i).vx
                 + bodies.(i).vy * bodies.(i).vy
                 + bodies.(i).vz * bodies.(i).vz );

            let int j = i+1;
            while (j < 5) {
                dx = bodies.(i).x - bodies.(j).x;
                dy = bodies.(i).y - bodies.(j).y;
                dz = bodies.(i).z - bodies.(j).z;

                rustrt.squareroot(dx*dx + dy*dy + dz*dz, distance);
                e -= (bodies.(i).mass * bodies.(j).mass) / distance;

                j += 1;
            }

            i += 1;
        }
        ret e;

    }
}

mod Body {

    const float PI = 3.141592653589793;
    const float SOLAR_MASS = 39.478417604357432; // was 4 * PI * PI originally
    const float DAYS_PER_YEAR = 365.24;

    type props = rec(mutable float x,
                     mutable float y,
                     mutable float z,
                     mutable float vx,
                     mutable float vy,
                     mutable float vz,
                     float mass);

    fn jupiter() -> Body.props {
        ret rec(
            mutable x  =  4.84143144246472090e+00,
            mutable y  = -1.16032004402742839e+00,
            mutable z  = -1.03622044471123109e-01,
            mutable vx =  1.66007664274403694e-03 * DAYS_PER_YEAR,
            mutable vy =  7.69901118419740425e-03 * DAYS_PER_YEAR,
            mutable vz = -6.90460016972063023e-05 * DAYS_PER_YEAR,
            mass       =  9.54791938424326609e-04 * SOLAR_MASS
            );
    }

    fn saturn() -> Body.props {
        ret rec(
            mutable x  =  8.34336671824457987e+00,
            mutable y  =  4.12479856412430479e+00,
            mutable z  = -4.03523417114321381e-01,
            mutable vx = -2.76742510726862411e-03 * DAYS_PER_YEAR,
            mutable vy =  4.99852801234917238e-03 * DAYS_PER_YEAR,
            mutable vz =  2.30417297573763929e-05 * DAYS_PER_YEAR,
            mass       =  2.85885980666130812e-04 * SOLAR_MASS
            );
   }

    fn uranus() -> Body.props {
        ret rec(
            mutable x  =  1.28943695621391310e+01,
            mutable y  = -1.51111514016986312e+01,
            mutable z  = -2.23307578892655734e-01,
            mutable vx =  2.96460137564761618e-03 * DAYS_PER_YEAR,
            mutable vy =  2.37847173959480950e-03 * DAYS_PER_YEAR,
            mutable vz = -2.96589568540237556e-05 * DAYS_PER_YEAR,
            mass       =  4.36624404335156298e-05 * SOLAR_MASS
            );
    }

    fn neptune() -> Body.props {
        ret rec(
            mutable x  =  1.53796971148509165e+01,
            mutable y  = -2.59193146099879641e+01,
            mutable z  =  1.79258772950371181e-01,
            mutable vx =  2.68067772490389322e-03 * DAYS_PER_YEAR,
            mutable vy =  1.62824170038242295e-03 * DAYS_PER_YEAR,
            mutable vz = -9.51592254519715870e-05 * DAYS_PER_YEAR,
            mass       =  5.15138902046611451e-05 * SOLAR_MASS
            );
   }

   fn sun() -> Body.props {
       ret rec(
           mutable x  =  0.0,
           mutable y  =  0.0,
           mutable z  =  0.0,
           mutable vx =  0.0,
           mutable vy =  0.0,
           mutable vz =  0.0,
           mass       =  SOLAR_MASS
           );
   }

   impure fn offsetMomentum(&Body.props props,
                            float px,
                            float py,
                            float pz) -> () {
       props.vx = -px / SOLAR_MASS;
       props.vy = -py / SOLAR_MASS;
       props.vz = -pz / SOLAR_MASS;
   }

}
<commit_msg>shootout: Hoist out the vector indexing on nbody; don't rely on LICM, which isn't working for some reason (insufficient alias info?) Speeds up nbody a bit.<commit_after>// xfail-boot
// based on:
// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java

fn main() {

    let vec[int] inputs = vec(
        50000
        //these segfault :(
        //500000,
        //5000000,
        //50000000
        );

    let vec[Body.props] bodies = NBodySystem.MakeNBodySystem();

    for (int n in inputs) {
        log NBodySystem.energy(bodies);

        let int i = 0;
        while (i < n) {
            NBodySystem.advance(bodies, 0.01);
            i += 1;
        }
        log NBodySystem.energy(bodies);
    }
}

// making a native call to sqrt
native "rust" mod rustrt {
    fn squareroot(&float input, &mutable float output);
}

// Body.props is a record of floats, so
// vec[Body.props] is a vector of records of floats

mod NBodySystem {

    fn MakeNBodySystem() -> vec[Body.props] {
        let vec[Body.props] bodies = vec(
            // these each return a Body.props
            Body.sun(),
            Body.jupiter(),
            Body.saturn(),
            Body.uranus(),
            Body.neptune());

        let float px = 0.0;
        let float py = 0.0;
        let float pz = 0.0;

        let int i = 0;
        while (i < 5) {
            px += bodies.(i).vx * bodies.(i).mass;
            py += bodies.(i).vy * bodies.(i).mass;
            pz += bodies.(i).vz * bodies.(i).mass;

            i += 1;
        }

        // side-effecting
        Body.offsetMomentum(bodies.(0), px, py, pz);

        ret bodies;
    }

    fn advance(vec[Body.props] bodies, float dt) -> () {

        let int i = 0;
        while (i < 5) {
            let int j = i+1;
            while (j < 5) {
                advance_one(bodies.(i), bodies.(j), dt);
                j += 1;
            }

            i += 1;
        }

        i = 0;
        while (i < 5) {

            bodies.(i).x += dt * bodies.(i).vx;
            bodies.(i).y += dt * bodies.(i).vy;
            bodies.(i).z += dt * bodies.(i).vz;

            i += 1;
        }
    }

    fn advance_one(&Body.props bi, &Body.props bj, float dt) {
        let float dx = bi.x - bj.x;
        let float dy = bi.y - bj.y;
        let float dz = bi.z - bj.z;

        let float dSquared = dx * dx + dy * dy + dz * dz;

        let float distance;
        rustrt.squareroot(dSquared, distance);
        let float mag = dt / (dSquared * distance);

        bi.vx -= dx * bj.mass * mag;
        bi.vy -= dy * bj.mass * mag;
        bi.vz -= dz * bj.mass * mag;

        bj.vx += dx * bi.mass * mag;
        bj.vy += dy * bi.mass * mag;
        bj.vz += dz * bi.mass * mag;
    }

    fn energy(vec[Body.props] bodies) -> float {
        let float dx;
        let float dy;
        let float dz;
        let float distance;
        let float e = 0.0;

        let int i = 0;
        while (i < 5) {
            e += 0.5 * bodies.(i).mass *
                (  bodies.(i).vx * bodies.(i).vx
                 + bodies.(i).vy * bodies.(i).vy
                 + bodies.(i).vz * bodies.(i).vz );

            let int j = i+1;
            while (j < 5) {
                dx = bodies.(i).x - bodies.(j).x;
                dy = bodies.(i).y - bodies.(j).y;
                dz = bodies.(i).z - bodies.(j).z;

                rustrt.squareroot(dx*dx + dy*dy + dz*dz, distance);
                e -= (bodies.(i).mass * bodies.(j).mass) / distance;

                j += 1;
            }

            i += 1;
        }
        ret e;

    }
}

mod Body {

    const float PI = 3.141592653589793;
    const float SOLAR_MASS = 39.478417604357432; // was 4 * PI * PI originally
    const float DAYS_PER_YEAR = 365.24;

    type props = rec(mutable float x,
                     mutable float y,
                     mutable float z,
                     mutable float vx,
                     mutable float vy,
                     mutable float vz,
                     float mass);

    fn jupiter() -> Body.props {
        ret rec(
            mutable x  =  4.84143144246472090e+00,
            mutable y  = -1.16032004402742839e+00,
            mutable z  = -1.03622044471123109e-01,
            mutable vx =  1.66007664274403694e-03 * DAYS_PER_YEAR,
            mutable vy =  7.69901118419740425e-03 * DAYS_PER_YEAR,
            mutable vz = -6.90460016972063023e-05 * DAYS_PER_YEAR,
            mass       =  9.54791938424326609e-04 * SOLAR_MASS
            );
    }

    fn saturn() -> Body.props {
        ret rec(
            mutable x  =  8.34336671824457987e+00,
            mutable y  =  4.12479856412430479e+00,
            mutable z  = -4.03523417114321381e-01,
            mutable vx = -2.76742510726862411e-03 * DAYS_PER_YEAR,
            mutable vy =  4.99852801234917238e-03 * DAYS_PER_YEAR,
            mutable vz =  2.30417297573763929e-05 * DAYS_PER_YEAR,
            mass       =  2.85885980666130812e-04 * SOLAR_MASS
            );
   }

    fn uranus() -> Body.props {
        ret rec(
            mutable x  =  1.28943695621391310e+01,
            mutable y  = -1.51111514016986312e+01,
            mutable z  = -2.23307578892655734e-01,
            mutable vx =  2.96460137564761618e-03 * DAYS_PER_YEAR,
            mutable vy =  2.37847173959480950e-03 * DAYS_PER_YEAR,
            mutable vz = -2.96589568540237556e-05 * DAYS_PER_YEAR,
            mass       =  4.36624404335156298e-05 * SOLAR_MASS
            );
    }

    fn neptune() -> Body.props {
        ret rec(
            mutable x  =  1.53796971148509165e+01,
            mutable y  = -2.59193146099879641e+01,
            mutable z  =  1.79258772950371181e-01,
            mutable vx =  2.68067772490389322e-03 * DAYS_PER_YEAR,
            mutable vy =  1.62824170038242295e-03 * DAYS_PER_YEAR,
            mutable vz = -9.51592254519715870e-05 * DAYS_PER_YEAR,
            mass       =  5.15138902046611451e-05 * SOLAR_MASS
            );
   }

   fn sun() -> Body.props {
       ret rec(
           mutable x  =  0.0,
           mutable y  =  0.0,
           mutable z  =  0.0,
           mutable vx =  0.0,
           mutable vy =  0.0,
           mutable vz =  0.0,
           mass       =  SOLAR_MASS
           );
   }

   impure fn offsetMomentum(&Body.props props,
                            float px,
                            float py,
                            float pz) -> () {
       props.vx = -px / SOLAR_MASS;
       props.vy = -py / SOLAR_MASS;
       props.vz = -pz / SOLAR_MASS;
   }

}
<|endoftext|>


<commit_before>use parser;
use interpreter::Interpreter;
use interpreter::StatementResult;
use value::Value;
use value::Number;

fn run_and_get_last_value(code: &str) -> Value {
    match run_and_get_last_result(code) {
        StatementResult::Value(ref v) => v.clone(),
        _ => panic!("Cannot unwrap value"),
    }
}

fn run_and_get_last_result(code: &str) -> StatementResult {
    let ast = parser::program(code);
    match ast {
        Ok(ast) => {
            let mut machine = Interpreter::new();
            machine.run_ast_as_program(&ast).unwrap().unwrap()
        }
        Err(_) => panic!("{:?}", ast),
    }
}

#[test]
fn literal_value_int() {
    assert_eq!(run_and_get_last_value("7;"),
               Value::Number(Number::Integer(7)));
}

#[test]
fn literal_value_float() {
    assert_eq!(run_and_get_last_value("7.0;"),
               Value::Number(Number::Float(7.0)));
}

#[test]
fn literal_value_bool_true() {
    assert_eq!(run_and_get_last_value("true;"), Value::Bool(true));
}

#[test]
fn literal_value_bool_false() {
    assert_eq!(run_and_get_last_value("false;"), Value::Bool(false));
}

#[test]
fn variable_reassignment_with_type_change() {
    assert_eq!(run_and_get_last_value("var x = 10; x = false; x;"),
               Value::Bool(false));
}

#[test]
fn arithmetic_1() {
    assert_eq!(run_and_get_last_value("(1 + 3 / (1 + 1)) * 12 - 1;"),
               Value::Number(Number::Float(29.0)));
}

#[test]
fn arithmetic_2() {
    assert_eq!(run_and_get_last_value("3 - 5 + 12 / 4 - 1;"),
               Value::Number(Number::Float(0.0)));
}

#[test]
fn arithmetic_3() {
    assert_eq!(run_and_get_last_value("10 // 3 + 5 - 12;"),
               Value::Number(Number::Integer(-4)));
}

#[test]
fn arithmetic_4() {
    assert_eq!(run_and_get_last_value("-10 / 4 + -5 - 12;"),
               Value::Number(Number::Float(-19.5)));
}

#[test]
fn i64_support() {
    assert_eq!(run_and_get_last_value("9223372036854775807;"),
               Value::Number(Number::Integer(9223372036854775807)));
}

#[test]
fn f64_support() {
    assert_eq!(run_and_get_last_value("1234567890.012345678;"),
               Value::Number(Number::Float(1234567890.012345678)));
}

#[test]
fn logical_and() {
    assert_eq!(run_and_get_last_value("true and true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false and true;"),
               Value::Bool(false));
    assert_eq!(run_and_get_last_value("true and false;"),
               Value::Bool(false));
    assert_eq!(run_and_get_last_value("false and false;"),
               Value::Bool(false));

    assert_eq!(run_and_get_last_value("2 and 1;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3.0 and 22.5;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("5 and 0;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("5.6 and 0.0;"), Value::Bool(false));
}

#[test]
fn logical_or() {
    assert_eq!(run_and_get_last_value("true or true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false or true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("true or false;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false or false;"),
               Value::Bool(false));

    assert_eq!(run_and_get_last_value("2 or 1;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3.0 or 22.5;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("5 or 0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("0 or 0.0;"), Value::Bool(false));
}

#[test]
fn logical_not() {
    assert_eq!(run_and_get_last_value("not true;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("not false;"), Value::Bool(true));

    assert_eq!(run_and_get_last_value("not 5;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("not 0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("not 0.0;"), Value::Bool(true));
}

#[test]
fn comparisons() {
    assert_eq!(run_and_get_last_value("1 < 2;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("1 > 2;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("1.0 < 2.0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("1.0 > 2.0;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("4 <= 4;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("2 >= 2;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3 == 3;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("7 == 7.0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("7 == 7.1;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("true == 1;"), Value::Bool(false));
}

#[test]
fn variable_declaration() {
    assert_eq!(run_and_get_last_value("var x = 5; x;"),
               Value::Number(Number::Integer(5)));
}

#[test]
fn variable_reassignment() {
    assert_eq!(run_and_get_last_value("var x = 10; x = 42; x;"),
               Value::Number(Number::Integer(42)));
}

#[test]
fn id_in_expr() {
    assert_eq!(run_and_get_last_value("var x = 5; x / 2 + x;"),
               Value::Number(Number::Float(7.5)));
}

#[test]
fn if_expr_true() {
    assert_eq!(run_and_get_last_value("var x = 5; if 1 < 2 { x = 6; } else { x = 7; } x;"),
               Value::Number(Number::Integer(6)));
}

#[test]
fn if_expr_false() {
    assert_eq!(run_and_get_last_value("var x = 5; if 1 > 2 { x = 6; } else { x = 7; } x;"),
               Value::Number(Number::Integer(7)));
}

#[test]
fn loop_and_break() {
    assert_eq!(run_and_get_last_value("var x = 5; loop { if x > 20 { break; } x = x + 5; } x;"),
               Value::Number(Number::Integer(25)));
}

#[test]
fn block_env() {
    assert_eq!(run_and_get_last_value("var x = 5; { var x = 10; x = 20; } x;"),
               Value::Number(Number::Integer(5)));
    assert_eq!(run_and_get_last_value("var x = 5; { var x = 10; x = 20; x; }"),
               Value::Number(Number::Integer(20)));
}

#[test]
fn test_println_runs() {
    assert_eq!(run_and_get_last_result("println();"), StatementResult::None);
    assert_eq!(run_and_get_last_result("println(5, true,);"),
               StatementResult::None);
}

#[test]
fn test_factorial() {
    assert_eq!(
        run_and_get_last_value("fn factorial(n) { if n < 2 { return 1; } return n * factorial(n - 1); } factorial(5); "),
        Value::Number(Number::Integer(120))
    );
    assert_eq!(
        run_and_get_last_value("fn factorial(n) { if n < 2 { return 1; } return n * factorial(n - 1); } factorial(10); "),
        Value::Number(Number::Integer(3628800))
    );
}

#[test]
fn test_curried_add() {
    let code = "fn addX(x) {
    return fn addXY(y) {
        return x + y;
    };
}

(addX(10))(20);
";
    assert_eq!(
        run_and_get_last_value(code), Value::Number(Number::Integer(30))
    );
}
<commit_msg>Return anonymous fn in curried_add test<commit_after>use parser;
use interpreter::Interpreter;
use interpreter::StatementResult;
use value::Value;
use value::Number;

fn run_and_get_last_value(code: &str) -> Value {
    match run_and_get_last_result(code) {
        StatementResult::Value(ref v) => v.clone(),
        _ => panic!("Cannot unwrap value"),
    }
}

fn run_and_get_last_result(code: &str) -> StatementResult {
    let ast = parser::program(code);
    match ast {
        Ok(ast) => {
            let mut machine = Interpreter::new();
            machine.run_ast_as_program(&ast).unwrap().unwrap()
        }
        Err(_) => panic!("{:?}", ast),
    }
}

#[test]
fn literal_value_int() {
    assert_eq!(run_and_get_last_value("7;"),
               Value::Number(Number::Integer(7)));
}

#[test]
fn literal_value_float() {
    assert_eq!(run_and_get_last_value("7.0;"),
               Value::Number(Number::Float(7.0)));
}

#[test]
fn literal_value_bool_true() {
    assert_eq!(run_and_get_last_value("true;"), Value::Bool(true));
}

#[test]
fn literal_value_bool_false() {
    assert_eq!(run_and_get_last_value("false;"), Value::Bool(false));
}

#[test]
fn variable_reassignment_with_type_change() {
    assert_eq!(run_and_get_last_value("var x = 10; x = false; x;"),
               Value::Bool(false));
}

#[test]
fn arithmetic_1() {
    assert_eq!(run_and_get_last_value("(1 + 3 / (1 + 1)) * 12 - 1;"),
               Value::Number(Number::Float(29.0)));
}

#[test]
fn arithmetic_2() {
    assert_eq!(run_and_get_last_value("3 - 5 + 12 / 4 - 1;"),
               Value::Number(Number::Float(0.0)));
}

#[test]
fn arithmetic_3() {
    assert_eq!(run_and_get_last_value("10 // 3 + 5 - 12;"),
               Value::Number(Number::Integer(-4)));
}

#[test]
fn arithmetic_4() {
    assert_eq!(run_and_get_last_value("-10 / 4 + -5 - 12;"),
               Value::Number(Number::Float(-19.5)));
}

#[test]
fn i64_support() {
    assert_eq!(run_and_get_last_value("9223372036854775807;"),
               Value::Number(Number::Integer(9223372036854775807)));
}

#[test]
fn f64_support() {
    assert_eq!(run_and_get_last_value("1234567890.012345678;"),
               Value::Number(Number::Float(1234567890.012345678)));
}

#[test]
fn logical_and() {
    assert_eq!(run_and_get_last_value("true and true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false and true;"),
               Value::Bool(false));
    assert_eq!(run_and_get_last_value("true and false;"),
               Value::Bool(false));
    assert_eq!(run_and_get_last_value("false and false;"),
               Value::Bool(false));

    assert_eq!(run_and_get_last_value("2 and 1;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3.0 and 22.5;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("5 and 0;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("5.6 and 0.0;"), Value::Bool(false));
}

#[test]
fn logical_or() {
    assert_eq!(run_and_get_last_value("true or true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false or true;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("true or false;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("false or false;"),
               Value::Bool(false));

    assert_eq!(run_and_get_last_value("2 or 1;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3.0 or 22.5;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("5 or 0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("0 or 0.0;"), Value::Bool(false));
}

#[test]
fn logical_not() {
    assert_eq!(run_and_get_last_value("not true;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("not false;"), Value::Bool(true));

    assert_eq!(run_and_get_last_value("not 5;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("not 0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("not 0.0;"), Value::Bool(true));
}

#[test]
fn comparisons() {
    assert_eq!(run_and_get_last_value("1 < 2;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("1 > 2;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("1.0 < 2.0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("1.0 > 2.0;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("4 <= 4;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("2 >= 2;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("3 == 3;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("7 == 7.0;"), Value::Bool(true));
    assert_eq!(run_and_get_last_value("7 == 7.1;"), Value::Bool(false));
    assert_eq!(run_and_get_last_value("true == 1;"), Value::Bool(false));
}

#[test]
fn variable_declaration() {
    assert_eq!(run_and_get_last_value("var x = 5; x;"),
               Value::Number(Number::Integer(5)));
}

#[test]
fn variable_reassignment() {
    assert_eq!(run_and_get_last_value("var x = 10; x = 42; x;"),
               Value::Number(Number::Integer(42)));
}

#[test]
fn id_in_expr() {
    assert_eq!(run_and_get_last_value("var x = 5; x / 2 + x;"),
               Value::Number(Number::Float(7.5)));
}

#[test]
fn if_expr_true() {
    assert_eq!(run_and_get_last_value("var x = 5; if 1 < 2 { x = 6; } else { x = 7; } x;"),
               Value::Number(Number::Integer(6)));
}

#[test]
fn if_expr_false() {
    assert_eq!(run_and_get_last_value("var x = 5; if 1 > 2 { x = 6; } else { x = 7; } x;"),
               Value::Number(Number::Integer(7)));
}

#[test]
fn loop_and_break() {
    assert_eq!(run_and_get_last_value("var x = 5; loop { if x > 20 { break; } x = x + 5; } x;"),
               Value::Number(Number::Integer(25)));
}

#[test]
fn block_env() {
    assert_eq!(run_and_get_last_value("var x = 5; { var x = 10; x = 20; } x;"),
               Value::Number(Number::Integer(5)));
    assert_eq!(run_and_get_last_value("var x = 5; { var x = 10; x = 20; x; }"),
               Value::Number(Number::Integer(20)));
}

#[test]
fn test_println_runs() {
    assert_eq!(run_and_get_last_result("println();"), StatementResult::None);
    assert_eq!(run_and_get_last_result("println(5, true,);"),
               StatementResult::None);
}

#[test]
fn test_factorial() {
    assert_eq!(
        run_and_get_last_value("fn factorial(n) { if n < 2 { return 1; } return n * factorial(n - 1); } factorial(5); "),
        Value::Number(Number::Integer(120))
    );
    assert_eq!(
        run_and_get_last_value("fn factorial(n) { if n < 2 { return 1; } return n * factorial(n - 1); } factorial(10); "),
        Value::Number(Number::Integer(3628800))
    );
}

#[test]
fn test_curried_add() {
    let code = "fn addX(x) {
    return fn(y) {
        return x + y;
    };
}

(addX(10))(20);
";
    assert_eq!(
        run_and_get_last_value(code), Value::Number(Number::Integer(30))
    );
}
<|endoftext|>


<commit_before>use std::str::Chars;
use std::iter::Peekable;
use std::iter::Enumerate;

use ::syntax::lexer::{Token, Lexer};
use ::syntax::next_is;

pub struct RustSyntax;

impl Lexer for RustSyntax {
    fn handle_char(&self, ch: char, mut iter: &mut Peekable<Enumerate<Chars>>, y_pos: usize, idx: usize) -> Option<Token> {
        match ch {
            '#' => {
                let st = idx;
                let mut end = idx;
                if next_is(&mut iter, '!') || next_is(&mut iter, '[') {
                    let mut s = String::from("#");
                    while let Some(&(e, c)) = iter.peek() {
                        if c == '\n' { break }
                        end = e;
                        s.push(iter.next().unwrap().1)
                    }
                    return Some(Token::Attribute(s));
                }
                return Some(Token::Hash)
            }

            '/' => {
                let st = idx;
                let mut end = idx;
                if next_is(&mut iter, '/') {
                    let mut s = String::from("/");
                    s.push(iter.next().unwrap().1);

                    let mut doc_comment = false;
                    if next_is(&mut iter, '/') || next_is(&mut iter, '!') {
                        doc_comment = true;
                    }

                    while let Some(&(e, c)) = iter.peek() {
                        if c == '\n' { break }
                        end = e;
                        s.push(iter.next().unwrap().1)
                    }

                    return Some(if doc_comment{ Token::DocComment(s) } else { Token::SingleLineComment(s) });
                }
                return Some(Token::ForwardSlash);
            }

            '"' => {
                let st = idx;
                let mut end = idx;
                let mut s = String::from("\"");
                while let Some(&(e, c)) = iter.peek() {
                    end = e;
                    s.push(iter.next().unwrap().1);
                    if c == '\\' {
                        if let Some(&(e, c_)) = iter.peek() {
                            // this is handling escaped single quotes...
                            if c_ == '"' {
                                s.push(iter.next().unwrap().1);
                                continue;
                            }
                        }
                    }
                    if c == '"' {
                        break;
                    }
                }
                return Some(Token::String(s));
            }

            '\'' => {
                let st = idx;
                let mut end = idx;
                let mut s = String::from("\'");
                while let Some(&(e, c)) = iter.peek() {
                    end = e;
                    s.push(iter.next().unwrap().1);
                    if c == '\\' {
                        if let Some(&(e, c_)) = iter.peek() {
                            // this is handling escaped single quotes...
                            if c_ == '\'' {
                                s.push(iter.next().unwrap().1);
                                continue;
                            }
                        }
                    }
                    if c == '\'' {
                        break;
                    }
                }
                return Some(Token::Special(s));
            }

            _ => None,
        }

    }

    fn handle_ident(&self, ch: char, mut iter: &mut Peekable<Enumerate<Chars>>, y_pos: usize) -> Token {
        let mut ident = String::new();
        ident.push(ch);
        let mut start = 0;

        if let Some(&(x, c)) = iter.peek() {
            start = x - 1;
        }

        while self.is_ident(iter.peek()) {
            ident.push(iter.next().unwrap().1)
        }

        let end = ident.len() - 1;
        let token;

        if next_is(&mut iter, '(') {
            // function calls or definitions
            token = Token::FunctionCallDef(ident);
        } else if next_is(&mut iter, '!') {
            // macro calls
            ident.push(iter.next().unwrap().1);
            token = Token::Special(ident);
        } else {
            // regular idents
            token = Token::Ident(ident);
        }

        token
    }
}

<commit_msg>Fix crash when inserting single quote<commit_after>use std::str::Chars;
use std::iter::Peekable;
use std::iter::Enumerate;

use ::syntax::lexer::{Token, Lexer};
use ::syntax::next_is;

pub struct RustSyntax;

impl Lexer for RustSyntax {
    fn handle_char(&self, ch: char, mut iter: &mut Peekable<Enumerate<Chars>>, y_pos: usize, idx: usize) -> Option<Token> {
        match ch {
            '#' => {
                let st = idx;
                let mut end = idx;
                if next_is(&mut iter, '!') || next_is(&mut iter, '[') {
                    let mut s = String::from("#");
                    while let Some(&(e, c)) = iter.peek() {
                        if c == '\n' { break }
                        end = e;
                        s.push(iter.next().unwrap().1)
                    }
                    return Some(Token::Attribute(s));
                }
                return Some(Token::Hash)
            }

            '/' => {
                let st = idx;
                let mut end = idx;
                if next_is(&mut iter, '/') {
                    let mut s = String::from("/");
                    s.push(iter.next().unwrap().1);

                    let mut doc_comment = false;
                    if next_is(&mut iter, '/') || next_is(&mut iter, '!') {
                        doc_comment = true;
                    }

                    while let Some(&(e, c)) = iter.peek() {
                        if c == '\n' { break }
                        end = e;
                        s.push(iter.next().unwrap().1)
                    }

                    return Some(if doc_comment{ Token::DocComment(s) } else { Token::SingleLineComment(s) });
                }
                return Some(Token::ForwardSlash);
            }

            '"' => {
                let st = idx;
                let mut end = idx;
                let mut s = String::from("\"");
                while let Some(&(e, c)) = iter.peek() {
                    end = e;
                    s.push(iter.next().unwrap().1);
                    if c == '\\' {
                        if let Some(&(e, c_)) = iter.peek() {
                            // this is handling escaped single quotes...
                            if c_ == '"' {
                                s.push(iter.next().unwrap().1);
                                continue;
                            }
                        }
                    }
                    if c == '"' {
                        break;
                    }
                }
                return Some(Token::String(s));
            }

            '\'' => {
                let st = idx;
                let mut end = idx;
                let mut s = String::from("'");
                while let Some(&(e, c)) = iter.peek() {
                    end = e;
                    s.push(iter.next().unwrap().1);
                    if c == '\\' {
                        if let Some(&(e, c_)) = iter.peek() {
                            // this is handling escaped single quotes...
                            if c_ == '\'' {
                                s.push(iter.next().unwrap().1);
                                continue;
                            }
                        }
                    }
                    if !c.is_alphanumeric() {
                        break;
                    }
                }
                return Some(Token::Special(s));
            }

            _ => None,
        }

    }

    fn handle_ident(&self, ch: char, mut iter: &mut Peekable<Enumerate<Chars>>, y_pos: usize) -> Token {
        let mut ident = String::new();
        ident.push(ch);
        let mut start = 0;

        if let Some(&(x, c)) = iter.peek() {
            start = x - 1;
        }

        while self.is_ident(iter.peek()) {
            ident.push(iter.next().unwrap().1)
        }

        let end = ident.len() - 1;
        let token;

        if next_is(&mut iter, '(') {
            // function calls or definitions
            token = Token::FunctionCallDef(ident);
        } else if next_is(&mut iter, '!') {
            // macro calls
            ident.push(iter.next().unwrap().1);
            token = Token::Special(ident);
        } else {
            // regular idents
            token = Token::Ident(ident);
        }

        token
    }
}

<|endoftext|>


<commit_before>use std::io::Read;
use error::{Error, ErrorKind};
use ::Result;
use reader::FbxEvent;

pub struct Parser {
    pos: u64,
}

impl Parser {
    pub fn new() -> Self {
        Parser {
            pos: 0,
        }
    }
    pub fn next<R: Read>(&mut self, _reader: &mut R) -> Result<FbxEvent> {
        Err(Error::new(self.pos, ErrorKind::Unimplemented("Parser is not implemented yet".to_string())))
    }
}
<commit_msg>Add modes to parser<commit_after>use std::io::Read;
use error::{Error, ErrorKind};
use ::Result;
use reader::FbxEvent;

#[derive(Clone, Copy, PartialEq, Eq)]
enum ParserMode {
    /// Reading magic binary (i.e. the first line)
    Magic,
    /// Reading binary FBX
    Binary,
    /// Reading ASCII FBX
    Ascii,
}

pub struct Parser {
    pos: u64,
    mode: ParserMode,
}

impl Parser {
    pub fn new() -> Self {
        Parser {
            pos: 0,
            mode: ParserMode::Magic,
        }
    }
    pub fn next<R: Read>(&mut self, reader: &mut R) -> Result<FbxEvent> {
        match self.mode {
            ParserMode::Magic => self.magic_next(reader),
            ParserMode::Binary => self.binary_next(reader),
            ParserMode::Ascii => self.ascii_next(reader),
        }
    }
    pub fn magic_next<R: Read>(&mut self, _reader: &mut R) -> Result<FbxEvent> {
        Err(Error::new(self.pos, ErrorKind::Unimplemented("Parser for magic binary is not implemented yet".to_string())))
    }
    pub fn binary_next<R: Read>(&mut self, _reader: &mut R) -> Result<FbxEvent> {
        Err(Error::new(self.pos, ErrorKind::Unimplemented("Parser for Binary FBX format is not implemented yet".to_string())))
    }
    pub fn ascii_next<R: Read>(&mut self, _reader: &mut R) -> Result<FbxEvent> {
        Err(Error::new(self.pos, ErrorKind::Unimplemented("Parser for ASCII FBX format is not implemented yet".to_string())))
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::collections::{VecDeque, vec_deque};
use std::str;
use std::cmp;
use std::mem;

use itertools::Itertools;
use rust_htslib::bcf;

pub fn match_variants(matchbcf: &str, max_dist: u32, max_len_diff: u32) -> Result<(), Box<Error>> {
    let inbcf = bcf::Reader::from_path(&"-")?;
    let mut header = bcf::Header::with_template(&inbcf.header);

    header.push_record(
        format!("##INFO=<ID=MATCHING,Number=A,Type=Integer,\
        Description=\"For each alternative allele, -1 if it does not match a variant in another VCF/BCF. \
        If it matches a variant, an id i>=0 is points to the i-th variant in the VCF/BCF (counting each \
        alternative allele separately). For indels, matching is fuzzy: distance of centres <= {}, difference of \
        lengths <= {}\">", max_dist, max_len_diff).as_bytes()
    );
    header.push_record(
        format!("##rust-bio-tools={}", env!("CARGO_PKG_VERSION")).as_bytes()
    );
    header.push_record(
        b"##rust-bio-tools-subcommand=vcf-match"
    );
    let mut outbcf = bcf::Writer::from_path(&"-", &header, false, false)?;
    let mut buffer = RecordBuffer::new(bcf::Reader::from_path(&matchbcf)?, max_dist);

    let mut rec = bcf::Record::new();
    let mut i = 0;
    loop {
        if let Err(e) = inbcf.read(&mut rec) {
            if e.is_eof() {
                break;
            }
            return Err(Box::new(e));
        }
        outbcf.translate(&mut rec);

        if let Some(rid) = rec.rid() {
            let chrom = inbcf.header.rid2name(rid);
            let pos = rec.pos();
            // move buffer to pos
            try!(buffer.fill(chrom, pos));

            let var = try!(Variant::new(&mut rec, &mut i));
            let matching = var.alleles.iter().map(|a| {
                for v in buffer.iter() {
                    if let Some(id) = var.matches(v, a, max_dist, max_len_diff) {
                        return id as i32;
                    }
                }
                -1
            }).collect_vec();

            try!(rec.push_info_integer(b"MATCHING", &matching));
            try!(outbcf.write(&rec));
        } else {
            try!(outbcf.write(&rec));
        }

        if (i) % 1000 == 0 {
            info!("{} variants written.", i);
        }
    }
    info!("{} variants written.", i);

    Ok(())
}

#[derive(Debug)]
pub struct Variant {
    id: u32,
    rid: u32,
    pos: u32,
    alleles: Vec<VariantType>
}

impl Variant {

    pub fn new(rec: &mut bcf::Record, id: &mut u32) -> Result<Self, Box<Error>> {
        let pos = rec.pos();

        let svlen = if let Ok(Some(svlen)) = rec.info(b"SVLEN").integer() {
            Some(svlen[0].abs() as u32)
        } else { None };
        let svtype = if let Ok(Some(svtype)) = rec.info(b"SVTYPE").string() {
            Some(svtype[0].to_owned())
        } else { None };
        let end = if let Ok(Some(end)) = rec.info(b"END").integer() {
            Some(end[0] as u32)
        } else { None };
        let inslen = if let Ok(Some(inslen)) = rec.info(b"INSLEN").integer() {
            Some(inslen[0] as u32)
        } else { None };
        let alleles = rec.alleles();
        let refallele = alleles[0];

        let _alleles: Vec<VariantType> = if let Some(svtype) = svtype {
            vec![
                if svtype == b"INS" {
                    let svlen = match (svlen, inslen) {
                        (Some(svlen), _)     => svlen,
                        (None, Some(inslen)) => inslen,
                        _ => {
                            return Err(Box::new(MatchError::MissingTag("SVLEN or INSLEN".to_owned())));
                        }
                    };
                    VariantType::Insertion(svlen)
                } else if svtype == b"DEL" {
                    let svlen = match(svlen, end) {
                        (Some(svlen), _)  => svlen,
                        (None, Some(end)) => end - 1 - pos,
                        _ => {
                            return Err(Box::new(MatchError::MissingTag("SVLEN or END".to_owned())));
                        }
                    };
                    VariantType::Deletion(svlen)
                } else {
                    warn!("Unsupported variant {}", try!(str::from_utf8(&svtype)));
                    VariantType::Unsupported
                }
            ]
        } else {
            let mut _alleles = Vec::with_capacity(alleles.len() - 1);
            for a in &alleles[1..] {
                _alleles.push(
                    if a.len() < refallele.len() {
                        VariantType::Deletion((refallele.len() - a.len()) as u32)
                    } else if a.len() > refallele.len() {
                        VariantType::Insertion((a.len() - refallele.len()) as u32)
                    } else if a.len() == 1 {
                        VariantType::SNV(a[0])
                    } else {
                        warn!("Unsupported variant {} -> {}", try!(str::from_utf8(refallele)), try!(str::from_utf8(a)));
                        VariantType::Unsupported
                    }
                );
            }
            _alleles
        };

        let var = Variant {
            id: *id,
            rid: rec.rid().unwrap(),
            pos: pos,
            alleles: _alleles
        };
        *id += alleles.len() as u32 - 1;
        Ok(var)
    }

    pub fn centerpoint(&self, allele: &VariantType) -> u32 {
        match allele {
            &VariantType::SNV(_) => self.pos,
            &VariantType::Insertion(_) => self.pos,
            &VariantType::Deletion(len) => (self.pos as f64 + len as f64 / 2.0) as u32,
            &VariantType::Unsupported => panic!("Unsupported variant.")
        }
    }

    pub fn matches(&self, other: &Variant, allele: &VariantType, max_dist: u32, max_len_diff: u32) -> Option<u32> {
        if allele.is_unsupported() {
            return None;
        }
        for (j, b) in other.alleles.iter().enumerate() {
            if b.is_unsupported() {
                continue;
            }
            let dist = (self.centerpoint(allele) as i32 - other.centerpoint(b) as i32).abs() as u32;
            match (allele, b) {
                (&VariantType::SNV(a), &VariantType::SNV(b)) => {
                    if a == b && dist == 0 {
                        return Some(other.id(j));
                    }
                },
                (&VariantType::Insertion(l1), &VariantType::Insertion(l2)) |
                (&VariantType::Deletion(l1), &VariantType::Deletion(l2)) => {
                    if (l1 as i32 - l2 as i32).abs() as u32 <= max_len_diff && dist <= max_dist {
                        return Some(other.id(j));
                    }
                },
                // TODO: for now, ignore complex variants
                _ => continue
            }
        }
        None
    }

    pub fn id(&self, allele: usize) -> u32 {
        self.id + allele as u32
    }
}

#[derive(Debug)]
pub enum VariantType {
    SNV(u8),
    Insertion(u32),
    Deletion(u32),
    Unsupported
}

impl VariantType {
    pub fn is_unsupported(&self) -> bool {
        match self {
            &VariantType::Unsupported => true,
            _ => false
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum MatchError {
        MissingTag(tag: String) {
            description("missing tag")
            display("missing tag {}", tag)
        }
    }
}

pub struct RecordBuffer {
    reader: bcf::Reader,
    ringbuffer: VecDeque<Variant>,
    ringbuffer2: VecDeque<Variant>,
    window: u32,
    i: u32
}

impl RecordBuffer {
    pub fn new(reader: bcf::Reader, window: u32) -> Self {
        RecordBuffer {
            reader: reader,
            ringbuffer: VecDeque::new(),
            ringbuffer2: VecDeque::new(),
            window: window,
            i: 0
        }
    }

    pub fn last_rid(&self) -> Option<u32> {
        self.ringbuffer.back().map(|var| var.rid)
    }

    pub fn next_rid(&self) -> Option<u32> {
        self.ringbuffer2.back().map(|var| var.rid)
    }

    fn swap_buffers(&mut self) {
        // swap with buffer for next rid
        mem::swap(&mut self.ringbuffer2, &mut self.ringbuffer);
        // clear second buffer
        self.ringbuffer2.clear();
    }

    fn drain_left(&mut self, rid: u32, window_start: u32) {
        // remove records too far left or from wrong rid
        let to_remove = self.ringbuffer.iter().take_while(|var| var.pos < window_start || var.rid != rid).count();
        self.ringbuffer.drain(..to_remove);
    }

    pub fn fill(&mut self, chrom: &[u8], pos: u32) -> Result<(), Box<Error>> {
        let window_start = cmp::max(pos as i32 - self.window as i32 - 1, 0) as u32;
        let window_end = pos + self.window;
        let rid = try!(self.reader.header.name2rid(chrom));

        match (self.last_rid(), self.next_rid()) {
            (Some(last_rid), _) => {
                if last_rid != rid {
                    self.swap_buffers();
                } else {
                    self.drain_left(rid, window_start);
                }
            },
            (_, Some(_)) => {
                self.swap_buffers();
                self.drain_left(rid, window_start);
            },
            _ => ()
        }

        if !self.ringbuffer2.is_empty() {
            // We have already read beyond the current rid. Hence we can't extend to the right for
            // this rid.
            return Ok(())
        }

        // extend to the right
        let mut rec = bcf::Record::new();
        loop {
            if let Err(e) = self.reader.read(&mut rec) {
                if e.is_eof() {
                    break;
                }
                return Err(Box::new(e));
            }
            let pos = rec.pos();
            let alt_count = rec.alleles().len() as u32 - 1;
            if let Some(rec_rid) = rec.rid() {
                if rec_rid == rid {
                    if pos > window_end {
                        // Record is beyond our window. Store it anyways but stop.
                        self.ringbuffer.push_back(try!(Variant::new(&mut rec, &mut self.i)));
                        break;
                    } else if pos >= window_start {
                        // Record is within our window.
                        self.ringbuffer.push_back(try!(Variant::new(&mut rec, &mut self.i)));
                    } else {
                        // Record is upstream of our window, ignore it
                        self.i += alt_count;
                        continue
                    }
                } else if rec_rid > rid {
                    // record comes from next rid. Store it in second buffer but stop filling.
                    self.ringbuffer2.push_back(try!(Variant::new(&mut rec, &mut self.i)));
                    break;
                } else {
                    // Record comes from previous rid. Ignore it.
                    self.i += alt_count;
                    continue;
                }
            } else {
                // skip records without proper rid
                self.i += alt_count;
                continue;
            }
        }

        Ok(())
    }

    pub fn iter(&self) -> vec_deque::Iter<Variant> {
        self.ringbuffer.iter()
    }
}
<commit_msg>Add todo.<commit_after>use std::error::Error;
use std::collections::{VecDeque, vec_deque};
use std::str;
use std::cmp;
use std::mem;

use itertools::Itertools;
use rust_htslib::bcf;

pub fn match_variants(matchbcf: &str, max_dist: u32, max_len_diff: u32) -> Result<(), Box<Error>> {
    let inbcf = bcf::Reader::from_path(&"-")?;
    let mut header = bcf::Header::with_template(&inbcf.header);

    header.push_record(
        format!("##INFO=<ID=MATCHING,Number=A,Type=Integer,\
        Description=\"For each alternative allele, -1 if it does not match a variant in another VCF/BCF. \
        If it matches a variant, an id i>=0 is points to the i-th variant in the VCF/BCF (counting each \
        alternative allele separately). For indels, matching is fuzzy: distance of centres <= {}, difference of \
        lengths <= {}\">", max_dist, max_len_diff).as_bytes()
    );
    header.push_record(
        format!("##rust-bio-tools={}", env!("CARGO_PKG_VERSION")).as_bytes()
    );
    header.push_record(
        b"##rust-bio-tools-subcommand=vcf-match"
    );
    let mut outbcf = bcf::Writer::from_path(&"-", &header, false, false)?;
    // TODO switch to bcf::RecordBuffer.
    let mut buffer = RecordBuffer::new(bcf::Reader::from_path(&matchbcf)?, max_dist);

    let mut rec = bcf::Record::new();
    let mut i = 0;
    loop {
        if let Err(e) = inbcf.read(&mut rec) {
            if e.is_eof() {
                break;
            }
            return Err(Box::new(e));
        }
        outbcf.translate(&mut rec);

        if let Some(rid) = rec.rid() {
            let chrom = inbcf.header.rid2name(rid);
            let pos = rec.pos();
            // move buffer to pos
            try!(buffer.fill(chrom, pos));

            let var = try!(Variant::new(&mut rec, &mut i));
            let matching = var.alleles.iter().map(|a| {
                for v in buffer.iter() {
                    if let Some(id) = var.matches(v, a, max_dist, max_len_diff) {
                        return id as i32;
                    }
                }
                -1
            }).collect_vec();

            try!(rec.push_info_integer(b"MATCHING", &matching));
            try!(outbcf.write(&rec));
        } else {
            try!(outbcf.write(&rec));
        }

        if (i) % 1000 == 0 {
            info!("{} variants written.", i);
        }
    }
    info!("{} variants written.", i);

    Ok(())
}

#[derive(Debug)]
pub struct Variant {
    id: u32,
    rid: u32,
    pos: u32,
    alleles: Vec<VariantType>
}

impl Variant {

    pub fn new(rec: &mut bcf::Record, id: &mut u32) -> Result<Self, Box<Error>> {
        let pos = rec.pos();

        let svlen = if let Ok(Some(svlen)) = rec.info(b"SVLEN").integer() {
            Some(svlen[0].abs() as u32)
        } else { None };
        let svtype = if let Ok(Some(svtype)) = rec.info(b"SVTYPE").string() {
            Some(svtype[0].to_owned())
        } else { None };
        let end = if let Ok(Some(end)) = rec.info(b"END").integer() {
            Some(end[0] as u32)
        } else { None };
        let inslen = if let Ok(Some(inslen)) = rec.info(b"INSLEN").integer() {
            Some(inslen[0] as u32)
        } else { None };
        let alleles = rec.alleles();
        let refallele = alleles[0];

        let _alleles: Vec<VariantType> = if let Some(svtype) = svtype {
            vec![
                if svtype == b"INS" {
                    let svlen = match (svlen, inslen) {
                        (Some(svlen), _)     => svlen,
                        (None, Some(inslen)) => inslen,
                        _ => {
                            return Err(Box::new(MatchError::MissingTag("SVLEN or INSLEN".to_owned())));
                        }
                    };
                    VariantType::Insertion(svlen)
                } else if svtype == b"DEL" {
                    let svlen = match(svlen, end) {
                        (Some(svlen), _)  => svlen,
                        (None, Some(end)) => end - 1 - pos,
                        _ => {
                            return Err(Box::new(MatchError::MissingTag("SVLEN or END".to_owned())));
                        }
                    };
                    VariantType::Deletion(svlen)
                } else {
                    warn!("Unsupported variant {}", try!(str::from_utf8(&svtype)));
                    VariantType::Unsupported
                }
            ]
        } else {
            let mut _alleles = Vec::with_capacity(alleles.len() - 1);
            for a in &alleles[1..] {
                _alleles.push(
                    if a.len() < refallele.len() {
                        VariantType::Deletion((refallele.len() - a.len()) as u32)
                    } else if a.len() > refallele.len() {
                        VariantType::Insertion((a.len() - refallele.len()) as u32)
                    } else if a.len() == 1 {
                        VariantType::SNV(a[0])
                    } else {
                        warn!("Unsupported variant {} -> {}", try!(str::from_utf8(refallele)), try!(str::from_utf8(a)));
                        VariantType::Unsupported
                    }
                );
            }
            _alleles
        };

        let var = Variant {
            id: *id,
            rid: rec.rid().unwrap(),
            pos: pos,
            alleles: _alleles
        };
        *id += alleles.len() as u32 - 1;
        Ok(var)
    }

    pub fn centerpoint(&self, allele: &VariantType) -> u32 {
        match allele {
            &VariantType::SNV(_) => self.pos,
            &VariantType::Insertion(_) => self.pos,
            &VariantType::Deletion(len) => (self.pos as f64 + len as f64 / 2.0) as u32,
            &VariantType::Unsupported => panic!("Unsupported variant.")
        }
    }

    pub fn matches(&self, other: &Variant, allele: &VariantType, max_dist: u32, max_len_diff: u32) -> Option<u32> {
        if allele.is_unsupported() {
            return None;
        }
        for (j, b) in other.alleles.iter().enumerate() {
            if b.is_unsupported() {
                continue;
            }
            let dist = (self.centerpoint(allele) as i32 - other.centerpoint(b) as i32).abs() as u32;
            match (allele, b) {
                (&VariantType::SNV(a), &VariantType::SNV(b)) => {
                    if a == b && dist == 0 {
                        return Some(other.id(j));
                    }
                },
                (&VariantType::Insertion(l1), &VariantType::Insertion(l2)) |
                (&VariantType::Deletion(l1), &VariantType::Deletion(l2)) => {
                    if (l1 as i32 - l2 as i32).abs() as u32 <= max_len_diff && dist <= max_dist {
                        return Some(other.id(j));
                    }
                },
                // TODO: for now, ignore complex variants
                _ => continue
            }
        }
        None
    }

    pub fn id(&self, allele: usize) -> u32 {
        self.id + allele as u32
    }
}

#[derive(Debug)]
pub enum VariantType {
    SNV(u8),
    Insertion(u32),
    Deletion(u32),
    Unsupported
}

impl VariantType {
    pub fn is_unsupported(&self) -> bool {
        match self {
            &VariantType::Unsupported => true,
            _ => false
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum MatchError {
        MissingTag(tag: String) {
            description("missing tag")
            display("missing tag {}", tag)
        }
    }
}

pub struct RecordBuffer {
    reader: bcf::Reader,
    ringbuffer: VecDeque<Variant>,
    ringbuffer2: VecDeque<Variant>,
    window: u32,
    i: u32
}

impl RecordBuffer {
    pub fn new(reader: bcf::Reader, window: u32) -> Self {
        RecordBuffer {
            reader: reader,
            ringbuffer: VecDeque::new(),
            ringbuffer2: VecDeque::new(),
            window: window,
            i: 0
        }
    }

    pub fn last_rid(&self) -> Option<u32> {
        self.ringbuffer.back().map(|var| var.rid)
    }

    pub fn next_rid(&self) -> Option<u32> {
        self.ringbuffer2.back().map(|var| var.rid)
    }

    fn swap_buffers(&mut self) {
        // swap with buffer for next rid
        mem::swap(&mut self.ringbuffer2, &mut self.ringbuffer);
        // clear second buffer
        self.ringbuffer2.clear();
    }

    fn drain_left(&mut self, rid: u32, window_start: u32) {
        // remove records too far left or from wrong rid
        let to_remove = self.ringbuffer.iter().take_while(|var| var.pos < window_start || var.rid != rid).count();
        self.ringbuffer.drain(..to_remove);
    }

    pub fn fill(&mut self, chrom: &[u8], pos: u32) -> Result<(), Box<Error>> {
        let window_start = cmp::max(pos as i32 - self.window as i32 - 1, 0) as u32;
        let window_end = pos + self.window;
        let rid = try!(self.reader.header.name2rid(chrom));

        match (self.last_rid(), self.next_rid()) {
            (Some(last_rid), _) => {
                if last_rid != rid {
                    self.swap_buffers();
                } else {
                    self.drain_left(rid, window_start);
                }
            },
            (_, Some(_)) => {
                self.swap_buffers();
                self.drain_left(rid, window_start);
            },
            _ => ()
        }

        if !self.ringbuffer2.is_empty() {
            // We have already read beyond the current rid. Hence we can't extend to the right for
            // this rid.
            return Ok(())
        }

        // extend to the right
        let mut rec = bcf::Record::new();
        loop {
            if let Err(e) = self.reader.read(&mut rec) {
                if e.is_eof() {
                    break;
                }
                return Err(Box::new(e));
            }
            let pos = rec.pos();
            let alt_count = rec.alleles().len() as u32 - 1;
            if let Some(rec_rid) = rec.rid() {
                if rec_rid == rid {
                    if pos > window_end {
                        // Record is beyond our window. Store it anyways but stop.
                        self.ringbuffer.push_back(try!(Variant::new(&mut rec, &mut self.i)));
                        break;
                    } else if pos >= window_start {
                        // Record is within our window.
                        self.ringbuffer.push_back(try!(Variant::new(&mut rec, &mut self.i)));
                    } else {
                        // Record is upstream of our window, ignore it
                        self.i += alt_count;
                        continue
                    }
                } else if rec_rid > rid {
                    // record comes from next rid. Store it in second buffer but stop filling.
                    self.ringbuffer2.push_back(try!(Variant::new(&mut rec, &mut self.i)));
                    break;
                } else {
                    // Record comes from previous rid. Ignore it.
                    self.i += alt_count;
                    continue;
                }
            } else {
                // skip records without proper rid
                self.i += alt_count;
                continue;
            }
        }

        Ok(())
    }

    pub fn iter(&self) -> vec_deque::Iter<Variant> {
        self.ringbuffer.iter()
    }
}
<|endoftext|>


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

//! Implementation of the install aspects of the compiler.
//!
//! This module is responsible for installing the standard library,
//! compiler, and documentation.

use std::env;
use std::fs;
use std::path::{Path, PathBuf, Component};
use std::process::Command;

use Build;
use dist::{sanitize_sh, tmpdir};

/// Installs everything.
pub fn install(build: &Build, stage: u32, host: &str) {
    let prefix_default = PathBuf::from("/usr/local");
    let docdir_default = PathBuf::from("share/doc/rust");
    let mandir_default = PathBuf::from("share/man");
    let libdir_default = PathBuf::from("lib");
    let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
    let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
    let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
    let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);

    let docdir = prefix.join(docdir);
    let libdir = prefix.join(libdir);
    let mandir = prefix.join(mandir);

    let destdir = env::var_os("DESTDIR").map(PathBuf::from);

    let prefix = add_destdir(&prefix, &destdir);
    let docdir = add_destdir(&docdir, &destdir);
    let libdir = add_destdir(&libdir, &destdir);
    let mandir = add_destdir(&mandir, &destdir);

    let empty_dir = build.out.join("tmp/empty_dir");
    t!(fs::create_dir_all(&empty_dir));
    if build.config.docs {
        install_sh(&build, "docs", "rust-docs", &build.rust_package_vers(),
                   stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
    }

    for target in build.config.target.iter() {
        install_sh(&build, "std", "rust-std", &build.rust_package_vers(),
                   stage, target, &prefix, &docdir, &libdir, &mandir, &empty_dir);
    }

    install_sh(&build, "rustc", "rustc", &build.rust_package_vers(),
               stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);

    if build.config.extended {
        install_sh(&build, "cargo", "cargo", &build.cargo_package_vers(),
                   stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
        install_sh(&build, "rls", "rls", &build.rls_package_vers(),
                   stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
    }

    t!(fs::remove_dir_all(&empty_dir));
}

fn install_sh(build: &Build, package: &str, name: &str, version: &str, stage: u32, host: &str,
              prefix: &Path, docdir: &Path, libdir: &Path, mandir: &Path, empty_dir: &Path) {
    println!("Install {} stage{} ({})", package, stage, host);
    let package_name = format!("{}-{}-{}", name, version, host);

    let mut cmd = Command::new("sh");
    cmd.current_dir(empty_dir)
       .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
       .arg(format!("--prefix={}", sanitize_sh(prefix)))
       .arg(format!("--docdir={}", sanitize_sh(docdir)))
       .arg(format!("--libdir={}", sanitize_sh(libdir)))
       .arg(format!("--mandir={}", sanitize_sh(mandir)))
       .arg("--disable-ldconfig");
    build.run(&mut cmd);
}

fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
    let mut ret = match *destdir {
        Some(ref dest) => dest.clone(),
        None => return path.to_path_buf(),
    };
    for part in path.components() {
        match part {
            Component::Normal(s) => ret.push(s),
            _ => {}
        }
    }
    return ret
}
<commit_msg>rustbuild: install rustc after cargo and rls<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of the install aspects of the compiler.
//!
//! This module is responsible for installing the standard library,
//! compiler, and documentation.

use std::env;
use std::fs;
use std::path::{Path, PathBuf, Component};
use std::process::Command;

use Build;
use dist::{sanitize_sh, tmpdir};

/// Installs everything.
pub fn install(build: &Build, stage: u32, host: &str) {
    let prefix_default = PathBuf::from("/usr/local");
    let docdir_default = PathBuf::from("share/doc/rust");
    let mandir_default = PathBuf::from("share/man");
    let libdir_default = PathBuf::from("lib");
    let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
    let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
    let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
    let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);

    let docdir = prefix.join(docdir);
    let libdir = prefix.join(libdir);
    let mandir = prefix.join(mandir);

    let destdir = env::var_os("DESTDIR").map(PathBuf::from);

    let prefix = add_destdir(&prefix, &destdir);
    let docdir = add_destdir(&docdir, &destdir);
    let libdir = add_destdir(&libdir, &destdir);
    let mandir = add_destdir(&mandir, &destdir);

    let empty_dir = build.out.join("tmp/empty_dir");
    t!(fs::create_dir_all(&empty_dir));
    if build.config.docs {
        install_sh(&build, "docs", "rust-docs", &build.rust_package_vers(),
                   stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
    }

    for target in build.config.target.iter() {
        install_sh(&build, "std", "rust-std", &build.rust_package_vers(),
                   stage, target, &prefix, &docdir, &libdir, &mandir, &empty_dir);
    }

    if build.config.extended {
        install_sh(&build, "cargo", "cargo", &build.cargo_package_vers(),
                   stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
        install_sh(&build, "rls", "rls", &build.rls_package_vers(),
                   stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);
    }

    install_sh(&build, "rustc", "rustc", &build.rust_package_vers(),
               stage, host, &prefix, &docdir, &libdir, &mandir, &empty_dir);

    t!(fs::remove_dir_all(&empty_dir));
}

fn install_sh(build: &Build, package: &str, name: &str, version: &str, stage: u32, host: &str,
              prefix: &Path, docdir: &Path, libdir: &Path, mandir: &Path, empty_dir: &Path) {
    println!("Install {} stage{} ({})", package, stage, host);
    let package_name = format!("{}-{}-{}", name, version, host);

    let mut cmd = Command::new("sh");
    cmd.current_dir(empty_dir)
       .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
       .arg(format!("--prefix={}", sanitize_sh(prefix)))
       .arg(format!("--docdir={}", sanitize_sh(docdir)))
       .arg(format!("--libdir={}", sanitize_sh(libdir)))
       .arg(format!("--mandir={}", sanitize_sh(mandir)))
       .arg("--disable-ldconfig");
    build.run(&mut cmd);
}

fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
    let mut ret = match *destdir {
        Some(ref dest) => dest.clone(),
        None => return path.to_path_buf(),
    };
    for part in path.components() {
        match part {
            Component::Normal(s) => ret.push(s),
            _ => {}
        }
    }
    return ret
}
<|endoftext|>