<commit_before>use crate::config::*;
use crate::errors::*;
use crate::process_handling::*;
use crate::report::report_coverage;
use crate::source_analysis::LineAnalysis;
use crate::statemachine::*;
use crate::test_loader::*;
use crate::traces::*;
use cargo::core::{
    compiler::CompileMode,
    InternedString, Package, Shell, Workspace,
};
use cargo::ops;
use cargo::ops::{
    clean, compile, CleanOptions, CompileFilter, CompileOptions, FilterRule, LibRule, Packages,
    TestOptions,
};
use cargo::util::{homedir, Config as CargoConfig};
use log::{debug, info, trace, warn};
use nix::unistd::*;
use std::collections::HashMap;
use std::env;
use std::ffi::CString;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;

pub mod breakpoint;
pub mod config;
pub mod errors;
mod process_handling;
pub mod report;
mod source_analysis;
mod statemachine;
pub mod test_loader;
pub mod traces;

mod ptrace_control;

static DOCTEST_FOLDER: &str = "target/doctests";

pub fn trace(configs: &[Config]) -> Result<TraceMap, RunError> {
    let mut tracemap = TraceMap::new();
    let mut ret = 0i32;
    let mut failure = Ok(());

    for config in configs.iter() {
        if config.name == "report" {
            continue;
        }
        //let result = result?;
        match launch_tarpaulin(config) {
            Ok((t, r)) => {
                tracemap.merge(&t);
                ret |= r;
            }
            Err(e) => {
                info!("Failure {}", e);
                if failure.is_ok() {
                    failure = Err(e);
                }
            }
        }
    }
    tracemap.dedup();
    if ret == 0 {
        Ok(tracemap)
    } else {
        Err(RunError::TestFailed)
    }
}

pub fn run(configs: &[Config]) -> Result<(), RunError> {
    let tracemap = trace(configs)?;
    if configs.len() == 1 {
        report_coverage(&configs[0], &tracemap)?;
    } else if !configs.is_empty() {
        let mut reported = false;
        for c in configs.iter() {
            if c.name == "report" {
                reported = true;
                report_coverage(c, &tracemap)?;
            }
        }
        if !reported {
            report_coverage(&configs[0], &tracemap)?;
        }
    }

    Ok(())
}

/// Launches tarpaulin with the given configuration.
pub fn launch_tarpaulin(config: &Config) -> Result<(TraceMap, i32), RunError> {
    if !config.name.is_empty() {
        info!("Running config {}", config.name);
    }
    setup_environment(&config);
    cargo::core::enable_nightly_features();
    let cwd = match config.manifest.parent() {
        Some(p) => p.to_path_buf(),
        None => PathBuf::new(),
    };
    let home = match homedir(&cwd) {
        Some(h) => h,
        None => {
            warn!("Warning failed to find home directory.");
            PathBuf::new()
        }
    };
    let mut cargo_config = CargoConfig::new(Shell::new(), cwd, home);
    let flag_quiet = if config.verbose { None } else { Some(true) };

    // This shouldn't fail so no checking the error.
    let _ = cargo_config.configure(
        0u32,
        flag_quiet,
        None,
        config.frozen,
        config.locked,
        config.offline,
        &config.target_dir,
        &config.unstable_features,
        &[],
    );

    let workspace = Workspace::new(config.manifest.as_path(), &cargo_config)
        .map_err(|e| RunError::Manifest(e.to_string()))?;

    let mut compile_options = get_compile_options(&config, &cargo_config)?;

    info!("Running Tarpaulin");

    if config.force_clean {
        debug!("Cleaning project");
        // Clean isn't expected to fail and if it does it likely won't have an effect
        let clean_opt = CleanOptions {
            config: &cargo_config,
            spec: vec![],
            target: None,
            profile_specified: config.force_clean,
            requested_profile: InternedString::new("dev"),
            doc: false,
        };
        let _ = clean(&workspace, &clean_opt);
    }
    let mut result = TraceMap::new();
    let mut return_code = 0i32;
    let project_analysis = source_analysis::get_line_analysis(&workspace, config);
    info!("Building project");
    for copt in compile_options.drain(..) {
        let run_result = match copt.build_config.mode {
            CompileMode::Build | CompileMode::Test | CompileMode::Bench => {
                run_tests(&workspace, copt, &project_analysis, config)
            }
            CompileMode::Doctest => run_doctests(&workspace, copt, &project_analysis, config),
            e => {
                debug!("Internal tarpaulin error. Unsupported compile mode {:?}", e);
                Err(RunError::Internal)
            }
        }?;
        result.merge(&run_result.0);
        return_code |= run_result.1;
    }
    result.dedup();
    Ok((result, return_code))
}

fn run_tests(
    workspace: &Workspace,
    compile_options: CompileOptions,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
) -> Result<(TraceMap, i32), RunError> {
    let mut result = TraceMap::new();
    let mut return_code = 0i32;
    let compilation = compile(&workspace, &compile_options);
    match compilation {
        Ok(comp) => {
            if config.no_run {
                info!("Project compiled successfully");
                return Ok((result, return_code));
            }
            // Examples are always in the binaries list with tests!
            if config
                .run_types
                .iter()
                .any(|x| !(*x == RunType::Tests || *x == RunType::Doctests))
            {
                // If we have binaries we have other artefacts to run
                for binary in comp.binaries {
                    if let Some(res) = get_test_coverage(
                        &workspace,
                        None,
                        binary.as_path(),
                        analysis,
                        config,
                        false,
                        false,
                    )? {
                        result.merge(&res.0);
                        return_code |= res.1;
                    }
                }
            }
            for &(ref package, ref name, ref path) in &comp.tests {
                debug!("Processing {}", name);
                if let Some(res) = get_test_coverage(
                    &workspace,
                    Some(package),
                    path.as_path(),
                    analysis,
                    config,
                    true,
                    false,
                )? {
                    result.merge(&res.0);
                    return_code |= res.1;
                }
                if config.run_ignored {
                    if let Some(res) = get_test_coverage(
                        &workspace,
                        Some(package),
                        path.as_path(),
                        analysis,
                        config,
                        true,
                        true,
                    )? {
                        result.merge(&res.0);
                        return_code |= res.1;
                    }
                }
            }
            result.dedup();
            Ok((result, return_code))
        }
        Err(e) => return Err(RunError::TestCompile(e.to_string())),
    }
}

fn run_doctests(
    workspace: &Workspace,
    compile_options: CompileOptions,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
) -> Result<(TraceMap, i32), RunError> {
    info!("Running doctests");
    let mut result = TraceMap::new();
    let mut return_code = 0i32;

    let opts = TestOptions {
        no_run: false,
        no_fail_fast: false,
        compile_opts: compile_options,
    };
    let _ = ops::run_tests(workspace, &opts, &[]);

    let mut packages: Vec<PathBuf> = workspace
        .members()
        .filter_map(|p| p.manifest_path().parent())
        .map(|x| x.join(DOCTEST_FOLDER))
        .collect();

    if packages.is_empty() {
        let doctest_dir = match config.manifest.parent() {
            Some(p) => p.join(DOCTEST_FOLDER),
            None => PathBuf::from(DOCTEST_FOLDER),
        };
        packages.push(doctest_dir);
    }

    for dir in &packages {
        let walker = WalkDir::new(dir).into_iter();
        for dt in walker
            .filter_map(|e| e.ok())
            .filter(|e| match e.metadata() {
                Ok(ref m) if m.is_file() && m.len() != 0 => true,
                _ => false,
            })
        {
            if let Some(res) =
                get_test_coverage(&workspace, None, dt.path(), analysis, config, true, false)?
            {
                result.merge(&res.0);
                return_code |= res.1;
            }
        }
    }
    result.dedup();
    Ok((result, return_code))
}

fn get_compile_options<'a>(
    config: &Config,
    cargo_config: &'a CargoConfig,
) -> Result<Vec<CompileOptions<'a>>, RunError> {
    let mut result = Vec::new();
    for run_type in &config.run_types {
        let mut copt = CompileOptions::new(cargo_config, (*run_type).into())
            .map_err(|e| RunError::Cargo(e.to_string()))?;
        if run_type == &RunType::Tests {
            if let CompileFilter::Default {
                ref mut required_features_filterable,
            } = copt.filter
            {
                *required_features_filterable = true;
            }
        } else if run_type == &RunType::Doctests {
            copt.filter = CompileFilter::new(
                LibRule::True,
                FilterRule::Just(vec![]),
                FilterRule::Just(vec![]),
                FilterRule::Just(vec![]),
                FilterRule::Just(vec![]),
            );
        } else if run_type == &RunType::Examples {
            copt.filter = CompileFilter::new(
                LibRule::True,
                FilterRule::Just(vec![]),
                FilterRule::Just(vec![]),
                FilterRule::All,
                FilterRule::Just(vec![]),
            );
        }

        copt.features = config.features.clone();
        copt.all_features = config.all_features;
        copt.no_default_features = config.no_default_features;
        copt.build_config.requested_profile = match config.release {
            true => InternedString::new("release"),
            false => InternedString::new("dev"),
        };
        copt.spec =
            match Packages::from_flags(config.all, config.exclude.clone(), config.packages.clone())
            {
                Ok(spec) => spec,
                Err(e) => {
                    return Err(RunError::Packages(e.to_string()));
                }
            };
        result.push(copt);
    }
    Ok(result)
}

fn setup_environment(config: &Config) {
    env::set_var("TARPAULIN", "1");
    let common_opts =
        " -C relocation-model=dynamic-no-pic -C link-dead-code -C opt-level=0 -C debuginfo=2 ";
    let rustflags = "RUSTFLAGS";
    let mut value = common_opts.to_string();
    if config.release {
        value = format!("{}-C debug-assertions=off ", value);
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    env::set_var(rustflags, value);
    // doesn't matter if we don't use it
    let rustdoc = "RUSTDOCFLAGS";
    let mut value = format!(
        "{} --persist-doctests {} -Z unstable-options ",
        common_opts, DOCTEST_FOLDER
    );
    if let Ok(vtemp) = env::var(rustdoc) {
        if !vtemp.contains("--persist-doctests") {
            value.push_str(vtemp.as_ref());
        }
    }
    env::set_var(rustdoc, value);
}

/// Returns the coverage statistics for a test executable in the given workspace
pub fn get_test_coverage(
    project: &Workspace,
    package: Option<&Package>,
    test: &Path,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
    can_quiet: bool,
    ignored: bool,
) -> Result<Option<(TraceMap, i32)>, RunError> {
    if !test.exists() {
        return Ok(None);
    }
    if let Err(e) = limit_affinity() {
        warn!("Failed to set processor affinity {}", e);
    }
    match fork() {
        Ok(ForkResult::Parent { child }) => {
            match collect_coverage(project, test, child, analysis, config) {
                Ok(t) => Ok(Some(t)),
                Err(e) => Err(RunError::TestCoverage(e.to_string())),
            }
        }
        Ok(ForkResult::Child) => {
            info!("Launching test");
            execute_test(test, package, ignored, can_quiet, config)?;
            Ok(None)
        }
        Err(err) => Err(RunError::TestCoverage(format!(
            "Failed to run test {}, Error: {}",
            test.display(),
            err.to_string()
        ))),
    }
}

/// Collects the coverage data from the launched test
fn collect_coverage(
    project: &Workspace,
    test_path: &Path,
    test: Pid,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
) -> Result<(TraceMap, i32), RunError> {
    let mut ret_code = 0;
    let mut traces = generate_tracemap(project, test_path, analysis, config)?;
    {
        trace!("Test PID is {}", test);
        let (mut state, mut data) = create_state_machine(test, &mut traces, config);
        loop {
            state = state.step(&mut data, config)?;
            if state.is_finished() {
                if let TestState::End(i) = state {
                    ret_code = i;
                }
                break;
            }
        }
    }
    Ok((traces, ret_code))
}

/// Launches the test executable
fn execute_test(
    test: &Path,
    package: Option<&Package>,
    ignored: bool,
    can_quiet: bool,
    config: &Config,
) -> Result<(), RunError> {
    let exec_path = CString::new(test.to_str().unwrap()).unwrap();
    info!("running {}", test.display());
    if let Some(pack) = package {
        if let Some(parent) = pack.manifest_path().parent() {
            let _ = env::set_current_dir(parent);
        }
    }

    let mut envars: Vec<CString> = Vec::new();

    for (key, value) in env::vars() {
        let mut temp = String::new();
        temp.push_str(key.as_str());
        temp.push('=');
        temp.push_str(value.as_str());
        envars.push(CString::new(temp).unwrap());
    }
    let mut argv = if ignored {
        vec![exec_path.clone(), CString::new("--ignored").unwrap()]
    } else {
        vec![exec_path.clone()]
    };
    if config.verbose {
        envars.push(CString::new("RUST_BACKTRACE=1").unwrap());
    } else if can_quiet {
        argv.push(CString::new("--quiet").unwrap());
    }
    for s in &config.varargs {
        argv.push(CString::new(s.as_bytes()).unwrap_or_default());
    }

    execute(exec_path, &argv, envars.as_slice())
}

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

    #[test]
    fn check_env() {
        let conf = Config::default();
        setup_environment(&conf);

        let tarp_var = env::var("TARPAULIN").unwrap();
        assert_eq!(tarp_var, "1");
    }
}
<commit_msg>fixup! deps: update to cargo 0.43<commit_after>use crate::config::*;
use crate::errors::*;
use crate::process_handling::*;
use crate::report::report_coverage;
use crate::source_analysis::LineAnalysis;
use crate::statemachine::*;
use crate::test_loader::*;
use crate::traces::*;
use cargo::core::{compiler::CompileMode, InternedString, Package, Shell, Workspace};
use cargo::ops;
use cargo::ops::{
    clean, compile, CleanOptions, CompileFilter, CompileOptions, FilterRule, LibRule, Packages,
    TestOptions,
};
use cargo::util::{homedir, Config as CargoConfig};
use log::{debug, info, trace, warn};
use nix::unistd::*;
use std::collections::HashMap;
use std::env;
use std::ffi::CString;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;

pub mod breakpoint;
pub mod config;
pub mod errors;
mod process_handling;
pub mod report;
mod source_analysis;
mod statemachine;
pub mod test_loader;
pub mod traces;

mod ptrace_control;

static DOCTEST_FOLDER: &str = "target/doctests";

pub fn trace(configs: &[Config]) -> Result<TraceMap, RunError> {
    let mut tracemap = TraceMap::new();
    let mut ret = 0i32;
    let mut failure = Ok(());

    for config in configs.iter() {
        if config.name == "report" {
            continue;
        }
        //let result = result?;
        match launch_tarpaulin(config) {
            Ok((t, r)) => {
                tracemap.merge(&t);
                ret |= r;
            }
            Err(e) => {
                info!("Failure {}", e);
                if failure.is_ok() {
                    failure = Err(e);
                }
            }
        }
    }
    tracemap.dedup();
    if ret == 0 {
        Ok(tracemap)
    } else {
        Err(RunError::TestFailed)
    }
}

pub fn run(configs: &[Config]) -> Result<(), RunError> {
    let tracemap = trace(configs)?;
    if configs.len() == 1 {
        report_coverage(&configs[0], &tracemap)?;
    } else if !configs.is_empty() {
        let mut reported = false;
        for c in configs.iter() {
            if c.name == "report" {
                reported = true;
                report_coverage(c, &tracemap)?;
            }
        }
        if !reported {
            report_coverage(&configs[0], &tracemap)?;
        }
    }

    Ok(())
}

/// Launches tarpaulin with the given configuration.
pub fn launch_tarpaulin(config: &Config) -> Result<(TraceMap, i32), RunError> {
    if !config.name.is_empty() {
        info!("Running config {}", config.name);
    }
    setup_environment(&config);
    cargo::core::enable_nightly_features();
    let cwd = match config.manifest.parent() {
        Some(p) => p.to_path_buf(),
        None => PathBuf::new(),
    };
    let home = match homedir(&cwd) {
        Some(h) => h,
        None => {
            warn!("Warning failed to find home directory.");
            PathBuf::new()
        }
    };
    let mut cargo_config = CargoConfig::new(Shell::new(), cwd, home);
    let flag_quiet = if config.verbose { None } else { Some(true) };

    // This shouldn't fail so no checking the error.
    let _ = cargo_config.configure(
        0u32,
        flag_quiet,
        None,
        config.frozen,
        config.locked,
        config.offline,
        &config.target_dir,
        &config.unstable_features,
        &[],
    );

    let workspace = Workspace::new(config.manifest.as_path(), &cargo_config)
        .map_err(|e| RunError::Manifest(e.to_string()))?;

    let mut compile_options = get_compile_options(&config, &cargo_config)?;

    info!("Running Tarpaulin");

    if config.force_clean {
        debug!("Cleaning project");
        // Clean isn't expected to fail and if it does it likely won't have an effect
        let clean_opt = CleanOptions {
            config: &cargo_config,
            spec: vec![],
            target: None,
            profile_specified: config.force_clean,
            requested_profile: InternedString::new("dev"),
            doc: false,
        };
        let _ = clean(&workspace, &clean_opt);
    }
    let mut result = TraceMap::new();
    let mut return_code = 0i32;
    let project_analysis = source_analysis::get_line_analysis(&workspace, config);
    info!("Building project");
    for copt in compile_options.drain(..) {
        let run_result = match copt.build_config.mode {
            CompileMode::Build | CompileMode::Test | CompileMode::Bench => {
                run_tests(&workspace, copt, &project_analysis, config)
            }
            CompileMode::Doctest => run_doctests(&workspace, copt, &project_analysis, config),
            e => {
                debug!("Internal tarpaulin error. Unsupported compile mode {:?}", e);
                Err(RunError::Internal)
            }
        }?;
        result.merge(&run_result.0);
        return_code |= run_result.1;
    }
    result.dedup();
    Ok((result, return_code))
}

fn run_tests(
    workspace: &Workspace,
    compile_options: CompileOptions,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
) -> Result<(TraceMap, i32), RunError> {
    let mut result = TraceMap::new();
    let mut return_code = 0i32;
    let compilation = compile(&workspace, &compile_options);
    match compilation {
        Ok(comp) => {
            if config.no_run {
                info!("Project compiled successfully");
                return Ok((result, return_code));
            }
            // Examples are always in the binaries list with tests!
            if config
                .run_types
                .iter()
                .any(|x| !(*x == RunType::Tests || *x == RunType::Doctests))
            {
                // If we have binaries we have other artefacts to run
                for binary in comp.binaries {
                    if let Some(res) = get_test_coverage(
                        &workspace,
                        None,
                        binary.as_path(),
                        analysis,
                        config,
                        false,
                        false,
                    )? {
                        result.merge(&res.0);
                        return_code |= res.1;
                    }
                }
            }
            for &(ref package, ref name, ref path) in &comp.tests {
                debug!("Processing {}", name);
                if let Some(res) = get_test_coverage(
                    &workspace,
                    Some(package),
                    path.as_path(),
                    analysis,
                    config,
                    true,
                    false,
                )? {
                    result.merge(&res.0);
                    return_code |= res.1;
                }
                if config.run_ignored {
                    if let Some(res) = get_test_coverage(
                        &workspace,
                        Some(package),
                        path.as_path(),
                        analysis,
                        config,
                        true,
                        true,
                    )? {
                        result.merge(&res.0);
                        return_code |= res.1;
                    }
                }
            }
            result.dedup();
            Ok((result, return_code))
        }
        Err(e) => return Err(RunError::TestCompile(e.to_string())),
    }
}

fn run_doctests(
    workspace: &Workspace,
    compile_options: CompileOptions,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
) -> Result<(TraceMap, i32), RunError> {
    info!("Running doctests");
    let mut result = TraceMap::new();
    let mut return_code = 0i32;

    let opts = TestOptions {
        no_run: false,
        no_fail_fast: false,
        compile_opts: compile_options,
    };
    let _ = ops::run_tests(workspace, &opts, &[]);

    let mut packages: Vec<PathBuf> = workspace
        .members()
        .filter_map(|p| p.manifest_path().parent())
        .map(|x| x.join(DOCTEST_FOLDER))
        .collect();

    if packages.is_empty() {
        let doctest_dir = match config.manifest.parent() {
            Some(p) => p.join(DOCTEST_FOLDER),
            None => PathBuf::from(DOCTEST_FOLDER),
        };
        packages.push(doctest_dir);
    }

    for dir in &packages {
        let walker = WalkDir::new(dir).into_iter();
        for dt in walker
            .filter_map(|e| e.ok())
            .filter(|e| match e.metadata() {
                Ok(ref m) if m.is_file() && m.len() != 0 => true,
                _ => false,
            })
        {
            if let Some(res) =
                get_test_coverage(&workspace, None, dt.path(), analysis, config, true, false)?
            {
                result.merge(&res.0);
                return_code |= res.1;
            }
        }
    }
    result.dedup();
    Ok((result, return_code))
}

fn get_compile_options<'a>(
    config: &Config,
    cargo_config: &'a CargoConfig,
) -> Result<Vec<CompileOptions<'a>>, RunError> {
    let mut result = Vec::new();
    for run_type in &config.run_types {
        let mut copt = CompileOptions::new(cargo_config, (*run_type).into())
            .map_err(|e| RunError::Cargo(e.to_string()))?;
        if run_type == &RunType::Tests {
            if let CompileFilter::Default {
                ref mut required_features_filterable,
            } = copt.filter
            {
                *required_features_filterable = true;
            }
        } else if run_type == &RunType::Doctests {
            copt.filter = CompileFilter::new(
                LibRule::True,
                FilterRule::Just(vec![]),
                FilterRule::Just(vec![]),
                FilterRule::Just(vec![]),
                FilterRule::Just(vec![]),
            );
        } else if run_type == &RunType::Examples {
            copt.filter = CompileFilter::new(
                LibRule::True,
                FilterRule::Just(vec![]),
                FilterRule::Just(vec![]),
                FilterRule::All,
                FilterRule::Just(vec![]),
            );
        }

        copt.features = config.features.clone();
        copt.all_features = config.all_features;
        copt.no_default_features = config.no_default_features;
        copt.build_config.requested_profile = match config.release {
            true => InternedString::new("release"),
            false => InternedString::new("dev"),
        };
        copt.spec =
            match Packages::from_flags(config.all, config.exclude.clone(), config.packages.clone())
            {
                Ok(spec) => spec,
                Err(e) => {
                    return Err(RunError::Packages(e.to_string()));
                }
            };
        result.push(copt);
    }
    Ok(result)
}

fn setup_environment(config: &Config) {
    env::set_var("TARPAULIN", "1");
    let common_opts =
        " -C relocation-model=dynamic-no-pic -C link-dead-code -C opt-level=0 -C debuginfo=2 ";
    let rustflags = "RUSTFLAGS";
    let mut value = common_opts.to_string();
    if config.release {
        value = format!("{}-C debug-assertions=off ", value);
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    env::set_var(rustflags, value);
    // doesn't matter if we don't use it
    let rustdoc = "RUSTDOCFLAGS";
    let mut value = format!(
        "{} --persist-doctests {} -Z unstable-options ",
        common_opts, DOCTEST_FOLDER
    );
    if let Ok(vtemp) = env::var(rustdoc) {
        if !vtemp.contains("--persist-doctests") {
            value.push_str(vtemp.as_ref());
        }
    }
    env::set_var(rustdoc, value);
}

/// Returns the coverage statistics for a test executable in the given workspace
pub fn get_test_coverage(
    project: &Workspace,
    package: Option<&Package>,
    test: &Path,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
    can_quiet: bool,
    ignored: bool,
) -> Result<Option<(TraceMap, i32)>, RunError> {
    if !test.exists() {
        return Ok(None);
    }
    if let Err(e) = limit_affinity() {
        warn!("Failed to set processor affinity {}", e);
    }
    match fork() {
        Ok(ForkResult::Parent { child }) => {
            match collect_coverage(project, test, child, analysis, config) {
                Ok(t) => Ok(Some(t)),
                Err(e) => Err(RunError::TestCoverage(e.to_string())),
            }
        }
        Ok(ForkResult::Child) => {
            info!("Launching test");
            execute_test(test, package, ignored, can_quiet, config)?;
            Ok(None)
        }
        Err(err) => Err(RunError::TestCoverage(format!(
            "Failed to run test {}, Error: {}",
            test.display(),
            err.to_string()
        ))),
    }
}

/// Collects the coverage data from the launched test
fn collect_coverage(
    project: &Workspace,
    test_path: &Path,
    test: Pid,
    analysis: &HashMap<PathBuf, LineAnalysis>,
    config: &Config,
) -> Result<(TraceMap, i32), RunError> {
    let mut ret_code = 0;
    let mut traces = generate_tracemap(project, test_path, analysis, config)?;
    {
        trace!("Test PID is {}", test);
        let (mut state, mut data) = create_state_machine(test, &mut traces, config);
        loop {
            state = state.step(&mut data, config)?;
            if state.is_finished() {
                if let TestState::End(i) = state {
                    ret_code = i;
                }
                break;
            }
        }
    }
    Ok((traces, ret_code))
}

/// Launches the test executable
fn execute_test(
    test: &Path,
    package: Option<&Package>,
    ignored: bool,
    can_quiet: bool,
    config: &Config,
) -> Result<(), RunError> {
    let exec_path = CString::new(test.to_str().unwrap()).unwrap();
    info!("running {}", test.display());
    if let Some(pack) = package {
        if let Some(parent) = pack.manifest_path().parent() {
            let _ = env::set_current_dir(parent);
        }
    }

    let mut envars: Vec<CString> = Vec::new();

    for (key, value) in env::vars() {
        let mut temp = String::new();
        temp.push_str(key.as_str());
        temp.push('=');
        temp.push_str(value.as_str());
        envars.push(CString::new(temp).unwrap());
    }
    let mut argv = if ignored {
        vec![exec_path.clone(), CString::new("--ignored").unwrap()]
    } else {
        vec![exec_path.clone()]
    };
    if config.verbose {
        envars.push(CString::new("RUST_BACKTRACE=1").unwrap());
    } else if can_quiet {
        argv.push(CString::new("--quiet").unwrap());
    }
    for s in &config.varargs {
        argv.push(CString::new(s.as_bytes()).unwrap_or_default());
    }

    execute(exec_path, &argv, envars.as_slice())
}

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

    #[test]
    fn check_env() {
        let conf = Config::default();
        setup_environment(&conf);

        let tarp_var = env::var("TARPAULIN").unwrap();
        assert_eq!(tarp_var, "1");
    }
}
<|endoftext|>


<commit_before>#![macro_use]
#![allow(unused)]

#[macro_use]
extern crate log;
extern crate libc;

mod util;

mod blocksplitter;
#[cfg(feature = "longest-match-cache")]
mod cache;
mod deflate;
mod gzip_container;
mod hash;
mod katajainen;
mod lz77;
mod squeeze;
mod tree;
mod zlib_container;

/// Options used throughout the program.
pub struct Options {
    /// Whether to print output
    pub verbose: bool,
    /// Whether to print more detailed output
    pub verbose_more: bool,
    /// Maximum amount of times to rerun forward and backward pass to optimize LZ77
    /// compression cost. Good values: 10, 15 for small files, 5 for files over
    /// several MB in size or it will be too slow.
    pub numiterations: i32,
    /// If true, splits the data in multiple deflate blocks with optimal choice
    /// for the block boundaries. Block splitting gives better compression. Default:
    /// true (1).
    pub blocksplitting: bool,
    /// If true, chooses the optimal block split points only after doing the iterative
    /// LZ77 compression. If false, chooses the block split points first, then does
    /// iterative LZ77 on each individual block. Depending on the file, either first
    /// or last gives the best compression. Default: false (0).
    pub blocksplittinglast: bool,
    /// Maximum amount of blocks to split into (0 for unlimited, but this can give
    /// extreme results that hurt compression on some files). Default value: 15.
    pub blocksplittingmax: i32,
}

impl Options {
    pub fn new() -> Options {
        Options {
            verbose: false,
            verbose_more: false,
            numiterations: 15,
            blocksplitting: true,
            blocksplittinglast: false,
            blocksplittingmax: 15,
        }
    }
}

/// Output format
#[derive(Clone, Copy)]
pub enum Format {
    GZIP,
    ZLIB,
    DEFLATE,
}

/**
 * Compresses according to the given output format and appends the result to the
 * output.
 *
 * options: global program options
 * output_type: the output format to use
 * out: pointer to the dynamic output array to which the result is appended. Must
 *   be freed after use
 * outsize: pointer to the dynamic output array size
 */
pub unsafe fn compress(options: *const Options, output_type: Format, input: *const u8, insize: usize, out: *mut *mut u8, outsize: *mut usize) {
    match output_type {
        Format::GZIP    => gzip_container::compress(options, input, insize, out, outsize),
        Format::ZLIB    => zlib_container::compress(options, input, insize, out, outsize),
        Format::DEFLATE => {
            let mut bp: u8 = 0;
            deflate::deflate(options, 2 /* Dynamic block */, true, input, insize, &mut bp, out, outsize)
        },
    }
}

#[cfg(test)]
mod test {
    extern crate flate2;

    use libc::{c_void, size_t};
    use libc::funcs::c95::string::memcmp;
    use std::io::Read;
    use std::ptr::null_mut;
    use std::slice;

    use self::flate2::read::{DeflateDecoder, GzDecoder, ZlibDecoder};

    use super::*;

    unsafe fn roundtrip(format: Format, bytes: &[u8]) {
        let options = Options { verbose: true, verbose_more: true, .. Options::new() };
        let mut compressed: *mut u8 = null_mut();
        let mut compressed_size: usize = 0;
        compress(&options, format, bytes.as_ptr(), bytes.len(), &mut compressed, &mut compressed_size);
        let decompressed = match format {
            Format::GZIP => {
                let mut d = GzDecoder::new(slice::from_raw_parts(compressed, compressed_size)).unwrap();
                let mut s = Vec::new();
                d.read_to_end(&mut s).unwrap();
                s
            }
            Format::ZLIB => {
                let mut d = ZlibDecoder::new(slice::from_raw_parts(compressed, compressed_size));
                let mut s = Vec::new();
                d.read_to_end(&mut s).unwrap();
                s
            }
            Format::DEFLATE => {
                let mut d = DeflateDecoder::new(slice::from_raw_parts(compressed, compressed_size));
                let mut s = Vec::new();
                d.read_to_end(&mut s).unwrap();
                s
            }
        };
        assert!(memcmp(bytes.as_ptr() as *const c_void, decompressed.as_ptr() as *const c_void, bytes.len() as size_t) == 0);
    }

    #[test]
    fn roundtrips() {
        unsafe {
            for format in vec![Format::GZIP, Format::ZLIB, Format::DEFLATE] {
                roundtrip(format, b"1");
                roundtrip(format, b"foobar");
            }
        }
    }

    #[test]
    #[ignore]
    fn compress_zero_bytes() {
        unsafe {
            for format in vec![Format::GZIP, Format::ZLIB, Format::DEFLATE] {
                roundtrip(format, b"");
            }
        }
    }
}
<commit_msg>Disable verbose output in tests<commit_after>#![macro_use]
#![allow(unused)]

#[macro_use]
extern crate log;
extern crate libc;

mod util;

mod blocksplitter;
#[cfg(feature = "longest-match-cache")]
mod cache;
mod deflate;
mod gzip_container;
mod hash;
mod katajainen;
mod lz77;
mod squeeze;
mod tree;
mod zlib_container;

/// Options used throughout the program.
pub struct Options {
    /// Whether to print output
    pub verbose: bool,
    /// Whether to print more detailed output
    pub verbose_more: bool,
    /// Maximum amount of times to rerun forward and backward pass to optimize LZ77
    /// compression cost. Good values: 10, 15 for small files, 5 for files over
    /// several MB in size or it will be too slow.
    pub numiterations: i32,
    /// If true, splits the data in multiple deflate blocks with optimal choice
    /// for the block boundaries. Block splitting gives better compression. Default:
    /// true (1).
    pub blocksplitting: bool,
    /// If true, chooses the optimal block split points only after doing the iterative
    /// LZ77 compression. If false, chooses the block split points first, then does
    /// iterative LZ77 on each individual block. Depending on the file, either first
    /// or last gives the best compression. Default: false (0).
    pub blocksplittinglast: bool,
    /// Maximum amount of blocks to split into (0 for unlimited, but this can give
    /// extreme results that hurt compression on some files). Default value: 15.
    pub blocksplittingmax: i32,
}

impl Options {
    pub fn new() -> Options {
        Options {
            verbose: false,
            verbose_more: false,
            numiterations: 15,
            blocksplitting: true,
            blocksplittinglast: false,
            blocksplittingmax: 15,
        }
    }
}

/// Output format
#[derive(Clone, Copy)]
pub enum Format {
    GZIP,
    ZLIB,
    DEFLATE,
}

/**
 * Compresses according to the given output format and appends the result to the
 * output.
 *
 * options: global program options
 * output_type: the output format to use
 * out: pointer to the dynamic output array to which the result is appended. Must
 *   be freed after use
 * outsize: pointer to the dynamic output array size
 */
pub unsafe fn compress(options: *const Options, output_type: Format, input: *const u8, insize: usize, out: *mut *mut u8, outsize: *mut usize) {
    match output_type {
        Format::GZIP    => gzip_container::compress(options, input, insize, out, outsize),
        Format::ZLIB    => zlib_container::compress(options, input, insize, out, outsize),
        Format::DEFLATE => {
            let mut bp: u8 = 0;
            deflate::deflate(options, 2 /* Dynamic block */, true, input, insize, &mut bp, out, outsize)
        },
    }
}

#[cfg(test)]
mod test {
    extern crate flate2;

    use libc::{c_void, size_t};
    use libc::funcs::c95::string::memcmp;
    use std::io::Read;
    use std::ptr::null_mut;
    use std::slice;

    use self::flate2::read::{DeflateDecoder, GzDecoder, ZlibDecoder};

    use super::*;

    unsafe fn roundtrip(format: Format, bytes: &[u8]) {
        let options = Options { verbose: false, verbose_more: false, .. Options::new() };
        let mut compressed: *mut u8 = null_mut();
        let mut compressed_size: usize = 0;
        compress(&options, format, bytes.as_ptr(), bytes.len(), &mut compressed, &mut compressed_size);
        let decompressed = match format {
            Format::GZIP => {
                let mut d = GzDecoder::new(slice::from_raw_parts(compressed, compressed_size)).unwrap();
                let mut s = Vec::new();
                d.read_to_end(&mut s).unwrap();
                s
            }
            Format::ZLIB => {
                let mut d = ZlibDecoder::new(slice::from_raw_parts(compressed, compressed_size));
                let mut s = Vec::new();
                d.read_to_end(&mut s).unwrap();
                s
            }
            Format::DEFLATE => {
                let mut d = DeflateDecoder::new(slice::from_raw_parts(compressed, compressed_size));
                let mut s = Vec::new();
                d.read_to_end(&mut s).unwrap();
                s
            }
        };
        assert!(memcmp(bytes.as_ptr() as *const c_void, decompressed.as_ptr() as *const c_void, bytes.len() as size_t) == 0);
    }

    #[test]
    fn roundtrips() {
        unsafe {
            for format in vec![Format::GZIP, Format::ZLIB, Format::DEFLATE] {
                roundtrip(format, b"1");
                roundtrip(format, b"foobar");
            }
        }
    }

    #[test]
    #[ignore]
    fn compress_zero_bytes() {
        unsafe {
            for format in vec![Format::GZIP, Format::ZLIB, Format::DEFLATE] {
                roundtrip(format, b"");
            }
        }
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![feature(unsafe_destructor)]
#![unstable]

//! A library for setting current values for stack scope,
//! such as application structure.

use std::cell::RefCell;
use std::intrinsics::TypeId;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{ Occupied, Vacant };

// Stores the current pointers for concrete types.
thread_local!(static KEY_CURRENT: RefCell<HashMap<TypeId, uint>>
    = RefCell::new(HashMap::new()));

/// Puts back the previous current pointer.
#[unstable]
pub struct CurrentGuard<'a, T: 'a> {
    _val: &'a mut T,
    old_ptr: Option<uint>
}

#[unstable]
impl<'a, T: 'static> CurrentGuard<'a, T> {
    /// Creates a new current guard.
    #[unstable]
    pub fn new(val: &mut T) -> CurrentGuard<T> {
        let id = TypeId::of::<T>();
        let ptr = val as *mut T as uint;
        let old_ptr = KEY_CURRENT.with(|current| {
            match current.borrow_mut().entry(id) {
                Occupied(mut entry) => Some(entry.set(ptr)),
                Vacant(entry) => {
                    entry.set(ptr);
                    None
                }
            }
        });
        CurrentGuard { old_ptr: old_ptr, _val: val }
    }
}

#[unsafe_destructor]
impl<'a, T: 'static> Drop for CurrentGuard<'a, T> {
    fn drop(&mut self) {
        let id = TypeId::of::<T>();
        match self.old_ptr {
            None => {
                KEY_CURRENT.with(|current| {
                    current.borrow_mut().remove(&id);
                });
                return;
            }
            Some(old_ptr) => {
                KEY_CURRENT.with(|current| {
                    match current.borrow_mut().entry(id) {
                        Occupied(mut entry) => { entry.set(old_ptr); }
                        Vacant(entry) => { entry.set(old_ptr); }
                    };
                });
            }
        };
    }
}

/// The current value of a type.
#[unstable]
pub struct Current<T>(());

#[unstable]
impl<T: 'static> Current<T> {
    /// Creates a new current object
    #[unstable]
    pub unsafe fn new() -> Current<T> { Current(()) }

    /// Gets mutable reference to current object.
    /// Requires mutable reference to prevent access to globals in safe code,
    /// and to prevent mutable borrows of same value in scope.
    /// Is unsafe because returned reference inherits lifetime from argument.
    #[unstable]
    pub unsafe fn current(&mut self) -> Option<&mut T> {
        use std::mem::transmute;
        let id = TypeId::of::<T>();
        let ptr: Option<uint> = KEY_CURRENT.with(|current| {
                current.borrow().get(&id).map(|id| *id)
            });
        let ptr = match ptr { None => { return None; } Some(x) => x };
        Some(transmute(ptr as *mut T))
    }

    /// Unwraps mutable reference to current object,
    /// but with nicer error message.
    #[unstable]
    pub unsafe fn current_unwrap(&mut self) -> &mut T {
        match self.current() {
            None => {
                use std::intrinsics::get_tydesc;
                let name = (*get_tydesc::<T>()).name;
                panic!("No current `{}` is set", name);
            }
            Some(x) => x
        }
    }
}

impl<T: 'static> Deref<T> for Current<T> {
    #[inline(always)]
    fn deref<'a>(&'a self) -> &'a T {
        use std::mem::transmute;
        unsafe {
            // Current does not contain anything,
            // so it is safe to transmute to mutable.
            transmute::<_, &'a mut Current<T>>(self).current_unwrap()
        }
    }
}

impl<T: 'static> DerefMut<T> for Current<T> {
    #[inline(always)]
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { self.current_unwrap() }
    }
}
<commit_msg>Upgraded to latest Rust<commit_after>#![deny(missing_docs)]
#![feature(unsafe_destructor)]
#![feature(associated_types)]
#![unstable]

//! A library for setting current values for stack scope,
//! such as application structure.

use std::cell::RefCell;
use std::intrinsics::TypeId;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{ Occupied, Vacant };
use std::ops::{ Deref, DerefMut };

// Stores the current pointers for concrete types.
thread_local!(static KEY_CURRENT: RefCell<HashMap<TypeId, uint>>
    = RefCell::new(HashMap::new()));

/// Puts back the previous current pointer.
#[unstable]
pub struct CurrentGuard<'a, T: 'a> {
    _val: &'a mut T,
    old_ptr: Option<uint>
}

#[unstable]
impl<'a, T: 'static> CurrentGuard<'a, T> {
    /// Creates a new current guard.
    #[unstable]
    pub fn new(val: &mut T) -> CurrentGuard<T> {
        let id = TypeId::of::<T>();
        let ptr = val as *mut T as uint;
        let old_ptr = KEY_CURRENT.with(|current| {
            match current.borrow_mut().entry(id) {
                Occupied(mut entry) => Some(entry.set(ptr)),
                Vacant(entry) => {
                    entry.set(ptr);
                    None
                }
            }
        });
        CurrentGuard { old_ptr: old_ptr, _val: val }
    }
}

#[unsafe_destructor]
impl<'a, T: 'static> Drop for CurrentGuard<'a, T> {
    fn drop(&mut self) {
        let id = TypeId::of::<T>();
        match self.old_ptr {
            None => {
                KEY_CURRENT.with(|current| {
                    current.borrow_mut().remove(&id);
                });
                return;
            }
            Some(old_ptr) => {
                KEY_CURRENT.with(|current| {
                    match current.borrow_mut().entry(id) {
                        Occupied(mut entry) => { entry.set(old_ptr); }
                        Vacant(entry) => { entry.set(old_ptr); }
                    };
                });
            }
        };
    }
}

/// The current value of a type.
#[unstable]
pub struct Current<T>(());

#[unstable]
impl<T: 'static> Current<T> {
    /// Creates a new current object
    #[unstable]
    pub unsafe fn new() -> Current<T> { Current(()) }

    /// Gets mutable reference to current object.
    /// Requires mutable reference to prevent access to globals in safe code,
    /// and to prevent mutable borrows of same value in scope.
    /// Is unsafe because returned reference inherits lifetime from argument.
    #[unstable]
    pub unsafe fn current(&mut self) -> Option<&mut T> {
        use std::mem::transmute;
        let id = TypeId::of::<T>();
        let ptr: Option<uint> = KEY_CURRENT.with(|current| {
                current.borrow().get(&id).map(|id| *id)
            });
        let ptr = match ptr { None => { return None; } Some(x) => x };
        Some(transmute(ptr as *mut T))
    }

    /// Unwraps mutable reference to current object,
    /// but with nicer error message.
    #[unstable]
    pub unsafe fn current_unwrap(&mut self) -> &mut T {
        match self.current() {
            None => {
                use std::intrinsics::get_tydesc;
                let name = (*get_tydesc::<T>()).name;
                panic!("No current `{}` is set", name);
            }
            Some(x) => x
        }
    }
}

impl<T: 'static> Deref for Current<T> {
    type Target = T;

    #[inline(always)]
    fn deref<'a>(&'a self) -> &'a T {
        use std::mem::transmute;
        unsafe {
            // Current does not contain anything,
            // so it is safe to transmute to mutable.
            transmute::<_, &'a mut Current<T>>(self).current_unwrap()
        }
    }
}

impl<T: 'static> DerefMut for Current<T> {
    #[inline(always)]
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { self.current_unwrap() }
    }
}
<|endoftext|>


<commit_before>//! `Future`-powered I/O at the core of Tokio
//!
//! This crate uses the `futures` crate to provide an event loop ("reactor
//! core") which can be used to drive I/O like TCP and UDP, spawned future
//! tasks, and other events like channels/timeouts. All asynchronous I/O is
//! powered by the `mio` crate.
//!
//! The concrete types provided in this crate are relatively bare bones but are
//! intended to be the essential foundation for further projects needing an
//! event loop. In this crate you'll find:
//!
//! * TCP, both streams and listeners
//! * UDP sockets
//! * Message queues
//! * Timeouts
//!
//! More functionality is likely to be added over time, but otherwise the crate
//! is intended to be flexible, with the `PollEvented` type accepting any
//! type that implements `mio::Evented`. For example, the `tokio-uds` crate
//! uses `PollEvented` to provide support for Unix domain sockets.
//!
//! Some other important tasks covered by this crate are:
//!
//! * The ability to spawn futures into an event loop. The `Handle` and `Pinned`
//!   types have a `spawn` method which allows executing a future on an event
//!   loop. The `Pinned::spawn` method crucially does not require the future
//!   itself to be `Send`.
//!
//! * The `Io` trait serves as an abstraction for future crates to build on top
//!   of. This packages up `Read` and `Write` functionality as well as the
//!   ability to poll for readiness on both ends.
//!
//! * All I/O is futures-aware. If any action in this crate returns "not ready"
//!   or "would block", then the current future task is scheduled to receive a
//!   notification when it would otherwise make progress.
//!
//! # Examples
//!
//! A simple TCP echo server:
//!
//! ```no_run
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use std::env;
//! use std::net::SocketAddr;
//!
//! use futures::Future;
//! use futures::stream::Stream;
//! use tokio_core::io::{copy, Io};
//! use tokio_core::net::TcpListener;
//! use tokio_core::reactor::Core;
//!
//! fn main() {
//!     let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
//!     let addr = addr.parse::<SocketAddr>().unwrap();
//!
//!     // Create the event loop that will drive this server
//!     let mut l = Core::new().unwrap();
//!     let handle = l.handle();
//!
//!     // Create a TCP listener which will listen for incoming connections
//!     let socket = TcpListener::bind(&addr, &handle).unwrap();
//!
//!     // Once we've got the TCP listener, inform that we have it
//!     println!("Listening on: {}", addr);
//!
//!     // Pull out the stream of incoming connections and then for each new
//!     // one spin up a new task copying data.
//!     //
//!     // We use the `io::copy` future to copy all data from the
//!     // reading half onto the writing half.
//!     let done = socket.incoming().for_each(|(socket, addr)| {
//!         let pair = futures::lazy(|| Ok(socket.split()));
//!         let amt = pair.and_then(|(reader, writer)| copy(reader, writer));
//!
//!         // Once all that is done we print out how much we wrote, and then
//!         // critically we *spawn* this future which allows it to run
//!         // concurrently with other connections.
//!         handle.spawn(amt.then(move |result| {
//!             println!("wrote {:?} bytes to {}", result, addr);
//!             Ok(())
//!         }));
//!
//!         Ok(())
//!     });
//!
//!     // Execute our server (modeled as a future) and wait for it to
//!     // complete.
//!     l.run(done).unwrap();
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/tokio-core/0.1")]
#![deny(missing_docs)]

#[macro_use]
extern crate futures;
extern crate mio;
extern crate slab;

#[macro_use]
extern crate scoped_tls;

#[macro_use]
extern crate log;

#[macro_use]
pub mod io;

mod mpsc_queue;
mod heap;
pub mod channel;
pub mod net;
pub mod reactor;
<commit_msg>Touch up some docs in tokio-core<commit_after>//! `Future`-powered I/O at the core of Tokio
//!
//! This crate uses the `futures` crate to provide an event loop ("reactor
//! core") which can be used to drive I/O like TCP and UDP, spawned future
//! tasks, and other events like channels/timeouts. All asynchronous I/O is
//! powered by the `mio` crate.
//!
//! The concrete types provided in this crate are relatively bare bones but are
//! intended to be the essential foundation for further projects needing an
//! event loop. In this crate you'll find:
//!
//! * TCP, both streams and listeners
//! * UDP sockets
//! * Timeouts
//! * An event loop to run futures
//!
//! More functionality is likely to be added over time, but otherwise the crate
//! is intended to be flexible, with the `PollEvented` type accepting any
//! type that implements `mio::Evented`. For example, the `tokio-uds` crate
//! uses `PollEvented` to provide support for Unix domain sockets.
//!
//! Some other important tasks covered by this crate are:
//!
//! * The ability to spawn futures into an event loop. The `Handle` and `Remote`
//!   types have a `spawn` method which allows executing a future on an event
//!   loop. The `Handle::spawn` method crucially does not require the future
//!   itself to be `Send`.
//!
//! * The `Io` trait serves as an abstraction for future crates to build on top
//!   of. This packages up `Read` and `Write` functionality as well as the
//!   ability to poll for readiness on both ends.
//!
//! * All I/O is futures-aware. If any action in this crate returns "not ready"
//!   or "would block", then the current future task is scheduled to receive a
//!   notification when it would otherwise make progress.
//!
//! # Examples
//!
//! A simple TCP echo server:
//!
//! ```no_run
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use futures::{Future, Stream};
//! use tokio_core::io::{copy, Io};
//! use tokio_core::net::TcpListener;
//! use tokio_core::reactor::Core;
//!
//! fn main() {
//!     // Create the event loop that will drive this server
//!     let mut core = Core::new().unwrap();
//!     let handle = core.handle();
//!
//!     // Bind the server's socket
//!     let addr = "127.0.0.1:12345".parse().unwrap();
//!     let sock = TcpListener::bind(&addr, &handle).unwrap();
//!
//!     // Pull out a stream of sockets for incoming connections
//!     let server = sock.incoming().for_each(|(sock, _)| {
//!         // Split up the reading and writing parts of the
//!         // socket
//!         let (reader, writer) = sock.split();
//!
//!         // A future that echos the data and returns how
//!         // many bytes were copied...
//!         let bytes_copied = copy(reader, writer);
//!
//!         // ... after which we'll print what happened
//!         let handle_conn = bytes_copied.map(|amt| {
//!             println!("wrote {} bytes", amt)
//!         }).map_err(|err| {
//!             println!("IO error {:?}", err)
//!         });
//!
//!         // Spawn the future as a concurrent task
//!         handle.spawn(handle_conn);
//!
//!         Ok(())
//!     });
//!
//!     // Spin up the server on the event loop
//!     core.run(server).unwrap();
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/tokio-core/0.1")]
#![deny(missing_docs)]

#[macro_use]
extern crate futures;
extern crate mio;
extern crate slab;

#[macro_use]
extern crate scoped_tls;

#[macro_use]
extern crate log;

#[macro_use]
pub mod io;

mod mpsc_queue;
mod heap;
#[doc(hidden)]
pub mod channel;
pub mod net;
pub mod reactor;
<|endoftext|>


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

use BinaryOp::*;
use Data::*;
use Expression::*;

#[derive(Clone,Debug,PartialEq)]
pub enum Data {
    Nil,
    Boolean(bool),
    Number(f64),
    Str(String),
}

#[derive(Clone,Debug)]
pub enum Expression {
    NilLiteral,
    BooleanLiteral(bool),
    NumberLiteral(f64),
    StrLiteral(String),
    Variable(String),
    Assignment{left: String, right: Box<Expression>},
    FunctionCall{name: String, args: Vec<Expression>},
    BinaryExpr{left: Box<Expression>, op: BinaryOp, right: Box<Expression>},
}

impl Expression {
    pub fn eval(&self, p: &mut Program) -> Data {
        match self {
            &NilLiteral => Nil,
            &BooleanLiteral(b) => Boolean(b),
            &NumberLiteral(n) => Number(n),
            &StrLiteral(ref s) => Str(s.clone()),
            &Variable(ref name) => {
                match p.vars.get(name) {
                    Some(d) => d.clone(),
                    None => Nil,
                }
            },
            &Assignment{ref left, ref right} => {
                let res = right.eval(p);
                p.vars.insert(left.clone(), res.clone());
                res
            },
            &FunctionCall{ref name, ref args} => {
                let f = match name.as_ref() {
                    "println" => println,
                    _ => return Nil,
                };

                let mut new_args = Vec::new();
                for item in args.iter() {
                    new_args.push(item.eval(p));
                }

                f(&new_args)
            },
            &BinaryExpr{ref left, ref op, ref right} => {
                let (left_data, right_data) = (left.eval(p), right.eval(p));
                op.eval(&left_data, &right_data)
            },
        }
    }
}

#[derive(Clone,Debug)]
pub enum BinaryOp {
    Add,
    Sub,
    Mul,
    Div,
    Eq,
    Lt,
    LtEq,
    Gt,
    GtEq,
}

impl BinaryOp {
    fn eval(&self, left: &Data, right: &Data) -> Data {
        match (self, left, right) {
            (&Add, &Number(l), &Number(r)) => Number(l+r),
            (&Sub, &Number(l), &Number(r)) => Number(l-r),
            (&Mul, &Number(l), &Number(r)) => Number(l*r),
            (&Div, &Number(l), &Number(r)) => Number(l/r),
            (&Eq, _, _) => Boolean(left == right),
            (&Lt, &Number(l), &Number(r)) => Boolean(l < r),
            (&LtEq, &Number(l), &Number(r)) => Boolean(l <= r),
            (&Gt, &Number(l), &Number(r)) => Boolean(l > r),
            (&GtEq, &Number(l), &Number(r)) => Boolean(l >= r),
            _ => Nil,
        }
    }
}

pub struct Program {
    pub vars: HashMap<String, Data>,
    pub funcs: HashMap<String, i64>,
}

impl Program {
    pub fn new() -> Self {
        Program {
            vars: HashMap::new(),
            funcs: HashMap::new(),
        }
    }

    pub fn eval(&mut self, e: &Expression) -> Data {
        e.eval(self)
    }
}

pub fn println(v: &Vec<Data>) -> Data {
    for item in v {
        print!("{:?}", item);
    }
    println!("");
    Data::Nil
}

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

    #[test]
    fn test_things() {
        let mut ast: Vec<Expression> = Vec::new();
        ast.push(Assignment {
            left: "x".to_owned(),
            right: Box::new(NumberLiteral(2.0)),
        });
        ast.push(FunctionCall {
            name: "println".to_owned(),
            args: vec![Variable("x".to_owned())]
        });

        let mut p = Program::new();
        for exp in ast {
            p.eval(&exp);
        }
    }

    #[test]
    fn test_binary_expr() {
        let cases = vec![
            // Add
            (Add, Number(1.0), Number(2.0), Number(3.0)),
            (Add, Boolean(false), Number(2.0), Nil),
            (Add, Number(2.0), Str("1.0".to_owned()), Nil),
            // Sub
            (Sub, Number(1.0), Number(2.0), Number(-1.0)),
            (Sub, Boolean(false), Number(2.0), Nil),
            (Sub, Number(2.0), Str("1.0".to_owned()), Nil),
            // Mul
            (Mul, Number(1.5), Number(2.0), Number(3.0)),
            (Mul, Boolean(false), Number(2.0), Nil),
            (Mul, Number(2.0), Str("1.0".to_owned()), Nil),
            // Div
            (Div, Number(1.0), Number(2.0), Number(0.5)),
            (Div, Boolean(false), Number(2.0), Nil),
            (Div, Number(2.0), Str("1.0".to_owned()), Nil),
            // Eq
            (Eq, Number(2.0), Number(2.0), Boolean(true)),
            (Eq, Number(-2.0), Number(2.0), Boolean(false)),
            (Eq, Str("foo".to_owned()), Str("foo".to_owned()), Boolean(true)),
            (Eq, Str("foo".to_owned()), Str("bar".to_owned()), Boolean(false)),
            (Eq, Boolean(false), Boolean(false), Boolean(true)),
            (Eq, Boolean(true), Boolean(true), Boolean(true)),
            (Eq, Boolean(true), Boolean(false), Boolean(false)),
            (Eq, Nil, Boolean(false), Boolean(false)),
            (Eq, Nil, Nil, Boolean(true)),
            // Lt
            (Lt, Number(-1.0), Number(0.5), Boolean(true)),
            (Lt, Number(1.0), Number(1.0), Boolean(false)),
            (Lt, Number(1.0), Number(0.5), Boolean(false)),
            // LtEq
            (LtEq, Number(-1.0), Number(0.5), Boolean(true)),
            (LtEq, Number(1.0), Number(1.0), Boolean(true)),
            (LtEq, Number(1.0), Number(0.5), Boolean(false)),
            // Gt
            (Gt, Number(-1.0), Number(0.5), Boolean(false)),
            (Gt, Number(1.0), Number(1.0), Boolean(false)),
            (Gt, Number(1.0), Number(0.5), Boolean(true)),
            // GtEq
            (GtEq, Number(-1.0), Number(0.5), Boolean(false)),
            (GtEq, Number(1.0), Number(1.0), Boolean(true)),
            (GtEq, Number(1.0), Number(0.5), Boolean(true)),
        ];

        for (op, left, right, exp) in cases {
            assert_eq!(op.eval(&left, &right), exp);
        }
    }
}
<commit_msg>Add if expression<commit_after>use std::collections::HashMap;

use BinaryOp::*;
use Data::*;
use Expression::*;

#[derive(Clone,Debug,PartialEq)]
pub enum Data {
    Nil,
    Boolean(bool),
    Number(f64),
    Str(String),
}

#[derive(Clone,Debug)]
pub enum Expression {
    NilLiteral,
    BooleanLiteral(bool),
    NumberLiteral(f64),
    StrLiteral(String),
    Variable(String),
    Assignment{left: String, right: Box<Expression>},
    FunctionCall{name: String, args: Vec<Expression>},
    BinaryExpr{left: Box<Expression>, op: BinaryOp, right: Box<Expression>},
    IfExpr{cond: Box<Expression>, body: Box<Expression>, else_branch: Option<Box<Expression>>},
}

impl Expression {
    pub fn eval(&self, p: &mut Program) -> Data {
        match self {
            &NilLiteral => Nil,
            &BooleanLiteral(b) => Boolean(b),
            &NumberLiteral(n) => Number(n),
            &StrLiteral(ref s) => Str(s.clone()),
            &Variable(ref name) => {
                match p.vars.get(name) {
                    Some(d) => d.clone(),
                    None => Nil,
                }
            },
            &Assignment{ref left, ref right} => {
                let res = right.eval(p);
                p.vars.insert(left.clone(), res.clone());
                res
            },
            &FunctionCall{ref name, ref args} => {
                let f = match name.as_ref() {
                    "println" => println,
                    _ => return Nil,
                };

                let mut new_args = Vec::new();
                for item in args.iter() {
                    new_args.push(item.eval(p));
                }

                f(&new_args)
            },
            &BinaryExpr{ref left, ref op, ref right} => {
                let (left_data, right_data) = (left.eval(p), right.eval(p));
                op.eval(&left_data, &right_data)
            },
            &IfExpr{ref cond, ref body, ref else_branch} => {
                if cond.eval(p) == Boolean(true) {
                    body.eval(p)
                } else if let &Some(ref b) = else_branch {
                    b.eval(p)
                } else {
                    Nil
                }
            },
        }
    }
}

#[derive(Clone,Debug)]
pub enum BinaryOp {
    Add,
    Sub,
    Mul,
    Div,
    Eq,
    Lt,
    LtEq,
    Gt,
    GtEq,
}

impl BinaryOp {
    fn eval(&self, left: &Data, right: &Data) -> Data {
        match (self, left, right) {
            (&Add, &Number(l), &Number(r)) => Number(l+r),
            (&Sub, &Number(l), &Number(r)) => Number(l-r),
            (&Mul, &Number(l), &Number(r)) => Number(l*r),
            (&Div, &Number(l), &Number(r)) => Number(l/r),
            (&Eq, _, _) => Boolean(left == right),
            (&Lt, &Number(l), &Number(r)) => Boolean(l < r),
            (&LtEq, &Number(l), &Number(r)) => Boolean(l <= r),
            (&Gt, &Number(l), &Number(r)) => Boolean(l > r),
            (&GtEq, &Number(l), &Number(r)) => Boolean(l >= r),
            _ => Nil,
        }
    }
}

pub struct Program {
    pub vars: HashMap<String, Data>,
    pub funcs: HashMap<String, i64>,
}

impl Program {
    pub fn new() -> Self {
        Program {
            vars: HashMap::new(),
            funcs: HashMap::new(),
        }
    }

    pub fn eval(&mut self, e: &Expression) -> Data {
        e.eval(self)
    }
}

pub fn println(v: &Vec<Data>) -> Data {
    for item in v {
        print!("{:?}", item);
    }
    println!("");
    Data::Nil
}

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

    #[test]
    fn test_things() {
        let mut ast: Vec<Expression> = Vec::new();
        ast.push(Assignment {
            left: "x".to_owned(),
            right: Box::new(NumberLiteral(2.0)),
        });
        ast.push(FunctionCall {
            name: "println".to_owned(),
            args: vec![Variable("x".to_owned())]
        });

        let mut p = Program::new();
        for exp in ast {
            p.eval(&exp);
        }
    }

    #[test]
    fn test_binary_expr() {
        let cases = vec![
            // Add
            (Add, Number(1.0), Number(2.0), Number(3.0)),
            (Add, Boolean(false), Number(2.0), Nil),
            (Add, Number(2.0), Str("1.0".to_owned()), Nil),
            // Sub
            (Sub, Number(1.0), Number(2.0), Number(-1.0)),
            (Sub, Boolean(false), Number(2.0), Nil),
            (Sub, Number(2.0), Str("1.0".to_owned()), Nil),
            // Mul
            (Mul, Number(1.5), Number(2.0), Number(3.0)),
            (Mul, Boolean(false), Number(2.0), Nil),
            (Mul, Number(2.0), Str("1.0".to_owned()), Nil),
            // Div
            (Div, Number(1.0), Number(2.0), Number(0.5)),
            (Div, Boolean(false), Number(2.0), Nil),
            (Div, Number(2.0), Str("1.0".to_owned()), Nil),
            // Eq
            (Eq, Number(2.0), Number(2.0), Boolean(true)),
            (Eq, Number(-2.0), Number(2.0), Boolean(false)),
            (Eq, Str("foo".to_owned()), Str("foo".to_owned()), Boolean(true)),
            (Eq, Str("foo".to_owned()), Str("bar".to_owned()), Boolean(false)),
            (Eq, Boolean(false), Boolean(false), Boolean(true)),
            (Eq, Boolean(true), Boolean(true), Boolean(true)),
            (Eq, Boolean(true), Boolean(false), Boolean(false)),
            (Eq, Nil, Boolean(false), Boolean(false)),
            (Eq, Nil, Nil, Boolean(true)),
            // Lt
            (Lt, Number(-1.0), Number(0.5), Boolean(true)),
            (Lt, Number(1.0), Number(1.0), Boolean(false)),
            (Lt, Number(1.0), Number(0.5), Boolean(false)),
            // LtEq
            (LtEq, Number(-1.0), Number(0.5), Boolean(true)),
            (LtEq, Number(1.0), Number(1.0), Boolean(true)),
            (LtEq, Number(1.0), Number(0.5), Boolean(false)),
            // Gt
            (Gt, Number(-1.0), Number(0.5), Boolean(false)),
            (Gt, Number(1.0), Number(1.0), Boolean(false)),
            (Gt, Number(1.0), Number(0.5), Boolean(true)),
            // GtEq
            (GtEq, Number(-1.0), Number(0.5), Boolean(false)),
            (GtEq, Number(1.0), Number(1.0), Boolean(true)),
            (GtEq, Number(1.0), Number(0.5), Boolean(true)),
        ];

        for (op, left, right, exp) in cases {
            assert_eq!(op.eval(&left, &right), exp);
        }
    }

    #[test]
    fn test_if_expr() {
        let mut p = Program::new();

        let cases = vec![
            (BooleanLiteral(true), NumberLiteral(1.0), None, Number(1.0)),
            (BooleanLiteral(true), NumberLiteral(1.0), Some(NumberLiteral(2.0)), Number(1.0)),
            (BooleanLiteral(false), NumberLiteral(1.0), None, Nil),
            (BooleanLiteral(false), NumberLiteral(1.0), Some(NumberLiteral(2.0)), Number(2.0)),
        ];

        for (cond, body, else_branch, exp) in cases {
            let x = IfExpr {
                cond: Box::new(cond),
                body: Box::new(body),
                else_branch: else_branch.map(|e| Box::new(e)),
            };

            assert_eq!(x.eval(&mut p), exp);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(associated_consts)]
#![feature(drain)]
#![feature(rc_would_unwrap)]

extern crate uuid;
extern crate typed_arena;
mod js_types;
mod alloc;

use std::collections::hash_set::HashSet;
use std::ptr::null_mut;
use std::rc::{Rc, Weak};
use uuid::Uuid;

use alloc::scope::Scope;
use js_types::js_type::JsVar;

pub struct ScopeManager {
    root_scope: Rc<Scope>,
    //curr_scope: Weak<Scope>,
    pub size: usize,
}

/*impl ScopeManager {
    pub fn new<F>(callback: F) -> ScopeManager
        where F: Fn() -> HashSet<Uuid> + 'static {
        let mut mgr =
            ScopeManager {
                root_scope: Rc::new(Scope::new(callback)),
                curr_scope: Rc::downgrade(&Rc::new(Scope::new(callback))),
                size: 1,
            };
        mgr.curr_scope = Rc::downgrade(&mgr.root_scope.clone());
        mgr
    }

    pub fn push_scope<F>(&mut self, callback: F) where F: Fn() -> HashSet<Uuid> + 'static {
        let weak_clone = self.curr_scope.clone();
        self.curr_scope =
            // Is this possible?
            if let Some(curr_scope) = self.curr_scope.upgrade() {
                Rc::downgrade(Rc::get_mut(&mut curr_scope)
                                .unwrap()
                                .add_child(Scope::as_child(weak_clone, callback)))
            } else {
                panic!("Unable to upgrade curr_scope to Rc! Underlying data was destroyed!");
            };
        self.size += 1;
    }

    pub fn pop_scope(&mut self) {
        let parent = self.curr_scope.parent.clone();
        if let Some(parent) = parent {
            if let Some(mut scope) = parent.upgrade() {
                // Pop old scope
                let num_children = scope.children.len();
                Rc::get_mut(&mut scope).unwrap().children.remove(num_children - 1);
                // Set curr_scope to old scope's parent
                self.curr_scope = &mut scope;
                self.size -= 1;
            }
        } else {
            panic!("Tried to pop to parent scope, but parent did not exist!");
        }
    }

    pub fn alloc(&mut self, var: JsVar) -> Uuid {
        Rc::get_mut(self.curr_scope).unwrap().alloc(var)
    }

    pub fn load(&self, uuid: Uuid) -> Option<JsVar> {
        self.curr_scope.get_var_copy(&uuid)
    }

    pub fn store(&mut self, var: JsVar) -> bool {
        Rc::get_mut(self.curr_scope).unwrap().update_var(var)
    }
}

pub fn init_gc<F>(callback: F) -> ScopeManager
    where F: Fn() -> HashSet<Uuid> + 'static {
    ScopeManager::new(callback)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::hash_set::HashSet;
    use std::ptr::null_mut;
    use std::rc::Rc;
    use uuid::Uuid;

    fn dummy_callback() -> HashSet<Uuid> {
        HashSet::new()
    }

    #[test]
    fn test_init_gc() {
        let mgr = init_gc(dummy_callback);
        //assert_eq!(mgr.size, 1);
        //assert!(mgr.curr_scope != null_mut());
        //assert!(mgr.root_scope.parent.is_none());
        unsafe { assert!(Rc::would_unwrap(&*mgr.curr_scope)); }
    }

    #[test]
    fn test_push_scope() {
        let mut mgr = init_gc(dummy_callback);
        mgr.push_scope(dummy_callback);
    }
}*/
<commit_msg>Add AllocBox to ScopeManager<commit_after>#![feature(associated_consts)]
#![feature(drain)]
#![feature(rc_would_unwrap)]

extern crate uuid;
extern crate typed_arena;
mod js_types;
mod alloc;

use std::cell::RefCell;
use std::collections::hash_set::HashSet;
use std::rc::Rc;
use uuid::Uuid;

use alloc::{Alloc, AllocBox};
use alloc::scope::Scope;
use js_types::js_type::{JsVar, JsPtrEnum};

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

impl ScopeManager {
    pub fn new<F>(alloc_box: Rc<RefCell<AllocBox>>, callback: F) -> ScopeManager
        where F: Fn() -> HashSet<Uuid> + 'static {
        ScopeManager {
            curr_scope: Rc::new(Scope::new(&alloc_box, callback)),
            alloc_box: alloc_box,
        }
    }

    pub fn push_scope<F>(&mut self, callback: F) where F: Fn() -> HashSet<Uuid> + 'static {
        self.curr_scope = Rc::new(Scope::as_child(&self.curr_scope, &self.alloc_box, callback));
    }

    pub fn pop_scope(&mut self) {
        if let Some(parent) = self.curr_scope.parent.clone() {
            // Set curr_scope to old scope's parent
            self.curr_scope = parent;
        } else {
            panic!("Tried to pop to parent scope, but parent did not exist!");
        }
    }

    pub fn alloc(&mut self, uuid: Uuid, ptr: JsPtrEnum) -> Uuid {
        Rc::get_mut(&mut self.curr_scope).unwrap().alloc(uuid, ptr)
    }

    pub fn load(&self, uuid: &Uuid) -> Option<JsPtrEnum> {
        self.curr_scope.get_ptr_copy(uuid)
    }

    pub fn store(&mut self, uuid: &Uuid, ptr: JsPtrEnum) -> bool {
        Rc::get_mut(&mut self.curr_scope).unwrap().update_ptr(uuid, ptr)
    }
}

pub fn init_gc<F>(callback: F) -> ScopeManager
    where F: Fn() -> HashSet<Uuid> + 'static {
    let alloc_box = Rc::new(RefCell::new(AllocBox::new()));
    ScopeManager::new(alloc_box, callback)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::hash_set::HashSet;
    use std::ptr::null_mut;
    use std::rc::Rc;
    use uuid::Uuid;

    fn dummy_callback() -> HashSet<Uuid> {
        HashSet::new()
    }
    // TODO
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A Glutin window back-end for the Piston game engine.

extern crate glutin;
extern crate gl;
extern crate window;
extern crate shader_version;
extern crate input;
#[macro_use]
extern crate quack;

// External crates.
use input::{
    keyboard,
    MouseButton,
    Button,
    Input,
    Motion,
};
use window::{
    WindowSettings,
    ShouldClose, Size, PollEvent, SwapBuffers,
    //CaptureCursor,
    DrawSize, Title,
    ExitOnEsc
};
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlutinWindow {
    /// The window.
    pub window: glutin::Window,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
    should_close: bool,
}

impl GlutinWindow {
    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlutinWindow {
        let (major, minor) = opengl.get_major_minor();
        let mut builder = glutin::WindowBuilder::new()
            .with_dimensions(settings.size[0], settings.size[1])
            .with_gl_version((major as u32, minor as u32))
            .with_title(settings.title.clone())
            .with_multisampling(settings.samples as u16);
        if settings.fullscreen {
            builder = builder.with_fullscreen(glutin::get_primary_monitor());
        }
        let window = builder
            .build().unwrap();
        unsafe { window.make_current(); }

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlutinWindow {
            window: window,
            last_mouse_pos: None,
            title: settings.title,
            exit_on_esc: settings.exit_on_esc,
            should_close: false,
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        use glutin::Event as E;
        use input::Input;

        if let Some((x, y)) = self.last_mouse_pos {
            self.last_mouse_pos = None;
            return Some(Input::Move(input::Motion::MouseRelative(x, y)));
        }

        match self.window.poll_events().next() {
            None => None,
            Some(E::Resized(w, h)) =>
                Some(Input::Resize(w, h)),
            Some(E::ReceivedCharacter(ch)) => {
                println!("{:?}", ch);
                let string = match ch {
                    // Ignore backspace and return ascii for Text event (like sdl2).
                    '\u{7f}' | '\r' => "".to_string(),
                    _ => ch.to_string(),
                };
                Some(Input::Text(string))
            },
            Some(E::Focused(focused)) =>
                Some(Input::Focus(focused)),
            Some(E::KeyboardInput(glutin::ElementState::Pressed, _, Some(key))) => {
                let piston_key = map_key(key);
                if let (true, input::keyboard::Key::Escape) = (self.exit_on_esc, piston_key) {
                    self.should_close = true;
                }
                Some(Input::Press(Button::Keyboard(piston_key)))
            },
            Some(E::KeyboardInput(glutin::ElementState::Released, _, Some(key))) =>
                Some(Input::Release(Button::Keyboard(map_key(key)))),
            Some(E::MouseMoved((x, y))) => {
                self.last_mouse_pos = Some((x as f64, y as f64));
                Some(Input::Move(
                    Motion::MouseCursor(x as f64, y as f64)))
            }
            Some(E::MouseWheel(y)) =>
                Some(Input::Move(
                    Motion::MouseScroll(0.0, y as f64))),
            Some(E::MouseInput(glutin::ElementState::Pressed, button)) =>
                Some(Input::Press(Button::Mouse(map_mouse(button)))),
            Some(E::MouseInput(glutin::ElementState::Released, button)) =>
                Some(Input::Release(Button::Mouse(map_mouse(button)))),
            _ => None,
        }
    }

    /*
    fn capture_cursor(&mut self, enabled: bool) {

    }
    */
}

quack! {
obj: GlutinWindow[]
get:
    fn () -> Size [] {
        if let Some((w, h)) = obj.window.get_outer_size() {
            Size([w, h])
        } else {
            Size([0, 0])
        }
    }
    fn () -> ShouldClose [] { ShouldClose(obj.window.should_close() || obj.should_close) }
    fn () -> DrawSize [] {
        if let Some((w, h)) = obj.window.get_inner_size() {
            DrawSize([w, h])
        } else {
            DrawSize([0, 0])
        }
    }
    fn () -> Title [] { Title(obj.title.clone()) }
    fn () -> ExitOnEsc [] { ExitOnEsc(obj.exit_on_esc) }
set:
    // fn (val: CaptureCursor) [] {}
    // fn (val: ShouldClose) [] {}
    fn (val: Title) [] {
        obj.title = val.0;
        obj.window.set_title(&obj.title);
    }
    fn (val: ExitOnEsc) [] { obj.exit_on_esc = val.0; }
action:
    fn (__: PollEvent) -> Option<Input> [] { obj.poll_event() }
    fn (__: SwapBuffers) -> () [] { obj.window.swap_buffers(); }
}

/// Maps Glutin's key to Piston's key.
pub fn map_key(keycode: glutin::VirtualKeyCode) -> keyboard::Key {
    use input::keyboard::Key;
    use glutin::VirtualKeyCode as K;

    match keycode {
        K::Key0 => Key::D0,
        K::Key1 => Key::D1,
        K::Key2 => Key::D2,
        K::Key3 => Key::D3,
        K::Key4 => Key::D4,
        K::Key5 => Key::D5,
        K::Key6 => Key::D6,
        K::Key7 => Key::D7,
        K::Key8 => Key::D8,
        K::Key9 => Key::D9,
        K::A => Key::A,
        K::B => Key::B,
        K::C => Key::C,
        K::D => Key::D,
        K::E => Key::E,
        K::F => Key::F,
        K::G => Key::G,
        K::H => Key::H,
        K::I => Key::I,
        K::J => Key::J,
        K::K => Key::K,
        K::L => Key::L,
        K::M => Key::M,
        K::N => Key::N,
        K::O => Key::O,
        K::P => Key::P,
        K::Q => Key::Q,
        K::R => Key::R,
        K::S => Key::S,
        K::T => Key::T,
        K::U => Key::U,
        K::V => Key::V,
        K::W => Key::W,
        K::X => Key::X,
        K::Y => Key::Y,
        K::Z => Key::Z,
        K::Apostrophe => Key::Unknown,
        K::Backslash => Key::Backslash,
        K::Back => Key::Backspace,
        // K::CapsLock => Key::CapsLock,
        K::Delete => Key::Delete,
        K::Comma => Key::Comma,
        K::Down => Key::Down,
        K::End => Key::End,
        K::Return => Key::Return,
        K::Equals => Key::Equals,
        K::Escape => Key::Escape,
        K::F1 => Key::F1,
        K::F2 => Key::F2,
        K::F3 => Key::F3,
        K::F4 => Key::F4,
        K::F5 => Key::F5,
        K::F6 => Key::F6,
        K::F7 => Key::F7,
        K::F8 => Key::F8,
        K::F9 => Key::F9,
        K::F10 => Key::F10,
        K::F11 => Key::F11,
        K::F12 => Key::F12,
        K::F13 => Key::F13,
        K::F14 => Key::F14,
        K::F15 => Key::F15,
        // K::F16 => Key::F16,
        // K::F17 => Key::F17,
        // K::F18 => Key::F18,
        // K::F19 => Key::F19,
        // K::F20 => Key::F20,
        // K::F21 => Key::F21,
        // K::F22 => Key::F22,
        // K::F23 => Key::F23,
        // K::F24 => Key::F24,
        // Possibly next code.
        // K::F25 => Key::Unknown,
        K::Numpad0 => Key::NumPad0,
        K::Numpad1 => Key::NumPad1,
        K::Numpad2 => Key::NumPad2,
        K::Numpad3 => Key::NumPad3,
        K::Numpad4 => Key::NumPad4,
        K::Numpad5 => Key::NumPad5,
        K::Numpad6 => Key::NumPad6,
        K::Numpad7 => Key::NumPad7,
        K::Numpad8 => Key::NumPad8,
        K::Numpad9 => Key::NumPad9,
        K::NumpadComma => Key::NumPadDecimal,
        K::Divide => Key::NumPadDivide,
        K::Multiply => Key::NumPadMultiply,
        K::Subtract => Key::NumPadMinus,
        K::Add => Key::NumPadPlus,
        K::NumpadEnter => Key::NumPadEnter,
        K::NumpadEquals => Key::NumPadEquals,
        K::LShift => Key::LShift,
        K::LControl => Key::LCtrl,
        K::LAlt => Key::LAlt,
        K::LMenu => Key::LGui,
        K::RShift => Key::RShift,
        K::RControl => Key::RCtrl,
        K::RAlt => Key::RAlt,
        K::RMenu => Key::RGui,
        // Map to backslash?
        // K::GraveAccent => Key::Unknown,
        K::Home => Key::Home,
        K::Insert => Key::Insert,
        K::Left => Key::Left,
        K::LBracket => Key::LeftBracket,
        // K::Menu => Key::Menu,
        K::Minus => Key::Minus,
        K::Numlock => Key::NumLockClear,
        K::PageDown => Key::PageDown,
        K::PageUp => Key::PageUp,
        K::Pause => Key::Pause,
        K::Period => Key::Period,
        // K::PrintScreen => Key::PrintScreen,
        K::Right => Key::Right,
        K::RBracket => Key::RightBracket,
        // K::ScrollLock => Key::ScrollLock,
        K::Semicolon => Key::Semicolon,
        K::Slash => Key::Slash,
        K::Space => Key::Space,
        K::Tab => Key::Tab,
        K::Up => Key::Up,
        // K::World1 => Key::Unknown,
        // K::World2 => Key::Unknown,
        _ => Key::Unknown,
    }
}

/// Maps Glutin's mouse button to Piston's mouse button.
pub fn map_mouse(mouse_button: glutin::MouseButton) -> MouseButton {
    use glutin::MouseButton as M;

    match mouse_button {
        M::Left => MouseButton::Left,
        M::Right => MouseButton::Right,
        M::Middle => MouseButton::Middle,
        M::Other(0) => MouseButton::X1,
        M::Other(1) => MouseButton::X2,
        M::Other(2) => MouseButton::Button6,
        M::Other(3) => MouseButton::Button7,
        M::Other(4) => MouseButton::Button8,
        _ => MouseButton::Unknown
    }
}
<commit_msg>Remove println<commit_after>#![deny(missing_docs)]

//! A Glutin window back-end for the Piston game engine.

extern crate glutin;
extern crate gl;
extern crate window;
extern crate shader_version;
extern crate input;
#[macro_use]
extern crate quack;

// External crates.
use input::{
    keyboard,
    MouseButton,
    Button,
    Input,
    Motion,
};
use window::{
    WindowSettings,
    ShouldClose, Size, PollEvent, SwapBuffers,
    //CaptureCursor,
    DrawSize, Title,
    ExitOnEsc
};
use shader_version::opengl::OpenGL;

/// Contains stuff for game window.
pub struct GlutinWindow {
    /// The window.
    pub window: glutin::Window,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
    should_close: bool,
}

impl GlutinWindow {
    /// Creates a new game window for GLFW.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlutinWindow {
        let (major, minor) = opengl.get_major_minor();
        let mut builder = glutin::WindowBuilder::new()
            .with_dimensions(settings.size[0], settings.size[1])
            .with_gl_version((major as u32, minor as u32))
            .with_title(settings.title.clone())
            .with_multisampling(settings.samples as u16);
        if settings.fullscreen {
            builder = builder.with_fullscreen(glutin::get_primary_monitor());
        }
        let window = builder
            .build().unwrap();
        unsafe { window.make_current(); }

        // Load the OpenGL function pointers
        gl::load_with(|s| window.get_proc_address(s));

        GlutinWindow {
            window: window,
            last_mouse_pos: None,
            title: settings.title,
            exit_on_esc: settings.exit_on_esc,
            should_close: false,
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        use glutin::Event as E;
        use input::Input;

        if let Some((x, y)) = self.last_mouse_pos {
            self.last_mouse_pos = None;
            return Some(Input::Move(input::Motion::MouseRelative(x, y)));
        }

        match self.window.poll_events().next() {
            None => None,
            Some(E::Resized(w, h)) =>
                Some(Input::Resize(w, h)),
            Some(E::ReceivedCharacter(ch)) => {
                let string = match ch {
                    // Ignore backspace and return ascii for Text event (like sdl2).
                    '\u{7f}' | '\r' => "".to_string(),
                    _ => ch.to_string(),
                };
                Some(Input::Text(string))
            },
            Some(E::Focused(focused)) =>
                Some(Input::Focus(focused)),
            Some(E::KeyboardInput(glutin::ElementState::Pressed, _, Some(key))) => {
                let piston_key = map_key(key);
                if let (true, input::keyboard::Key::Escape) = (self.exit_on_esc, piston_key) {
                    self.should_close = true;
                }
                Some(Input::Press(Button::Keyboard(piston_key)))
            },
            Some(E::KeyboardInput(glutin::ElementState::Released, _, Some(key))) =>
                Some(Input::Release(Button::Keyboard(map_key(key)))),
            Some(E::MouseMoved((x, y))) => {
                self.last_mouse_pos = Some((x as f64, y as f64));
                Some(Input::Move(
                    Motion::MouseCursor(x as f64, y as f64)))
            }
            Some(E::MouseWheel(y)) =>
                Some(Input::Move(
                    Motion::MouseScroll(0.0, y as f64))),
            Some(E::MouseInput(glutin::ElementState::Pressed, button)) =>
                Some(Input::Press(Button::Mouse(map_mouse(button)))),
            Some(E::MouseInput(glutin::ElementState::Released, button)) =>
                Some(Input::Release(Button::Mouse(map_mouse(button)))),
            _ => None,
        }
    }

    /*
    fn capture_cursor(&mut self, enabled: bool) {

    }
    */
}

quack! {
obj: GlutinWindow[]
get:
    fn () -> Size [] {
        if let Some((w, h)) = obj.window.get_outer_size() {
            Size([w, h])
        } else {
            Size([0, 0])
        }
    }
    fn () -> ShouldClose [] { ShouldClose(obj.window.should_close() || obj.should_close) }
    fn () -> DrawSize [] {
        if let Some((w, h)) = obj.window.get_inner_size() {
            DrawSize([w, h])
        } else {
            DrawSize([0, 0])
        }
    }
    fn () -> Title [] { Title(obj.title.clone()) }
    fn () -> ExitOnEsc [] { ExitOnEsc(obj.exit_on_esc) }
set:
    // fn (val: CaptureCursor) [] {}
    // fn (val: ShouldClose) [] {}
    fn (val: Title) [] {
        obj.title = val.0;
        obj.window.set_title(&obj.title);
    }
    fn (val: ExitOnEsc) [] { obj.exit_on_esc = val.0; }
action:
    fn (__: PollEvent) -> Option<Input> [] { obj.poll_event() }
    fn (__: SwapBuffers) -> () [] { obj.window.swap_buffers(); }
}

/// Maps Glutin's key to Piston's key.
pub fn map_key(keycode: glutin::VirtualKeyCode) -> keyboard::Key {
    use input::keyboard::Key;
    use glutin::VirtualKeyCode as K;

    match keycode {
        K::Key0 => Key::D0,
        K::Key1 => Key::D1,
        K::Key2 => Key::D2,
        K::Key3 => Key::D3,
        K::Key4 => Key::D4,
        K::Key5 => Key::D5,
        K::Key6 => Key::D6,
        K::Key7 => Key::D7,
        K::Key8 => Key::D8,
        K::Key9 => Key::D9,
        K::A => Key::A,
        K::B => Key::B,
        K::C => Key::C,
        K::D => Key::D,
        K::E => Key::E,
        K::F => Key::F,
        K::G => Key::G,
        K::H => Key::H,
        K::I => Key::I,
        K::J => Key::J,
        K::K => Key::K,
        K::L => Key::L,
        K::M => Key::M,
        K::N => Key::N,
        K::O => Key::O,
        K::P => Key::P,
        K::Q => Key::Q,
        K::R => Key::R,
        K::S => Key::S,
        K::T => Key::T,
        K::U => Key::U,
        K::V => Key::V,
        K::W => Key::W,
        K::X => Key::X,
        K::Y => Key::Y,
        K::Z => Key::Z,
        K::Apostrophe => Key::Unknown,
        K::Backslash => Key::Backslash,
        K::Back => Key::Backspace,
        // K::CapsLock => Key::CapsLock,
        K::Delete => Key::Delete,
        K::Comma => Key::Comma,
        K::Down => Key::Down,
        K::End => Key::End,
        K::Return => Key::Return,
        K::Equals => Key::Equals,
        K::Escape => Key::Escape,
        K::F1 => Key::F1,
        K::F2 => Key::F2,
        K::F3 => Key::F3,
        K::F4 => Key::F4,
        K::F5 => Key::F5,
        K::F6 => Key::F6,
        K::F7 => Key::F7,
        K::F8 => Key::F8,
        K::F9 => Key::F9,
        K::F10 => Key::F10,
        K::F11 => Key::F11,
        K::F12 => Key::F12,
        K::F13 => Key::F13,
        K::F14 => Key::F14,
        K::F15 => Key::F15,
        // K::F16 => Key::F16,
        // K::F17 => Key::F17,
        // K::F18 => Key::F18,
        // K::F19 => Key::F19,
        // K::F20 => Key::F20,
        // K::F21 => Key::F21,
        // K::F22 => Key::F22,
        // K::F23 => Key::F23,
        // K::F24 => Key::F24,
        // Possibly next code.
        // K::F25 => Key::Unknown,
        K::Numpad0 => Key::NumPad0,
        K::Numpad1 => Key::NumPad1,
        K::Numpad2 => Key::NumPad2,
        K::Numpad3 => Key::NumPad3,
        K::Numpad4 => Key::NumPad4,
        K::Numpad5 => Key::NumPad5,
        K::Numpad6 => Key::NumPad6,
        K::Numpad7 => Key::NumPad7,
        K::Numpad8 => Key::NumPad8,
        K::Numpad9 => Key::NumPad9,
        K::NumpadComma => Key::NumPadDecimal,
        K::Divide => Key::NumPadDivide,
        K::Multiply => Key::NumPadMultiply,
        K::Subtract => Key::NumPadMinus,
        K::Add => Key::NumPadPlus,
        K::NumpadEnter => Key::NumPadEnter,
        K::NumpadEquals => Key::NumPadEquals,
        K::LShift => Key::LShift,
        K::LControl => Key::LCtrl,
        K::LAlt => Key::LAlt,
        K::LMenu => Key::LGui,
        K::RShift => Key::RShift,
        K::RControl => Key::RCtrl,
        K::RAlt => Key::RAlt,
        K::RMenu => Key::RGui,
        // Map to backslash?
        // K::GraveAccent => Key::Unknown,
        K::Home => Key::Home,
        K::Insert => Key::Insert,
        K::Left => Key::Left,
        K::LBracket => Key::LeftBracket,
        // K::Menu => Key::Menu,
        K::Minus => Key::Minus,
        K::Numlock => Key::NumLockClear,
        K::PageDown => Key::PageDown,
        K::PageUp => Key::PageUp,
        K::Pause => Key::Pause,
        K::Period => Key::Period,
        // K::PrintScreen => Key::PrintScreen,
        K::Right => Key::Right,
        K::RBracket => Key::RightBracket,
        // K::ScrollLock => Key::ScrollLock,
        K::Semicolon => Key::Semicolon,
        K::Slash => Key::Slash,
        K::Space => Key::Space,
        K::Tab => Key::Tab,
        K::Up => Key::Up,
        // K::World1 => Key::Unknown,
        // K::World2 => Key::Unknown,
        _ => Key::Unknown,
    }
}

/// Maps Glutin's mouse button to Piston's mouse button.
pub fn map_mouse(mouse_button: glutin::MouseButton) -> MouseButton {
    use glutin::MouseButton as M;

    match mouse_button {
        M::Left => MouseButton::Left,
        M::Right => MouseButton::Right,
        M::Middle => MouseButton::Middle,
        M::Other(0) => MouseButton::X1,
        M::Other(1) => MouseButton::X2,
        M::Other(2) => MouseButton::Button6,
        M::Other(3) => MouseButton::Button7,
        M::Other(4) => MouseButton::Button8,
        _ => MouseButton::Unknown
    }
}
<|endoftext|>


<commit_before>#[derive(Debug,PartialEq)]
pub enum Token {
    Number(String),
    // String(String),
    // Name(String),
    SomethingElse,
    ParenOpening,
    ParenClosing,
}

pub fn tokenizer(input: &str) -> Vec<Token> {
    let mut tokens: Vec<Token> = vec![];

    let mut char_iter = input.chars().peekable();
    while let Some(mut c) = char_iter.next() {
        match c {
            c if c.is_whitespace() => (),
            '(' => tokens.push(Token::ParenOpening),
            ')' => tokens.push(Token::ParenClosing),
            '0'...'9' => {
                let mut value = String::new();
                value.push(c);

                while match char_iter.peek() {
                    Some(&'0'...'9') => true,
                    _ => false,
                } {
                    value.push(c);
                    match char_iter.next() {
                        Some(v) => c = v,
                        None => break,
                    }
                }
                tokens.push(Token::Number(value));
            }
            _ => tokens.push(Token::SomethingElse),
        }
    }

    tokens
}
<commit_msg>small enhancement<commit_after>#[derive(Debug,PartialEq)]
pub enum Token {
    Number(String),
    // String(String),
    // Name(String),
    SomethingElse,
    ParenOpening,
    ParenClosing,
}

pub fn tokenizer(input: &str) -> Vec<Token> {
    let mut tokens: Vec<Token> = vec![];

    let mut char_iter = input.chars().peekable();
    while let Some(mut c) = char_iter.next() {
        match c {
            c if c.is_whitespace() => (),
            '(' => tokens.push(Token::ParenOpening),
            ')' => tokens.push(Token::ParenClosing),
            '0'...'9' => {
                let mut value = String::new();
                value.push(c);

                while match char_iter.peek() {
                    Some(&'0'...'9') => true,
                    _ => false,
                } {
                    value.push(c);
                    c = match char_iter.next() {
                        Some(c) => c,
                        None => break,
                    }
                }
                tokens.push(Token::Number(value));
            }
            _ => tokens.push(Token::SomethingElse),
        }
    }

    tokens
}
<|endoftext|>