<commit_before>extern crate flate2;
#[cfg(feature = "ndarray_volumes")]
extern crate ndarray;
extern crate nifti;
#[macro_use]
extern crate pretty_assertions;

use nifti::{Endianness, InMemNiftiObject, NiftiHeader, NiftiObject, NiftiType, NiftiVolume};

#[test]
fn minimal_nii_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_nii() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.hdr";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr_and_img_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal2.hdr";
    // should attempt to read "resources/minimal2.img.gz"
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.hdr.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_pair() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const HDR_FILE_NAME: &str = "resources/minimal.hdr.gz";
    const IMG_FILE_NAME: &str = "resources/minimal.img.gz";
    let obj = InMemNiftiObject::from_file_pair(HDR_FILE_NAME, IMG_FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn f32_nii_gz() {
    let f32_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 11, 11, 11, 1, 1, 1, 1],
        datatype: 16,
        bitpix: 32,
        pixdim: [1., 1., 1., 1., 1., 1., 1., 1.],
        vox_offset: 352.,
        scl_slope: 1.,
        scl_inter: 0.,
        srow_x: [1., 0., 0., 0.],
        srow_y: [0., 1., 0., 0.],
        srow_z: [0., 0., 1., 0.],
        sform_code: 2,
        magic: *b"n+1\0",
        endianness: Endianness::LE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/f32.nii.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &f32_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Float32);
    assert_eq!(volume.dim(), [11, 11, 11].as_ref());

    assert_eq!(volume.get_f32(&[5, 5, 5]).unwrap(), 1.);
    assert_eq!(volume.get_f32(&[5, 0, 0]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[0, 5, 0]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[0, 0, 5]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[5, 0, 4]).unwrap(), 0.4);
    assert_eq!(volume.get_f32(&[0, 8, 5]).unwrap(), 0.8);
}
<commit_msg>Add InMemNiftiVolume::from_raw_data test<commit_after>extern crate flate2;
#[cfg(feature = "ndarray_volumes")]
extern crate ndarray;
extern crate nifti;
#[macro_use]
extern crate pretty_assertions;

use nifti::{Endianness, InMemNiftiObject, NiftiHeader, NiftiObject, NiftiType, NiftiVolume};

#[test]
fn minimal_nii_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_nii() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 352.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"n+1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.nii";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.hdr";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr_and_img_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal2.hdr";
    // should attempt to read "resources/minimal2.img.gz"
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_hdr_gz() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/minimal.hdr.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn minimal_by_pair() {
    let minimal_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 64, 64, 10, 0, 0, 0, 0],
        datatype: 2,
        bitpix: 8,
        pixdim: [0., 3., 3., 3., 0., 0., 0., 0.],
        vox_offset: 0.,
        scl_slope: 0.,
        scl_inter: 0.,
        magic: *b"ni1\0",
        endianness: Endianness::BE,
        ..Default::default()
    };

    const HDR_FILE_NAME: &str = "resources/minimal.hdr.gz";
    const IMG_FILE_NAME: &str = "resources/minimal.img.gz";
    let obj = InMemNiftiObject::from_file_pair(HDR_FILE_NAME, IMG_FILE_NAME).unwrap();
    assert_eq!(obj.header(), &minimal_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Uint8);
    assert_eq!(volume.dim(), [64, 64, 10].as_ref());
}

#[test]
fn f32_nii_gz() {
    let f32_hdr = NiftiHeader {
        sizeof_hdr: 348,
        dim: [3, 11, 11, 11, 1, 1, 1, 1],
        datatype: 16,
        bitpix: 32,
        pixdim: [1., 1., 1., 1., 1., 1., 1., 1.],
        vox_offset: 352.,
        scl_slope: 1.,
        scl_inter: 0.,
        srow_x: [1., 0., 0., 0.],
        srow_y: [0., 1., 0., 0.],
        srow_z: [0., 0., 1., 0.],
        sform_code: 2,
        magic: *b"n+1\0",
        endianness: Endianness::LE,
        ..Default::default()
    };

    const FILE_NAME: &str = "resources/f32.nii.gz";
    let obj = InMemNiftiObject::from_file(FILE_NAME).unwrap();
    assert_eq!(obj.header(), &f32_hdr);
    let volume = obj.volume();
    assert_eq!(volume.data_type(), NiftiType::Float32);
    assert_eq!(volume.dim(), [11, 11, 11].as_ref());

    assert_eq!(volume.get_f32(&[5, 5, 5]).unwrap(), 1.);
    assert_eq!(volume.get_f32(&[5, 0, 0]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[0, 5, 0]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[0, 0, 5]).unwrap(), 0.);
    assert_eq!(volume.get_f32(&[5, 0, 4]).unwrap(), 0.4);
    assert_eq!(volume.get_f32(&[0, 8, 5]).unwrap(), 0.8);
}

#[cfg(feature = "ndarray_volumes")]
#[test]
fn test_false_4d() {
    use ndarray::Ix3;
    use nifti:: {InMemNiftiVolume, IntoNdArray};

    let (w, h, d) = (5, 5, 5);
    let mut header = NiftiHeader {
        dim: [4, w, h, d, 1, 1, 1, 1],
        datatype: 2,
        bitpix: 8,
        ..Default::default()
    };
    let raw_data = vec![0; (w * h * d) as usize];
    let mut volume = InMemNiftiVolume::from_raw_data(&header, raw_data).unwrap();
    assert_eq!(header.dim[0], 4);
    assert_eq!(volume.dimensionality(), 4);
    if header.dim[header.dim[0] as usize] == 1 {
        header.dim[0] -= 1;
        volume = InMemNiftiVolume::from_raw_data(&header, volume.to_raw_data()).unwrap();
    }
    assert_eq!(volume.dimensionality(), 3);
    let dyn_data = volume.to_ndarray::<f32>().unwrap();
    assert_eq!(dyn_data.ndim(), 3);
    let data = dyn_data.into_dimensionality::<Ix3>().unwrap();
    assert_eq!(data.ndim(), 3); // Obvious, but it's to avoid being optimized away
}
<|endoftext|>


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

extern crate cc;
extern crate cmake;
extern crate pkg_config;

use std::env::VarError;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::{env, fs, io};

use cc::Build;
use cmake::Config;
use pkg_config::{Config as PkgConfig, Library};
use walkdir::WalkDir;

const GRPC_VERSION: &'static str = "1.17.2";

fn probe_library(library: &str, cargo_metadata: bool) -> Library {
    match PkgConfig::new()
        .atleast_version(GRPC_VERSION)
        .cargo_metadata(cargo_metadata)
        .probe(library)
    {
        Ok(lib) => lib,
        Err(e) => panic!("can't find library {} via pkg-config: {:?}", library, e),
    }
}

fn prepare_grpc() {
    let mut modules = vec![
        "grpc",
        "grpc/third_party/zlib",
        "grpc/third_party/cares/cares",
        "grpc/third_party/address_sorting",
    ];

    if cfg!(feature = "secure") {
        modules.push("grpc/third_party/boringssl");
    }

    for module in modules {
        if is_directory_empty(module).unwrap_or(true) {
            panic!(
                "Can't find module {}. You need to run `git submodule \
                 update --init --recursive` first to build the project.",
                module
            );
        }
    }
}

fn is_directory_empty<P: AsRef<Path>>(p: P) -> Result<bool, io::Error> {
    let mut entries = fs::read_dir(p)?;
    Ok(entries.next().is_none())
}

fn build_grpc(cc: &mut Build, library: &str) {
    prepare_grpc();

    let dst = {
        let mut config = Config::new("grpc");
        if !cfg!(feature = "secure") {
            // boringssl's configuration is still included, but targets
            // will never be built, hence specify a fake go to get rid of
            // the unnecessary dependency.
            config.define("GO_EXECUTABLE", "fake-go-nonexist");
        }
        if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "macos") {
            config.cxxflag("-stdlib=libc++");
        }
        if env::var("CARGO_CFG_TARGET_ENV").unwrap_or("".to_owned()) == "musl" {
            config.define("CMAKE_CXX_COMPILER", "g++");
        }

        // Cross-compile support for iOS
        match env::var("TARGET").unwrap_or("".to_owned()).as_str() {
            "aarch64-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphoneos")
                    .define("CMAKE_OSX_ARCHITECTURES", "arm64");
            }
            "armv7-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphoneos")
                    .define("CMAKE_OSX_ARCHITECTURES", "armv7");
            }
            "armv7s-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphoneos")
                    .define("CMAKE_OSX_ARCHITECTURES", "armv7s");
            }
            "i386-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphonesimulator")
                    .define("CMAKE_OSX_ARCHITECTURES", "i386");
            }
            "x86_64-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphonesimulator")
                    .define("CMAKE_OSX_ARCHITECTURES", "x86_64");
            }
            _ => {}
        };

        // Allow overriding of the target passed to cmake
        // (needed for Android crosscompile)
        match env::var("CMAKE_TARGET_OVERRIDE") {
            Ok(val) => {
                config.target(&val);
            }
            Err(_) => {}
        };

        // We don't need to generate install targets.
        config.define("gRPC_INSTALL", "false");
        // We don't need to build csharp target.
        config.define("gRPC_BUILD_CSHARP_EXT", "false");
        // We don't need to build codegen target.
        config.define("gRPC_BUILD_CODEGEN", "false");
        // We don't need to build benchmarks.
        config.define("gRPC_BENCHMARK_PROVIDER", "none");
        if cfg!(feature = "openssl") {
            config.define("gRPC_SSL_PROVIDER", "package");
            config.define("EMBED_OPENSSL", "false");
            // Problem is: Ubuntu Trusty shipped with openssl 1.0.1f. Which doesn't
            // support alpn. And Google's gRPC checks for support of ALPN in plane
            // old Makefile, but not in CMake.
            config.cxxflag("-DTSI_OPENSSL_ALPN_SUPPORT=0");
            setup_openssl(&mut config)
        }
        if cfg!(feature = "no-omit-frame-pointer") {
            config
                .cflag("-fno-omit-frame-pointer")
                .cxxflag("-fno-omit-frame-pointer");
        }
        config.build_target(library).uses_cxx11().build()
    };

    let mut zlib = "z";
    let build_dir = format!("{}/build", dst.display());
    let third_party = vec![
        "cares/cares/lib",
        "zlib",
        "boringssl/ssl",
        "boringssl/crypto",
    ];
    if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "windows") {
        let profile = match &*env::var("PROFILE").unwrap_or("debug".to_owned()) {
            "bench" | "release" => {
                zlib = "zlibstatic";
                "Release"
            }
            _ => {
                zlib = "zlibstaticd";
                "Debug"
            }
        };
        println!("cargo:rustc-link-search=native={}/{}", build_dir, profile);
        for path in third_party {
            println!(
                "cargo:rustc-link-search=native={}/third_party/{}/{}",
                build_dir, path, profile
            );
        }
    } else {
        println!("cargo:rustc-link-search=native={}", build_dir);
        for path in third_party {
            println!(
                "cargo:rustc-link-search=native={}/third_party/{}",
                build_dir, path,
            );
        }
    }

    println!("cargo:rustc-link-lib=static={}", zlib);
    println!("cargo:rustc-link-lib=static=cares");
    println!("cargo:rustc-link-lib=static=gpr");
    println!("cargo:rustc-link-lib=static=address_sorting");
    println!("cargo:rustc-link-lib=static={}", library);

    if cfg!(feature = "secure") {
        if cfg!(feature = "openssl") && !cfg!(feature = "openssl-vendored") {
            println!("cargo:rustc-link-lib=ssl");
            println!("cargo:rustc-link-lib=crypto");
        } else {
            println!("cargo:rustc-link-lib=static=ssl");
            println!("cargo:rustc-link-lib=static=crypto");
        }
    }

    cc.include("grpc/include");
}

#[cfg(feature = "openssl-vendored")]
fn setup_openssl(config: &mut Config) {
    // openssl-sys uses openssl-src to build the library. openssl-src uses
    // configure/make to build the library which makes it hard to detect
    // what's the actual path of the library. Here assumes the directory
    // structure as follow (which is the behavior of 0.9.47):
    // install_dir/
    //     include/
    //     lib/
    // Remove the hack when sfackler/rust-openssl#1117 is resolved.
    config.register_dep("openssl");
    if env::var("DEP_OPENSSL_ROOT").is_err() {
        let include_str = env::var("DEP_OPENSSL_INCLUDE").unwrap();
        let include_dir = Path::new(&include_str);
        let root_dir = format!("{}", include_dir.parent().unwrap().display());
        env::set_var("DEP_OPENSSL_ROOT", &root_dir);
    }
}

#[cfg(not(feature = "openssl-vendored"))]
fn setup_openssl(_config: &mut Config) {}

fn get_env(name: &str) -> Option<String> {
    println!("cargo:rerun-if-env-changed={}", name);
    match env::var(name) {
        Ok(s) => Some(s),
        Err(VarError::NotPresent) => None,
        Err(VarError::NotUnicode(s)) => {
            panic!("unrecognize env var of {}: {:?}", name, s.to_string_lossy());
        }
    }
}

// Generate the bindings to grpc C-core.
// Try to disable the generation of platform-related bindings.
fn bindgen_grpc(mut config: bindgen::Builder, file_path: &PathBuf) {
    // Search header files with API interface
    let mut headers = Vec::new();
    for result in WalkDir::new(Path::new("./grpc/include")) {
        let dent = result.expect("Error happened when search headers");
        if !dent.file_type().is_file() {
            continue;
        }
        let mut file = fs::File::open(dent.path()).expect("couldn't open headers");
        let mut buf = String::new();
        file.read_to_string(&mut buf)
            .expect("Coundn't read header content");
        if buf.contains("GRPCAPI") || buf.contains("GPRAPI") {
            headers.push(String::from(dent.path().to_str().unwrap()));
        }
    }

    // To control the order of bindings
    headers.sort();
    for path in headers {
        config = config.header(path);
    }

    config
        .header("grpc_wrap.cc")
        .clang_arg("-xc++")
        .clang_arg("-I./grpc/include")
        .clang_arg("-std=c++11")
        .whitelist_recursively(false)
        .whitelist_function(r"\bgrpc_.*")
        .whitelist_function(r"\bgpr_.*")
        .whitelist_function(r"\bgrpcwrap_.*")
        .whitelist_var(r"\bGRPC_.*")
        .whitelist_type(r"\bgrpc_.*")
        .whitelist_type(r"\bgpr_.*")
        .whitelist_type(r"\bgrpcwrap_.*")
        .whitelist_type(r"\bcensus_context.*")
        .whitelist_type(r"\bverify_peer_options.*")
        .blacklist_function(r"\bgpr_mu_.*")
        .blacklist_function(r"\bgpr_cv_.*")
        .blacklist_function(r"\bgpr_once_.*")
        .blacklist_type(r"gpr_mu")
        .blacklist_type(r"gpr_cv")
        .blacklist_type(r"gpr_once")
        .constified_enum_module(r"grpc_status_code")
        .no_copy("grpc_slice")
        .default_enum_style(bindgen::EnumVariation::Rust {
            non_exhaustive: false,
        })
        .generate()
        .expect("Unable to generate grpc bindings")
        .write_to_file(file_path)
        .expect("Couldn't write bindings!");
}

// Determine if need to update bindings. Supported platforms do not
// need to be updated by default unless the UPDATE_BIND is specified.
// Other platforms use bindgen to generate the bindings every time.
fn config_binding_path(config: bindgen::Builder) {
    let file_path: PathBuf;
    println!("cargo:rerun-if-changed=bindings/x86_64-unknown-linux-gnu-bindings.rs");
    match env::var("TARGET").unwrap_or("".to_owned()).as_str() {
        "x86_64-unknown-linux-gnu" => {
            file_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
                .join("bindings")
                .join("x86_64-unknown-linux-gnu-bindings.rs");
            if env::var("UPDATE_BIND").map(|s| s == "1").unwrap_or(false) {
                bindgen_grpc(config, &file_path);
            }
        }
        _ => {
            file_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("grpc-bindings.rs");
            bindgen_grpc(config, &file_path);
        }
    };
    println!(
        "cargo:rustc-env=BINDING_PATH={}",
        file_path.to_str().unwrap()
    );
}

fn main() {
    println!("cargo:rerun-if-changed=grpc_wrap.cc");
    println!("cargo:rerun-if-changed=grpc");
    println!("cargo:rerun-if-env-changed=UPDATE_BIND");

    let mut cc = Build::new();
    let mut bind_config = bindgen::Builder::default();

    let library = if cfg!(feature = "secure") {
        cc.define("GRPC_SYS_SECURE", None);
        bind_config = bind_config.clang_arg("-DGRPC_SYS_SECURE");
        "grpc"
    } else {
        "grpc_unsecure"
    };

    if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "windows") {
        // At lease win7
        cc.define("_WIN32_WINNT", Some("0x0700"));
        bind_config = bind_config.clang_arg("-D _WIN32_WINNT=0x0700");
    }

    if get_env("GRPCIO_SYS_USE_PKG_CONFIG").map_or(false, |s| s == "1") {
        // Print cargo metadata.
        let lib_core = probe_library(library, true);
        for inc_path in lib_core.include_paths {
            cc.include(inc_path);
        }
    } else {
        build_grpc(&mut cc, library);
    }

    cc.cpp(true);
    if !cfg!(target_env = "msvc") {
        cc.flag("-std=c++11");
    }
    cc.file("grpc_wrap.cc");

    cc.warnings_into_errors(true);

    cc.compile("libgrpc_wrap.a");

    config_binding_path(bind_config);
}
<commit_msg>grpc-sys: fix ssl path when using openssl (#387)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate cc;
extern crate cmake;
extern crate pkg_config;

use std::env::VarError;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::{env, fs, io};

use cc::Build;
use cmake::Config;
use pkg_config::{Config as PkgConfig, Library};
use walkdir::WalkDir;

const GRPC_VERSION: &'static str = "1.17.2";

fn probe_library(library: &str, cargo_metadata: bool) -> Library {
    match PkgConfig::new()
        .atleast_version(GRPC_VERSION)
        .cargo_metadata(cargo_metadata)
        .probe(library)
    {
        Ok(lib) => lib,
        Err(e) => panic!("can't find library {} via pkg-config: {:?}", library, e),
    }
}

fn prepare_grpc() {
    let mut modules = vec![
        "grpc",
        "grpc/third_party/zlib",
        "grpc/third_party/cares/cares",
        "grpc/third_party/address_sorting",
    ];

    if cfg!(feature = "secure") {
        modules.push("grpc/third_party/boringssl");
    }

    for module in modules {
        if is_directory_empty(module).unwrap_or(true) {
            panic!(
                "Can't find module {}. You need to run `git submodule \
                 update --init --recursive` first to build the project.",
                module
            );
        }
    }
}

fn is_directory_empty<P: AsRef<Path>>(p: P) -> Result<bool, io::Error> {
    let mut entries = fs::read_dir(p)?;
    Ok(entries.next().is_none())
}

fn trim_start<'a>(s: &'a str, prefix: &str) -> Option<&'a str> {
    if s.starts_with(prefix) {
        Some(s.trim_start_matches(prefix))
    } else {
        None
    }
}

fn build_grpc(cc: &mut Build, library: &str) {
    prepare_grpc();

    let mut third_party = vec!["cares/cares/lib", "zlib"];

    let dst = {
        let mut config = Config::new("grpc");
        if !cfg!(feature = "secure") {
            // boringssl's configuration is still included, but targets
            // will never be built, hence specify a fake go to get rid of
            // the unnecessary dependency.
            config.define("GO_EXECUTABLE", "fake-go-nonexist");
        }
        if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "macos") {
            config.cxxflag("-stdlib=libc++");
        }
        if env::var("CARGO_CFG_TARGET_ENV").unwrap_or("".to_owned()) == "musl" {
            config.define("CMAKE_CXX_COMPILER", "g++");
        }

        // Cross-compile support for iOS
        match env::var("TARGET").unwrap_or("".to_owned()).as_str() {
            "aarch64-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphoneos")
                    .define("CMAKE_OSX_ARCHITECTURES", "arm64");
            }
            "armv7-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphoneos")
                    .define("CMAKE_OSX_ARCHITECTURES", "armv7");
            }
            "armv7s-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphoneos")
                    .define("CMAKE_OSX_ARCHITECTURES", "armv7s");
            }
            "i386-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphonesimulator")
                    .define("CMAKE_OSX_ARCHITECTURES", "i386");
            }
            "x86_64-apple-ios" => {
                config
                    .define("CMAKE_OSX_SYSROOT", "iphonesimulator")
                    .define("CMAKE_OSX_ARCHITECTURES", "x86_64");
            }
            _ => {}
        };

        // Allow overriding of the target passed to cmake
        // (needed for Android crosscompile)
        match env::var("CMAKE_TARGET_OVERRIDE") {
            Ok(val) => {
                config.target(&val);
            }
            Err(_) => {}
        };

        // We don't need to generate install targets.
        config.define("gRPC_INSTALL", "false");
        // We don't need to build csharp target.
        config.define("gRPC_BUILD_CSHARP_EXT", "false");
        // We don't need to build codegen target.
        config.define("gRPC_BUILD_CODEGEN", "false");
        // We don't need to build benchmarks.
        config.define("gRPC_BENCHMARK_PROVIDER", "none");
        if cfg!(feature = "openssl") {
            config.define("gRPC_SSL_PROVIDER", "package");
            config.define("EMBED_OPENSSL", "false");
            // Problem is: Ubuntu Trusty shipped with openssl 1.0.1f. Which doesn't
            // support alpn. And Google's gRPC checks for support of ALPN in plane
            // old Makefile, but not in CMake.
            config.cxxflag("-DTSI_OPENSSL_ALPN_SUPPORT=0");
            setup_openssl(&mut config)
        } else if cfg!(feature = "secure") {
            third_party.extend_from_slice(&["boringssl/ssl", "boringssl/crypto"]);
        }
        if cfg!(feature = "no-omit-frame-pointer") {
            config
                .cflag("-fno-omit-frame-pointer")
                .cxxflag("-fno-omit-frame-pointer");
        }
        config.build_target(library).uses_cxx11().build()
    };

    let mut zlib = "z";
    let build_dir = format!("{}/build", dst.display());
    if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "windows") {
        let profile = match &*env::var("PROFILE").unwrap_or("debug".to_owned()) {
            "bench" | "release" => {
                zlib = "zlibstatic";
                "Release"
            }
            _ => {
                zlib = "zlibstaticd";
                "Debug"
            }
        };
        println!("cargo:rustc-link-search=native={}/{}", build_dir, profile);
        for path in third_party {
            println!(
                "cargo:rustc-link-search=native={}/third_party/{}/{}",
                build_dir, path, profile
            );
        }
    } else {
        println!("cargo:rustc-link-search=native={}", build_dir);
        for path in third_party {
            println!(
                "cargo:rustc-link-search=native={}/third_party/{}",
                build_dir, path,
            );
        }
    }

    println!("cargo:rustc-link-lib=static={}", zlib);
    println!("cargo:rustc-link-lib=static=cares");
    println!("cargo:rustc-link-lib=static=gpr");
    println!("cargo:rustc-link-lib=static=address_sorting");
    println!("cargo:rustc-link-lib=static={}", library);

    if cfg!(feature = "secure") {
        if cfg!(feature = "openssl") && !cfg!(feature = "openssl-vendored") {
            figure_ssl_path(&build_dir);
        } else {
            println!("cargo:rustc-link-lib=static=ssl");
            println!("cargo:rustc-link-lib=static=crypto");
        }
    }

    cc.include("grpc/include");
}

fn figure_ssl_path(build_dir: &str) {
    let path = format!("{}/CMakeCache.txt", build_dir);
    let f = BufReader::new(std::fs::File::open(&path).unwrap());
    let mut cnt = 0;
    for l in f.lines() {
        let l = l.unwrap();
        let t = trim_start(&l, "OPENSSL_CRYPTO_LIBRARY:FILEPATH=")
            .or_else(|| trim_start(&l, "OPENSSL_SSL_LIBRARY:FILEPATH="));
        if let Some(s) = t {
            let path = Path::new(s);
            println!(
                "cargo:rustc-link-search=native={}",
                path.parent().unwrap().display()
            );
            cnt += 1;
        }
    }
    if cnt != 2 {
        panic!(
            "CMake cache invalid, file {} contains {} ssl keys!",
            path, cnt
        );
    }
    println!("cargo:rustc-link-lib=ssl");
    println!("cargo:rustc-link-lib=crypto");
}

#[cfg(feature = "openssl-vendored")]
fn setup_openssl(config: &mut Config) {
    // openssl-sys uses openssl-src to build the library. openssl-src uses
    // configure/make to build the library which makes it hard to detect
    // what's the actual path of the library. Here assumes the directory
    // structure as follow (which is the behavior of 0.9.47):
    // install_dir/
    //     include/
    //     lib/
    // Remove the hack when sfackler/rust-openssl#1117 is resolved.
    config.register_dep("openssl");
    if env::var("DEP_OPENSSL_ROOT").is_err() {
        let include_str = env::var("DEP_OPENSSL_INCLUDE").unwrap();
        let include_dir = Path::new(&include_str);
        let root_dir = format!("{}", include_dir.parent().unwrap().display());
        env::set_var("DEP_OPENSSL_ROOT", &root_dir);
    }
}

#[cfg(not(feature = "openssl-vendored"))]
fn setup_openssl(_config: &mut Config) {}

fn get_env(name: &str) -> Option<String> {
    println!("cargo:rerun-if-env-changed={}", name);
    match env::var(name) {
        Ok(s) => Some(s),
        Err(VarError::NotPresent) => None,
        Err(VarError::NotUnicode(s)) => {
            panic!("unrecognize env var of {}: {:?}", name, s.to_string_lossy());
        }
    }
}

// Generate the bindings to grpc C-core.
// Try to disable the generation of platform-related bindings.
fn bindgen_grpc(mut config: bindgen::Builder, file_path: &PathBuf) {
    // Search header files with API interface
    let mut headers = Vec::new();
    for result in WalkDir::new(Path::new("./grpc/include")) {
        let dent = result.expect("Error happened when search headers");
        if !dent.file_type().is_file() {
            continue;
        }
        let mut file = fs::File::open(dent.path()).expect("couldn't open headers");
        let mut buf = String::new();
        file.read_to_string(&mut buf)
            .expect("Coundn't read header content");
        if buf.contains("GRPCAPI") || buf.contains("GPRAPI") {
            headers.push(String::from(dent.path().to_str().unwrap()));
        }
    }

    // To control the order of bindings
    headers.sort();
    for path in headers {
        config = config.header(path);
    }

    config
        .header("grpc_wrap.cc")
        .clang_arg("-xc++")
        .clang_arg("-I./grpc/include")
        .clang_arg("-std=c++11")
        .whitelist_recursively(false)
        .whitelist_function(r"\bgrpc_.*")
        .whitelist_function(r"\bgpr_.*")
        .whitelist_function(r"\bgrpcwrap_.*")
        .whitelist_var(r"\bGRPC_.*")
        .whitelist_type(r"\bgrpc_.*")
        .whitelist_type(r"\bgpr_.*")
        .whitelist_type(r"\bgrpcwrap_.*")
        .whitelist_type(r"\bcensus_context.*")
        .whitelist_type(r"\bverify_peer_options.*")
        .blacklist_function(r"\bgpr_mu_.*")
        .blacklist_function(r"\bgpr_cv_.*")
        .blacklist_function(r"\bgpr_once_.*")
        .blacklist_type(r"gpr_mu")
        .blacklist_type(r"gpr_cv")
        .blacklist_type(r"gpr_once")
        .constified_enum_module(r"grpc_status_code")
        .no_copy("grpc_slice")
        .default_enum_style(bindgen::EnumVariation::Rust {
            non_exhaustive: false,
        })
        .generate()
        .expect("Unable to generate grpc bindings")
        .write_to_file(file_path)
        .expect("Couldn't write bindings!");
}

// Determine if need to update bindings. Supported platforms do not
// need to be updated by default unless the UPDATE_BIND is specified.
// Other platforms use bindgen to generate the bindings every time.
fn config_binding_path(config: bindgen::Builder) {
    let file_path: PathBuf;
    println!("cargo:rerun-if-changed=bindings/x86_64-unknown-linux-gnu-bindings.rs");
    match env::var("TARGET").unwrap_or("".to_owned()).as_str() {
        "x86_64-unknown-linux-gnu" => {
            file_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
                .join("bindings")
                .join("x86_64-unknown-linux-gnu-bindings.rs");
            if env::var("UPDATE_BIND").map(|s| s == "1").unwrap_or(false) {
                bindgen_grpc(config, &file_path);
            }
        }
        _ => {
            file_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("grpc-bindings.rs");
            bindgen_grpc(config, &file_path);
        }
    };
    println!(
        "cargo:rustc-env=BINDING_PATH={}",
        file_path.to_str().unwrap()
    );
}

fn main() {
    println!("cargo:rerun-if-changed=grpc_wrap.cc");
    println!("cargo:rerun-if-changed=grpc");
    println!("cargo:rerun-if-env-changed=UPDATE_BIND");

    let mut cc = Build::new();
    let mut bind_config = bindgen::Builder::default();

    let library = if cfg!(feature = "secure") {
        cc.define("GRPC_SYS_SECURE", None);
        bind_config = bind_config.clang_arg("-DGRPC_SYS_SECURE");
        "grpc"
    } else {
        "grpc_unsecure"
    };

    if get_env("CARGO_CFG_TARGET_OS").map_or(false, |s| s == "windows") {
        // At lease win7
        cc.define("_WIN32_WINNT", Some("0x0700"));
        bind_config = bind_config.clang_arg("-D _WIN32_WINNT=0x0700");
    }

    if get_env("GRPCIO_SYS_USE_PKG_CONFIG").map_or(false, |s| s == "1") {
        // Print cargo metadata.
        let lib_core = probe_library(library, true);
        for inc_path in lib_core.include_paths {
            cc.include(inc_path);
        }
    } else {
        build_grpc(&mut cc, library);
    }

    cc.cpp(true);
    if !cfg!(target_env = "msvc") {
        cc.flag("-std=c++11");
    }
    cc.file("grpc_wrap.cc");

    cc.warnings_into_errors(true);

    cc.compile("libgrpc_wrap.a");

    config_binding_path(bind_config);
}
<|endoftext|>


<commit_before>extern crate rgen3_save;
extern crate rgen3_string;
extern crate rand;

use rand::{Rng, thread_rng};
use rgen3_save::{Pokemon, SaveSections, TrainerInfo};
use std::collections::HashSet;

static PREFIX_NAMES: [&'static str; 52] =
    ["Acid", "Axel", "Baal", "Bike", "Bull", "Bald", "Cave", "Diet", "Dray", "Duke", "Easy",
     "Fact", "Face", "Fowl", "Fuzz", "Goat", "Hair", "Head", "Hiss", "Idea", "Iris", "Iron",
     "Jack", "John", "Kart", "Lady", "Limb", "Lime", "Mace", "Mars", "Naga", "Nuke", "Nude",
     "Omen", "Orca", "Poke", "Pyre", "Quiz", "Risk", "Road", "Sock", "Swag", "Teal", "Tree",
     "Ugly", "Vamp", "Vibe", "Wolf", "Xray", "Yoga", "Zeta", "Zoom"];

static SUFFIX_NAMES: [&'static str; 23] = ["Adder", "Baker", "Biter", "Coder", "Curer", "Diver",
                                           "Eater", "Faker", "Flier", "Frier", "Gamer", "Gazer",
                                           "Giver", "Laser", "Lover", "Maker", "Order", "Racer",
                                           "Taker", "Tamer", "Voter", "Waker", "Zoner"];

fn gen_pokemon<R: Rng>(rng: &mut R,
                       chosen_names: &mut HashSet<String>,
                       trainer: &TrainerInfo)
                       -> Pokemon {
    let mut pokemon = Pokemon::default();
    let mut name;
    loop {
        let prefix = rng.choose(&PREFIX_NAMES).unwrap();
        let suffix = rng.choose(&SUFFIX_NAMES).unwrap();
        name = format!("{} {}", prefix, suffix);
        // Make sure we don't use the same name twice in our team
        if !chosen_names.contains(&name) {
            break;
        }
    }
    rgen3_string::encode_string(&name, &mut pokemon.nickname.0);
    chosen_names.insert(name);
    {
        if pokemon.active_data.is_none() {
            pokemon.active_data = Some(Default::default());
        }
        {
            let active_data = pokemon.active_data.as_mut().unwrap();
            pokemon.personality = rng.gen();
            active_data.level = rng.gen_range(80, 100);
            active_data.total_hp = rng.gen_range(800, 999);
            active_data.current_hp = active_data.total_hp;
            active_data.attack = rng.gen_range(800, 999);
            active_data.defense = rng.gen_range(800, 999);
            active_data.speed = rng.gen_range(800, 999);
            active_data.sp_attack = rng.gen_range(800, 999);
            active_data.sp_defense = rng.gen_range(800, 999);
        }
        while pokemon.set_species(rng.gen_range(1, 412)).is_err() {}
        pokemon.data.growth.experience = std::u32::MAX / 2;
        pokemon.data.growth.friendship = 0xFF;
        pokemon.data.growth.pp_bonuses = 0xFF;
        pokemon.data.attacks.move1 = rng.gen_range(0, 354);
        pokemon.data.attacks.move2 = rng.gen_range(0, 354);
        pokemon.data.attacks.move3 = rng.gen_range(0, 354);
        pokemon.data.attacks.move4 = rng.gen_range(0, 354);
        pokemon.data.attacks.pp1 = 99;
        pokemon.data.attacks.pp2 = 99;
        pokemon.data.attacks.pp3 = 99;
        pokemon.data.attacks.pp4 = 99;
        pokemon.data.evs_and_condition.hp = 0xFF;
        pokemon.data.evs_and_condition.attack = 0xFF;
        pokemon.data.evs_and_condition.defense = 0xFF;
        pokemon.data.evs_and_condition.speed = 0xFF;
        pokemon.data.evs_and_condition.sp_attack = 0xFF;
        pokemon.data.evs_and_condition.sp_defense = 0xFF;
        pokemon.data.evs_and_condition.coolness = 0xFF;
        pokemon.data.evs_and_condition.beauty = 0xFF;
        pokemon.data.evs_and_condition.cuteness = 0xFF;
        pokemon.data.evs_and_condition.smartness = 0xFF;
        pokemon.data.evs_and_condition.toughness = 0xFF;
        pokemon.ot_id = trainer.full_id();
        pokemon.ot_name = trainer.name;
    }
    pokemon
}

fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().expect("Need path to save as first arg");
    let mut save = rgen3_save::Save::load_from_file(&path).unwrap();
    let mut rng = thread_rng();
    {
        let SaveSections { trainer, team, pc_boxes } = save.sections();
        let mut chosen_names = HashSet::new();
        team.clear();
        for _ in 0..6 {
            team.push(gen_pokemon(&mut rng, &mut chosen_names, trainer));
        }
        for b in pc_boxes.iter_mut() {
            for p in &mut b.pokemon {
                *p = Some(gen_pokemon(&mut rng, &mut chosen_names, trainer));
            }
        }
    }
    save.save_to_file(path).unwrap();
}
<commit_msg>pokefill: Don't use more exp than necessary for max level<commit_after>extern crate rgen3_save;
extern crate rgen3_string;
extern crate rand;

use rand::{Rng, thread_rng};
use rgen3_save::{Pokemon, SaveSections, TrainerInfo};
use std::collections::HashSet;

static PREFIX_NAMES: [&'static str; 52] =
    ["Acid", "Axel", "Baal", "Bike", "Bull", "Bald", "Cave", "Diet", "Dray", "Duke", "Easy",
     "Fact", "Face", "Fowl", "Fuzz", "Goat", "Hair", "Head", "Hiss", "Idea", "Iris", "Iron",
     "Jack", "John", "Kart", "Lady", "Limb", "Lime", "Mace", "Mars", "Naga", "Nuke", "Nude",
     "Omen", "Orca", "Poke", "Pyre", "Quiz", "Risk", "Road", "Sock", "Swag", "Teal", "Tree",
     "Ugly", "Vamp", "Vibe", "Wolf", "Xray", "Yoga", "Zeta", "Zoom"];

static SUFFIX_NAMES: [&'static str; 23] = ["Adder", "Baker", "Biter", "Coder", "Curer", "Diver",
                                           "Eater", "Faker", "Flier", "Frier", "Gamer", "Gazer",
                                           "Giver", "Laser", "Lover", "Maker", "Order", "Racer",
                                           "Taker", "Tamer", "Voter", "Waker", "Zoner"];

fn gen_pokemon<R: Rng>(rng: &mut R,
                       chosen_names: &mut HashSet<String>,
                       trainer: &TrainerInfo)
                       -> Pokemon {
    let mut pokemon = Pokemon::default();
    let mut name;
    loop {
        let prefix = rng.choose(&PREFIX_NAMES).unwrap();
        let suffix = rng.choose(&SUFFIX_NAMES).unwrap();
        name = format!("{} {}", prefix, suffix);
        // Make sure we don't use the same name twice in our team
        if !chosen_names.contains(&name) {
            break;
        }
    }
    rgen3_string::encode_string(&name, &mut pokemon.nickname.0);
    chosen_names.insert(name);
    {
        if pokemon.active_data.is_none() {
            pokemon.active_data = Some(Default::default());
        }
        {
            let active_data = pokemon.active_data.as_mut().unwrap();
            pokemon.personality = rng.gen();
            active_data.level = rng.gen_range(80, 100);
            active_data.total_hp = rng.gen_range(800, 999);
            active_data.current_hp = active_data.total_hp;
            active_data.attack = rng.gen_range(800, 999);
            active_data.defense = rng.gen_range(800, 999);
            active_data.speed = rng.gen_range(800, 999);
            active_data.sp_attack = rng.gen_range(800, 999);
            active_data.sp_defense = rng.gen_range(800, 999);
        }
        while pokemon.set_species(rng.gen_range(1, 412)).is_err() {}
        pokemon.data.growth.experience = 1_640_000;
        pokemon.data.growth.friendship = 0xFF;
        pokemon.data.growth.pp_bonuses = 0xFF;
        pokemon.data.attacks.move1 = rng.gen_range(0, 354);
        pokemon.data.attacks.move2 = rng.gen_range(0, 354);
        pokemon.data.attacks.move3 = rng.gen_range(0, 354);
        pokemon.data.attacks.move4 = rng.gen_range(0, 354);
        pokemon.data.attacks.pp1 = 99;
        pokemon.data.attacks.pp2 = 99;
        pokemon.data.attacks.pp3 = 99;
        pokemon.data.attacks.pp4 = 99;
        pokemon.data.evs_and_condition.hp = 0xFF;
        pokemon.data.evs_and_condition.attack = 0xFF;
        pokemon.data.evs_and_condition.defense = 0xFF;
        pokemon.data.evs_and_condition.speed = 0xFF;
        pokemon.data.evs_and_condition.sp_attack = 0xFF;
        pokemon.data.evs_and_condition.sp_defense = 0xFF;
        pokemon.data.evs_and_condition.coolness = 0xFF;
        pokemon.data.evs_and_condition.beauty = 0xFF;
        pokemon.data.evs_and_condition.cuteness = 0xFF;
        pokemon.data.evs_and_condition.smartness = 0xFF;
        pokemon.data.evs_and_condition.toughness = 0xFF;
        pokemon.ot_id = trainer.full_id();
        pokemon.ot_name = trainer.name;
    }
    pokemon
}

fn main() {
    let mut args = std::env::args().skip(1);
    let path = args.next().expect("Need path to save as first arg");
    let mut save = rgen3_save::Save::load_from_file(&path).unwrap();
    let mut rng = thread_rng();
    {
        let SaveSections { trainer, team, pc_boxes } = save.sections();
        let mut chosen_names = HashSet::new();
        team.clear();
        for _ in 0..6 {
            team.push(gen_pokemon(&mut rng, &mut chosen_names, trainer));
        }
        for b in pc_boxes.iter_mut() {
            for p in &mut b.pokemon {
                *p = Some(gen_pokemon(&mut rng, &mut chosen_names, trainer));
            }
        }
    }
    save.save_to_file(path).unwrap();
}
<|endoftext|>


<commit_before>use libc;
use std::cell::Cell;

use cairo::{self, MatrixTrait};

use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::{self, RsvgDrawingCtx};
use handle::RsvgHandle;
use node::{boxed_node_new, NodeResult, NodeTrait, NodeType, RsvgCNodeImpl, RsvgNode};
use parsers::parse;
use property_bag::PropertyBag;

coord_units!(ClipPathUnits, CoordUnits::UserSpaceOnUse);

pub struct NodeClipPath {
    units: Cell<ClipPathUnits>,
}

impl NodeClipPath {
    fn new() -> NodeClipPath {
        NodeClipPath {
            units: Cell::new(ClipPathUnits::default()),
        }
    }

    pub fn get_units(&self) -> ClipPathUnits {
        self.units.get()
    }

    pub fn to_cairo_context(&self, node: &RsvgNode, draw_ctx: *mut RsvgDrawingCtx) {
        let clip_units = self.units.get();

        let clip_path_state = node.get_state_mut();
        let affine_save = clip_path_state.affine;

        let orig_bbox = drawing_ctx::get_bbox(draw_ctx).clone();

        if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
            let rect = orig_bbox.rect.unwrap();

            let bbtransform = cairo::Matrix::new(rect.width, 0.0, 0.0, rect.height, rect.x, rect.y);

            let bbtransform = cairo::Matrix::multiply(&bbtransform, &affine_save);
            clip_path_state.affine = bbtransform;
        }

        drawing_ctx::state_push(draw_ctx);

        drawing_ctx::state_reinherit_top(draw_ctx, node.get_state(), 0);
        drawing_ctx::push_discrete_layer(draw_ctx, &node.get_computed_values(), true);
        node.draw_children(draw_ctx, -1, true);
        drawing_ctx::pop_discrete_layer(draw_ctx, &node.get_computed_values(), true);

        drawing_ctx::state_pop(draw_ctx);

        if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
            clip_path_state.affine = affine_save;
        }

        // FIXME: this is an EPIC HACK to keep the clipping context from
        // accumulating bounding boxes.  We'll remove this later, when we
        // are able to extract bounding boxes from outside the
        // general drawing loop.
        drawing_ctx::set_bbox(draw_ctx, &orig_bbox);

        let cr = drawing_ctx::get_cairo_context(draw_ctx);
        cr.clip();
    }
}

impl NodeTrait for NodeClipPath {
    fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::ClipPathUnits => {
                    self.units.set(parse("clipPathUnits", value, (), None)?)
                }

                _ => (),
            }
        }

        Ok(())
    }

    fn draw(&self, _: &RsvgNode, _: *mut RsvgDrawingCtx, _: i32, _: bool) {
        // nothing; clip paths are handled specially
    }

    fn get_c_impl(&self) -> *const RsvgCNodeImpl {
        unreachable!();
    }
}

#[no_mangle]
pub extern "C" fn rsvg_node_clip_path_new(
    _: *const libc::c_char,
    raw_parent: *const RsvgNode,
) -> *const RsvgNode {
    boxed_node_new(
        NodeType::ClipPath,
        raw_parent,
        Box::new(NodeClipPath::new()),
    )
}
<commit_msg>wip: clip_path.rs: set the cr's transform when we are in objectBoundingBox mode<commit_after>use libc;
use std::cell::Cell;

use cairo::{self, MatrixTrait};

use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::{self, RsvgDrawingCtx};
use handle::RsvgHandle;
use node::{boxed_node_new, NodeResult, NodeTrait, NodeType, RsvgCNodeImpl, RsvgNode};
use parsers::parse;
use property_bag::PropertyBag;

coord_units!(ClipPathUnits, CoordUnits::UserSpaceOnUse);

pub struct NodeClipPath {
    units: Cell<ClipPathUnits>,
}

impl NodeClipPath {
    fn new() -> NodeClipPath {
        NodeClipPath {
            units: Cell::new(ClipPathUnits::default()),
        }
    }

    pub fn get_units(&self) -> ClipPathUnits {
        self.units.get()
    }

    pub fn to_cairo_context(&self, node: &RsvgNode, draw_ctx: *mut RsvgDrawingCtx) {
        let clip_units = self.units.get();

        let orig_bbox = drawing_ctx::get_bbox(draw_ctx).clone();

        let cr = drawing_ctx::get_cairo_context(draw_ctx);

        let cr_save_transform = cr.get_matrix();

        if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
            let rect = orig_bbox.rect.unwrap();

            let bbtransform = cairo::Matrix::new(rect.width, 0.0, 0.0, rect.height, rect.x, rect.y);
            cr.transform(bbtransform);
        }

        drawing_ctx::state_push(draw_ctx);

        drawing_ctx::state_reinherit_top(draw_ctx, node.get_state(), 0);
        drawing_ctx::push_discrete_layer(draw_ctx, &node.get_computed_values(), true);
        node.draw_children(draw_ctx, -1, true);
        drawing_ctx::pop_discrete_layer(draw_ctx, &node.get_computed_values(), true);

        drawing_ctx::state_pop(draw_ctx);

        // FIXME: this is an EPIC HACK to keep the clipping context from
        // accumulating bounding boxes.  We'll remove this later, when we
        // are able to extract bounding boxes from outside the
        // general drawing loop.
        drawing_ctx::set_bbox(draw_ctx, &orig_bbox);

        let cr = drawing_ctx::get_cairo_context(draw_ctx);
        cr.clip();

        if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
            cr.set_matrix(cr_save_transform);
        }
    }
}

impl NodeTrait for NodeClipPath {
    fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::ClipPathUnits => {
                    self.units.set(parse("clipPathUnits", value, (), None)?)
                }

                _ => (),
            }
        }

        Ok(())
    }

    fn draw(&self, _: &RsvgNode, _: *mut RsvgDrawingCtx, _: i32, _: bool) {
        // nothing; clip paths are handled specially
    }

    fn get_c_impl(&self) -> *const RsvgCNodeImpl {
        unreachable!();
    }
}

#[no_mangle]
pub extern "C" fn rsvg_node_clip_path_new(
    _: *const libc::c_char,
    raw_parent: *const RsvgNode,
) -> *const RsvgNode {
    boxed_node_new(
        NodeType::ClipPath,
        raw_parent,
        Box::new(NodeClipPath::new()),
    )
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate time;
#[macro_use]
extern crate clap;
extern crate presort;
extern crate stats;

mod inc_tree;

use std::fs::OpenOptions;
use std::io::Write;
use rand::Rng;
use time::Duration;
use clap::{App, Arg};
use presort::{PresortedVec, PermutedVec};
use stats::{mean,stddev};
use inc_tree::{Tree, IncTree, dump, update, update_no_pad};
use inc_tree::sortvec::SortVec;

const ADD_SIZE: usize = 5;

fn main() {
    //command-line
    let args = App::new("presort_bench")
    .arg(Arg::with_name("vec")
        .long("vec")
        .help("Use the default vector implementation")
        .conflicts_with_all(&["presort","presort_pad","permute","permute_pad"])
    ).arg(Arg::with_name("presort")
        .long("presort")
        .help("Use the presorted vector implementation")
        .conflicts_with_all(&["vec","presort_pad","permute","permute_pad"])
    ).arg(Arg::with_name("presort_pad")
        .long("presort_pad")
        .help("Use the persorted vector implementation with padding")
        .conflicts_with_all(&["vec","presort","permute","permute_pad"])
    ).arg(Arg::with_name("permute")
        .long("permute")
        .help("Use the permuted vector implementation")
        .conflicts_with_all(&["vec","presort","persort_pad","permute_pad"])
    ).arg(Arg::with_name("permute_pad")
        .long("permute_pad")
        .help("Use the permuted vector implementation with padding")
        .conflicts_with_all(&["vec","presort","persort_pad","permute"])
    ).args_from_usage("\
        --tag [tag]                                 'max depth of initial tree'
        [data_size] -b [data_size]                  'data size in bytes (unused)'
        [initial_max_depth] -d [initial_max_depth]  'max depth of initial tree'
        [initial_nodes] -n [initial_nodes]          'nodes of initial tree'
        [edits] -e [edits]                          'nodes to modify'
        [shape] -s [shape]                          'chance for a shape edit'
        [add] -a [add]                              'chance to add a branch (rather than remove)'
        [change] -c [change]                        'chance to change sort order'
        [trials] -t [trials]                        'repetitions to average'
        [outfile] -o [outfile]                      'append output to this file'
        [header] -h                                 'write out a header to the results' ")
    .get_matches();
    let tag = match args.value_of("tag") {
        None => "none",
        Some(t) => t
    };
    let b = value_t!(args.value_of("data_size"), usize).unwrap_or(4);
    let d = value_t!(args.value_of("initial_max_depth"), usize).unwrap_or(13);
    let n = value_t!(args.value_of("initial_nodes"), usize).unwrap_or(10000);
    let e = value_t!(args.value_of("edits"), usize).unwrap_or(0);
    let s = value_t!(args.value_of("shape"), f32).unwrap_or(0.0);
    let a = value_t!(args.value_of("add"), f32).unwrap_or(0.5);
    let c = value_t!(args.value_of("change"), f32).unwrap_or(0.5);
    let t = value_t!(args.value_of("trials"), usize).unwrap_or(1);
    let mut o: Box<Write> = if let Some(f) = args.value_of("outfile") {
        Box::new(
            OpenOptions::new()
            .create(true)
            .write(true)
            .append(true)
            .open(f)
            .unwrap()
        )
    } else { Box::new(std::io::stdout()) };

    //write out header
    if args.is_present("header"){
        writeln!(o, "{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
            "timestamp",
            "user_tag",
            "vec_type",
            "data_size",
            "depth",
            "nodes",
            "edits",
            "chance_shape",
            "chance_add",
            "chance_reorder",
            "time_dump", "sd_dump",
            "time_init_sort", "sd_init_sort",
            "time_modification", "sd_modification",
            "time_update", "sd_update",
            "time_sort", "sd_sort"
        ).unwrap();
    }
    if t == 0 {return}

    // average multiple trials
    let mut dur_dump = Vec::new();
    let mut dur_init_sort = Vec::new();
    let mut dur_modify = Vec::new();
    let mut dur_update = Vec::new();
    let mut dur_sort = Vec::new();

    for _ in 0..t {
        //create target vector
        let mut vec =
            if args.is_present("vec") {
                VecVersion::Vec(Vec::new())
            } else if args.is_present("presort") {
                VecVersion::Presort(PresortedVec::new())
            } else if args.is_present("presort_pad") {
                VecVersion::PrePad(PresortedVec::new())
            } else if args.is_present("permute") {
                VecVersion::Permut(PermutedVec::new())
            } else if args.is_present("permute_pad") {
                VecVersion::PerPad(PermutedVec::new())
            } else {
                VecVersion::Vec(Vec::new())
            };

        //initial tree creation
        let tree = build_tree(d,n);

        //initial dump
        dur_dump.push(Duration::span(||{
            match vec {
                VecVersion::Vec(ref mut v) => dump(&tree, 0, v),
                VecVersion::Presort(ref mut v) => dump(&tree, 0, v),
                VecVersion::PrePad(ref mut v) => dump(&tree, 0, v),
                VecVersion::Permut(ref mut v) => dump(&tree, 0, v),
                VecVersion::PerPad(ref mut v) => dump(&tree, 0, v),
            };
        }).num_nanoseconds().unwrap());

        //initial sort
        dur_init_sort.push(Duration::span(||{
            match vec {
                VecVersion::Vec(ref mut v) => v.sort(),
                VecVersion::Presort(ref mut v) => v.sort(),
                VecVersion::PrePad(ref mut v) => v.sort(),
                VecVersion::Permut(ref mut v) => v.sort(),
                VecVersion::PerPad(ref mut v) => v.sort(),
            };
        }).num_nanoseconds().unwrap());

        //modify tree
        dur_modify.push(Duration::span(||{
            let mut rng = rand::thread_rng();
            if rng.gen::<f32>() < s {
                if rng.gen::<f32>() < a {
                    add_branches(&tree, d, e, ADD_SIZE);
                } else {
                    remove_branches(&tree, d, e);
                }
            } else {
                if rng.gen::<f32>() < c {
                    mutate_vals(&tree, d, e);
                } else {
                    incr_vals(&tree, d, e);
                }
            }
        }).num_nanoseconds().unwrap());

        //update tree
        dur_update.push(Duration::span(||{
            match vec {
                VecVersion::Vec(ref mut v) => update_no_pad(&tree, 0, v),
                VecVersion::Presort(ref mut v) => update_no_pad(&tree, 0, v),
                VecVersion::PrePad(ref mut v) => update(&tree, 0, v),
                VecVersion::Permut(ref mut v) => update_no_pad(&tree, 0, v),
                VecVersion::PerPad(ref mut v) => update(&tree, 0, v),
            };
        }).num_nanoseconds().unwrap());

        //sort tree
        dur_sort.push(Duration::span(||{
            match vec {
                VecVersion::Vec(ref mut v) => v.sort(),
                VecVersion::Presort(ref mut v) => v.sort(),
                VecVersion::PrePad(ref mut v) => v.sort(),
                VecVersion::Permut(ref mut v) => v.sort(),
                VecVersion::PerPad(ref mut v) => v.sort(),
            };
        }).num_nanoseconds().unwrap());
    }

    //write out results
    let vec =
        if args.is_present("vec") {"vec"}
        else if args.is_present("presort") {"presort"}
        else if args.is_present("presort_pad") {"presort_pad"}
        else if args.is_present("permute") {"permute"}
        else if args.is_present("permute_pad") {"permute_pad"}
        else {"vec"};

    writeln!(o, "{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
        time::precise_time_s() as usize,
        tag,vec,b,d,n,e,s,a,c,
        mean(dur_dump.clone().into_iter()), stddev(dur_dump.into_iter()),
        mean(dur_init_sort.clone().into_iter()), stddev(dur_init_sort.into_iter()),
        mean(dur_modify.clone().into_iter()), stddev(dur_modify.into_iter()),
        mean(dur_update.clone().into_iter()), stddev(dur_update.into_iter()),
        mean(dur_sort.clone().into_iter()), stddev(dur_sort.into_iter()),
    ).unwrap();
}

enum VecVersion<T: Ord> {
    Vec(Vec<T>),
    Presort(PresortedVec<T>),
    PrePad(PresortedVec<T>),
    Permut(PermutedVec<T>),
    PerPad(PermutedVec<T>),
}

//creates a random tree with the requested parameters
fn build_tree(max_depth: usize, nodes: usize) -> Tree<usize> {
    let mut rng = rand::thread_rng();
    let max_depth = std::cmp::max(max_depth, 1);

    let tree = Tree::new_node(rng.gen());

    for _ in 0..nodes {
        let mut branch = tree.clone();
        let depth = rng.gen::<usize>() % max_depth;
        for _ in 0..depth {
            let num = branch.num_children();
            if num <= 0 {break};
            branch = branch.get_child(rng.gen::<usize>() % num);
        }
        branch.push_child(Tree::new_node(rng.gen()));
    }

    tree
}

fn random_subtree(tree: &Tree<usize>, high_depth: usize) -> Tree<usize> {
    let mut rng = rand::thread_rng();
    let mut subtree = tree.clone();
    let depth = rng.gen::<usize>() % high_depth;
    for _ in 0..depth {
        let num = subtree.num_children();
        if num <= 0 { return subtree; }
        subtree = subtree.get_child(rng.gen::<usize>() % num);
    }
    return subtree;
}

fn mutate_vals(tree: &Tree<usize>, high_depth: usize, edits: usize) {
    let mut rng = rand::thread_rng();
    for _ in 0..edits {
        random_subtree(tree, high_depth).set_data(rng.gen());
    }
}

fn incr_vals(tree: &Tree<usize>, high_depth: usize, edits: usize) {
    for _ in 0..edits {
        let subtree = random_subtree(tree, high_depth);
        subtree.set_data(subtree.get_data() + 1);
    }
}

fn add_branches(tree: &Tree<usize>, high_depth: usize, adds: usize, new_nodes: usize) {
    for _ in 0..adds {
        let new_hight = (new_nodes as f32).log(2.0) as usize;
        let branch = build_tree(new_hight, new_nodes);
        random_subtree(tree, high_depth).push_child(branch);
    }
}

fn remove_branches(tree: &Tree<usize>, high_depth: usize, removes: usize) {
    for _ in 0..removes {
        let t = random_subtree(tree, high_depth);
        // remove this branch, unless it's root
        if let Some((parent, index)) = t.get_parent() {
            parent.remove_child(index);
        }
    }
}
<commit_msg>limit float decimals in benchmark output<commit_after>extern crate rand;
extern crate time;
#[macro_use]
extern crate clap;
extern crate presort;
extern crate stats;

mod inc_tree;

use std::fs::OpenOptions;
use std::io::Write;
use rand::Rng;
use time::Duration;
use clap::{App, Arg};
use presort::{PresortedVec, PermutedVec};
use stats::{mean,stddev};
use inc_tree::{Tree, IncTree, dump, update, update_no_pad};
use inc_tree::sortvec::SortVec;

const ADD_SIZE: usize = 5;

fn main() {
    //command-line
    let args = App::new("presort_bench")
    .arg(Arg::with_name("vec")
        .long("vec")
        .help("Use the default vector implementation")
        .conflicts_with_all(&["presort","presort_pad","permute","permute_pad"])
    ).arg(Arg::with_name("presort")
        .long("presort")
        .help("Use the presorted vector implementation")
        .conflicts_with_all(&["vec","presort_pad","permute","permute_pad"])
    ).arg(Arg::with_name("presort_pad")
        .long("presort_pad")
        .help("Use the persorted vector implementation with padding")
        .conflicts_with_all(&["vec","presort","permute","permute_pad"])
    ).arg(Arg::with_name("permute")
        .long("permute")
        .help("Use the permuted vector implementation")
        .conflicts_with_all(&["vec","presort","persort_pad","permute_pad"])
    ).arg(Arg::with_name("permute_pad")
        .long("permute_pad")
        .help("Use the permuted vector implementation with padding")
        .conflicts_with_all(&["vec","presort","persort_pad","permute"])
    ).args_from_usage("\
        --tag [tag]                                 'max depth of initial tree'
        [data_size] -b [data_size]                  'data size in bytes (unused)'
        [initial_max_depth] -d [initial_max_depth]  'max depth of initial tree'
        [initial_nodes] -n [initial_nodes]          'nodes of initial tree'
        [edits] -e [edits]                          'nodes to modify'
        [shape] -s [shape]                          'chance for a shape edit'
        [add] -a [add]                              'chance to add a branch (rather than remove)'
        [change] -c [change]                        'chance to change sort order'
        [trials] -t [trials]                        'repetitions to average'
        [outfile] -o [outfile]                      'append output to this file'
        [header] -h                                 'write out a header to the results' ")
    .get_matches();
    let tag = match args.value_of("tag") {
        None => "none",
        Some(t) => t
    };
    let b = value_t!(args.value_of("data_size"), usize).unwrap_or(4);
    let d = value_t!(args.value_of("initial_max_depth"), usize).unwrap_or(13);
    let n = value_t!(args.value_of("initial_nodes"), usize).unwrap_or(10000);
    let e = value_t!(args.value_of("edits"), usize).unwrap_or(0);
    let s = value_t!(args.value_of("shape"), f32).unwrap_or(0.0);
    let a = value_t!(args.value_of("add"), f32).unwrap_or(0.5);
    let c = value_t!(args.value_of("change"), f32).unwrap_or(0.5);
    let t = value_t!(args.value_of("trials"), usize).unwrap_or(1);
    let mut o: Box<Write> = if let Some(f) = args.value_of("outfile") {
        Box::new(
            OpenOptions::new()
            .create(true)
            .write(true)
            .append(true)
            .open(f)
            .unwrap()
        )
    } else { Box::new(std::io::stdout()) };

    //write out header
    if args.is_present("header"){
        writeln!(o, "{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}",
            "timestamp",
            "user_tag",
            "vec_type",
            "data_size",
            "depth",
            "nodes",
            "edits",
            "chance_shape",
            "chance_add",
            "chance_reorder",
            "time_dump", "sd_dump",
            "time_init_sort", "sd_init_sort",
            "time_modification", "sd_modification",
            "time_update", "sd_update",
            "time_sort", "sd_sort"
        ).unwrap();
    }
    if t == 0 {return}

    // average multiple trials
    let mut dur_dump = Vec::new();
    let mut dur_init_sort = Vec::new();
    let mut dur_modify = Vec::new();
    let mut dur_update = Vec::new();
    let mut dur_sort = Vec::new();

    for _ in 0..t {
        //create target vector
        let mut vec =
            if args.is_present("vec") {
                VecVersion::Vec(Vec::new())
            } else if args.is_present("presort") {
                VecVersion::Presort(PresortedVec::new())
            } else if args.is_present("presort_pad") {
                VecVersion::PrePad(PresortedVec::new())
            } else if args.is_present("permute") {
                VecVersion::Permut(PermutedVec::new())
            } else if args.is_present("permute_pad") {
                VecVersion::PerPad(PermutedVec::new())
            } else {
                VecVersion::Vec(Vec::new())
            };

        //initial tree creation
        let tree = build_tree(d,n);

        //initial dump
        dur_dump.push(Duration::span(||{
            match vec {
                VecVersion::Vec(ref mut v) => dump(&tree, 0, v),
                VecVersion::Presort(ref mut v) => dump(&tree, 0, v),
                VecVersion::PrePad(ref mut v) => dump(&tree, 0, v),
                VecVersion::Permut(ref mut v) => dump(&tree, 0, v),
                VecVersion::PerPad(ref mut v) => dump(&tree, 0, v),
            };
        }).num_nanoseconds().unwrap());

        //initial sort
        dur_init_sort.push(Duration::span(||{
            match vec {
                VecVersion::Vec(ref mut v) => v.sort(),
                VecVersion::Presort(ref mut v) => v.sort(),
                VecVersion::PrePad(ref mut v) => v.sort(),
                VecVersion::Permut(ref mut v) => v.sort(),
                VecVersion::PerPad(ref mut v) => v.sort(),
            };
        }).num_nanoseconds().unwrap());

        //modify tree
        dur_modify.push(Duration::span(||{
            let mut rng = rand::thread_rng();
            if rng.gen::<f32>() < s {
                if rng.gen::<f32>() < a {
                    add_branches(&tree, d, e, ADD_SIZE);
                } else {
                    remove_branches(&tree, d, e);
                }
            } else {
                if rng.gen::<f32>() < c {
                    mutate_vals(&tree, d, e);
                } else {
                    incr_vals(&tree, d, e);
                }
            }
        }).num_nanoseconds().unwrap());

        //update tree
        dur_update.push(Duration::span(||{
            match vec {
                VecVersion::Vec(ref mut v) => update_no_pad(&tree, 0, v),
                VecVersion::Presort(ref mut v) => update_no_pad(&tree, 0, v),
                VecVersion::PrePad(ref mut v) => update(&tree, 0, v),
                VecVersion::Permut(ref mut v) => update_no_pad(&tree, 0, v),
                VecVersion::PerPad(ref mut v) => update(&tree, 0, v),
            };
        }).num_nanoseconds().unwrap());

        //sort tree
        dur_sort.push(Duration::span(||{
            match vec {
                VecVersion::Vec(ref mut v) => v.sort(),
                VecVersion::Presort(ref mut v) => v.sort(),
                VecVersion::PrePad(ref mut v) => v.sort(),
                VecVersion::Permut(ref mut v) => v.sort(),
                VecVersion::PerPad(ref mut v) => v.sort(),
            };
        }).num_nanoseconds().unwrap());
    }

    //write out results
    let vec =
        if args.is_present("vec") {"vec"}
        else if args.is_present("presort") {"presort"}
        else if args.is_present("presort_pad") {"presort_pad"}
        else if args.is_present("permute") {"permute"}
        else if args.is_present("permute_pad") {"permute_pad"}
        else {"vec"};

    writeln!(o, "{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\t{:.5}\t{:.5}\t{:.5}\t{:.5}\t{:.5}\t{:.5}\t{:.5}\t{:.5}\t{:.5}\t{:.5}",
        time::precise_time_s() as usize,
        tag,vec,b,d,n,e,s,a,c,
        mean(dur_dump.clone().into_iter()), stddev(dur_dump.into_iter()),
        mean(dur_init_sort.clone().into_iter()), stddev(dur_init_sort.into_iter()),
        mean(dur_modify.clone().into_iter()), stddev(dur_modify.into_iter()),
        mean(dur_update.clone().into_iter()), stddev(dur_update.into_iter()),
        mean(dur_sort.clone().into_iter()), stddev(dur_sort.into_iter()),
    ).unwrap();
}

enum VecVersion<T: Ord> {
    Vec(Vec<T>),
    Presort(PresortedVec<T>),
    PrePad(PresortedVec<T>),
    Permut(PermutedVec<T>),
    PerPad(PermutedVec<T>),
}

//creates a random tree with the requested parameters
fn build_tree(max_depth: usize, nodes: usize) -> Tree<usize> {
    let mut rng = rand::thread_rng();
    let max_depth = std::cmp::max(max_depth, 1);

    let tree = Tree::new_node(rng.gen());

    for _ in 0..nodes {
        let mut branch = tree.clone();
        let depth = rng.gen::<usize>() % max_depth;
        for _ in 0..depth {
            let num = branch.num_children();
            if num <= 0 {break};
            branch = branch.get_child(rng.gen::<usize>() % num);
        }
        branch.push_child(Tree::new_node(rng.gen()));
    }

    tree
}

fn random_subtree(tree: &Tree<usize>, high_depth: usize) -> Tree<usize> {
    let mut rng = rand::thread_rng();
    let mut subtree = tree.clone();
    let depth = rng.gen::<usize>() % high_depth;
    for _ in 0..depth {
        let num = subtree.num_children();
        if num <= 0 { return subtree; }
        subtree = subtree.get_child(rng.gen::<usize>() % num);
    }
    return subtree;
}

fn mutate_vals(tree: &Tree<usize>, high_depth: usize, edits: usize) {
    let mut rng = rand::thread_rng();
    for _ in 0..edits {
        random_subtree(tree, high_depth).set_data(rng.gen());
    }
}

fn incr_vals(tree: &Tree<usize>, high_depth: usize, edits: usize) {
    for _ in 0..edits {
        let subtree = random_subtree(tree, high_depth);
        subtree.set_data(subtree.get_data() + 1);
    }
}

fn add_branches(tree: &Tree<usize>, high_depth: usize, adds: usize, new_nodes: usize) {
    for _ in 0..adds {
        let new_hight = (new_nodes as f32).log(2.0) as usize;
        let branch = build_tree(new_hight, new_nodes);
        random_subtree(tree, high_depth).push_child(branch);
    }
}

fn remove_branches(tree: &Tree<usize>, high_depth: usize, removes: usize) {
    for _ in 0..removes {
        let t = random_subtree(tree, high_depth);
        // remove this branch, unless it's root
        if let Some((parent, index)) = t.get_parent() {
            parent.remove_child(index);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>ConvertibleColour RGB is always linear, Colour RGB is always sRGB<commit_after><|endoftext|>


<commit_before>//! Parse a Rust source file into a `syn::File` and print out a debug
//! representation of the syntax tree.
//!
//! Use the following command from this directory to test this program by
//! running it on its own source code:
//!
//!     cargo run -- src/main.rs
//!
//! The output will begin with:
//!
//!     File {
//!         shebang: None,
//!         attrs: [
//!             Attribute {
//!                 pound_token: Pound,
//!                 style: Inner(
//!         ...
//!     }

use std::borrow::Cow;
use std::env;
use std::ffi::OsStr;
use std::fmt::{self, Display};
use std::fs;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process;

use colored::Colorize;

enum Error {
    IncorrectUsage,
    ReadFile(io::Error),
    ParseFile {
        error: syn::Error,
        filepath: PathBuf,
        source_code: String,
    },
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            IncorrectUsage => write!(f, "Usage: dump-syntax path/to/filename.rs"),
            ReadFile(error) => write!(f, "Unable to read file: {}", error),
            ParseFile {
                error,
                filepath,
                source_code,
            } => render_location(f, error, filepath, source_code),
        }
    }
}

fn main() {
    if let Err(error) = try_main() {
        let _ = writeln!(io::stderr(), "{}", error);
        process::exit(1);
    }
}

fn try_main() -> Result<(), Error> {
    let mut args = env::args_os();
    let _ = args.next(); // executable name

    let filepath = match (args.next(), args.next()) {
        (Some(arg), None) => PathBuf::from(arg),
        _ => return Err(Error::IncorrectUsage),
    };

    let code = fs::read_to_string(&filepath).map_err(Error::ReadFile)?;
    let syntax = syn::parse_file(&code).map_err({
        |error| Error::ParseFile {
            error,
            filepath,
            source_code: code,
        }
    })?;
    println!("{:#?}", syntax);

    Ok(())
}

fn render_location(
    formatter: &mut fmt::Formatter,
    err: &syn::Error,
    filepath: &Path,
    code: &str,
) -> fmt::Result {
    let start = err.span().start();
    let mut end = err.span().end();

    if start.line == end.line && start.column == end.column {
        return render_fallback(formatter, err);
    }

    let code_line = match code.lines().nth(start.line - 1) {
        Some(line) => line,
        None => return render_fallback(formatter, err),
    };

    if end.line > start.line {
        end.line = start.line;
        end.column = code_line.len();
    }

    let filename = filepath
        .file_name()
        .map(OsStr::to_string_lossy)
        .unwrap_or(Cow::Borrowed("main.rs"));

    write!(
        formatter,
        "\n\
         {error}{header}\n\
         {indent}{arrow} {filename}:{linenum}:{colnum}\n\
         {indent} {pipe} \n\
         {label} {pipe} {code}\n\
         {indent} {pipe} {offset}{underline} {message}\n\
         ",
        error = "error".red().bold(),
        header = ": Syn unable to parse file".bold(),
        indent = " ".repeat(start.line.to_string().len()),
        arrow = "-->".blue().bold(),
        filename = filename,
        linenum = start.line,
        colnum = start.column,
        pipe = "|".blue().bold(),
        label = start.line.to_string().blue().bold(),
        code = code_line.trim_end(),
        offset = " ".repeat(start.column),
        underline = "^".repeat(end.column - start.column).red().bold(),
        message = err.to_string().red(),
    )
}

fn render_fallback(formatter: &mut fmt::Formatter, err: &syn::Error) -> fmt::Result {
    write!(formatter, "Unable to parse file: {}", err)
}
<commit_msg>Show example of rustc-style error message in comment<commit_after>//! Parse a Rust source file into a `syn::File` and print out a debug
//! representation of the syntax tree.
//!
//! Use the following command from this directory to test this program by
//! running it on its own source code:
//!
//!     cargo run -- src/main.rs
//!
//! The output will begin with:
//!
//!     File {
//!         shebang: None,
//!         attrs: [
//!             Attribute {
//!                 pound_token: Pound,
//!                 style: Inner(
//!         ...
//!     }

use std::borrow::Cow;
use std::env;
use std::ffi::OsStr;
use std::fmt::{self, Display};
use std::fs;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process;

use colored::Colorize;

enum Error {
    IncorrectUsage,
    ReadFile(io::Error),
    ParseFile {
        error: syn::Error,
        filepath: PathBuf,
        source_code: String,
    },
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            IncorrectUsage => write!(f, "Usage: dump-syntax path/to/filename.rs"),
            ReadFile(error) => write!(f, "Unable to read file: {}", error),
            ParseFile {
                error,
                filepath,
                source_code,
            } => render_location(f, error, filepath, source_code),
        }
    }
}

fn main() {
    if let Err(error) = try_main() {
        let _ = writeln!(io::stderr(), "{}", error);
        process::exit(1);
    }
}

fn try_main() -> Result<(), Error> {
    let mut args = env::args_os();
    let _ = args.next(); // executable name

    let filepath = match (args.next(), args.next()) {
        (Some(arg), None) => PathBuf::from(arg),
        _ => return Err(Error::IncorrectUsage),
    };

    let code = fs::read_to_string(&filepath).map_err(Error::ReadFile)?;
    let syntax = syn::parse_file(&code).map_err({
        |error| Error::ParseFile {
            error,
            filepath,
            source_code: code,
        }
    })?;
    println!("{:#?}", syntax);

    Ok(())
}

// Render a rustc-style error message, including colors.
//
//     error: Syn unable to parse file
//       --> main.rs:40:17
//        |
//     40 |     fn fmt(&self formatter: &mut fmt::Formatter) -> fmt::Result {
//        |                  ^^^^^^^^^ expected `,`
//
fn render_location(
    formatter: &mut fmt::Formatter,
    err: &syn::Error,
    filepath: &Path,
    code: &str,
) -> fmt::Result {
    let start = err.span().start();
    let mut end = err.span().end();

    if start.line == end.line && start.column == end.column {
        return render_fallback(formatter, err);
    }

    let code_line = match code.lines().nth(start.line - 1) {
        Some(line) => line,
        None => return render_fallback(formatter, err),
    };

    if end.line > start.line {
        end.line = start.line;
        end.column = code_line.len();
    }

    let filename = filepath
        .file_name()
        .map(OsStr::to_string_lossy)
        .unwrap_or(Cow::Borrowed("main.rs"));

    write!(
        formatter,
        "\n\
         {error}{header}\n\
         {indent}{arrow} {filename}:{linenum}:{colnum}\n\
         {indent} {pipe}\n\
         {label} {pipe} {code}\n\
         {indent} {pipe} {offset}{underline} {message}\n\
         ",
        error = "error".red().bold(),
        header = ": Syn unable to parse file".bold(),
        indent = " ".repeat(start.line.to_string().len()),
        arrow = "-->".blue().bold(),
        filename = filename,
        linenum = start.line,
        colnum = start.column,
        pipe = "|".blue().bold(),
        label = start.line.to_string().blue().bold(),
        code = code_line.trim_end(),
        offset = " ".repeat(start.column),
        underline = "^".repeat(end.column - start.column).red().bold(),
        message = err.to_string().red(),
    )
}

fn render_fallback(formatter: &mut fmt::Formatter, err: &syn::Error) -> fmt::Result {
    write!(formatter, "Unable to parse file: {}", err)
}
<|endoftext|>


<commit_before>import std::time;
import time::tm;
import mre::model::{model, error};

// Create a class to act as our model. Unfortunately Rust's classes aren't
// finished yet, and are missing a couple features that would help clean up
// models. First, there's no way to mix in implementation of functions, so we
// need to duplicate some code that's common across all models. Second, there
// is no way to have multiple constructors or static functions, so we need to
// move error handling out into a wrapper function. So to keep the api clean,
// we cheat and hide the class so we can make a function that acts like what we
// want.
class _person {
    let model: model;

    new(model: model) {
        self.model = model;
    }

    fn id() -> @str {
        self.model._id
    }

    fn timestamp() -> @str {
        self.model.get_str("timestamp")
    }

    fn set_timestamp(timestamp: @str) -> bool {
        self.model.set_str("timestamp", timestamp)
    }

    fn name() -> @str {
        self.model.get_str("name")
    }

    fn set_name(name: @str) -> bool {
        self.model.set_str("name", name)
    }

    fn create() -> result<(), error> {
        self.model.create()
    }

    fn save() -> result<(), error> {
        self.model.save()
    }

    fn delete() {
        self.model.delete()
    }
}

// We want the type named "person", but we don't "person" to be the built-in
// class constructor.
type person = _person;

// Create a new person model.
fn person(es: client, name: @str) -> person {
    // We'll let ES come up with a unique id.
    let person = _person(model(es, @"helloeveryone", @"person", @""));

    person.set_name(name);
    person.set_timestamp(@time::now().rfc3339());

    person
}

// Return the last 100 people we have said hello to.
fn last_50(es: client) -> [person] {
    // Sort by reverse timestamp.
    model::search(es) { |bld|
        bld
            .set_indices(["helloeveryone"])
            .set_types(["person"])
            .set_source(*json_dict_builder()
                .insert("size", 50.0)
                .insert_list("sort") { |bld|
                    bld.push_dict { |bld|
                        bld.insert("timestamp", "desc");
                    };
                }
            );
    }.map { |model| _person(model) }
}
<commit_msg>Update some documentation.<commit_after>import std::time;
import time::tm;
import mre::model::{model, error};

// Create a class to act as our model. Unfortunately Rust's classes aren't
// finished yet, and are missing a couple features that would help clean up
// models. First, there's no way to mix in implementation of functions, so we
// need to duplicate some code that's common across all models. Second, there
// is no way to have multiple constructors or static functions, so we need to
// move error handling out into a wrapper function. So to keep the api clean,
// we cheat and hide the class so we can make a function that acts like what we
// want.
class _person {
    let model: model;

    new(model: model) {
        self.model = model;
    }

    fn id() -> @str {
        self.model._id
    }

    fn timestamp() -> @str {
        self.model.get_str("timestamp")
    }

    fn set_timestamp(timestamp: @str) -> bool {
        self.model.set_str("timestamp", timestamp)
    }

    fn name() -> @str {
        self.model.get_str("name")
    }

    fn set_name(name: @str) -> bool {
        self.model.set_str("name", name)
    }

    fn create() -> result<(), error> {
        self.model.create()
    }

    fn save() -> result<(), error> {
        self.model.save()
    }

    fn delete() {
        self.model.delete()
    }
}

// We want the type named "person", but we don't "person" to be the built-in
// class constructor.
type person = _person;

// Create a new person model.
fn person(es: client, name: @str) -> person {
    // Create a person. We'll store the model in the ES index named
    // "helloeveryone", under the type "person". We'd like ES to make the index
    // for us, so we leave the id blank.
    let person = _person(model(es, @"helloeveryone", @"person", @""));

    person.set_name(name);
    person.set_timestamp(@time::now().rfc3339());

    person
}

// Return the last 50 people we have said hello to.
fn last_50(es: client) -> [person] {
    // This query can be a little complicated for those who have never used
    // elasticsearch. All it says is that we want to fetch 50 documents on the
    // index "helloeveryone" and the type "person", sorted by time.
    model::search(es) { |bld|
        bld
            .set_indices(["helloeveryone"])
            .set_types(["person"])
            .set_source(*json_dict_builder()
                .insert("size", 50.0)
                .insert_list("sort") { |bld|
                    bld.push_dict { |bld|
                        bld.insert("timestamp", "desc");
                    };
                }
            );
    }.map { |model|
        // Construct a person model from the raw model data.
        _person(model)
    }
}
<|endoftext|>