<commit_before>#![feature(test)]

extern crate test;
extern crate num;
extern crate rand;

use std::mem::replace;
use test::Bencher;
use num::{BigInt, BigUint, Zero, One, FromPrimitive};
use num::bigint::RandBigInt;
use rand::{SeedableRng, StdRng};

fn get_rng() -> StdRng {
    let seed: &[_] = &[1, 2, 3, 4];
    SeedableRng::from_seed(seed)
}

fn multiply_bench(b: &mut Bencher, xbits: usize, ybits: usize) {
    let mut rng = get_rng();
    let x = rng.gen_bigint(xbits);
    let y = rng.gen_bigint(ybits);

    b.iter(|| &x * &y);
}

fn divide_bench(b: &mut Bencher, xbits: usize, ybits: usize) {
    let mut rng = get_rng();
    let x = rng.gen_bigint(xbits);
    let y = rng.gen_bigint(ybits);

    b.iter(|| &x / &y);
}

fn factorial(n: usize) -> BigUint {
    let mut f: BigUint = One::one();
    for i in 1..(n+1) {
        let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
        f = f * bu;
    }
    f
}

fn fib(n: usize) -> BigUint {
    let mut f0: BigUint = Zero::zero();
    let mut f1: BigUint = One::one();
    for _ in 0..n {
        let f2 = f0 + &f1;
        f0 = replace(&mut f1, f2);
    }
    f0
}

#[bench]
fn multiply_0(b: &mut Bencher) {
    multiply_bench(b, 1 << 8, 1 << 8);
}

#[bench]
fn multiply_1(b: &mut Bencher) {
    multiply_bench(b, 1 << 8, 1 << 16);
}

#[bench]
fn multiply_2(b: &mut Bencher) {
    multiply_bench(b, 1 << 16, 1 << 16);
}

#[bench]
fn divide_0(b: &mut Bencher) {
    divide_bench(b, 1 << 8, 1 << 6);
}

#[bench]
fn divide_1(b: &mut Bencher) {
    divide_bench(b, 1 << 12, 1 << 8);
}

#[bench]
fn divide_2(b: &mut Bencher) {
    divide_bench(b, 1 << 16, 1 << 12);
}

#[bench]
fn factorial_100(b: &mut Bencher) {
    b.iter(|| factorial(100));
}

#[bench]
fn fib_100(b: &mut Bencher) {
    b.iter(|| fib(100));
}

#[bench]
fn fac_to_string(b: &mut Bencher) {
    let fac = factorial(100);
    b.iter(|| fac.to_string());
}

#[bench]
fn fib_to_string(b: &mut Bencher) {
    let fib = fib(100);
    b.iter(|| fib.to_string());
}

fn to_str_radix_bench(b: &mut Bencher, radix: u32) {
    let mut rng = get_rng();
    let x = rng.gen_bigint(1009);
    b.iter(|| x.to_str_radix(radix));
}

#[bench]
fn to_str_radix_02(b: &mut Bencher) {
    to_str_radix_bench(b, 2);
}

#[bench]
fn to_str_radix_08(b: &mut Bencher) {
    to_str_radix_bench(b, 8);
}

#[bench]
fn to_str_radix_10(b: &mut Bencher) {
    to_str_radix_bench(b, 10);
}

#[bench]
fn to_str_radix_16(b: &mut Bencher) {
    to_str_radix_bench(b, 16);
}

#[bench]
fn to_str_radix_36(b: &mut Bencher) {
    to_str_radix_bench(b, 36);
}

fn from_str_radix_bench(b: &mut Bencher, radix: u32) {
    use num::Num;
    let mut rng = get_rng();
    let x = rng.gen_bigint(1009);
    let s = x.to_str_radix(radix);
    assert_eq!(x, BigInt::from_str_radix(&s, radix).unwrap());
    b.iter(|| BigInt::from_str_radix(&s, radix));
}

#[bench]
fn from_str_radix_02(b: &mut Bencher) {
    from_str_radix_bench(b, 2);
}

#[bench]
fn from_str_radix_08(b: &mut Bencher) {
    from_str_radix_bench(b, 8);
}

#[bench]
fn from_str_radix_10(b: &mut Bencher) {
    from_str_radix_bench(b, 10);
}

#[bench]
fn from_str_radix_16(b: &mut Bencher) {
    from_str_radix_bench(b, 16);
}

#[bench]
fn from_str_radix_36(b: &mut Bencher) {
    from_str_radix_bench(b, 36);
}

#[bench]
fn shr(b: &mut Bencher) {
    let n = { let one : BigUint = One::one(); one << 1000 };
    b.iter(|| {
        let mut m = n.clone();
        for _ in 0..10 {
            m = m >> 1;
        }
    })
}
<commit_msg>bigint: add a Hash test<commit_after>#![feature(test)]

extern crate test;
extern crate num;
extern crate rand;

use std::mem::replace;
use test::Bencher;
use num::{BigInt, BigUint, Zero, One, FromPrimitive};
use num::bigint::RandBigInt;
use rand::{SeedableRng, StdRng};

fn get_rng() -> StdRng {
    let seed: &[_] = &[1, 2, 3, 4];
    SeedableRng::from_seed(seed)
}

fn multiply_bench(b: &mut Bencher, xbits: usize, ybits: usize) {
    let mut rng = get_rng();
    let x = rng.gen_bigint(xbits);
    let y = rng.gen_bigint(ybits);

    b.iter(|| &x * &y);
}

fn divide_bench(b: &mut Bencher, xbits: usize, ybits: usize) {
    let mut rng = get_rng();
    let x = rng.gen_bigint(xbits);
    let y = rng.gen_bigint(ybits);

    b.iter(|| &x / &y);
}

fn factorial(n: usize) -> BigUint {
    let mut f: BigUint = One::one();
    for i in 1..(n+1) {
        let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
        f = f * bu;
    }
    f
}

fn fib(n: usize) -> BigUint {
    let mut f0: BigUint = Zero::zero();
    let mut f1: BigUint = One::one();
    for _ in 0..n {
        let f2 = f0 + &f1;
        f0 = replace(&mut f1, f2);
    }
    f0
}

#[bench]
fn multiply_0(b: &mut Bencher) {
    multiply_bench(b, 1 << 8, 1 << 8);
}

#[bench]
fn multiply_1(b: &mut Bencher) {
    multiply_bench(b, 1 << 8, 1 << 16);
}

#[bench]
fn multiply_2(b: &mut Bencher) {
    multiply_bench(b, 1 << 16, 1 << 16);
}

#[bench]
fn divide_0(b: &mut Bencher) {
    divide_bench(b, 1 << 8, 1 << 6);
}

#[bench]
fn divide_1(b: &mut Bencher) {
    divide_bench(b, 1 << 12, 1 << 8);
}

#[bench]
fn divide_2(b: &mut Bencher) {
    divide_bench(b, 1 << 16, 1 << 12);
}

#[bench]
fn factorial_100(b: &mut Bencher) {
    b.iter(|| factorial(100));
}

#[bench]
fn fib_100(b: &mut Bencher) {
    b.iter(|| fib(100));
}

#[bench]
fn fac_to_string(b: &mut Bencher) {
    let fac = factorial(100);
    b.iter(|| fac.to_string());
}

#[bench]
fn fib_to_string(b: &mut Bencher) {
    let fib = fib(100);
    b.iter(|| fib.to_string());
}

fn to_str_radix_bench(b: &mut Bencher, radix: u32) {
    let mut rng = get_rng();
    let x = rng.gen_bigint(1009);
    b.iter(|| x.to_str_radix(radix));
}

#[bench]
fn to_str_radix_02(b: &mut Bencher) {
    to_str_radix_bench(b, 2);
}

#[bench]
fn to_str_radix_08(b: &mut Bencher) {
    to_str_radix_bench(b, 8);
}

#[bench]
fn to_str_radix_10(b: &mut Bencher) {
    to_str_radix_bench(b, 10);
}

#[bench]
fn to_str_radix_16(b: &mut Bencher) {
    to_str_radix_bench(b, 16);
}

#[bench]
fn to_str_radix_36(b: &mut Bencher) {
    to_str_radix_bench(b, 36);
}

fn from_str_radix_bench(b: &mut Bencher, radix: u32) {
    use num::Num;
    let mut rng = get_rng();
    let x = rng.gen_bigint(1009);
    let s = x.to_str_radix(radix);
    assert_eq!(x, BigInt::from_str_radix(&s, radix).unwrap());
    b.iter(|| BigInt::from_str_radix(&s, radix));
}

#[bench]
fn from_str_radix_02(b: &mut Bencher) {
    from_str_radix_bench(b, 2);
}

#[bench]
fn from_str_radix_08(b: &mut Bencher) {
    from_str_radix_bench(b, 8);
}

#[bench]
fn from_str_radix_10(b: &mut Bencher) {
    from_str_radix_bench(b, 10);
}

#[bench]
fn from_str_radix_16(b: &mut Bencher) {
    from_str_radix_bench(b, 16);
}

#[bench]
fn from_str_radix_36(b: &mut Bencher) {
    from_str_radix_bench(b, 36);
}

#[bench]
fn shr(b: &mut Bencher) {
    let n = { let one : BigUint = One::one(); one << 1000 };
    b.iter(|| {
        let mut m = n.clone();
        for _ in 0..10 {
            m = m >> 1;
        }
    })
}

#[bench]
fn hash(b: &mut Bencher) {
    use std::collections::HashSet;
    let mut rng = get_rng();
    let v: Vec<BigInt> = (1000..2000).map(|bits| rng.gen_bigint(bits)).collect();
    b.iter(|| {
        let h: HashSet<&BigInt> = v.iter().collect();
        assert_eq!(h.len(), v.len());
    });
}
<|endoftext|>


<commit_before>use env_logger::Builder as LogBuilder;
use log::{debug,
          error,
          info,
          LevelFilter};
use regex::Regex;
use reqwest::Url;
use std::{error,
          fmt,
          fs::{self,
               File},
          io::{self,
               BufRead},
          path::PathBuf,
          process::Command,
          str::FromStr};
use structopt::StructOpt;

lazy_static::lazy_static! {
    static ref RE: Regex = Regex::new(r"\*\s(?P<ident>.*) \((?P<target>.*)\)").expect("valid regex");
}

#[allow(dead_code)]
const ACCEPTANCE_URL: &str = "https://bldr.acceptance.habitat.sh";
const PACKAGES_ENDPOINT: &str = "v1/depot/pkgs/";
const DOWNLOAD_ENDPOINT: &str = "download";

/// Wraps an owned `String` and implements the `Error` trait for it.
#[derive(Debug)]
struct StringError(String);

impl StringError {
    fn new(error: String) -> Self { Self(error) }
}

impl error::Error for StringError {}

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
}

#[derive(Debug, PartialEq)]
struct Package {
    ident:  String,
    target: String,
}

impl Package {
    /// Create a new package
    fn new(ident: String, target: String) -> Self { Self { ident, target } }

    /// The filename to write the package to
    fn filename(&self) -> PathBuf {
        PathBuf::from_str(&format!("{}-{}.hart", self.ident.replace("/", "-"), self.target)).expect("valid path")
    }

    /// The url to download the package
    fn url(&self, base: &str) -> Result<Url, Box<dyn std::error::Error>> {
        let params = &[("target", &self.target)];
        let url = Url::parse(base)?.join(PACKAGES_ENDPOINT)?
                                   .join(&format!("{}/", self.ident))?
                                   .join(DOWNLOAD_ENDPOINT)?;
        let url = Url::parse_with_params(url.as_str(), params)?;
        Ok(url)
    }

    /// Download the package from `base_url` and save the hart file in `base_dir`
    fn download(&self,
                base_url: &str,
                base_dir: &PathBuf)
                -> Result<(), Box<dyn std::error::Error>> {
        let url = self.url(base_url)?;
        let output_path = base_dir.join(self.filename());
        debug!("Downloading package from '{}' and writing to {:?}",
               url,
               output_path.as_os_str());
        let mut response = reqwest::get(url)?.error_for_status()?;
        let mut output_file = File::create(&output_path)?;
        let written = io::copy(&mut response, &mut output_file)?;
        info!("Wrote {} bytes to {:?}", written, output_path.as_os_str());
        Ok(())
    }

    /// Upload the package that has been saved in `base_dir` using the hab command
    fn upload(&self,
              base_dir: &PathBuf,
              auth: &str,
              channel: &Option<String>,
              force: bool)
              -> Result<(), Box<dyn std::error::Error>> {
        let path = base_dir.join(self.filename());
        let mut command = Command::new("hab");
        command.arg("pkg").arg("upload");
        command.arg("--auth").arg(auth);
        if let Some(channel) = channel {
            command.arg("--channel").arg(channel);
        }
        if force {
            command.arg("--force");
        }
        command.arg(&path);
        let command_str = format!("{:?}", command).replace("\"", "");
        debug!("Uploading {:?} with command '{}'",
               path.as_os_str(),
               command_str);
        let status = command.status()?;
        if !status.success() {
            return Err(Box::new(StringError::new(format!("Failed to execute \
                                                          '{}' with {}",
                                                         command_str, status))));
        };

        info!("Uploaded '{}' with target '{}'", self.ident, self.target);
        Ok(())
    }
}

impl FromStr for Package {
    type Err = Box<dyn std::error::Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let captures = RE.captures(&s).ok_or("failed to parse")?;
        Ok(Self::new(String::from(&captures["ident"]),
                     String::from(&captures["target"])))
    }
}

#[derive(StructOpt, Debug)]
#[structopt()]
struct Opt {
    /// Builder live authentication token
    #[structopt(long, short = "z")]
    auth: String,

    /// The builder acceptance url
    #[structopt(default_value = "ACCEPTANCE_URL", long)]
    acceptance_url: String,

    /// The channel to tag packages with when promoting to live
    #[structopt(long, short)]
    channel: Option<String>,

    /// Force upload the packages to live
    #[structopt(long)]
    force: bool,

    /// The temporary directory to write hart files to
    #[structopt(default_value = "one-off-release-tmp-dir", long)]
    tmp_dir: PathBuf,

    /// Log level
    #[structopt(default_value = "info",
                short,
                long,
                possible_values(&["trace", "debug", "info", "warn", "error"]))]
    log_level: LevelFilter,
}

fn main() {
    let Opt { auth,
              acceptance_url,
              channel,
              force,
              tmp_dir,
              log_level, } = Opt::from_args();

    LogBuilder::new().default_format_timestamp(false)
                     .default_format_module_path(false)
                     .filter_level(log_level)
                     .filter(Some("hyper"), LevelFilter::Warn)
                     .filter(Some("reqwest"), LevelFilter::Warn)
                     .filter(Some("tokio_reactor"), LevelFilter::Warn)
                     .init();

    // Create the temporary output directory
    if let Err(e) = fs::create_dir(&tmp_dir) {
        error!("Failed to create {:?}, err: {}", tmp_dir, e);
        return;
    };

    // Read all lines from stdin until an empty line
    let stdin = io::stdin();
    let lines = stdin.lock()
                     .lines()
                     .map(|l| l.expect("to read a line"))
                     .take_while(|l| !l.is_empty())
                     .collect::<Vec<_>>();

    // Parse each line into a package
    let packages = lines.iter()
                        .filter_map(|l| {
                            let package_result = l.parse();
                            if package_result.is_err() {
                                error!("Failed to parse line '{}'", l);
                                return None;
                            }
                            package_result.ok()
                        })
                        .collect::<Vec<Package>>();

    // Download all packages
    for p in packages.iter() {
        if let Err(e) = p.download(&acceptance_url, &tmp_dir) {
            error!("Failed to download {:?}, err: {}", p, e);
        }
    }

    // Upload all packages
    for p in packages.iter() {
        if let Err(e) = p.upload(&tmp_dir, &auth, &channel, force) {
            error!("Failed to upload {:?}, err: {}", p, e);
        }
    }
}

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

    #[test]
    fn test_parse() {
        assert!("bad input".parse::<Package>().is_err());
        assert_eq!("* package (target)".parse::<Package>().unwrap(),
                   Package::new(String::from("package"), String::from("target")));
        assert_eq!("* core/hab-backline/0.84.33/20190819190300 (x86_64-linux)".parse::<Package>()
                                                                              .unwrap(),
                   Package::new(String::from("core/hab-backline/0.84.33/20190819190300"),
                                String::from("x86_64-linux")));
    }

    #[test]
    fn test_package_url() {
        let p = Package::new(String::from("package"), String::from("target"));
        assert!(p.url("bad url").is_err());
        assert_eq!(p.url("https://test.url").unwrap().as_str(),
                   "https://test.url/v1/depot/pkgs/package/download?target=target");
        let p = Package::new(String::from("core/hab-backline/0.84.33/20190819190300"),
                             String::from("x86_64-linux"));
        assert_eq!(p.url(ACCEPTANCE_URL).unwrap().as_str(),
                   format!("{}/{}core/hab-backline/0.84.33/20190819190300/{}?target=x86_64-linux",
                           ACCEPTANCE_URL, PACKAGES_ENDPOINT, DOWNLOAD_ENDPOINT));
    }

    #[test]
    fn test_package_filename() {
        let p = Package::new(String::from("package"), String::from("target"));
        assert_eq!(p.filename().as_os_str(), "package-target.hart");
        let p = Package::new(String::from("core/hab-backline/0.84.33/20190819190300"),
                             String::from("x86_64-linux"));
        assert_eq!(p.filename().as_os_str(),
                   "core-hab-backline-0.84.33-20190819190300-x86_64-linux.hart");
    }
}
<commit_msg>Use ACCEPTANCE_URL constant<commit_after>use env_logger::Builder as LogBuilder;
use log::{debug,
          error,
          info,
          LevelFilter};
use regex::Regex;
use reqwest::Url;
use std::{error,
          fmt,
          fs::{self,
               File},
          io::{self,
               BufRead},
          path::PathBuf,
          process::Command,
          str::FromStr};
use structopt::StructOpt;

lazy_static::lazy_static! {
    static ref RE: Regex = Regex::new(r"\*\s(?P<ident>.*) \((?P<target>.*)\)").expect("valid regex");
}

#[allow(dead_code)]
const ACCEPTANCE_URL: &str = "https://bldr.acceptance.habitat.sh";
const PACKAGES_ENDPOINT: &str = "v1/depot/pkgs/";
const DOWNLOAD_ENDPOINT: &str = "download";

/// Wraps an owned `String` and implements the `Error` trait for it.
#[derive(Debug)]
struct StringError(String);

impl StringError {
    fn new(error: String) -> Self { Self(error) }
}

impl error::Error for StringError {}

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
}

#[derive(Debug, PartialEq)]
struct Package {
    ident:  String,
    target: String,
}

impl Package {
    /// Create a new package
    fn new(ident: String, target: String) -> Self { Self { ident, target } }

    /// The filename to write the package to
    fn filename(&self) -> PathBuf {
        PathBuf::from_str(&format!("{}-{}.hart", self.ident.replace("/", "-"), self.target)).expect("valid path")
    }

    /// The url to download the package
    fn url(&self, base: &str) -> Result<Url, Box<dyn std::error::Error>> {
        let params = &[("target", &self.target)];
        let url = Url::parse(base)?.join(PACKAGES_ENDPOINT)?
                                   .join(&format!("{}/", self.ident))?
                                   .join(DOWNLOAD_ENDPOINT)?;
        let url = Url::parse_with_params(url.as_str(), params)?;
        Ok(url)
    }

    /// Download the package from `base_url` and save the hart file in `base_dir`
    fn download(&self,
                base_url: &str,
                base_dir: &PathBuf)
                -> Result<(), Box<dyn std::error::Error>> {
        let url = self.url(base_url)?;
        let output_path = base_dir.join(self.filename());
        debug!("Downloading package from '{}' and writing to {:?}",
               url,
               output_path.as_os_str());
        let mut response = reqwest::get(url)?.error_for_status()?;
        let mut output_file = File::create(&output_path)?;
        let written = io::copy(&mut response, &mut output_file)?;
        info!("Wrote {} bytes to {:?}", written, output_path.as_os_str());
        Ok(())
    }

    /// Upload the package that has been saved in `base_dir` using the hab command
    fn upload(&self,
              base_dir: &PathBuf,
              auth: &str,
              channel: &Option<String>,
              force: bool)
              -> Result<(), Box<dyn std::error::Error>> {
        let path = base_dir.join(self.filename());
        let mut command = Command::new("hab");
        command.arg("pkg").arg("upload");
        command.arg("--auth").arg(auth);
        if let Some(channel) = channel {
            command.arg("--channel").arg(channel);
        }
        if force {
            command.arg("--force");
        }
        command.arg(&path);
        let command_str = format!("{:?}", command).replace("\"", "");
        debug!("Uploading {:?} with command '{}'",
               path.as_os_str(),
               command_str);
        let status = command.status()?;
        if !status.success() {
            return Err(Box::new(StringError::new(format!("Failed to execute \
                                                          '{}' with {}",
                                                         command_str, status))));
        };

        info!("Uploaded '{}' with target '{}'", self.ident, self.target);
        Ok(())
    }
}

impl FromStr for Package {
    type Err = Box<dyn std::error::Error>;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let captures = RE.captures(&s).ok_or("failed to parse")?;
        Ok(Self::new(String::from(&captures["ident"]),
                     String::from(&captures["target"])))
    }
}

#[derive(StructOpt, Debug)]
#[structopt()]
struct Opt {
    /// Builder live authentication token
    #[structopt(long, short = "z")]
    auth: String,

    /// The builder acceptance url
    #[structopt(default_value = ACCEPTANCE_URL, long)]
    acceptance_url: String,

    /// The channel to tag packages with when promoting to live
    #[structopt(long, short)]
    channel: Option<String>,

    /// Force upload the packages to live
    #[structopt(long)]
    force: bool,

    /// The temporary directory to write hart files to
    #[structopt(default_value = "one-off-release-tmp-dir", long)]
    tmp_dir: PathBuf,

    /// Log level
    #[structopt(default_value = "info",
                short,
                long,
                possible_values(&["trace", "debug", "info", "warn", "error"]))]
    log_level: LevelFilter,
}

fn main() {
    let Opt { auth,
              acceptance_url,
              channel,
              force,
              tmp_dir,
              log_level, } = Opt::from_args();

    LogBuilder::new().default_format_timestamp(false)
                     .default_format_module_path(false)
                     .filter_level(log_level)
                     .filter(Some("hyper"), LevelFilter::Warn)
                     .filter(Some("reqwest"), LevelFilter::Warn)
                     .filter(Some("tokio_reactor"), LevelFilter::Warn)
                     .init();

    // Create the temporary output directory
    if let Err(e) = fs::create_dir(&tmp_dir) {
        error!("Failed to create {:?}, err: {}", tmp_dir, e);
        return;
    };

    // Read all lines from stdin until an empty line
    let stdin = io::stdin();
    let lines = stdin.lock()
                     .lines()
                     .map(|l| l.expect("to read a line"))
                     .take_while(|l| !l.is_empty())
                     .collect::<Vec<_>>();

    // Parse each line into a package
    let packages = lines.iter()
                        .filter_map(|l| {
                            let package_result = l.parse();
                            if package_result.is_err() {
                                error!("Failed to parse line '{}'", l);
                                return None;
                            }
                            package_result.ok()
                        })
                        .collect::<Vec<Package>>();

    // Download all packages
    for p in packages.iter() {
        if let Err(e) = p.download(&acceptance_url, &tmp_dir) {
            error!("Failed to download {:?}, err: {}", p, e);
        }
    }

    // Upload all packages
    for p in packages.iter() {
        if let Err(e) = p.upload(&tmp_dir, &auth, &channel, force) {
            error!("Failed to upload {:?}, err: {}", p, e);
        }
    }
}

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

    #[test]
    fn test_parse() {
        assert!("bad input".parse::<Package>().is_err());
        assert_eq!("* package (target)".parse::<Package>().unwrap(),
                   Package::new(String::from("package"), String::from("target")));
        assert_eq!("* core/hab-backline/0.84.33/20190819190300 (x86_64-linux)".parse::<Package>()
                                                                              .unwrap(),
                   Package::new(String::from("core/hab-backline/0.84.33/20190819190300"),
                                String::from("x86_64-linux")));
    }

    #[test]
    fn test_package_url() {
        let p = Package::new(String::from("package"), String::from("target"));
        assert!(p.url("bad url").is_err());
        assert_eq!(p.url("https://test.url").unwrap().as_str(),
                   "https://test.url/v1/depot/pkgs/package/download?target=target");
        let p = Package::new(String::from("core/hab-backline/0.84.33/20190819190300"),
                             String::from("x86_64-linux"));
        assert_eq!(p.url(ACCEPTANCE_URL).unwrap().as_str(),
                   format!("{}/{}core/hab-backline/0.84.33/20190819190300/{}?target=x86_64-linux",
                           ACCEPTANCE_URL, PACKAGES_ENDPOINT, DOWNLOAD_ENDPOINT));
    }

    #[test]
    fn test_package_filename() {
        let p = Package::new(String::from("package"), String::from("target"));
        assert_eq!(p.filename().as_os_str(), "package-target.hart");
        let p = Package::new(String::from("core/hab-backline/0.84.33/20190819190300"),
                             String::from("x86_64-linux"));
        assert_eq!(p.filename().as_os_str(),
                   "core-hab-backline-0.84.33-20190819190300-x86_64-linux.hart");
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::LinkedList;

use expr::{Expr, Proc, Prim};

pub struct Env {
    global: HashMap<String, Expr>,
    local: LinkedList<HashMap<String, Expr>>,
    fglobal: HashMap<String, Proc>,
    flocal: LinkedList<HashMap<String, Proc>>,
    // pglobal: HashMap<String, Box<Fn(&mut Env, Expr) -> Result<Expr, String>>>,
    // plocal: LinkedList<HashMap<String, Box<Fn(&mut Env, Expr) -> Result<Expr, String>>>>,
}

impl Env {
    pub fn new() -> Env {
        let mut env = Env {
            global: HashMap::new(),
            local: LinkedList::new(),
            fglobal: HashMap::new(),
            flocal: LinkedList::new()
            // pglobal: HashMap::new(),
            // plocal: LinkedList::new()
        };
        env.fregister("+".to_string(), Proc::Prim(Prim::Add));
        env.fregister("-".to_string(), Proc::Prim(Prim::Sub));
        env.fregister("/".to_string(), Proc::Prim(Prim::Div));
        env.fregister("*".to_string(), Proc::Prim(Prim:: Mul));
        env.fregister("concat".to_string(), Proc::Prim(Prim::Concat));
        env.fregister("funcall".to_string(), Proc::Prim(Prim::Funcall));
        env.fregister("car".to_string(), Proc::Prim(Prim::Car));
        env.fregister("cdr".to_string(), Proc::Prim(Prim::Cdr));
        env.fregister("current-time-string".to_string(), Proc::Prim(Prim::CurrentTimeString));
        env.fregister("skk-calc".to_string(), Proc::Prim(Prim::SkkCalc));
        env.fregister("skk-gadget-units-conversion".to_string(),  Proc::Prim(Prim::SkkGadgetUnitsConversion));
        env
    }
    pub fn new_local(&mut self) {
        self.local.push_front(HashMap::new());
        self.flocal.push_front(HashMap::new());
        // self.plocal.push_front(HashMap::new());
    }

    pub fn end_local(&mut self) {
        self.local.pop_front();
        self.flocal.pop_front();
        // self.plocal.pop_front();
    }

    pub fn register(&mut self, name: String, value: Expr) {
        match self.local.front_mut() {
            Some(l) => l.insert(name, value),
            None => self.global.insert(name, value)
        };
    }

    pub fn fregister(&mut self, name: String, value: Proc) {
        match self.flocal.front_mut() {
            Some(l) => l.insert(name, value),
            None => self.fglobal.insert(name, value)
        };
    }

    // pub fn pregister(&mut self, name: String, value: Box<Fn(&mut Env, Expr) -> Result<Expr, String>>) {
    //     match self.plocal.front_mut() {
    //         Some(l) => l.insert(name, value),
    //         None => self.pglobal.insert(name, value)
    //     };
    // }

    pub fn find(&self, name: &String)  -> Result<&Expr, String> {
        for m in self.local.iter() {
            match m.get(name) {
                Some(v) => return Ok(v),
                None => ()
            }
        };
        match self.global.get(name) {
            Some(v) => Ok(v),
            None => Err(format!("Variable {:} ist't bound", name))
        }
    }

    pub fn ffind(&self, name: &String)  -> Result<&Proc, String> {
        for m in self.flocal.iter() {
            match m.get(name) {
                Some(v) => return Ok(v),
                None => ()
            }
        };
        match self.fglobal.get(name) {
            Some(v) => Ok(v),
            None => Err(format!("Variable {:} ist't bound", name))
        }
    }

    // pub fn pfind(&self, name: &String)  -> Option<&Box<Fn(&mut Env, Expr) -> Result<Expr, String>>> {
    //     for map in self.plocal.iter() {
    //         match map.get(name) {
    //             Some(v) => return Some(v),
    //             None => ()
    //         }
    //     };
    //     self.pglobal.get(name)
    // }
}
<commit_msg>improve error message<commit_after>use std::collections::HashMap;
use std::collections::LinkedList;

use expr::{Expr, Proc, Prim};

pub struct Env {
    global: HashMap<String, Expr>,
    local: LinkedList<HashMap<String, Expr>>,
    fglobal: HashMap<String, Proc>,
    flocal: LinkedList<HashMap<String, Proc>>,
    // pglobal: HashMap<String, Box<Fn(&mut Env, Expr) -> Result<Expr, String>>>,
    // plocal: LinkedList<HashMap<String, Box<Fn(&mut Env, Expr) -> Result<Expr, String>>>>,
}

impl Env {
    pub fn new() -> Env {
        let mut env = Env {
            global: HashMap::new(),
            local: LinkedList::new(),
            fglobal: HashMap::new(),
            flocal: LinkedList::new()
            // pglobal: HashMap::new(),
            // plocal: LinkedList::new()
        };
        env.fregister("+".to_string(), Proc::Prim(Prim::Add));
        env.fregister("-".to_string(), Proc::Prim(Prim::Sub));
        env.fregister("/".to_string(), Proc::Prim(Prim::Div));
        env.fregister("*".to_string(), Proc::Prim(Prim:: Mul));
        env.fregister("concat".to_string(), Proc::Prim(Prim::Concat));
        env.fregister("funcall".to_string(), Proc::Prim(Prim::Funcall));
        env.fregister("car".to_string(), Proc::Prim(Prim::Car));
        env.fregister("cdr".to_string(), Proc::Prim(Prim::Cdr));
        env.fregister("current-time-string".to_string(), Proc::Prim(Prim::CurrentTimeString));
        env.fregister("skk-calc".to_string(), Proc::Prim(Prim::SkkCalc));
        env.fregister("skk-gadget-units-conversion".to_string(),  Proc::Prim(Prim::SkkGadgetUnitsConversion));
        env
    }
    pub fn new_local(&mut self) {
        self.local.push_front(HashMap::new());
        self.flocal.push_front(HashMap::new());
        // self.plocal.push_front(HashMap::new());
    }

    pub fn end_local(&mut self) {
        self.local.pop_front();
        self.flocal.pop_front();
        // self.plocal.pop_front();
    }

    pub fn register(&mut self, name: String, value: Expr) {
        match self.local.front_mut() {
            Some(l) => l.insert(name, value),
            None => self.global.insert(name, value)
        };
    }

    pub fn fregister(&mut self, name: String, value: Proc) {
        match self.flocal.front_mut() {
            Some(l) => l.insert(name, value),
            None => self.fglobal.insert(name, value)
        };
    }

    // pub fn pregister(&mut self, name: String, value: Box<Fn(&mut Env, Expr) -> Result<Expr, String>>) {
    //     match self.plocal.front_mut() {
    //         Some(l) => l.insert(name, value),
    //         None => self.pglobal.insert(name, value)
    //     };
    // }

    pub fn find(&self, name: &String)  -> Result<&Expr, String> {
        for m in self.local.iter() {
            match m.get(name) {
                Some(v) => return Ok(v),
                None => ()
            }
        };
        match self.global.get(name) {
            Some(v) => Ok(v),
            None => Err(format!("Variable {:} isn't bound", name))
        }
    }

    pub fn ffind(&self, name: &String)  -> Result<&Proc, String> {
        for m in self.flocal.iter() {
            match m.get(name) {
                Some(v) => return Ok(v),
                None => ()
            }
        };
        match self.fglobal.get(name) {
            Some(v) => Ok(v),
            None => Err(format!("Function {:} isn't bound", name))
        }
    }

    // pub fn pfind(&self, name: &String)  -> Option<&Box<Fn(&mut Env, Expr) -> Result<Expr, String>>> {
    //     for map in self.plocal.iter() {
    //         match map.get(name) {
    //             Some(v) => return Some(v),
    //             None => ()
    //         }
    //     };
    //     self.pglobal.get(name)
    // }
}
<|endoftext|>


<commit_before>#![feature(test)]
#![feature(step_by)]
extern crate raw_nbits_vec;
extern crate test;
extern crate num;

mod tests {
    macro_rules! bench_test {
        ($(($m: ident, $nbits: ident, $storage: ident)),*) => {
            mod get {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            let n = test::black_box(1000);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                            unsafe { vec.set_len(n) }
                            b.iter(|| {
                                (0..n).fold(0, |_a, i| vec.get(i));
                            })
                        }
                    }
                )*
            }
            mod resize {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        use num::Zero;
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            let n = test::black_box(1000);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::new();
                            b.iter(|| {
                                for i in (0..n).step_by(10) {
                                    vec.resize(i, $storage::zero());
                                }
                            })
                        }
                    }
                )*
            }
            mod set {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            b.iter(|| {
                                let n = test::black_box(1000);
                                let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                                unsafe { vec.set_len(n) };
                                for i in 0..n {
                                    vec.set(i, 0b1010);
                                }
                            });
                        }
                    }
                )*
            }
            mod new {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            b.iter(|| {
                                let n = test::black_box(1000);
                                let vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                                vec
                            });
                        }
                    }
                 )*
            }
            mod push {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn push(b: &mut Bencher) {
                            let n = test::black_box(1000);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                            b.iter(|| {
                                for i in 0..n {
                                    vec.push(1);
                                }
                            });
                        }
                    }
                 )*
            }
        }
    }
    bench_test! {
        (test_4bits_usize, N4, usize),
        (test_4bits_u64, N4, u64),
        (test_4bits_u32, N4, u32),
        (test_4bits_u16, N4, u16),
        (test_4bits_u8, N4, u8),
        (test_3bits_usize, N3, usize),
        (test_3bits_u64, N3, u64),
        (test_3bits_u32, N3, u32),
        (test_3bits_u16, N3, u16),
        (test_3bits_u8, N3, u8),
        (test_2bits_usize, N2, usize),
        (test_2bits_u64, N2, u64),
        (test_2bits_u32, N2, u32),
        (test_2bits_u16, N2, u16),
        (test_2bits_u8, N2, u8),
        (test_1bits_usize, N1, usize),
        (test_1bits_u64, N1, u64),
        (test_1bits_u32, N1, u32),
        (test_1bits_u16, N1, u16),
        (test_1bits_u8, N1, u8)
    }
}
<commit_msg>Fix bench warnings.<commit_after>#![feature(test)]
#![feature(step_by)]
extern crate raw_nbits_vec;
extern crate test;
extern crate num;

mod tests {
    macro_rules! bench_test {
        ($(($m: ident, $nbits: ident, $storage: ident)),*) => {
            mod get {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            let n = test::black_box(1000);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                            unsafe { vec.set_len(n) }
                            b.iter(|| {
                                (0..n).fold(0, |_a, i| vec.get(i));
                            })
                        }
                    }
                )*
            }
            mod resize {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        use num::Zero;
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            let n = test::black_box(1000);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::new();
                            b.iter(|| {
                                for i in (0..n).step_by(10) {
                                    vec.resize(i, $storage::zero());
                                }
                            })
                        }
                    }
                )*
            }
            mod set {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            b.iter(|| {
                                let n = test::black_box(1000);
                                let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                                unsafe { vec.set_len(n) };
                                for i in 0..n {
                                    vec.set(i, 0b1010);
                                }
                            });
                        }
                    }
                )*
            }
            mod new {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn bench(b: &mut Bencher) {
                            b.iter(|| {
                                let n = test::black_box(1000);
                                let vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                                vec
                            });
                        }
                    }
                 )*
            }
            mod push {
                $(
                    mod $m {
                        use raw_nbits_vec::*;
                        use test::{self, Bencher};
                        #[bench]
                        fn push(b: &mut Bencher) {
                            let n = test::black_box(1000);
                            let mut vec: NbitsVec<$nbits, $storage> = NbitsVec::with_capacity(n);
                            b.iter(|| {
                                for _i in 0..n {
                                    vec.push(1);
                                }
                            });
                        }
                    }
                 )*
            }
        }
    }
    bench_test! {
        (test_4bits_usize, N4, usize),
        (test_4bits_u64, N4, u64),
        (test_4bits_u32, N4, u32),
        (test_4bits_u16, N4, u16),
        (test_4bits_u8, N4, u8),
        (test_3bits_usize, N3, usize),
        (test_3bits_u64, N3, u64),
        (test_3bits_u32, N3, u32),
        (test_3bits_u16, N3, u16),
        (test_3bits_u8, N3, u8),
        (test_2bits_usize, N2, usize),
        (test_2bits_u64, N2, u64),
        (test_2bits_u32, N2, u32),
        (test_2bits_u16, N2, u16),
        (test_2bits_u8, N2, u8),
        (test_1bits_usize, N1, usize),
        (test_1bits_u64, N1, u64),
        (test_1bits_u32, N1, u32),
        (test_1bits_u16, N1, u16),
        (test_1bits_u8, N1, u8)
    }
}
<|endoftext|>


<commit_before>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_name = "jit"]
#![allow(raw_pointer_derive, non_camel_case_types, non_upper_case_globals)]
#![deny(unused_attributes, dead_code, unused_parens, unknown_lints, unreachable_code, unused_allocation, unused_allocation, unused_must_use)]
#![feature(alloc, libc, core, convert, plugin, unboxed_closures, optin_builtin_traits)]
#![plugin(rustc_bitflags)]
#![stable]
//! This crate wraps LibJIT in an idiomatic style.
//! For example, here's a quick example which makes a multiply function using LibJIT:
//!
//! ```rust
//! #![feature(plugin)]
//! #![plugin(jit_macros)]
//! extern crate jit;
//! #[no_link] #[macro_use]
//! extern crate jit_macros;
//! use jit::{Context, get, Type};
//! fn main() {
//!     // make a new context to make functions on
//!     let mut ctx = Context::<()>::new();
//!     jit_func!(ctx, func, mul(x: isize, y: isize) -> isize, {
//!         func.insn_return(x * y);
//!     }, |mul| {
//!         assert_eq!(mul((4, 5)), 20);
//!     });
//! }
//! ```
#[no_link] #[macro_use]
extern crate rustc_bitflags;
extern crate alloc;
extern crate libc;
extern crate libjit_sys as raw;
use raw::*;
use libc::c_void;
use std::mem;
pub use compile::Compile;
pub use context::{Builder, Context};
pub use elf::*;
pub use function::{flags, Abi, UncompiledFunction, Func, CompiledFunction};
pub use function::flags::CallFlags;
pub use label::Label;
pub use insn::{Block, Instruction, InstructionIter};
pub use types::kind::TypeKind;
pub use types::{kind, get, Type, Field, Fields, Params, CowType, StaticType, Ty, TaggedType};
pub use types::consts as typecs;
pub use value::Val;

extern fn free_data<T>(data: *mut c_void) {
    unsafe {
        let actual_data:Box<T> = mem::transmute(data);
        mem::drop(actual_data);
    }
}

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
    unsafe {
        jit_init()
    }
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
    unsafe {
        jit_uses_interpreter() != 0
    }
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
    unsafe {
        jit_supports_threads() != 0
    }
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
    unsafe {
        jit_supports_virtual_memory() != 0
    }
}
#[macro_use]
mod macros;
mod context;
mod compile;
mod elf;
mod function;
mod insn;
mod label;
mod types;
mod util;
mod value;
<commit_msg>Declare associated_consts feature<commit_after>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_name = "jit"]
#![allow(raw_pointer_derive, non_camel_case_types, non_upper_case_globals)]
#![deny(unused_attributes, dead_code, unused_parens, unknown_lints, unreachable_code, unused_allocation, unused_allocation, unused_must_use)]
#![feature(alloc, libc, core, convert, plugin, unboxed_closures, optin_builtin_traits, associated_consts)]
#![plugin(rustc_bitflags)]
#![stable]
//! This crate wraps LibJIT in an idiomatic style.
//! For example, here's a quick example which makes a multiply function using LibJIT:
//!
//! ```rust
//! #![feature(plugin)]
//! #![plugin(jit_macros)]
//! extern crate jit;
//! #[no_link] #[macro_use]
//! extern crate jit_macros;
//! use jit::{Context, get, Type};
//! fn main() {
//!     // make a new context to make functions on
//!     let mut ctx = Context::<()>::new();
//!     jit_func!(ctx, func, mul(x: isize, y: isize) -> isize, {
//!         func.insn_return(x * y);
//!     }, |mul| {
//!         assert_eq!(mul((4, 5)), 20);
//!     });
//! }
//! ```
#[no_link] #[macro_use]
extern crate rustc_bitflags;
extern crate alloc;
extern crate libc;
extern crate libjit_sys as raw;
use raw::*;
use libc::c_void;
use std::mem;
pub use compile::Compile;
pub use context::{Builder, Context};
pub use elf::*;
pub use function::{flags, Abi, UncompiledFunction, Func, CompiledFunction};
pub use function::flags::CallFlags;
pub use label::Label;
pub use insn::{Block, Instruction, InstructionIter};
pub use types::kind::TypeKind;
pub use types::{kind, get, Type, Field, Fields, Params, CowType, StaticType, Ty, TaggedType};
pub use types::consts as typecs;
pub use value::Val;

extern fn free_data<T>(data: *mut c_void) {
    unsafe {
        let actual_data:Box<T> = mem::transmute(data);
        mem::drop(actual_data);
    }
}

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
    unsafe {
        jit_init()
    }
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
    unsafe {
        jit_uses_interpreter() != 0
    }
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
    unsafe {
        jit_supports_threads() != 0
    }
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
    unsafe {
        jit_supports_virtual_memory() != 0
    }
}
#[macro_use]
mod macros;
mod context;
mod compile;
mod elf;
mod function;
mod insn;
mod label;
mod types;
mod util;
mod value;
<|endoftext|>


<commit_before>use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use std::collections::HashMap;
use std::fs;
use std::path::Path;

use super::{constants, Clip, ElmaError, utils::trim_string};

/// LGR related errors.
#[derive(Debug, PartialEq, Eq, Clone, Ord, PartialOrd)]
pub enum LGRError {
    /// Error parsing version.
    InvalidVersion(Vec<u8>),
    /// Invalid header.
    InvalidHeader(i32),
    /// Invalid clipping.
    InvalidClip(u32),
    /// Invalid transparency.
    InvalidTransparency(u32),
    /// Error parsing PictureType.
    InvalidPictureType(u32),
    /// Invalid PCX data.
    InvalidPCXData((String, Vec<u8>, Vec<u8>)),
}

/// LGR structure.
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct LGR {
    /// LGR/filename.
    pub name: String,
    /// List of pictures.
    pub picture_list: HashMap<String, Picture>,
    /// Picture data.
    pub picture_data: HashMap<String, Vec<u8>>,
}

/// LGR picture structure.
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct Picture {
    /// Picture type.
    pub picture_type: PictureType,
    /// Default distance, 1-999.
    pub distance: u16,
    /// Default clipping.
    pub clipping: Clip,
    /// Transparency.
    pub transparency: Transparency,
}

/// Picture types.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum PictureType {
    /// Normal picture.
    Normal = 100,
    /// Texture.
    Texture = 101,
    /// Mask for textures.
    Mask = 102,
}

impl Default for PictureType {
    fn default() -> Self {
        PictureType::Normal
    }
}

/// Transparency.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Transparency {
    /// No transparency. Only valid for ´Mask´ picture types.
    Solid = 10,
    /// Palette index 0 is transparent color.
    Palette = 11,
    /// Top left pixel is transparent color.
    TopLeft = 12,
    /// Top right pixel is transparent color.
    TopRight = 13,
    /// Bottom left pixel is transparent color.
    BottomLeft = 14,
    /// Bottom right pixel is transparent color.
    BottomRight = 15,
}

impl Default for Transparency {
    fn default() -> Self {
        Transparency::TopLeft
    }
}

impl LGR {
    /// Creates a new LGR.
    pub fn new() -> Self {
        Self::default()
    }

    /// Loads a LGR from file.
    pub fn load<P: AsRef<Path>>(file: P) -> Result<Self, ElmaError> {
        let buffer = fs::read(file)?;
        Self::parse_lgr(&buffer)
    }

    /// Load a LGR from bytes.
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// # use elma::lgr::*;
    /// let lgr = LGR::from_bytes(&[0,1,2]).unwrap();
    /// ```
    pub fn from_bytes<B: AsRef<[u8]>>(buffer: B) -> Result<Self, ElmaError> {
        Self::parse_lgr(buffer.as_ref())
    }

    fn parse_lgr(buffer: &[u8]) -> Result<Self, ElmaError> {
        let mut lgr = Self::new();

        let (version, mut buffer) = buffer.split_at(5);
        // there are no other LGR versions possible, so no need to store it (?)
        if version != b"LGR12" {
            return Err(ElmaError::InvalidLGRFile(LGRError::InvalidVersion(
                version.to_vec(),
            )));
        }

        let picture_len = buffer.read_u32::<LE>()? as usize;
        let expected_header = buffer.read_i32::<LE>()?;
        if expected_header != constants::LGR {
            return Err(ElmaError::InvalidLGRFile(LGRError::InvalidHeader(
                expected_header,
            )));
        }

        // picture.lst section
        let list_len = buffer.read_u32::<LE>()? as usize;
        lgr.parse_list_data(&buffer, list_len)?;
        let (_, buffer) = buffer.split_at(26 * list_len);

        // pcx data
        let bytes_read = lgr.parse_picture_data(&buffer, picture_len)?;

        let (_, mut expected_eof) = buffer.split_at(bytes_read);

        let expected_eof = expected_eof.read_i32::<LE>()?;
        if expected_eof != constants::LGR_EOF {
            return Err(ElmaError::EOFMismatch);
        }

        Ok(lgr)
    }

    fn parse_list_data(&mut self, buffer: &[u8], len: usize) -> Result<(), ElmaError> {
        let (names, buffer) = buffer.split_at(len * 10);
        let (mut picture_types, buffer) = buffer.split_at(len * 4);
        let (mut distances, buffer) = buffer.split_at(len * 4);
        let (mut clippings, buffer) = buffer.split_at(len * 4);
        let (mut transparencies, _) = buffer.split_at(len * 4);

        for n in 0..len {
            let name = trim_string(&names[10 * n..(10 * n) + 10])?;
            let picture_type = match picture_types.read_u32::<LE>()? {
                100 => PictureType::Normal,
                101 => PictureType::Texture,
                102 => PictureType::Mask,
                e => return Err(ElmaError::InvalidLGRFile(LGRError::InvalidPictureType(e))),
            };
            let distance = distances.read_u32::<LE>()? as u16;
            let clipping = match clippings.read_u32::<LE>()? {
                0 => Clip::Unclipped,
                1 => Clip::Ground,
                2 => Clip::Sky,
                e => return Err(ElmaError::InvalidLGRFile(LGRError::InvalidClip(e))),
            };
            let transparency = match transparencies.read_u32::<LE>()? {
                10 => Transparency::Solid,
                11 => Transparency::Palette,
                12 => Transparency::TopLeft,
                13 => Transparency::TopRight,
                14 => Transparency::BottomLeft,
                15 => Transparency::BottomRight,
                e => return Err(ElmaError::InvalidLGRFile(LGRError::InvalidTransparency(e))),
            };

            self.picture_list.insert(
                name,
                Picture {
                    picture_type,
                    distance,
                    clipping,
                    transparency,
                },
            );
        }
        Ok(())
    }

    fn parse_picture_data(&mut self, mut buffer: &[u8], len: usize) -> Result<usize, ElmaError> {
        let mut bytes_read = 0;
        // pcx data
        for _ in 0..len {
            let (name, remaining) = buffer.split_at(13);
            let name = trim_string(&name)?;
            let expected = &[0x95, 0x4C, 0x00, 0x98, 0x95, 0x4C, 0x00];
            let (buf_val, remaining) = remaining.split_at(7);
            if expected != buf_val {
                let e = (name, expected.to_vec(), buf_val.to_vec());
                return Err(ElmaError::InvalidLGRFile(LGRError::InvalidPCXData(e)));
            }
            let (mut bytes_len, remaining) = remaining.split_at(4);
            let bytes_len = bytes_len.read_i32::<LE>()? as usize;
            let data = remaining[..bytes_len].to_vec();

            self.picture_data.insert(name, data);
            buffer = &buffer[24 + bytes_len..];
            bytes_read += 24 + bytes_len;
        }
        Ok(bytes_read)
    }

    /// Returns a Vec with bytes representing the LGR as a buffer.
    pub fn as_bytes(&self) -> Result<Vec<u8>, ElmaError> {
        let mut bytes = vec![];
        bytes.extend_from_slice(&self.write_picture_list());
        bytes.extend_from_slice(&self.write_picture_data());
        Ok(bytes)
    }

    fn write_picture_list(&self) -> Vec<u8> {
        let bytes = vec![];
        bytes
    }

    fn write_picture_data(&self) -> Vec<u8> {
        let bytes = vec![];
        bytes
    }

    /// Save the LGR to a file.
    pub fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), ElmaError> {
        let bytes = self.as_bytes()?;
        fs::write(filename, &bytes)?;

        Ok(())
    }
}
<commit_msg>add: preliminary lgr writing attempt<commit_after>use byteorder::{ReadBytesExt, WriteBytesExt, LE};
use std::fs;
use std::path::Path;

use super::{constants, Clip, ElmaError, utils::{string_null_pad, trim_string}};

/// LGR related errors.
#[derive(Debug, PartialEq, Eq, Clone, Ord, PartialOrd)]
pub enum LGRError {
    /// Error parsing version.
    InvalidVersion(Vec<u8>),
    /// Invalid header.
    InvalidHeader(i32),
    /// Invalid clipping.
    InvalidClip(u32),
    /// Invalid transparency.
    InvalidTransparency(u32),
    /// Error parsing PictureType.
    InvalidPictureType(u32),
    /// Invalid PCX data.
    InvalidPCXData((String, Vec<u8>, Vec<u8>)),
}

/// LGR structure.
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct LGR {
    /// LGR/filename.
    pub name: String,
    /// List of pictures.
    pub picture_list: Vec<Picture>,
    /// Picture data.
    pub picture_data: Vec<PictureData>,
}

/// LGR picture structure.
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct Picture {
    /// Picture name.
    pub name: String,
    /// Picture type.
    pub picture_type: PictureType,
    /// Default distance, 1-999.
    pub distance: u16,
    /// Default clipping.
    pub clipping: Clip,
    /// Transparency.
    pub transparency: Transparency,
}

/// LGR picture data structure.
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct PictureData {
    /// Picture name.
    pub name: String,
    /// Picture data.
    pub data: Vec<u8>,
}

/// Picture types.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum PictureType {
    /// Normal picture.
    Normal = 100,
    /// Texture.
    Texture = 101,
    /// Mask for textures.
    Mask = 102,
}

impl Default for PictureType {
    fn default() -> Self {
        PictureType::Normal
    }
}

/// Transparency.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Transparency {
    /// No transparency. Only valid for ´Mask´ picture types.
    Solid = 10,
    /// Palette index 0 is transparent color.
    Palette = 11,
    /// Top left pixel is transparent color.
    TopLeft = 12,
    /// Top right pixel is transparent color.
    TopRight = 13,
    /// Bottom left pixel is transparent color.
    BottomLeft = 14,
    /// Bottom right pixel is transparent color.
    BottomRight = 15,
}

impl Default for Transparency {
    fn default() -> Self {
        Transparency::TopLeft
    }
}

impl LGR {
    /// Creates a new LGR.
    pub fn new() -> Self {
        Self::default()
    }

    /// Loads a LGR from file.
    pub fn load<P: AsRef<Path>>(file: P) -> Result<Self, ElmaError> {
        let buffer = fs::read(file)?;
        Self::parse_lgr(&buffer)
    }

    /// Load a LGR from bytes.
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// # use elma::lgr::*;
    /// let lgr = LGR::from_bytes(&[0,1,2]).unwrap();
    /// ```
    pub fn from_bytes<B: AsRef<[u8]>>(buffer: B) -> Result<Self, ElmaError> {
        Self::parse_lgr(buffer.as_ref())
    }

    fn parse_lgr(buffer: &[u8]) -> Result<Self, ElmaError> {
        let mut lgr = Self::new();

        let (version, mut buffer) = buffer.split_at(5);
        // there are no other LGR versions possible, so no need to store it (?)
        if version != b"LGR12" {
            return Err(ElmaError::InvalidLGRFile(LGRError::InvalidVersion(
                version.to_vec(),
            )));
        }

        let picture_len = buffer.read_u32::<LE>()? as usize;
        let expected_header = buffer.read_i32::<LE>()?;
        if expected_header != constants::LGR {
            return Err(ElmaError::InvalidLGRFile(LGRError::InvalidHeader(
                expected_header,
            )));
        }

        // picture.lst section
        let list_len = buffer.read_u32::<LE>()? as usize;
        lgr.parse_list_data(&buffer, list_len)?;
        let (_, buffer) = buffer.split_at(26 * list_len);

        // pcx data
        let bytes_read = lgr.parse_picture_data(&buffer, picture_len)?;

        let (_, mut expected_eof) = buffer.split_at(bytes_read);

        let expected_eof = expected_eof.read_i32::<LE>()?;
        if expected_eof != constants::LGR_EOF {
            return Err(ElmaError::EOFMismatch);
        }

        Ok(lgr)
    }

    fn parse_list_data(&mut self, buffer: &[u8], len: usize) -> Result<(), ElmaError> {
        let (names, buffer) = buffer.split_at(len * 10);
        let (mut picture_types, buffer) = buffer.split_at(len * 4);
        let (mut distances, buffer) = buffer.split_at(len * 4);
        let (mut clippings, buffer) = buffer.split_at(len * 4);
        let (mut transparencies, _) = buffer.split_at(len * 4);

        for n in 0..len {
            let name = trim_string(&names[10 * n..(10 * n) + 10])?;
            let picture_type = match picture_types.read_u32::<LE>()? {
                100 => PictureType::Normal,
                101 => PictureType::Texture,
                102 => PictureType::Mask,
                e => return Err(ElmaError::InvalidLGRFile(LGRError::InvalidPictureType(e))),
            };
            let distance = distances.read_u32::<LE>()? as u16;
            let clipping = match clippings.read_u32::<LE>()? {
                0 => Clip::Unclipped,
                1 => Clip::Ground,
                2 => Clip::Sky,
                e => return Err(ElmaError::InvalidLGRFile(LGRError::InvalidClip(e))),
            };
            let transparency = match transparencies.read_u32::<LE>()? {
                10 => Transparency::Solid,
                11 => Transparency::Palette,
                12 => Transparency::TopLeft,
                13 => Transparency::TopRight,
                14 => Transparency::BottomLeft,
                15 => Transparency::BottomRight,
                e => return Err(ElmaError::InvalidLGRFile(LGRError::InvalidTransparency(e))),
            };

            self.picture_list.push(Picture {
                name,
                picture_type,
                distance,
                clipping,
                transparency,
            });
        }
        Ok(())
    }

    fn parse_picture_data(&mut self, mut buffer: &[u8], len: usize) -> Result<usize, ElmaError> {
        let mut bytes_read = 0;
        // pcx data
        for _ in 0..len {
            let (name, remaining) = buffer.split_at(13);
            let name = trim_string(&name)?;
            let expected = &[0x95, 0x4C, 0x00, 0x98, 0x95, 0x4C, 0x00];
            let (buf_val, remaining) = remaining.split_at(7);
            if expected != buf_val {
                let e = (name, expected.to_vec(), buf_val.to_vec());
                return Err(ElmaError::InvalidLGRFile(LGRError::InvalidPCXData(e)));
            }
            let (mut bytes_len, remaining) = remaining.split_at(4);
            let bytes_len = bytes_len.read_i32::<LE>()? as usize;
            let data = remaining[..bytes_len].to_vec();

            self.picture_data.push(PictureData { name, data });
            buffer = &buffer[24 + bytes_len..];
            bytes_read += 24 + bytes_len;
        }
        Ok(bytes_read)
    }

    /// Returns a Vec with bytes representing the LGR as a buffer.
    pub fn to_bytes(&self) -> Result<Vec<u8>, ElmaError> {
        let mut bytes = vec![];
        bytes.extend_from_slice(b"LGR12");
        bytes.write_u32::<LE>(self.picture_data.len() as u32)?;
        bytes.write_i32::<LE>(constants::LGR)?;
        bytes.extend_from_slice(&self.write_picture_list()?);
        bytes.extend_from_slice(&self.write_picture_data()?);
        bytes.write_i32::<LE>(constants::LGR_EOF)?;

        Ok(bytes)
    }

    fn write_picture_list(&self) -> Result<Vec<u8>, ElmaError> {
        let mut bytes = vec![];
        bytes.write_u32::<LE>(self.picture_list.len() as u32)?;
        let mut names = vec![];
        let mut picture_types = vec![];
        let mut distances = vec![];
        let mut clippings = vec![];
        let mut transparencies = vec![];

        for picture in self.picture_list.iter() {
            names.extend_from_slice(&string_null_pad(&picture.name, 10)?);
            picture_types.write_u32::<LE>(picture.picture_type as u32)?;
            distances.write_u32::<LE>(picture.distance as u32)?;
            clippings.write_u32::<LE>(picture.clipping as u32)?;
            transparencies.write_u32::<LE>(picture.transparency as u32)?;
        }

        bytes.extend_from_slice(&names);
        bytes.extend_from_slice(&picture_types);
        bytes.extend_from_slice(&distances);
        bytes.extend_from_slice(&clippings);
        bytes.extend_from_slice(&transparencies);

        Ok(bytes)
    }

    fn write_picture_data(&self) -> Result<Vec<u8>, ElmaError> {
        let mut bytes = vec![];
        let marker = &[0x95, 0x4C, 0x00, 0x98, 0x95, 0x4C, 0x00];

        for picture in self.picture_data.iter() {
            bytes.extend_from_slice(&string_null_pad(&picture.name, 13)?);
            bytes.extend_from_slice(marker);
            bytes.write_u32::<LE>(picture.data.len() as u32)?;
            bytes.extend_from_slice(&picture.data);
        }

        Ok(bytes)
    }

    /// Save the LGR to a file.
    pub fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), ElmaError> {
        let bytes = self.to_bytes()?;
        fs::write(filename, &bytes)?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>// #![feature(plugin, custom_attribute)]
// #![plugin(c_import)]
#![deny(missing_docs)]

//! Message Passing Interface bindings for Rust
//!
//! The [Message Passing Interface][MPI] (MPI) is a specification for a
//! message-passing style concurrency library. Implementations of MPI are often used to structure
//! parallel computation on High Performance Computing systems. The MPI specification describes
//! bindings for the C programming language (and through it C++) as well as for the Fortran
//! programming language. This library tries to bridge the gap into a more rustic world.
//!
//! [MPI]: http://www.mpi-forum.org
//!
//! # Usage
//!
//! Add the `mpi` crate as a dependency in your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! mpi = "0.2"
//! ```
//!
//! Then use it in your program like this:
//!
//! ```no_run
//! extern crate mpi;
//!
//! use mpi::traits::*;
//!
//! fn main() {
//!     let universe = mpi::initialize().unwrap();
//!     let world = universe.world();
//!     let size = world.size();
//!     let rank = world.rank();
//!
//!     if size != 2 {
//!         panic!("Size of MPI_COMM_WORLD must be 2, but is {}!", size);
//!      }
//!
//!     match rank {
//!         0 => {
//!             let msg = vec![4.0f64, 8.0, 15.0];
//!             world.process_at_rank(rank + 1).send(&msg[..]);
//!         }
//!         1 => {
//!             let (msg, status) = world.receive_vec::<f64>();
//!             println!("Process {} got message {:?}.\nStatus is: {:?}", rank, msg, status);
//!         }
//!         _ => unreachable!()
//!     }
//! }
//! ```
//!
//! # Features
//!
//! The bindings follow the MPI 3.1 specification.
//!
//! Currently supported:
//!
//! - **Groups, Contexts, Communicators**:
//!   - Group and (Intra-)Communicator management from section 6 is mostly complete.
//!   - no Inter-Communicators
//!   - noprocess topologies
//! - **Point to point communication**:
//!   - standard, buffered, synchronous and ready mode send in blocking and non-blocking variants
//!   - receive in blocking and non-blocking variants
//!   - send-receive
//!   - probe
//!   - matched probe/receive
//! - **Collective communication**:
//!   - barrier in blocking and non-blocking variants
//!   - broadcast
//!   - (all) gather
//!   - scatter
//!   - all to all
//!   - no varying counts operations
//!   - no reductions/scans
//! - **Datatypes**: Bridging between Rust types and MPI basic types as well as custom MPI datatypes
//! which can act as views into buffers.
//!
//! Not supported (yet):
//!
//! - Process management
//! - One-sided communication (RMA)
//! - MPI parallel I/O
//! - A million small things
//!
//! The sub-modules contain a more detailed description of which features are and are not
//! supported.

use std::mem;
use std::string::{FromUtf8Error};

extern crate libc;

use libc::{c_char, c_int};

extern crate conv;

use conv::ConvUtil;

/// The raw C language MPI API
///
/// Documented in the [Message Passing Interface specification][spec]
///
/// [spec]: http://www.mpi-forum.org/docs/docs.html
#[allow(missing_docs, dead_code, non_snake_case, non_camel_case_types)]
pub mod ffi;

pub mod collective;
pub mod datatype;
pub mod point_to_point;
pub mod raw;
pub mod request;
pub mod topology;
pub mod traits;

#[doc(inline)]
pub use topology::{initialize, initialize_with_threading, Threading};

use ffi::MPI_Aint;

/// Encodes error values returned by MPI functions.
pub type Error = c_int;
/// Encodes number of values in multi-value messages.
pub type Count = c_int;
/// Can be used to tag messages on the sender side and match on the receiver side.
pub type Tag = c_int;
/// An address in memory
pub type Address = MPI_Aint;

/// Identifies the version of the MPI standard implemented by the library.
///
/// Returns a tuple of `(version, subversion)`, e.g. `(3, 0)`.
///
/// Can be called without initializing MPI.
pub fn get_version() -> (c_int, c_int) {
    let mut version: c_int = unsafe { mem::uninitialized() };
    let mut subversion: c_int = unsafe { mem::uninitialized() };
    unsafe { ffi::MPI_Get_version(&mut version, &mut subversion); }
    (version, subversion)
}

/// Describes the version of the MPI library itself.
///
/// Can return an `Err` if the description of the MPI library is not a UTF-8 string.
///
/// Can be called without initializing MPI.
pub fn get_library_version() -> Result<String, FromUtf8Error> {
    let bufsize = ffi::RSMPI_MAX_LIBRARY_VERSION_STRING.value_as().expect(
        &format!("MPI_MAX_LIBRARY_SIZE ({}) cannot be expressed as a usize.",
            ffi::RSMPI_MAX_LIBRARY_VERSION_STRING)
        );
    let mut buf = vec![0u8; bufsize];
    let mut len: c_int = 0;

    unsafe { ffi::MPI_Get_library_version(buf.as_mut_ptr() as *mut c_char, &mut len); }
    buf.truncate(len.value_as().expect(
        &format!("Length of library version string ({}) cannot be expressed as a usize.", len)));
    String::from_utf8(buf)
}
<commit_msg>Enable additional lints using clippy.<commit_after>// #![feature(plugin, custom_attribute)]
// #![plugin(c_import)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", warn(cast_possible_truncation))]
#![cfg_attr(feature="clippy", warn(cast_possible_wrap))]
#![cfg_attr(feature="clippy", warn(cast_precision_loss))]
#![cfg_attr(feature="clippy", warn(cast_sign_loss))]
#![cfg_attr(feature="clippy", warn(mut_mut))]
#![cfg_attr(feature="clippy", warn(mutex_integer))]
#![cfg_attr(feature="clippy", warn(non_ascii_literal))]
#![cfg_attr(feature="clippy", warn(option_unwrap_used))]
#![cfg_attr(feature="clippy", warn(result_unwrap_used))]
#![cfg_attr(feature="clippy", warn(string_add))]
#![cfg_attr(feature="clippy", warn(string_add_assign))]
#![cfg_attr(feature="clippy", warn(unicode_not_nfc))]
#![cfg_attr(feature="clippy", warn(wrong_pub_self_convention))]

#![deny(missing_docs)]

//! Message Passing Interface bindings for Rust
//!
//! The [Message Passing Interface][MPI] (MPI) is a specification for a
//! message-passing style concurrency library. Implementations of MPI are often used to structure
//! parallel computation on High Performance Computing systems. The MPI specification describes
//! bindings for the C programming language (and through it C++) as well as for the Fortran
//! programming language. This library tries to bridge the gap into a more rustic world.
//!
//! [MPI]: http://www.mpi-forum.org
//!
//! # Usage
//!
//! Add the `mpi` crate as a dependency in your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! mpi = "0.2"
//! ```
//!
//! Then use it in your program like this:
//!
//! ```no_run
//! extern crate mpi;
//!
//! use mpi::traits::*;
//!
//! fn main() {
//!     let universe = mpi::initialize().unwrap();
//!     let world = universe.world();
//!     let size = world.size();
//!     let rank = world.rank();
//!
//!     if size != 2 {
//!         panic!("Size of MPI_COMM_WORLD must be 2, but is {}!", size);
//!      }
//!
//!     match rank {
//!         0 => {
//!             let msg = vec![4.0f64, 8.0, 15.0];
//!             world.process_at_rank(rank + 1).send(&msg[..]);
//!         }
//!         1 => {
//!             let (msg, status) = world.receive_vec::<f64>();
//!             println!("Process {} got message {:?}.\nStatus is: {:?}", rank, msg, status);
//!         }
//!         _ => unreachable!()
//!     }
//! }
//! ```
//!
//! # Features
//!
//! The bindings follow the MPI 3.1 specification.
//!
//! Currently supported:
//!
//! - **Groups, Contexts, Communicators**:
//!   - Group and (Intra-)Communicator management from section 6 is mostly complete.
//!   - no Inter-Communicators
//!   - noprocess topologies
//! - **Point to point communication**:
//!   - standard, buffered, synchronous and ready mode send in blocking and non-blocking variants
//!   - receive in blocking and non-blocking variants
//!   - send-receive
//!   - probe
//!   - matched probe/receive
//! - **Collective communication**:
//!   - barrier in blocking and non-blocking variants
//!   - broadcast
//!   - (all) gather
//!   - scatter
//!   - all to all
//!   - no varying counts operations
//!   - no reductions/scans
//! - **Datatypes**: Bridging between Rust types and MPI basic types as well as custom MPI datatypes
//! which can act as views into buffers.
//!
//! Not supported (yet):
//!
//! - Process management
//! - One-sided communication (RMA)
//! - MPI parallel I/O
//! - A million small things
//!
//! The sub-modules contain a more detailed description of which features are and are not
//! supported.

use std::mem;
use std::string::{FromUtf8Error};

extern crate libc;

use libc::{c_char, c_int};

extern crate conv;

use conv::ConvUtil;

/// The raw C language MPI API
///
/// Documented in the [Message Passing Interface specification][spec]
///
/// [spec]: http://www.mpi-forum.org/docs/docs.html
#[allow(missing_docs, dead_code, non_snake_case, non_camel_case_types)]
pub mod ffi;

pub mod collective;
pub mod datatype;
pub mod point_to_point;
pub mod raw;
pub mod request;
pub mod topology;
pub mod traits;

#[doc(inline)]
pub use topology::{initialize, initialize_with_threading, Threading};

use ffi::MPI_Aint;

/// Encodes error values returned by MPI functions.
pub type Error = c_int;
/// Encodes number of values in multi-value messages.
pub type Count = c_int;
/// Can be used to tag messages on the sender side and match on the receiver side.
pub type Tag = c_int;
/// An address in memory
pub type Address = MPI_Aint;

/// Identifies the version of the MPI standard implemented by the library.
///
/// Returns a tuple of `(version, subversion)`, e.g. `(3, 0)`.
///
/// Can be called without initializing MPI.
pub fn get_version() -> (c_int, c_int) {
    let mut version: c_int = unsafe { mem::uninitialized() };
    let mut subversion: c_int = unsafe { mem::uninitialized() };
    unsafe { ffi::MPI_Get_version(&mut version, &mut subversion); }
    (version, subversion)
}

/// Describes the version of the MPI library itself.
///
/// Can return an `Err` if the description of the MPI library is not a UTF-8 string.
///
/// Can be called without initializing MPI.
pub fn get_library_version() -> Result<String, FromUtf8Error> {
    let bufsize = ffi::RSMPI_MAX_LIBRARY_VERSION_STRING.value_as().expect(
        &format!("MPI_MAX_LIBRARY_SIZE ({}) cannot be expressed as a usize.",
            ffi::RSMPI_MAX_LIBRARY_VERSION_STRING)
        );
    let mut buf = vec![0u8; bufsize];
    let mut len: c_int = 0;

    unsafe { ffi::MPI_Get_library_version(buf.as_mut_ptr() as *mut c_char, &mut len); }
    buf.truncate(len.value_as().expect(
        &format!("Length of library version string ({}) cannot be expressed as a usize.", len)));
    String::from_utf8(buf)
}
<|endoftext|>


<commit_before>#![crate_name = "liquid"]
#![doc(html_root_url = "https://cobalt-org.github.io/liquid-rust/")]

extern crate regex;

use std::collections::HashMap;
use template::Template;
use lexer::Token;
use lexer::Element;
use tags::{IfBlock, ForBlock, RawBlock, CommentBlock};
use std::string::ToString;
use std::default::Default;
pub use value::Value;
pub use context::Context;

mod template;
mod output;
mod text;
pub mod lexer;
mod parser;
mod tags;
mod filters;
mod value;
mod variable;
mod context;

/// The ErrorMode to use.
/// This currently does not have an effect, until
/// ErrorModes are properly implemented.
#[derive(Clone, Copy)]
pub enum ErrorMode{
    Strict,
    Warn,
    Lax
}

impl Default for ErrorMode {
   fn default() -> ErrorMode { ErrorMode::Warn }
}

/// A trait for creating custom tags.
pub trait Tag {
    fn initialize(&self, tag_name: &str, arguments: &[Token], options : &LiquidOptions) -> Box<Renderable>;
}

/// The trait to use when implementing custom block-size tags ({% if something %})
pub trait Block {
    fn initialize<'a>(&'a self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &'a LiquidOptions<'a>) -> Result<Box<Renderable +'a>, String>;
}

/// Any object (tag/block) that can be rendered by liquid must implement this trait.
pub trait Renderable{
    fn render(&self, context: &mut Context) -> Option<String>;
}

#[derive(Default)]
pub struct LiquidOptions<'a> {
    pub blocks : HashMap<String, Box<Block + 'a>>,
    pub tags : HashMap<String, Box<Tag + 'a>>,
    pub error_mode : ErrorMode
}

/// Parses a liquid template, returning a Template object.
/// # Examples
///
/// ## Minimal Template
///
/// ```
/// use std::default::Default;
/// use liquid::Renderable;
/// use liquid::LiquidOptions;
/// use liquid::Context;
/// let mut options : LiquidOptions = Default::default();
/// let template = liquid::parse("Liquid!", &mut options).unwrap();
/// let mut data = Context::new();
/// let output = template.render(&mut data);
/// assert_eq!(output.unwrap(), "Liquid!".to_string());
/// ```
///
pub fn parse<'a, 'b> (text: &str, options: &'b mut LiquidOptions<'a>) -> Result<Template<'b>, String>{
    let tokens = lexer::tokenize(&text);
    options.blocks.insert("raw".to_string(), Box::new(RawBlock) as Box<Block>);
    options.blocks.insert("if".to_string(), Box::new(IfBlock) as Box<Block>);
    options.blocks.insert("for".to_string(), Box::new(ForBlock) as Box<Block>);
    options.blocks.insert("comment".to_string(), Box::new(CommentBlock) as Box<Block>);
    match parser::parse(&tokens, options) {
        Ok(renderables) => Ok(Template::new(renderables)),
        Err(e) => Err(e)
    }
}

<commit_msg>Expose the template type.<commit_after>#![crate_name = "liquid"]
#![doc(html_root_url = "https://cobalt-org.github.io/liquid-rust/")]

extern crate regex;

use std::collections::HashMap;
use template::Template;
use lexer::Token;
use lexer::Element;
use tags::{IfBlock, ForBlock, RawBlock, CommentBlock};
use std::string::ToString;
use std::default::Default;
pub use value::Value;
pub use context::Context;
pub use template::Template;

mod template;
mod output;
mod text;
pub mod lexer;
mod parser;
mod tags;
mod filters;
mod value;
mod variable;
mod context;

/// The ErrorMode to use.
/// This currently does not have an effect, until
/// ErrorModes are properly implemented.
#[derive(Clone, Copy)]
pub enum ErrorMode{
    Strict,
    Warn,
    Lax
}

impl Default for ErrorMode {
   fn default() -> ErrorMode { ErrorMode::Warn }
}

/// A trait for creating custom tags.
pub trait Tag {
    fn initialize(&self, tag_name: &str, arguments: &[Token], options : &LiquidOptions) -> Box<Renderable>;
}

/// The trait to use when implementing custom block-size tags ({% if something %})
pub trait Block {
    fn initialize<'a>(&'a self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &'a LiquidOptions<'a>) -> Result<Box<Renderable +'a>, String>;
}

/// Any object (tag/block) that can be rendered by liquid must implement this trait.
pub trait Renderable{
    fn render(&self, context: &mut Context) -> Option<String>;
}

#[derive(Default)]
pub struct LiquidOptions<'a> {
    pub blocks : HashMap<String, Box<Block + 'a>>,
    pub tags : HashMap<String, Box<Tag + 'a>>,
    pub error_mode : ErrorMode
}

/// Parses a liquid template, returning a Template object.
/// # Examples
///
/// ## Minimal Template
///
/// ```
/// use std::default::Default;
/// use liquid::Renderable;
/// use liquid::LiquidOptions;
/// use liquid::Context;
/// let mut options : LiquidOptions = Default::default();
/// let template = liquid::parse("Liquid!", &mut options).unwrap();
/// let mut data = Context::new();
/// let output = template.render(&mut data);
/// assert_eq!(output.unwrap(), "Liquid!".to_string());
/// ```
///
pub fn parse<'a, 'b> (text: &str, options: &'b mut LiquidOptions<'a>) -> Result<Template<'b>, String>{
    let tokens = lexer::tokenize(&text);
    options.blocks.insert("raw".to_string(), Box::new(RawBlock) as Box<Block>);
    options.blocks.insert("if".to_string(), Box::new(IfBlock) as Box<Block>);
    options.blocks.insert("for".to_string(), Box::new(ForBlock) as Box<Block>);
    options.blocks.insert("comment".to_string(), Box::new(CommentBlock) as Box<Block>);
    match parser::parse(&tokens, options) {
        Ok(renderables) => Ok(Template::new(renderables)),
        Err(e) => Err(e)
    }
}

<|endoftext|>