<commit_before>#![feature(test)]

use compiletest_rs as compiletest;
extern crate tester as test;

use std::env::{set_var, var};
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

#[must_use]
fn clippy_driver_path() -> PathBuf {
    if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
        PathBuf::from(path)
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/clippy-driver"))
    }
}

#[must_use]
fn host_libs() -> PathBuf {
    if let Some(path) = option_env!("HOST_LIBS") {
        PathBuf::from(path)
    } else {
        Path::new("target").join(env!("PROFILE"))
    }
}

#[must_use]
fn target_libs() -> Option<PathBuf> {
    option_env!("TARGET_LIBS").map(PathBuf::from)
}

#[must_use]
fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

#[must_use]
fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn config(mode: &str, dir: PathBuf) -> compiletest::Config {
    let mut config = compiletest::Config::default();

    let cfg_mode = mode.parse().expect("Invalid mode");
    if let Ok(name) = var::<&str>("TESTNAME") {
        config.filter = Some(name)
    }

    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }

    // When we'll want to use `extern crate ..` for a dependency that is used
    // both by the crate and the compiler itself, we can't simply pass -L flags
    // as we'll get a duplicate matching versions. Instead, disambiguate with
    // `--extern dep=path`.
    // See https://github.com/rust-lang/rust-clippy/issues/4015.
    let needs_disambiguation = ["serde", "regex", "clippy_lints"];
    // This assumes that deps are compiled (they are for Cargo integration tests).
    let deps = fs::read_dir(target_libs().unwrap_or_else(host_libs).join("deps")).unwrap();
    let disambiguated = deps
        .filter_map(|dep| {
            let path = dep.ok()?.path();
            let name = path.file_name()?.to_string_lossy();
            // NOTE: This only handles a single dep
            // https://github.com/laumann/compiletest-rs/issues/101
            needs_disambiguation.iter().find_map(|dep| {
                if name.starts_with(&format!("lib{}-", dep)) && name.ends_with(".rlib") {
                    Some(format!("--extern {}={}", dep, path.display()))
                } else {
                    None
                }
            })
        })
        .collect::<Vec<_>>();

    config.target_rustcflags = Some(format!(
        "-L {0} -L {0}/deps {1} -Dwarnings -Zui-testing {2}",
        host_libs().display(),
        target_libs().map_or_else(String::new, |path| format!("-L {0} -L {0}/deps", path.display())),
        disambiguated.join(" ")
    ));

    config.mode = cfg_mode;
    config.build_base = if rustc_test_suite().is_some() {
        // we don't need access to the stderr files on travis
        let mut path = PathBuf::from(env!("OUT_DIR"));
        path.push("test_build_base");
        path
    } else {
        let mut path = std::env::current_dir().unwrap();
        path.push("target/debug/test_build_base");
        path
    };
    config.src_base = dir;
    config.rustc_path = clippy_driver_path();
    config
}

fn run_mode(mode: &str, dir: PathBuf) {
    let cfg = config(mode, dir);
    compiletest::run_tests(&cfg);
}

#[allow(clippy::identity_conversion)]
fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDescAndFn>) -> Result<bool, io::Error> {
    let mut result = true;
    let opts = compiletest::test_opts(config);
    for dir in fs::read_dir(&config.src_base)? {
        let dir = dir?;
        if !dir.file_type()?.is_dir() {
            continue;
        }
        let dir_path = dir.path();
        set_var("CARGO_MANIFEST_DIR", &dir_path);
        for file in fs::read_dir(&dir_path)? {
            let file = file?;
            let file_path = file.path();
            if !file.file_type()?.is_file() {
                continue;
            }
            if file_path.extension() != Some(OsStr::new("rs")) {
                continue;
            }
            let paths = compiletest::common::TestPaths {
                file: file_path,
                base: config.src_base.clone(),
                relative_dir: dir_path.file_name().unwrap().into(),
            };
            let test_name = compiletest::make_test_name(&config, &paths);
            let index = tests
                .iter()
                .position(|test| test.desc.name == test_name)
                .expect("The test should be in there");
            result &= test::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
        }
    }
    Ok(result)
}

fn run_ui_toml() {
    let path = PathBuf::from("tests/ui-toml").canonicalize().unwrap();
    let config = config("ui", path);
    let tests = compiletest::make_tests(&config);

    let res = run_ui_toml_tests(&config, tests);
    match res {
        Ok(true) => {},
        Ok(false) => panic!("Some tests failed"),
        Err(e) => {
            println!("I/O failure during tests: {:?}", e);
        },
    }
}

fn prepare_env() {
    set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
    set_var("CLIPPY_TESTS", "true");
    //set_var("RUST_BACKTRACE", "0");
}

#[test]
fn compile_test() {
    prepare_env();
    run_mode("ui", "tests/ui".into());
    run_ui_toml();
}
<commit_msg>Fix lint warning in compile-test.rs<commit_after>#![feature(test)]

use compiletest_rs as compiletest;
extern crate tester as test;

use std::env::{set_var, var};
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

#[must_use]
fn clippy_driver_path() -> PathBuf {
    if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
        PathBuf::from(path)
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/clippy-driver"))
    }
}

#[must_use]
fn host_libs() -> PathBuf {
    if let Some(path) = option_env!("HOST_LIBS") {
        PathBuf::from(path)
    } else {
        Path::new("target").join(env!("PROFILE"))
    }
}

#[must_use]
fn target_libs() -> Option<PathBuf> {
    option_env!("TARGET_LIBS").map(PathBuf::from)
}

#[must_use]
fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

#[must_use]
fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn config(mode: &str, dir: PathBuf) -> compiletest::Config {
    let mut config = compiletest::Config::default();

    let cfg_mode = mode.parse().expect("Invalid mode");
    if let Ok(name) = var::<&str>("TESTNAME") {
        config.filter = Some(name)
    }

    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }

    // When we'll want to use `extern crate ..` for a dependency that is used
    // both by the crate and the compiler itself, we can't simply pass -L flags
    // as we'll get a duplicate matching versions. Instead, disambiguate with
    // `--extern dep=path`.
    // See https://github.com/rust-lang/rust-clippy/issues/4015.
    let needs_disambiguation = ["serde", "regex", "clippy_lints"];
    // This assumes that deps are compiled (they are for Cargo integration tests).
    let deps = fs::read_dir(target_libs().unwrap_or_else(host_libs).join("deps")).unwrap();
    let disambiguated = deps
        .filter_map(|dep| {
            let path = dep.ok()?.path();
            let name = path.file_name()?.to_string_lossy();
            // NOTE: This only handles a single dep
            // https://github.com/laumann/compiletest-rs/issues/101
            needs_disambiguation.iter().find_map(|dep| {
                if name.starts_with(&format!("lib{}-", dep)) && name.ends_with(".rlib") {
                    Some(format!("--extern {}={}", dep, path.display()))
                } else {
                    None
                }
            })
        })
        .collect::<Vec<_>>();

    config.target_rustcflags = Some(format!(
        "-L {0} -L {0}/deps {1} -Dwarnings -Zui-testing {2}",
        host_libs().display(),
        target_libs().map_or_else(String::new, |path| format!("-L {0} -L {0}/deps", path.display())),
        disambiguated.join(" ")
    ));

    config.mode = cfg_mode;
    config.build_base = if rustc_test_suite().is_some() {
        // we don't need access to the stderr files on travis
        let mut path = PathBuf::from(env!("OUT_DIR"));
        path.push("test_build_base");
        path
    } else {
        let mut path = std::env::current_dir().unwrap();
        path.push("target/debug/test_build_base");
        path
    };
    config.src_base = dir;
    config.rustc_path = clippy_driver_path();
    config
}

fn run_mode(mode: &str, dir: PathBuf) {
    let cfg = config(mode, dir);
    compiletest::run_tests(&cfg);
}

#[allow(clippy::identity_conversion)]
fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDescAndFn>) -> Result<bool, io::Error> {
    let mut result = true;
    let opts = compiletest::test_opts(config);
    for dir in fs::read_dir(&config.src_base)? {
        let dir = dir?;
        if !dir.file_type()?.is_dir() {
            continue;
        }
        let dir_path = dir.path();
        set_var("CARGO_MANIFEST_DIR", &dir_path);
        for file in fs::read_dir(&dir_path)? {
            let file = file?;
            let file_path = file.path();
            if file.file_type()?.is_dir() {
                continue;
            }
            if file_path.extension() != Some(OsStr::new("rs")) {
                continue;
            }
            let paths = compiletest::common::TestPaths {
                file: file_path,
                base: config.src_base.clone(),
                relative_dir: dir_path.file_name().unwrap().into(),
            };
            let test_name = compiletest::make_test_name(&config, &paths);
            let index = tests
                .iter()
                .position(|test| test.desc.name == test_name)
                .expect("The test should be in there");
            result &= test::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
        }
    }
    Ok(result)
}

fn run_ui_toml() {
    let path = PathBuf::from("tests/ui-toml").canonicalize().unwrap();
    let config = config("ui", path);
    let tests = compiletest::make_tests(&config);

    let res = run_ui_toml_tests(&config, tests);
    match res {
        Ok(true) => {},
        Ok(false) => panic!("Some tests failed"),
        Err(e) => {
            println!("I/O failure during tests: {:?}", e);
        },
    }
}

fn prepare_env() {
    set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
    set_var("CLIPPY_TESTS", "true");
    //set_var("RUST_BACKTRACE", "0");
}

#[test]
fn compile_test() {
    prepare_env();
    run_mode("ui", "tests/ui".into());
    run_ui_toml();
}
<|endoftext|>


<commit_before>extern crate rosc;
extern crate byteorder;

use byteorder::{ByteOrder, BigEndian};
use std::mem;
use std::ascii::AsciiExt;

use rosc::{decoder, encoder};

#[test]
fn test_decode_no_args() {
    // message to build: /some/valid/address/4 ,
    let raw_addr = "/some/valid/address/4";
    let addr = encoder::encode_string(raw_addr);
    let type_tags = encoder::encode_string(",");
    let merged: Vec<u8> = addr.into_iter()
                              .chain(type_tags.into_iter())
                              .collect();
    let osc_packet: Result<rosc::OscPacket, rosc::OscError> = decoder::decode(&merged);
    assert!(osc_packet.is_ok());
    match osc_packet {
        Ok(rosc::OscPacket::Message(msg)) => {
            assert_eq!(raw_addr, msg.addr);
            assert!(msg.args.is_none());
        }
        Ok(_) => panic!("Expected an OscMessage!"),
        Err(e) => panic!(e),
    }
}

#[test]
fn test_decode_args() {
    // /another/valid/address/123 ,fdih 3.1415 3.14159265359 12345678i32
    // -1234567891011
    let addr = encoder::encode_string("/another/valid/address/123");
    // args
    let f = 3.1415f32;
    let mut f_bytes: [u8; 4] = [0u8; 4];
    BigEndian::write_f32(&mut f_bytes, f);
    assert_eq!(BigEndian::read_f32(&f_bytes), f);

    let d = 3.14159265359f64;
    let mut d_bytes: [u8; 8] = [0u8; 8];
    BigEndian::write_f64(&mut d_bytes, d);
    assert_eq!(BigEndian::read_f64(&d_bytes), d);

    let i = 12345678i32;
    let i_bytes: [u8; 4] = unsafe { mem::transmute(i.to_be()) };

    let l = -1234567891011i64;
    let h_bytes: [u8; 8] = unsafe { mem::transmute(l.to_be()) };

    let blob_size: [u8; 4] = unsafe { mem::transmute(6u32.to_be()) };
    let blob: Vec<u8> = vec![1u8, 2u8, 3u8, 4u8, 5u8, 6u8];

    let s = "I am an osc test string.";
    assert!(s.is_ascii());
    // Osc strings are null terminated like in C!
    let s_bytes: Vec<u8> = encoder::encode_string(s);

    let c = '$';
    let c_bytes: [u8; 4] = unsafe { mem::transmute((c as u32).to_be()) };

    let type_tags = encoder::encode_string(",fdsTFibhNIc");

    let args: Vec<u8> = f_bytes.iter()
                               .chain(d_bytes.iter())
                               .chain(s_bytes.iter())
                               .chain(i_bytes.iter())
                               .chain(blob_size.iter())
                               .chain(blob.iter())
                               .chain(vec![0u8, 0u8].iter())
                               .chain(h_bytes.iter())
                               .chain(c_bytes.iter())
                               .map(|x| *x)
                               .collect::<Vec<u8>>();

    let merged: Vec<u8> = addr.into_iter()
                              .chain(type_tags.into_iter())
                              .chain(args)
                              .collect::<Vec<u8>>();

    match decoder::decode(&merged).unwrap() {
        rosc::OscPacket::Message(msg) => {
            for arg in msg.args.unwrap() {
                match arg {
                    rosc::OscType::Int(x) => assert_eq!(i, x),
                    rosc::OscType::Long(x) => assert_eq!(l, x),
                    rosc::OscType::Float(x) => assert_eq!(f, x),
                    rosc::OscType::Double(x) => assert_eq!(d, x),
                    rosc::OscType::String(x) => assert_eq!(s, x),
                    rosc::OscType::Blob(x) => assert_eq!(blob, x),
                    // cant assign bool args to type_tag
                    // , so there is no real test wether the value is
                    // correct or not
                    rosc::OscType::Bool(_) => (),
                    rosc::OscType::Inf => (),
                    rosc::OscType::Nil => (),
                    // test time-tags, midi-messages and chars
                    rosc::OscType::Char(x) => assert_eq!(c, x),
                    _ => panic!(),
                }

            }
        }
        _ => panic!("Expected an OSC message!"),
    }
}
<commit_msg>Remove unused import<commit_after>extern crate rosc;
extern crate byteorder;

use byteorder::{ByteOrder, BigEndian};
use std::mem;

use rosc::{decoder, encoder};

#[test]
fn test_decode_no_args() {
    // message to build: /some/valid/address/4 ,
    let raw_addr = "/some/valid/address/4";
    let addr = encoder::encode_string(raw_addr);
    let type_tags = encoder::encode_string(",");
    let merged: Vec<u8> = addr.into_iter()
                              .chain(type_tags.into_iter())
                              .collect();
    let osc_packet: Result<rosc::OscPacket, rosc::OscError> = decoder::decode(&merged);
    assert!(osc_packet.is_ok());
    match osc_packet {
        Ok(rosc::OscPacket::Message(msg)) => {
            assert_eq!(raw_addr, msg.addr);
            assert!(msg.args.is_none());
        }
        Ok(_) => panic!("Expected an OscMessage!"),
        Err(e) => panic!(e),
    }
}

#[test]
fn test_decode_args() {
    // /another/valid/address/123 ,fdih 3.1415 3.14159265359 12345678i32
    // -1234567891011
    let addr = encoder::encode_string("/another/valid/address/123");
    // args
    let f = 3.1415f32;
    let mut f_bytes: [u8; 4] = [0u8; 4];
    BigEndian::write_f32(&mut f_bytes, f);
    assert_eq!(BigEndian::read_f32(&f_bytes), f);

    let d = 3.14159265359f64;
    let mut d_bytes: [u8; 8] = [0u8; 8];
    BigEndian::write_f64(&mut d_bytes, d);
    assert_eq!(BigEndian::read_f64(&d_bytes), d);

    let i = 12345678i32;
    let i_bytes: [u8; 4] = unsafe { mem::transmute(i.to_be()) };

    let l = -1234567891011i64;
    let h_bytes: [u8; 8] = unsafe { mem::transmute(l.to_be()) };

    let blob_size: [u8; 4] = unsafe { mem::transmute(6u32.to_be()) };
    let blob: Vec<u8> = vec![1u8, 2u8, 3u8, 4u8, 5u8, 6u8];

    let s = "I am an osc test string.";
    assert!(s.is_ascii());
    // Osc strings are null terminated like in C!
    let s_bytes: Vec<u8> = encoder::encode_string(s);

    let c = '$';
    let c_bytes: [u8; 4] = unsafe { mem::transmute((c as u32).to_be()) };

    let type_tags = encoder::encode_string(",fdsTFibhNIc");

    let args: Vec<u8> = f_bytes.iter()
                               .chain(d_bytes.iter())
                               .chain(s_bytes.iter())
                               .chain(i_bytes.iter())
                               .chain(blob_size.iter())
                               .chain(blob.iter())
                               .chain(vec![0u8, 0u8].iter())
                               .chain(h_bytes.iter())
                               .chain(c_bytes.iter())
                               .map(|x| *x)
                               .collect::<Vec<u8>>();

    let merged: Vec<u8> = addr.into_iter()
                              .chain(type_tags.into_iter())
                              .chain(args)
                              .collect::<Vec<u8>>();

    match decoder::decode(&merged).unwrap() {
        rosc::OscPacket::Message(msg) => {
            for arg in msg.args.unwrap() {
                match arg {
                    rosc::OscType::Int(x) => assert_eq!(i, x),
                    rosc::OscType::Long(x) => assert_eq!(l, x),
                    rosc::OscType::Float(x) => assert_eq!(f, x),
                    rosc::OscType::Double(x) => assert_eq!(d, x),
                    rosc::OscType::String(x) => assert_eq!(s, x),
                    rosc::OscType::Blob(x) => assert_eq!(blob, x),
                    // cant assign bool args to type_tag
                    // , so there is no real test wether the value is
                    // correct or not
                    rosc::OscType::Bool(_) => (),
                    rosc::OscType::Inf => (),
                    rosc::OscType::Nil => (),
                    // test time-tags, midi-messages and chars
                    rosc::OscType::Char(x) => assert_eq!(c, x),
                    _ => panic!(),
                }

            }
        }
        _ => panic!("Expected an OSC message!"),
    }
}
<|endoftext|>


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

// Inspired by Clang's clang-format-diff:
//
// https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py

#![deny(warnings)]

extern crate getopts;
extern crate regex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json as json;

use std::{env, fmt, process};
use std::collections::HashSet;
use std::error::Error;
use std::io::{self, BufRead};

use regex::Regex;

/// The default pattern of files to format.
///
/// We only want to format rust files by default.
const DEFAULT_PATTERN: &'static str = r".*\.rs";

#[derive(Debug)]
enum FormatDiffError {
    IncorrectOptions(getopts::Fail),
    IncorrectFilter(regex::Error),
    IoError(io::Error),
}

impl fmt::Display for FormatDiffError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Display::fmt(self.cause().unwrap(), f)
    }
}

impl Error for FormatDiffError {
    fn description(&self) -> &str {
        self.cause().unwrap().description()
    }

    fn cause(&self) -> Option<&Error> {
        Some(match *self {
            FormatDiffError::IoError(ref e) => e,
            FormatDiffError::IncorrectFilter(ref e) => e,
            FormatDiffError::IncorrectOptions(ref e) => e,
        })
    }
}

impl From<getopts::Fail> for FormatDiffError {
    fn from(fail: getopts::Fail) -> Self {
        FormatDiffError::IncorrectOptions(fail)
    }
}

impl From<regex::Error> for FormatDiffError {
    fn from(err: regex::Error) -> Self {
        FormatDiffError::IncorrectFilter(err)
    }
}

impl From<io::Error> for FormatDiffError {
    fn from(fail: io::Error) -> Self {
        FormatDiffError::IoError(fail)
    }
}

fn main() {
    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("v", "verbose", "use verbose output");
    opts.optopt(
        "p",
        "skip-prefix",
        "skip the smallest prefix containing NUMBER slashes",
        "NUMBER",
    );
    opts.optopt(
        "f",
        "filter",
        "custom pattern selecting file paths to reformat",
        "PATTERN",
    );

    if let Err(e) = run(&opts) {
        println!("{}", opts.usage(e.description()));
        process::exit(1);
    }
}

#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
struct Range {
    file: String,
    range: [u32; 2],
}

fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> {
    let matches = opts.parse(env::args().skip(1))?;

    if matches.opt_present("h") {
        println!("{}", opts.usage("usage: "));
        return Ok(());
    }

    let verbose = matches.opt_present("v");

    let filter = matches
        .opt_str("f")
        .unwrap_or_else(|| DEFAULT_PATTERN.into());

    let skip_prefix = matches
        .opt_str("p")
        .and_then(|p| p.parse::<u32>().ok())
        .unwrap_or(0);

    let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?;

    run_rustfmt(&files, &ranges, verbose)
}

fn run_rustfmt(
    files: &HashSet<String>,
    ranges: &[Range],
    verbose: bool,
) -> Result<(), FormatDiffError> {
    if files.is_empty() || ranges.is_empty() {
        if verbose {
            println!("No files to format found");
        }
        return Ok(());
    }

    let ranges_as_json = json::to_string(ranges).unwrap();
    if verbose {
        print!("rustfmt");
        for file in files {
            print!(" {:?}", file);
        }
        print!(" --file-lines {:?}", ranges_as_json);
    }

    let exit_status = process::Command::new("rustfmt")
        .args(files)
        .arg("--file-lines")
        .arg(ranges_as_json)
        .status()?;

    if !exit_status.success() {
        return Err(FormatDiffError::IoError(io::Error::new(
            io::ErrorKind::Other,
            format!("rustfmt failed with {}", exit_status),
        )));
    }
    Ok(())
}

/// Scans a diff from `from`, and returns the set of files found, and the ranges
/// in those files.
fn scan_diff<R>(
    from: R,
    skip_prefix: u32,
    file_filter: &str,
) -> Result<(HashSet<String>, Vec<Range>), FormatDiffError>
where
    R: io::Read,
{
    let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{}}}(\S*)", skip_prefix);
    let diff_pattern = Regex::new(&diff_pattern).unwrap();

    let lines_pattern = Regex::new(r"^@@.*\+(\d+)(,(\d+))?").unwrap();

    let file_filter = Regex::new(&format!("^{}$", file_filter))?;

    let mut current_file = None;

    let mut files = HashSet::new();
    let mut ranges = vec![];
    for line in io::BufReader::new(from).lines() {
        let line = line.unwrap();

        if let Some(captures) = diff_pattern.captures(&line) {
            current_file = Some(captures.get(1).unwrap().as_str().to_owned());
        }

        let file = match current_file {
            Some(ref f) => &**f,
            None => continue,
        };

        // TODO(emilio): We could avoid this most of the time if needed, but
        // it's not clear it's worth it.
        if !file_filter.is_match(file) {
            continue;
        }

        let lines_captures = match lines_pattern.captures(&line) {
            Some(captures) => captures,
            None => continue,
        };

        let start_line = lines_captures
            .get(1)
            .unwrap()
            .as_str()
            .parse::<u32>()
            .unwrap();
        let line_count = match lines_captures.get(3) {
            Some(line_count) => line_count.as_str().parse::<u32>().unwrap(),
            None => 1,
        };

        if line_count == 0 {
            continue;
        }

        let end_line = start_line + line_count - 1;
        files.insert(file.to_owned());
        ranges.push(Range {
            file: file.to_owned(),
            range: [start_line, end_line],
        });
    }

    Ok((files, ranges))
}

#[test]
fn scan_simple_git_diff() {
    const DIFF: &'static str = include_str!("test/bindgen.diff");
    let (files, ranges) = scan_diff(DIFF.as_bytes(), 1, r".*\.rs").expect("scan_diff failed?");

    assert!(
        files.contains("src/ir/traversal.rs"),
        "Should've matched the filter"
    );

    assert!(
        !files.contains("tests/headers/anon_enum.hpp"),
        "Shouldn't have matched the filter"
    );

    assert_eq!(
        &ranges,
        &[
            Range {
                file: "src/ir/item.rs".into(),
                range: [148, 158],
            },
            Range {
                file: "src/ir/item.rs".into(),
                range: [160, 170],
            },
            Range {
                file: "src/ir/traversal.rs".into(),
                range: [9, 16],
            },
            Range {
                file: "src/ir/traversal.rs".into(),
                range: [35, 43],
            }
        ]
    );
}
<commit_msg>rustfmt-format-diff: Use logging macros instead of "-v" option.<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Inspired by Clang's clang-format-diff:
//
// https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py

#![deny(warnings)]

extern crate env_logger;
extern crate getopts;
#[macro_use]
extern crate log;
extern crate regex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json as json;

use std::{env, fmt, process};
use std::collections::HashSet;
use std::error::Error;
use std::io::{self, BufRead};

use regex::Regex;

/// The default pattern of files to format.
///
/// We only want to format rust files by default.
const DEFAULT_PATTERN: &'static str = r".*\.rs";

#[derive(Debug)]
enum FormatDiffError {
    IncorrectOptions(getopts::Fail),
    IncorrectFilter(regex::Error),
    IoError(io::Error),
}

impl fmt::Display for FormatDiffError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Display::fmt(self.cause().unwrap(), f)
    }
}

impl Error for FormatDiffError {
    fn description(&self) -> &str {
        self.cause().unwrap().description()
    }

    fn cause(&self) -> Option<&Error> {
        Some(match *self {
            FormatDiffError::IoError(ref e) => e,
            FormatDiffError::IncorrectFilter(ref e) => e,
            FormatDiffError::IncorrectOptions(ref e) => e,
        })
    }
}

impl From<getopts::Fail> for FormatDiffError {
    fn from(fail: getopts::Fail) -> Self {
        FormatDiffError::IncorrectOptions(fail)
    }
}

impl From<regex::Error> for FormatDiffError {
    fn from(err: regex::Error) -> Self {
        FormatDiffError::IncorrectFilter(err)
    }
}

impl From<io::Error> for FormatDiffError {
    fn from(fail: io::Error) -> Self {
        FormatDiffError::IoError(fail)
    }
}

fn main() {
    let _ = env_logger::init();

    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optopt(
        "p",
        "skip-prefix",
        "skip the smallest prefix containing NUMBER slashes",
        "NUMBER",
    );
    opts.optopt(
        "f",
        "filter",
        "custom pattern selecting file paths to reformat",
        "PATTERN",
    );

    if let Err(e) = run(&opts) {
        println!("{}", opts.usage(e.description()));
        process::exit(1);
    }
}

#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
struct Range {
    file: String,
    range: [u32; 2],
}

fn run(opts: &getopts::Options) -> Result<(), FormatDiffError> {
    let matches = opts.parse(env::args().skip(1))?;

    if matches.opt_present("h") {
        println!("{}", opts.usage("usage: "));
        return Ok(());
    }

    let filter = matches
        .opt_str("f")
        .unwrap_or_else(|| DEFAULT_PATTERN.into());

    let skip_prefix = matches
        .opt_str("p")
        .and_then(|p| p.parse::<u32>().ok())
        .unwrap_or(0);

    let (files, ranges) = scan_diff(io::stdin(), skip_prefix, &filter)?;

    run_rustfmt(&files, &ranges)
}

fn run_rustfmt(files: &HashSet<String>, ranges: &[Range]) -> Result<(), FormatDiffError> {
    if files.is_empty() || ranges.is_empty() {
        debug!("No files to format found");
        return Ok(());
    }

    let ranges_as_json = json::to_string(ranges).unwrap();

    debug!("Files: {:?}", files);
    debug!("Ranges: {:?}", ranges);

    let exit_status = process::Command::new("rustfmt")
        .args(files)
        .arg("--file-lines")
        .arg(ranges_as_json)
        .status()?;

    if !exit_status.success() {
        return Err(FormatDiffError::IoError(io::Error::new(
            io::ErrorKind::Other,
            format!("rustfmt failed with {}", exit_status),
        )));
    }
    Ok(())
}

/// Scans a diff from `from`, and returns the set of files found, and the ranges
/// in those files.
fn scan_diff<R>(
    from: R,
    skip_prefix: u32,
    file_filter: &str,
) -> Result<(HashSet<String>, Vec<Range>), FormatDiffError>
where
    R: io::Read,
{
    let diff_pattern = format!(r"^\+\+\+\s(?:.*?/){{{}}}(\S*)", skip_prefix);
    let diff_pattern = Regex::new(&diff_pattern).unwrap();

    let lines_pattern = Regex::new(r"^@@.*\+(\d+)(,(\d+))?").unwrap();

    let file_filter = Regex::new(&format!("^{}$", file_filter))?;

    let mut current_file = None;

    let mut files = HashSet::new();
    let mut ranges = vec![];
    for line in io::BufReader::new(from).lines() {
        let line = line.unwrap();

        if let Some(captures) = diff_pattern.captures(&line) {
            current_file = Some(captures.get(1).unwrap().as_str().to_owned());
        }

        let file = match current_file {
            Some(ref f) => &**f,
            None => continue,
        };

        // TODO(emilio): We could avoid this most of the time if needed, but
        // it's not clear it's worth it.
        if !file_filter.is_match(file) {
            continue;
        }

        let lines_captures = match lines_pattern.captures(&line) {
            Some(captures) => captures,
            None => continue,
        };

        let start_line = lines_captures
            .get(1)
            .unwrap()
            .as_str()
            .parse::<u32>()
            .unwrap();
        let line_count = match lines_captures.get(3) {
            Some(line_count) => line_count.as_str().parse::<u32>().unwrap(),
            None => 1,
        };

        if line_count == 0 {
            continue;
        }

        let end_line = start_line + line_count - 1;
        files.insert(file.to_owned());
        ranges.push(Range {
            file: file.to_owned(),
            range: [start_line, end_line],
        });
    }

    Ok((files, ranges))
}

#[test]
fn scan_simple_git_diff() {
    const DIFF: &'static str = include_str!("test/bindgen.diff");
    let (files, ranges) = scan_diff(DIFF.as_bytes(), 1, r".*\.rs").expect("scan_diff failed?");

    assert!(
        files.contains("src/ir/traversal.rs"),
        "Should've matched the filter"
    );

    assert!(
        !files.contains("tests/headers/anon_enum.hpp"),
        "Shouldn't have matched the filter"
    );

    assert_eq!(
        &ranges,
        &[
            Range {
                file: "src/ir/item.rs".into(),
                range: [148, 158],
            },
            Range {
                file: "src/ir/item.rs".into(),
                range: [160, 170],
            },
            Range {
                file: "src/ir/traversal.rs".into(),
                range: [9, 16],
            },
            Range {
                file: "src/ir/traversal.rs".into(),
                range: [35, 43],
            }
        ]
    );
}
<|endoftext|>


<commit_before>
use async_std::net::*;
use bench::*;

use float_ord::FloatOrd;

use nhanh::*;

use serde::{
    ser::{SerializeStruct, Serializer},
    Serialize,
};
use std::collections::HashMap;

fn local_address(port: u16) -> SocketAddr {
    format!("127.0.0.1:{}", port)
        .parse()
        .expect("local address")
}

#[derive(Debug, Clone, Serialize)]
struct NetcodeScenario {
    scenario_name: &'static str,
    #[serde(skip_serializing)]
    transfers: Vec<client::Transfer>,
}

#[derive(Debug, Clone, Serialize)]
struct Scenario {
    #[serde(flatten)]
    netcode_scenario: NetcodeScenario,
    #[serde(flatten)]
    network_config: runner::NetworkConfig,
}

impl Scenario {
    async fn run(&self, port: u16, protocol: Protocol) -> Report {
        let server_address = local_address(port);
        let client_options = client::Options {
            address: server_address,
            protocol,
            transfers: self.netcode_scenario.transfers.clone(),
        };

        let runner_options = runner::Options {
            network_config: self.network_config.clone(),
            client_options,
            start_server: true,
        };

        let results =
            runner::runner_main(runner_options).await.expect(&format!(
                "running scenario {} against protocol {:?}",
                self.netcode_scenario.scenario_name, protocol
            ));

        Report {
            mean_ping_ms: results.mean.as_secs_f64() * 1e3,
            ping_deviation_ms: results.deviation.as_secs_f64() * 1e3,
        }
    }
}

#[derive(Debug, Clone)]
struct Benchmark {
    scenario: Scenario,
    reports: HashMap<Protocol, Report>,
    least_latent: Protocol,
    least_variant: Protocol,
}

impl Benchmark {
    fn from_reports(
        scenario: Scenario,
        reports: HashMap<Protocol, Report>,
    ) -> Self {
        let (least_latent, least_variant) = {
            let (least_latent, _) = reports
                .iter()
                .min_by_key(|(_, report)| FloatOrd(report.mean_ping_ms))
                .unwrap();
            let (least_variant, _) = reports
                .iter()
                .min_by_key(|(_, report)| FloatOrd(report.ping_deviation_ms))
                .unwrap();

            (*least_latent, *least_variant)
        };

        Self {
            scenario,
            reports,
            least_latent,
            least_variant,
        }
    }
}

impl Serialize for Benchmark {
    fn serialize<S>(
        &self,
        serializer: S,
    ) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let network_config_fields = 6;
        let report_fields = 2;
        let summary_fields = 2;
        let total_fields = network_config_fields
            + report_fields * self.reports.len()
            + summary_fields;

        let mut state =
            serializer.serialize_struct("Benchmark", total_fields)?;

        let cfg = &self.scenario.network_config;

        // Conditions
        state.serialize_field("network_delay_ms", &cfg.delay)?;
        state.serialize_field("network_jitter_ms", &cfg.delay)?;
        state.serialize_field(
            "network_delay_correlation",
            &cfg.delay_correlation,
        )?;
        state.serialize_field("network_random_loss", &cfg.random_loss)?;
        state.serialize_field(
            "network_random_loss_correlation",
            &cfg.random_loss_correlation,
        )?;
        state.serialize_field(
            "network_rate_limit_kbits",
            &cfg.rate_limit_kbps,
        )?;

        // Results
        for (protocol, report) in &self.reports {
            state.serialize_field(
                Box::leak(Box::new(format!(
                    "{:?}_mean_round_trip_ms",
                    protocol
                ))),
                &report.mean_ping_ms,
            )?;
            state.serialize_field(
                Box::leak(Box::new(format!(
                    "{:?}_round_trip_deviation_ms",
                    protocol
                ))),
                &report.ping_deviation_ms,
            )?;
        }

        state.serialize_field("least_latent", &self.least_latent)?;
        state.serialize_field("least_variant", &self.least_variant)?;

        state.end()
    }
}

#[derive(Debug, Clone, Serialize)]
struct Report {
    mean_ping_ms: f64,
    ping_deviation_ms: f64,
}

const DEFAULT_RETURN_COUNT: Option<usize> = Some(200);

fn scenarios() -> Vec<Scenario> {
    vec![
        Scenario {
            netcode_scenario: NetcodeScenario {
                scenario_name: "transfer_0_200B_60Hz",
                transfers: vec![client::Transfer {
                    stream_id: StreamId(0),
                    size: 200,
                    hertz: 60,
                    return_count: DEFAULT_RETURN_COUNT,
                }],
            },
            network_config: runner::NetworkConfig::default(),
        },
        Scenario {
            netcode_scenario: NetcodeScenario {
                scenario_name: "transfer_0_200B_60Hz-transfer_1_800_240Hz",
                transfers: vec![
                    client::Transfer {
                        stream_id: StreamId(0),
                        size: 200,
                        hertz: 60,
                        return_count: DEFAULT_RETURN_COUNT,
                    },
                    client::Transfer {
                        stream_id: StreamId(1),
                        size: 200,
                        hertz: 240,
                        return_count: None,
                    },
                ],
            },
            network_config: runner::NetworkConfig::default(),
        },
        Scenario {
            netcode_scenario: NetcodeScenario {
                scenario_name: "transfer_0_200B_60Hz-transfer_1_800_240Hz",
                transfers: vec![
                    client::Transfer {
                        stream_id: StreamId(0),
                        size: 200,
                        hertz: 60,
                        return_count: DEFAULT_RETURN_COUNT,
                    },
                    client::Transfer {
                        stream_id: StreamId(1),
                        size: 200,
                        hertz: 240,
                        return_count: None,
                    },
                ],
            },
            network_config: runner::NetworkConfig {
                rate_limit_kbps: 1024,
                ..Default::default()
            },
        },
    ]
}

#[async_std::main]
async fn main() {
    let scenarios = scenarios();

    let output = std::io::stdout();
    let mut writer = csv::Writer::from_writer(output);

    let mut port = 1025;
    for scenario in scenarios {
        let mut reports = HashMap::new();
        for protocol in &ALL_PROTOCOLS {
            let report = scenario.run(port, *protocol).await;
            reports.insert(*protocol, report);
            port += 1;
        }
        let benchmark = Benchmark::from_reports(scenario, reports);
        writer
            .serialize(benchmark)
            .expect("writing benchmark to stdout");
    }
}
<commit_msg>Allow filtering scenarios from invocation<commit_after>use async_std::net::*;
use bench::*;
use structopt::StructOpt;

use float_ord::FloatOrd;

use nhanh::*;

use serde::{
    ser::{SerializeStruct, Serializer},
    Serialize,
};
use std::collections::HashMap;

fn local_address(port: u16) -> SocketAddr {
    format!("127.0.0.1:{}", port)
        .parse()
        .expect("local address")
}

#[derive(Debug, Clone, Serialize)]
struct NetcodeScenario {
    scenario_name: &'static str,
    #[serde(skip_serializing)]
    transfers: Vec<client::Transfer>,
}

#[derive(Debug, Clone, Serialize)]
struct Scenario {
    #[serde(flatten)]
    netcode_scenario: NetcodeScenario,
    #[serde(flatten)]
    network_config: runner::NetworkConfig,
}

impl Scenario {
    async fn run(&self, port: u16, protocol: Protocol) -> Report {
        let server_address = local_address(port);
        let client_options = client::Options {
            address: server_address,
            protocol,
            transfers: self.netcode_scenario.transfers.clone(),
        };

        let runner_options = runner::Options {
            network_config: self.network_config.clone(),
            client_options,
            start_server: true,
        };

        let results =
            runner::runner_main(runner_options).await.expect(&format!(
                "running scenario {} against protocol {:?}",
                self.netcode_scenario.scenario_name, protocol
            ));

        Report {
            mean_ping_ms: results.mean.as_secs_f64() * 1e3,
            ping_deviation_ms: results.deviation.as_secs_f64() * 1e3,
        }
    }
}

#[derive(Debug, Clone)]
struct Benchmark {
    scenario: Scenario,
    reports: HashMap<Protocol, Report>,
    least_latent: Protocol,
    least_variant: Protocol,
}

impl Benchmark {
    fn from_reports(
        scenario: Scenario,
        reports: HashMap<Protocol, Report>,
    ) -> Self {
        let (least_latent, least_variant) = {
            let (least_latent, _) = reports
                .iter()
                .min_by_key(|(_, report)| FloatOrd(report.mean_ping_ms))
                .unwrap();
            let (least_variant, _) = reports
                .iter()
                .min_by_key(|(_, report)| FloatOrd(report.ping_deviation_ms))
                .unwrap();

            (*least_latent, *least_variant)
        };

        Self {
            scenario,
            reports,
            least_latent,
            least_variant,
        }
    }
}

impl Serialize for Benchmark {
    fn serialize<S>(
        &self,
        serializer: S,
    ) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let network_config_fields = 6;
        let report_fields = 2;
        let summary_fields = 2;
        let total_fields = network_config_fields
            + report_fields * self.reports.len()
            + summary_fields;

        let mut state =
            serializer.serialize_struct("Benchmark", total_fields)?;

        let cfg = &self.scenario.network_config;

        // Conditions
        state.serialize_field("network_delay_ms", &cfg.delay)?;
        state.serialize_field("network_jitter_ms", &cfg.delay)?;
        state.serialize_field(
            "network_delay_correlation",
            &cfg.delay_correlation,
        )?;
        state.serialize_field("network_random_loss", &cfg.random_loss)?;
        state.serialize_field(
            "network_random_loss_correlation",
            &cfg.random_loss_correlation,
        )?;
        state.serialize_field(
            "network_rate_limit_kbits",
            &cfg.rate_limit_kbps,
        )?;

        // Results
        for (protocol, report) in &self.reports {
            state.serialize_field(
                Box::leak(Box::new(format!(
                    "{:?}_mean_round_trip_ms",
                    protocol
                ))),
                &report.mean_ping_ms,
            )?;
            state.serialize_field(
                Box::leak(Box::new(format!(
                    "{:?}_round_trip_deviation_ms",
                    protocol
                ))),
                &report.ping_deviation_ms,
            )?;
        }

        state.serialize_field("least_latent", &self.least_latent)?;
        state.serialize_field("least_variant", &self.least_variant)?;

        state.end()
    }
}

#[derive(Debug, Clone, Serialize)]
struct Report {
    mean_ping_ms: f64,
    ping_deviation_ms: f64,
}

const DEFAULT_RETURN_COUNT: Option<usize> = Some(200);

fn scenarios() -> Vec<Scenario> {
    vec![
        Scenario {
            netcode_scenario: NetcodeScenario {
                scenario_name: "transfer_0_200B_60Hz",
                transfers: vec![client::Transfer {
                    stream_id: StreamId(0),
                    size: 200,
                    hertz: 60,
                    return_count: DEFAULT_RETURN_COUNT,
                }],
            },
            network_config: runner::NetworkConfig::default(),
        },
        Scenario {
            netcode_scenario: NetcodeScenario {
                scenario_name: "transfer_0_200B_60Hz-transfer_1_800_240Hz",
                transfers: vec![
                    client::Transfer {
                        stream_id: StreamId(0),
                        size: 200,
                        hertz: 60,
                        return_count: DEFAULT_RETURN_COUNT,
                    },
                    client::Transfer {
                        stream_id: StreamId(1),
                        size: 200,
                        hertz: 240,
                        return_count: None,
                    },
                ],
            },
            network_config: runner::NetworkConfig::default(),
        },
        Scenario {
            netcode_scenario: NetcodeScenario {
                scenario_name: "transfer_0_200B_60Hz-transfer_1_800_240Hz",
                transfers: vec![
                    client::Transfer {
                        stream_id: StreamId(0),
                        size: 200,
                        hertz: 60,
                        return_count: DEFAULT_RETURN_COUNT,
                    },
                    client::Transfer {
                        stream_id: StreamId(1),
                        size: 200,
                        hertz: 240,
                        return_count: None,
                    },
                ],
            },
            network_config: runner::NetworkConfig {
                rate_limit_kbps: 1024,
                ..Default::default()
            },
        },
    ]
}

#[derive(Debug, StructOpt)]
struct Options {
    #[structopt(long, short = "f")]
    scenario_filter: Option<String>,
}

#[async_std::main]
async fn main() {
    let options = Options::from_args();

    let scenarios = scenarios();
    let scenarios = scenarios.into_iter().filter(|s| {
        options
            .scenario_filter
            .as_ref()
            .map(|pattern| {
                s.netcode_scenario
                    .scenario_name
                    .matches(pattern.as_str())
                    .next()
                    .is_some()
            })
            .unwrap_or(false)
    });

    let output = std::io::stdout();
    let mut writer = csv::Writer::from_writer(output);

    let mut port = 1025;
    for scenario in scenarios {
        let mut reports = HashMap::new();
        for protocol in &ALL_PROTOCOLS {
            let report = scenario.run(port, *protocol).await;
            reports.insert(*protocol, report);
            port += 1;
        }
        let benchmark = Benchmark::from_reports(scenario, reports);
        writer
            .serialize(benchmark)
            .expect("writing benchmark to stdout");
    }
}
<|endoftext|>


<commit_before>use std::io::{Cursor, Read};
use std::io::Result as IoResult;

use bytes::Buf;
use criterion::*;
use input_buffer::InputBuffer;

use tungstenite::buffer::ReadBuffer;

const CHUNK_SIZE: usize = 4096;

/// A FIFO buffer for reading packets from the network.
#[derive(Debug)]
pub struct StackReadBuffer<const CHUNK_SIZE: usize> {
    storage: Cursor<Vec<u8>>,
    chunk: [u8; CHUNK_SIZE],
}

impl<const CHUNK_SIZE: usize> StackReadBuffer<CHUNK_SIZE> {
    /// Create a new empty input buffer.
    pub fn new() -> Self {
        Self::with_capacity(CHUNK_SIZE)
    }

    /// Create a new empty input buffer with a given `capacity`.
    pub fn with_capacity(capacity: usize) -> Self {
        Self::from_partially_read(Vec::with_capacity(capacity))
    }

    /// Create a input buffer filled with previously read data.
    pub fn from_partially_read(part: Vec<u8>) -> Self {
        Self { storage: Cursor::new(part), chunk: [0; CHUNK_SIZE] }
    }

    /// Get a cursor to the data storage.
    pub fn as_cursor(&self) -> &Cursor<Vec<u8>> {
        &self.storage
    }

    /// Get a cursor to the mutable data storage.
    pub fn as_cursor_mut(&mut self) -> &mut Cursor<Vec<u8>> {
        &mut self.storage
    }

    /// Consume the `ReadBuffer` and get the internal storage.
    pub fn into_vec(mut self) -> Vec<u8> {
        // Current implementation of `tungstenite-rs` expects that the `into_vec()` drains
        // the data from the container that has already been read by the cursor.
        self.clean_up();

        // Now we can safely return the internal container.
        self.storage.into_inner()
    }

    /// Read next portion of data from the given input stream.
    pub fn read_from<S: Read>(&mut self, stream: &mut S) -> IoResult<usize> {
        self.clean_up();
        let size = stream.read(&mut self.chunk)?;
        self.storage.get_mut().extend_from_slice(&self.chunk[..size]);
        Ok(size)
    }

    /// Cleans ups the part of the vector that has been already read by the cursor.
    fn clean_up(&mut self) {
        let pos = self.storage.position() as usize;
        self.storage.get_mut().drain(0..pos).count();
        self.storage.set_position(0);
    }
}

impl<const CHUNK_SIZE: usize> Buf for StackReadBuffer<CHUNK_SIZE> {
    fn remaining(&self) -> usize {
        Buf::remaining(self.as_cursor())
    }

    fn chunk(&self) -> &[u8] {
        Buf::chunk(self.as_cursor())
    }

    fn advance(&mut self, cnt: usize) {
        Buf::advance(self.as_cursor_mut(), cnt)
    }
}

impl<const CHUNK_SIZE: usize> Default for StackReadBuffer<CHUNK_SIZE> {
    fn default() -> Self {
        Self::new()
    }
}

#[inline]
fn input_buffer(mut stream: impl Read) {
    let mut buffer = InputBuffer::with_capacity(CHUNK_SIZE);
    while buffer.read_from(&mut stream).unwrap() != 0 {}
}

#[inline]
fn stack_read_buffer(mut stream: impl Read) {
    let mut buffer = StackReadBuffer::<CHUNK_SIZE>::new();
    while buffer.read_from(&mut stream).unwrap() != 0 {}
}

#[inline]
fn heap_read_buffer(mut stream: impl Read) {
    let mut buffer = ReadBuffer::<CHUNK_SIZE>::new();
    while buffer.read_from(&mut stream).unwrap() != 0 {}
}

fn benchmark(c: &mut Criterion) {
    const STREAM_SIZE: usize = 1024 * 1024 * 4;
    let data: Vec<u8> = (0..STREAM_SIZE).map(|_| rand::random()).collect();
    let stream = Cursor::new(data);

    let mut group = c.benchmark_group("buffers");
    group.throughput(Throughput::Bytes(STREAM_SIZE as u64));
    group.bench_function("InputBuffer", |b| b.iter(|| input_buffer(black_box(stream.clone()))));
    group.bench_function("ReadBuffer (stack)", |b| b.iter(|| stack_read_buffer(black_box(stream.clone()))));
    group.bench_function("ReadBuffer (heap)", |b| b.iter(|| heap_read_buffer(black_box(stream.clone()))));
    group.finish();
}

criterion_group!(benches, benchmark);
criterion_main!(benches);
<commit_msg>minor: re-format the `buffer.rs`<commit_after>use std::io::Result as IoResult;
use std::io::{Cursor, Read};

use bytes::Buf;
use criterion::*;
use input_buffer::InputBuffer;

use tungstenite::buffer::ReadBuffer;

const CHUNK_SIZE: usize = 4096;

/// A FIFO buffer for reading packets from the network.
#[derive(Debug)]
pub struct StackReadBuffer<const CHUNK_SIZE: usize> {
    storage: Cursor<Vec<u8>>,
    chunk: [u8; CHUNK_SIZE],
}

impl<const CHUNK_SIZE: usize> StackReadBuffer<CHUNK_SIZE> {
    /// Create a new empty input buffer.
    pub fn new() -> Self {
        Self::with_capacity(CHUNK_SIZE)
    }

    /// Create a new empty input buffer with a given `capacity`.
    pub fn with_capacity(capacity: usize) -> Self {
        Self::from_partially_read(Vec::with_capacity(capacity))
    }

    /// Create a input buffer filled with previously read data.
    pub fn from_partially_read(part: Vec<u8>) -> Self {
        Self { storage: Cursor::new(part), chunk: [0; CHUNK_SIZE] }
    }

    /// Get a cursor to the data storage.
    pub fn as_cursor(&self) -> &Cursor<Vec<u8>> {
        &self.storage
    }

    /// Get a cursor to the mutable data storage.
    pub fn as_cursor_mut(&mut self) -> &mut Cursor<Vec<u8>> {
        &mut self.storage
    }

    /// Consume the `ReadBuffer` and get the internal storage.
    pub fn into_vec(mut self) -> Vec<u8> {
        // Current implementation of `tungstenite-rs` expects that the `into_vec()` drains
        // the data from the container that has already been read by the cursor.
        self.clean_up();

        // Now we can safely return the internal container.
        self.storage.into_inner()
    }

    /// Read next portion of data from the given input stream.
    pub fn read_from<S: Read>(&mut self, stream: &mut S) -> IoResult<usize> {
        self.clean_up();
        let size = stream.read(&mut self.chunk)?;
        self.storage.get_mut().extend_from_slice(&self.chunk[..size]);
        Ok(size)
    }

    /// Cleans ups the part of the vector that has been already read by the cursor.
    fn clean_up(&mut self) {
        let pos = self.storage.position() as usize;
        self.storage.get_mut().drain(0..pos).count();
        self.storage.set_position(0);
    }
}

impl<const CHUNK_SIZE: usize> Buf for StackReadBuffer<CHUNK_SIZE> {
    fn remaining(&self) -> usize {
        Buf::remaining(self.as_cursor())
    }

    fn chunk(&self) -> &[u8] {
        Buf::chunk(self.as_cursor())
    }

    fn advance(&mut self, cnt: usize) {
        Buf::advance(self.as_cursor_mut(), cnt)
    }
}

impl<const CHUNK_SIZE: usize> Default for StackReadBuffer<CHUNK_SIZE> {
    fn default() -> Self {
        Self::new()
    }
}

#[inline]
fn input_buffer(mut stream: impl Read) {
    let mut buffer = InputBuffer::with_capacity(CHUNK_SIZE);
    while buffer.read_from(&mut stream).unwrap() != 0 {}
}

#[inline]
fn stack_read_buffer(mut stream: impl Read) {
    let mut buffer = StackReadBuffer::<CHUNK_SIZE>::new();
    while buffer.read_from(&mut stream).unwrap() != 0 {}
}

#[inline]
fn heap_read_buffer(mut stream: impl Read) {
    let mut buffer = ReadBuffer::<CHUNK_SIZE>::new();
    while buffer.read_from(&mut stream).unwrap() != 0 {}
}

fn benchmark(c: &mut Criterion) {
    const STREAM_SIZE: usize = 1024 * 1024 * 4;
    let data: Vec<u8> = (0..STREAM_SIZE).map(|_| rand::random()).collect();
    let stream = Cursor::new(data);

    let mut group = c.benchmark_group("buffers");
    group.throughput(Throughput::Bytes(STREAM_SIZE as u64));
    group.bench_function("InputBuffer", |b| b.iter(|| input_buffer(black_box(stream.clone()))));
    group.bench_function("ReadBuffer (stack)", |b| {
        b.iter(|| stack_read_buffer(black_box(stream.clone())))
    });
    group.bench_function("ReadBuffer (heap)", |b| {
        b.iter(|| heap_read_buffer(black_box(stream.clone())))
    });
    group.finish();
}

criterion_group!(benches, benchmark);
criterion_main!(benches);
<|endoftext|>


<commit_before>// Copyright (c) 2015-2016, Johan Sköld.
// License: http://opensource.org/licenses/ISC

use std::env;
use std::io::{Write};
use std::path::PathBuf;
use std::process::{Command, Stdio};

fn main() {
    let target = env::var("TARGET").unwrap();
    let profile = env::var("PROFILE").unwrap();

    let first_div = target.find('-').unwrap();
    let last_div = target.rfind('-').unwrap();

    let arch = &target[..first_div];
    let platform = &target[(first_div + 1)..last_div];
    let compiler = &target[(last_div + 1)..];
    let bitness = if arch == "x86_64" { 64 } else { 32 };

    match compiler {
        "msvc" => build_msvc(bitness),
        "gnu" | "darwin" => build_gmake(bitness, &profile, platform),
        _ => panic!("Unsupported compiler"),
    }
}

/// Builds the bgfx binaries for `msvc` targets.
fn build_msvc(bitness: u32) {
    let vs_version = env::var("VisualStudioVersion").expect("Visual Studio version not detected");
    let platform = if bitness == 32 { "X86" } else { "X64" };

    let vs_release = match vs_version.as_ref() {
        "12.0" => "2013",
        "14.0" => "2015",
        "15.0" => "2017",
        _ => panic!(format!("Unknown Visual Studio version: {:?}", vs_version)),
    };

    Command::new("bx/tools/bin/windows/genie.exe")
        .current_dir("bgfx")
        .arg("--with-dynamic-runtime")
        .arg("--with-tools")
        // .arg(format!("--with-windows={}",
        //              env::var("WindowsSDKVersion")
        //                  .unwrap_or("8.1".to_string())
        //                  .replace("\\", "")))
        .arg(format!("vs{}", vs_release))
        .output()
        .expect("Failed to generate project files");

    let status = Command::new("MSBuild.exe")
        .current_dir("bgfx")
        .arg("/p:Configuration=Release")
        .arg(format!("/p:Platform={}", platform))
        .arg(format!(".build/projects/vs{}/bgfx.vcxproj", vs_release))
        .status()
        .expect("Failed to build bgfx");

    if status.code().unwrap() != 0 {
        panic!("Failed to build bgfx");
    }

    let status = Command::new("MSBuild.exe")
        .current_dir("bgfx")
        .arg("/p:Configuration=Release")
        .arg(format!("/p:Platform={}", platform))
        .arg(format!(".build/projects/vs{}/bx.vcxproj", vs_release))
        .status()
        .expect("Failed to build bx");

    if status.code().unwrap() != 0 {
        panic!("Failed to build bx");
    }

    let status = Command::new("MSBuild.exe")
        .current_dir("bgfx")
        .arg("/p:Configuration=Release")
        .arg(format!("/p:Platform={}", platform))
        .arg(format!(".build/projects/vs{}/bimg.vcxproj", vs_release))
        .status()
        .expect("Failed to build bimg");

    if status.code().unwrap() != 0 {
        panic!("Failed to build bimg");
    }

    // Build tools
    let status = Command::new("devenv.exe")
        .current_dir("bgfx")
        .arg(format!(".build/projects/vs{}/bgfx.sln", vs_release))
        .arg("/Build")
        .arg(format!("Release|x{}", bitness))
        .status()
        .expect("Failed to build tools");

    if status.code().unwrap() != 0 {
        panic!("Failed to build tools");
    }

    Command::new("cmd")
        .current_dir("bgfx")
        .arg("/C")
        .arg(format!("copy .build\\win{}_vs{}\\bin\\geometrycRelease.exe tools\\bin\\windows\\geometryc.exe", bitness, vs_release))
        .status().ok()
        .and_then(|s| s.code())
        .and_then(|s| if s == 0 {Some(0)} else {None})
        .expect("Failed to copy geometryc.exe");

    Command::new("cmd")
        .current_dir("bgfx")
        .arg("/C")
        .arg(format!("copy .build\\win{}_vs{}\\bin\\shadercRelease.exe tools\\bin\\windows\\shaderc.exe", bitness, vs_release))
        .status().ok()
        .and_then(|s| s.code())
        .and_then(|s| if s == 0 {Some(0)} else {None})
        .expect("Failed to copy shaderc.exe");

    Command::new("cmd")
        .current_dir("bgfx")
        .arg("/C")
        .arg(format!("copy .build\\win{}_vs{}\\bin\\texturecRelease.exe tools\\bin\\windows\\texturec.exe", bitness, vs_release))
        .status().ok()
        .and_then(|s| s.code())
        .and_then(|s| if s == 0 {Some(0)} else {None})
        .expect("Failed to copy texturec.exe");

    Command::new("cmd")
        .current_dir("bgfx")
        .arg("/C")
        .arg(format!("copy .build\\win{}_vs{}\\bin\\texturevRelease.exe tools\\bin\\windows\\texturev.exe", bitness, vs_release))
        .status().ok()
        .and_then(|s| s.code())
        .and_then(|s| if s == 0 {Some(0)} else {None})
        .expect("Failed to copy texturev.exe");

    let mut path = PathBuf::from(env::current_dir().unwrap());
    path.push("bgfx");
    path.push(".build");
    path.push(format!("win{}_vs{}", bitness, vs_release));
    path.push("bin");

    println!("cargo:rustc-link-lib=static=bgfxRelease");
    println!("cargo:rustc-link-lib=static=bxRelease");
    println!("cargo:rustc-link-lib=static=bimgRelease");
    println!("cargo:rustc-link-lib=gdi32");
    println!("cargo:rustc-link-lib=user32");
    println!("cargo:rustc-link-lib=psapi");
    println!("cargo:rustc-link-search=native={}", path.as_os_str().to_str().unwrap());
}

/// Builds the bgfx binaries for makefile based targets.
fn build_gmake(bitness: u32, profile: &str, platform: &str) {
    let project_name = match platform {
        "pc-windows" => "gmake-mingw-gcc",
        "unknown-linux" => "gmake-linux",
        "apple" => "gmake-osx",
        _ => panic!("Unsupported OS"),
    };

    let output_name = match platform {
        "pc-windows" => format!("win{}_mingw-gcc", bitness),
        "unknown-linux" => format!("linux{}_gcc", bitness),
        "apple" => format!("osx{}_clang", bitness),
        _ => unreachable!(),
    };

    // Generate makefiles
    let status = Command::new("make")
        .arg("-C")
        .arg("bgfx")
        .arg(format!(".build/projects/{}", project_name))
        .status()
        .expect("Failed to generate makefiles");

    if status.code().unwrap() != 0 {
        panic!("Failed to generate makefiles.");
    }

    // C flags
    let cflags = if platform == "pc-windows" && bitness == 32 {
        "-fPIC -DBGFX_CONFIG_MULTITHREADED=1 -mincoming-stack-boundary=2"
    } else {
        "-fPIC -DBGFX_CONFIG_MULTITHREADED=1"
    };

    // Build bgfx
    let status = Command::new("make")
        .env("CFLAGS", cflags)
        .arg("-R")
        .arg("-C")
        .arg(format!("bgfx/.build/projects/{}", project_name))
        .arg(format!("config={}{}", profile, bitness))
        .arg("verbose=1")
        .arg("bgfx")
        .arg("bx")
        .arg("bimg")
        .status()
        .expect("Failed to build bgfx");

    if status.code().unwrap() != 0 {
        panic!("Failed to build bgfx.");
    }

    // Output linker config
    let mut path = PathBuf::from(env::current_dir().unwrap());
    path.push("bgfx");
    path.push(".build");
    path.push(output_name);
    path.push("bin");

    let config = if profile == "debug" {
        "Debug"
    } else {
        "Release"
    };
    println!("cargo:rustc-link-lib=bgfx{}", config);
    println!("cargo:rustc-link-lib=bx{}", config);
    println!("cargo:rustc-link-lib=bimg{}", config);
    println!("cargo:rustc-link-lib=stdc++");
    println!("cargo:rustc-link-search=native={}", path.as_os_str().to_str().unwrap());

    match platform {
        "pc-windows" => {
            println!("cargo:rustc-link-lib=gdi32");
            println!("cargo:rustc-link-lib=opengl32");
            println!("cargo:rustc-link-lib=psapi");
        }
        "unknown-linux" => {
            println!("cargo:rustc-link-lib=GL");
            println!("cargo:rustc-link-lib=X11");
        }
        "apple" => {
            println!("cargo:rustc-link-lib=framework=Cocoa");
            println!("cargo:rustc-link-lib=framework=QuartzCore");
            println!("cargo:rustc-link-lib=framework=OpenGL");

            if should_link_metal() {
                println!("cargo:rustc-link-lib=framework=Metal");
            }
        }
        _ => unreachable!(),
    }
}

/// Determines whether we should link with Metal on OSX. The Metal framework
/// is only included starting with OSX 10.11. We do this through the C
/// compiler so we can test the same macro bgfx tests for support with.
fn should_link_metal() -> bool {
    let test = "#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__\nv=__ENVIRONMENT_MAC_OS_X_VER\
                SION_MIN_REQUIRED__\n#else\nv=1\n#endif";

    let mut cc = Command::new("cc")
        .arg("-xc")
        .arg("-E")
        .arg("-")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

    {
        let mut stdin = cc.stdin.take().unwrap();
        stdin.write_fmt(format_args!("{}", test)).unwrap();
    }

    let output = cc.wait_with_output().unwrap();
    let output_str = String::from_utf8(output.stdout).unwrap();
    let ver_line = output_str
        .lines()
        .find(|l| l.starts_with("v="))
        .unwrap();
    let ver_str = &ver_line[2..];
    let ver = ver_str.parse::<u32>().unwrap();

    ver >= 101100
}<commit_msg>Build tools in darwin and Linux<commit_after>// Copyright (c) 2015-2016, Johan Sköld.
// License: http://opensource.org/licenses/ISC

use std::env;
use std::io::{Write};
use std::path::PathBuf;
use std::process::{Command, Stdio};

fn main() {
    let target = env::var("TARGET").unwrap();
    let profile = env::var("PROFILE").unwrap();

    let first_div = target.find('-').unwrap();
    let last_div = target.rfind('-').unwrap();

    let arch = &target[..first_div];
    let platform = &target[(first_div + 1)..last_div];
    let compiler = &target[(last_div + 1)..];
    let bitness = if arch == "x86_64" { 64 } else { 32 };

    match compiler {
        "msvc" => build_msvc(bitness),
        "gnu" | "darwin" => build_gmake(bitness, &profile, platform),
        _ => panic!("Unsupported compiler"),
    }
}

/// Builds the bgfx binaries for `msvc` targets.
fn build_msvc(bitness: u32) {
    let vs_version = env::var("VisualStudioVersion").expect("Visual Studio version not detected");
    let platform = if bitness == 32 { "X86" } else { "X64" };

    let vs_release = match vs_version.as_ref() {
        "12.0" => "2013",
        "14.0" => "2015",
        "15.0" => "2017",
        _ => panic!(format!("Unknown Visual Studio version: {:?}", vs_version)),
    };

    Command::new("bx/tools/bin/windows/genie.exe")
        .current_dir("bgfx")
        .arg("--with-dynamic-runtime")
        .arg("--with-tools")
        // .arg(format!("--with-windows={}",
        //              env::var("WindowsSDKVersion")
        //                  .unwrap_or("8.1".to_string())
        //                  .replace("\\", "")))
        .arg(format!("vs{}", vs_release))
        .output()
        .expect("Failed to generate project files");

    let status = Command::new("MSBuild.exe")
        .current_dir("bgfx")
        .arg("/p:Configuration=Release")
        .arg(format!("/p:Platform={}", platform))
        .arg(format!(".build/projects/vs{}/bgfx.vcxproj", vs_release))
        .status()
        .expect("Failed to build bgfx");

    if status.code().unwrap() != 0 {
        panic!("Failed to build bgfx");
    }

    let status = Command::new("MSBuild.exe")
        .current_dir("bgfx")
        .arg("/p:Configuration=Release")
        .arg(format!("/p:Platform={}", platform))
        .arg(format!(".build/projects/vs{}/bx.vcxproj", vs_release))
        .status()
        .expect("Failed to build bx");

    if status.code().unwrap() != 0 {
        panic!("Failed to build bx");
    }

    let status = Command::new("MSBuild.exe")
        .current_dir("bgfx")
        .arg("/p:Configuration=Release")
        .arg(format!("/p:Platform={}", platform))
        .arg(format!(".build/projects/vs{}/bimg.vcxproj", vs_release))
        .status()
        .expect("Failed to build bimg");

    if status.code().unwrap() != 0 {
        panic!("Failed to build bimg");
    }

    // Build tools
    let status = Command::new("devenv.exe")
        .current_dir("bgfx")
        .arg(format!(".build/projects/vs{}/bgfx.sln", vs_release))
        .arg("/Build")
        .arg(format!("Release|x{}", bitness))
        .status()
        .expect("Failed to build tools");

    if status.code().unwrap() != 0 {
        panic!("Failed to build tools");
    }

    Command::new("cmd")
        .current_dir("bgfx")
        .arg("/C")
        .arg(format!("copy .build\\win{}_vs{}\\bin\\geometrycRelease.exe tools\\bin\\windows\\geometryc.exe", bitness, vs_release))
        .status().ok()
        .and_then(|s| s.code())
        .and_then(|s| if s == 0 {Some(0)} else {None})
        .expect("Failed to copy geometryc.exe");

    Command::new("cmd")
        .current_dir("bgfx")
        .arg("/C")
        .arg(format!("copy .build\\win{}_vs{}\\bin\\shadercRelease.exe tools\\bin\\windows\\shaderc.exe", bitness, vs_release))
        .status().ok()
        .and_then(|s| s.code())
        .and_then(|s| if s == 0 {Some(0)} else {None})
        .expect("Failed to copy shaderc.exe");

    Command::new("cmd")
        .current_dir("bgfx")
        .arg("/C")
        .arg(format!("copy .build\\win{}_vs{}\\bin\\texturecRelease.exe tools\\bin\\windows\\texturec.exe", bitness, vs_release))
        .status().ok()
        .and_then(|s| s.code())
        .and_then(|s| if s == 0 {Some(0)} else {None})
        .expect("Failed to copy texturec.exe");

    Command::new("cmd")
        .current_dir("bgfx")
        .arg("/C")
        .arg(format!("copy .build\\win{}_vs{}\\bin\\texturevRelease.exe tools\\bin\\windows\\texturev.exe", bitness, vs_release))
        .status().ok()
        .and_then(|s| s.code())
        .and_then(|s| if s == 0 {Some(0)} else {None})
        .expect("Failed to copy texturev.exe");

    let mut path = PathBuf::from(env::current_dir().unwrap());
    path.push("bgfx");
    path.push(".build");
    path.push(format!("win{}_vs{}", bitness, vs_release));
    path.push("bin");

    println!("cargo:rustc-link-lib=static=bgfxRelease");
    println!("cargo:rustc-link-lib=static=bxRelease");
    println!("cargo:rustc-link-lib=static=bimgRelease");
    println!("cargo:rustc-link-lib=gdi32");
    println!("cargo:rustc-link-lib=user32");
    println!("cargo:rustc-link-lib=psapi");
    println!("cargo:rustc-link-search=native={}", path.as_os_str().to_str().unwrap());
}

/// Builds the bgfx binaries for makefile based targets.
fn build_gmake(bitness: u32, profile: &str, platform: &str) {
    let project_name = match platform {
        "pc-windows" => "gmake-mingw-gcc",
        "unknown-linux" => "gmake-linux",
        "apple" => "gmake-osx",
        _ => panic!("Unsupported OS"),
    };

    let output_name = match platform {
        "pc-windows" => format!("win{}_mingw-gcc", bitness),
        "unknown-linux" => format!("linux{}_gcc", bitness),
        "apple" => format!("osx{}_clang", bitness),
        _ => unreachable!(),
    };

    // Generate makefiles
    let status = Command::new("make")
        .arg("-C")
        .arg("bgfx")
        .arg(format!(".build/projects/{}", project_name))
        .status()
        .expect("Failed to generate makefiles");

    if status.code().unwrap() != 0 {
        panic!("Failed to generate makefiles.");
    }

    // C flags
    let cflags = if platform == "pc-windows" && bitness == 32 {
        "-fPIC -DBGFX_CONFIG_MULTITHREADED=1 -mincoming-stack-boundary=2"
    } else {
        "-fPIC -DBGFX_CONFIG_MULTITHREADED=1"
    };

    // Build bgfx
    let status = Command::new("make")
        .env("CFLAGS", cflags)
        .arg("-R")
        .arg("-C")
        .arg(format!("bgfx/.build/projects/{}", project_name))
        .arg(format!("config={}{}", profile, bitness))
        .arg("verbose=1")
        .arg("bgfx")
        .arg("bx")
        .arg("bimg")
        .status()
        .expect("Failed to build bgfx");

    if status.code().unwrap() != 0 {
        panic!("Failed to build bgfx.");
    }

    // Generate tools
    let status = Command::new("make")
        .arg("-C")
        .arg("bgfx")
        .arg("tools")
        .status()
        .expect("Failed to generate tools");

    if status.code().unwrap() != 0 {
        panic!("Failed to generate tools.");
    }

    // Output linker config
    let mut path = PathBuf::from(env::current_dir().unwrap());
    path.push("bgfx");
    path.push(".build");
    path.push(output_name);
    path.push("bin");

    let config = if profile == "debug" {
        "Debug"
    } else {
        "Release"
    };
    println!("cargo:rustc-link-lib=bgfx{}", config);
    println!("cargo:rustc-link-lib=bx{}", config);
    println!("cargo:rustc-link-lib=bimg{}", config);
    println!("cargo:rustc-link-lib=stdc++");
    println!("cargo:rustc-link-search=native={}", path.as_os_str().to_str().unwrap());

    match platform {
        "pc-windows" => {
            println!("cargo:rustc-link-lib=gdi32");
            println!("cargo:rustc-link-lib=opengl32");
            println!("cargo:rustc-link-lib=psapi");
        }
        "unknown-linux" => {
            println!("cargo:rustc-link-lib=GL");
            println!("cargo:rustc-link-lib=X11");
        }
        "apple" => {
            println!("cargo:rustc-link-lib=framework=Cocoa");
            println!("cargo:rustc-link-lib=framework=QuartzCore");
            println!("cargo:rustc-link-lib=framework=OpenGL");

            if should_link_metal() {
                println!("cargo:rustc-link-lib=framework=Metal");
            }
        }
        _ => unreachable!(),
    }
}

/// Determines whether we should link with Metal on OSX. The Metal framework
/// is only included starting with OSX 10.11. We do this through the C
/// compiler so we can test the same macro bgfx tests for support with.
fn should_link_metal() -> bool {
    let test = "#ifdef __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__\nv=__ENVIRONMENT_MAC_OS_X_VER\
                SION_MIN_REQUIRED__\n#else\nv=1\n#endif";

    let mut cc = Command::new("cc")
        .arg("-xc")
        .arg("-E")
        .arg("-")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

    {
        let mut stdin = cc.stdin.take().unwrap();
        stdin.write_fmt(format_args!("{}", test)).unwrap();
    }

    let output = cc.wait_with_output().unwrap();
    let output_str = String::from_utf8(output.stdout).unwrap();
    let ver_line = output_str
        .lines()
        .find(|l| l.starts_with("v="))
        .unwrap();
    let ver_str = &ver_line[2..];
    let ver = ver_str.parse::<u32>().unwrap();

    ver >= 101100
}<|endoftext|>


<commit_before>use std::result::Result as RResult;
use std::path::Path;

use libimagstore::store::{FileLockEntry, Store};

pub struct Mail<'a> {
    fle: FileLockEntry<'a>,
    parsedmail: ParsedMail,
}

impl<'a> Mail<'a> {

    /// Imports a mail from the Path passed
    pub fn import_from_path<P: AsRef<Path>>(store: &Store, p: P) -> Result<Mail> {
        unimplemented!()
    }

    /// Imports a mail from the String passed
    pub fn import_from_string<S: AsRef<str>>(store: &Store, s: S) -> Result<Mail> {
        unimplemented!()
    }

    /// Opens a mail by the passed hash
    pub fn open<S: AsRef<str>>(store: &Store, hash: S) -> Result<Option<Mail>> {
        unimplemented!()
    }

    pub fn get_field<S: AsRef<str>>(&self, field: S) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_from(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_to(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_subject(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_message_id(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_in_reply_to(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

}
<commit_msg>Add intermediate buffer type for abstracting away lifetime foo from mailparse<commit_after>use std::result::Result as RResult;
use std::path::Path;

use libimagstore::store::{FileLockEntry, Store};

use mailparse::{MailParseError, ParsedMail, parse_mail};

use result::Result;

struct Buffer(String);

impl Buffer {
    pub fn parsed<'a>(&'a self) -> RResult<ParsedMail<'a>, MailParseError> {
        parse_mail(self.0.as_bytes())
    }
}

impl From<String> for Buffer {
    fn from(data: String) -> Buffer {
        Buffer(data)
    }
}

pub struct Mail<'a> {
    fle: FileLockEntry<'a>,
    buffer: Buffer,
}

impl<'a> Mail<'a> {

    /// Imports a mail from the Path passed
    pub fn import_from_path<P: AsRef<Path>>(store: &Store, p: P) -> Result<Mail> {
        unimplemented!()
    }

    /// Imports a mail from the String passed
    pub fn import_from_string<S: AsRef<str>>(store: &Store, s: S) -> Result<Mail> {
        unimplemented!()
    }

    /// Opens a mail by the passed hash
    pub fn open<S: AsRef<str>>(store: &Store, hash: S) -> Result<Option<Mail>> {
        unimplemented!()
    }

    pub fn get_field<S: AsRef<str>>(&self, field: S) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_from(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_to(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_subject(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_message_id(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

    pub fn get_in_reply_to(&self) -> Result<Option<&str>> {
        unimplemented!()
    }

}
<|endoftext|>


<commit_before>use std::fmt::Display;
use thiserror::Error;

#[derive(Error, Debug)]
#[error("braced error: {msg}")]
struct BracedError {
    msg: String,
}

#[derive(Error, Debug)]
#[error("braced error")]
struct BracedUnused {
    extra: usize,
}

#[derive(Error, Debug)]
#[error("tuple error: {0}")]
struct TupleError(usize);

#[derive(Error, Debug)]
#[error("unit error")]
struct UnitError;

#[derive(Error, Debug)]
enum EnumError {
    #[error("braced error: {id}")]
    Braced { id: usize },
    #[error("tuple error: {0}")]
    Tuple(usize),
    #[error("unit error")]
    Unit,
}

#[derive(Error, Debug)]
#[error("1 + 1 = {}", 1 + 1)]
struct Arithmetic;

#[derive(Error, Debug)]
#[error("!bool = {}", not(.0))]
struct NestedShorthand(bool);

fn not(bool: &bool) -> bool {
    !*bool
}

fn assert<T: Display>(expected: &str, value: T) {
    assert_eq!(expected, value.to_string());
}

#[test]
fn test_display() {
    assert(
        "braced error: T",
        BracedError {
            msg: "T".to_owned(),
        },
    );
    assert("braced error", BracedUnused { extra: 0 });
    assert("tuple error: 0", TupleError(0));
    assert("unit error", UnitError);
    assert("braced error: 0", EnumError::Braced { id: 0 });
    assert("tuple error: 0", EnumError::Tuple(0));
    assert("unit error", EnumError::Unit);
    assert("1 + 1 = 2", Arithmetic);
    assert("!bool = false", NestedShorthand(true));
}
<commit_msg>Collapse some needlessly verbose code in test<commit_after>use std::fmt::Display;
use thiserror::Error;

#[derive(Error, Debug)]
#[error("braced error: {msg}")]
struct BracedError {
    msg: String,
}

#[derive(Error, Debug)]
#[error("braced error")]
struct BracedUnused {
    extra: usize,
}

#[derive(Error, Debug)]
#[error("tuple error: {0}")]
struct TupleError(usize);

#[derive(Error, Debug)]
#[error("unit error")]
struct UnitError;

#[derive(Error, Debug)]
enum EnumError {
    #[error("braced error: {id}")]
    Braced { id: usize },
    #[error("tuple error: {0}")]
    Tuple(usize),
    #[error("unit error")]
    Unit,
}

#[derive(Error, Debug)]
#[error("1 + 1 = {}", 1 + 1)]
struct Arithmetic;

#[derive(Error, Debug)]
#[error("!bool = {}", not(.0))]
struct NestedShorthand(bool);

fn not(bool: &bool) -> bool {
    !*bool
}

fn assert<T: Display>(expected: &str, value: T) {
    assert_eq!(expected, value.to_string());
}

#[test]
fn test_display() {
    let msg = "T".to_owned();
    assert("braced error: T", BracedError { msg });
    assert("braced error", BracedUnused { extra: 0 });
    assert("tuple error: 0", TupleError(0));
    assert("unit error", UnitError);
    assert("braced error: 0", EnumError::Braced { id: 0 });
    assert("tuple error: 0", EnumError::Tuple(0));
    assert("unit error", EnumError::Unit);
    assert("1 + 1 = 2", Arithmetic);
    assert("!bool = false", NestedShorthand(true));
}
<|endoftext|>