<commit_before>use std::path::PathBuf;
use std::process::Command;
use std::env;
use std::io::stderr;
use std::io::Write;

pub use clap::App;

use clap::{Arg, ArgMatches};
use log;
use log::LogLevelFilter;

use configuration::Configuration;
use error::RuntimeError;
use error::RuntimeErrorKind;
use error::MapErrInto;
use logger::ImagLogger;

use libimagstore::store::Store;

#[derive(Debug)]
pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Option<Configuration>,
    cli_matches: ArgMatches<'a>,
    store: Store,
}

impl<'a> Runtime<'a> {

    /**
     * Gets the CLI spec for the program and retreives the config file path (or uses the default on
     * in $HOME/.imag/config, $XDG_CONFIG_DIR/imag/config or from env("$IMAG_CONFIG")
     * and builds the Runtime object with it.
     *
     * The cli_spec object should be initially build with the ::get_default_cli_builder() function.
     *
     */
    pub fn new(cli_spec: App<'a, 'a>) -> Result<Runtime<'a>, RuntimeError> {
        use std::env;

        use libimagstore::hook::position::HookPosition as HP;
        use libimagstore::hook::Hook;
        use libimagstore::error::StoreErrorKind;
        use libimagstorestdhook::debug::DebugHook;
        use libimagstorestdhook::vcs::git::delete::DeleteHook as GitDeleteHook;
        use libimagstorestdhook::vcs::git::update::UpdateHook as GitUpdateHook;
        use libimagerror::trace::trace_error;
        use libimagerror::trace::trace_error_dbg;
        use libimagerror::into::IntoError;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();

        let is_debugging = matches.is_present("debugging");
        let is_verbose   = matches.is_present("verbosity");
        let colored      = !matches.is_present("no-color-output");

        Runtime::init_logger(is_debugging, is_verbose, colored);

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map_or_else(|| {
                env::var("HOME")
                    .map(PathBuf::from)
                    .map(|mut p| { p.push(".imag"); p})
                    .unwrap_or_else(|_| {
                        panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
                    })
            }, PathBuf::from);
        let storepath = matches.value_of("storepath")
                                .map_or_else(|| {
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                }, PathBuf::from);

        let configpath = matches.value_of("config")
                                .map_or_else(|| rtp.clone(), PathBuf::from);

        let cfg = match Configuration::new(&configpath) {
            Err(e) => if e.err_type() != ConfigErrorKind::NoConfigFileFound {
                return Err(RuntimeErrorKind::Instantiate.into_error_with_cause(Box::new(e)));
            } else {
                warn!("No config file found.");
                warn!("Continuing without configuration file");
                None
            },

            Ok(mut cfg) => {
                if let Err(e) = cfg.override_config(get_override_specs(&matches)) {
                    error!("Could not apply config overrides");
                    trace_error(&e);

                    // TODO: continue question (interactive)
                }

                Some(cfg)
            }
        };

        let store_config = match cfg {
            Some(ref c) => c.store_config().cloned(),
            None        => None,
        };

        if is_debugging {
            write!(stderr(), "Config: {:?}\n", cfg).ok();
            write!(stderr(), "Store-config: {:?}\n", store_config).ok();
        }

        Store::new(storepath.clone(), store_config).map(|mut store| {
            // If we are debugging, generate hooks for all positions
            if is_debugging {
                let hooks : Vec<(Box<Hook>, &str, HP)> = vec![
                    (Box::new(DebugHook::new(HP::PreCreate))          , "debug", HP::PreCreate),
                    (Box::new(DebugHook::new(HP::PostCreate))         , "debug", HP::PostCreate),
                    (Box::new(DebugHook::new(HP::PreRetrieve))        , "debug", HP::PreRetrieve),
                    (Box::new(DebugHook::new(HP::PostRetrieve))       , "debug", HP::PostRetrieve),
                    (Box::new(DebugHook::new(HP::PreUpdate))          , "debug", HP::PreUpdate),
                    (Box::new(DebugHook::new(HP::PostUpdate))         , "debug", HP::PostUpdate),
                    (Box::new(DebugHook::new(HP::PreDelete))          , "debug", HP::PreDelete),
                    (Box::new(DebugHook::new(HP::PostDelete))         , "debug", HP::PostDelete),
                ];

                // If hook registration fails, trace the error and warn, but continue.
                for (hook, aspectname, position) in hooks {
                    if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) {
                        if e.err_type() == StoreErrorKind::HookRegisterError {
                            trace_error_dbg(&e);
                            warn!("Registering debug hook with store failed");
                        } else {
                            trace_error(&e);
                        };
                    }
                }
            }

            let sp = storepath;

            let hooks : Vec<(Box<Hook>, &str, HP)> = vec![
                (Box::new(GitDeleteHook::new(sp.clone(), HP::PreDelete))     , "vcs", HP::PreDelete),
                (Box::new(GitUpdateHook::new(sp, HP::PostUpdate))    , "vcs", HP::PostUpdate),
            ];

            for (hook, aspectname, position) in hooks {
                if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) {
                    if e.err_type() == StoreErrorKind::HookRegisterError {
                        trace_error_dbg(&e);
                        warn!("Registering debug hook with store failed");
                    } else {
                        trace_error(&e);
                    };
                }
            }

            Runtime {
                cli_matches: matches,
                configuration: cfg,
                rtp: rtp,
                store: store,
            }
        })
        .map_err_into(RuntimeErrorKind::Instantiate)
    }

    /**
     * Get a commandline-interface builder object from `clap`
     *
     * This commandline interface builder object already contains some predefined interface flags:
     *   * -v | --verbose for verbosity
     *   * --debug for debugging
     *   * -c <file> | --config <file> for alternative configuration file
     *   * -r <path> | --rtp <path> for alternative runtimepath
     *   * --store <path> for alternative store path
     * Each has the appropriate help text included.
     *
     * The `appname` shall be "imag-<command>".
     */
    pub fn get_default_cli_builder(appname: &'a str,
                                   version: &'a str,
                                   about: &'a str)
        -> App<'a, 'a>
    {
        App::new(appname)
            .version(version)
            .author("Matthias Beyer <mail@beyermatthias.de>")
            .about(about)
            .arg(Arg::with_name(Runtime::arg_verbosity_name())
                .short("v")
                .long("verbose")
                .help("Enables verbosity")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_debugging_name())
                .long("debug")
                .help("Enables debugging output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_no_color_output_name())
                .long("no-color")
                .help("Disable color output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_config_name())
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_config_override_name())
                 .long("override-config")
                 .help("Override a configuration settings. Use 'key=value' pairs, where the key is a path in the TOML configuration. The value must be present in the configuration and be convertible to the type of the configuration setting. If the argument does not contain a '=', it gets ignored. Setting Arrays and Tables is not yet supported.")
                 .required(false)
                 .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_runtimepath_name())
                .long("rtp")
                .help("Alternative runtimepath")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_storepath_name())
                .long("store")
                .help("Alternative storepath. Must be specified as full path, can be outside of the RTP")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_editor_name())
                .long("editor")
                .help("Set editor")
                .required(false)
                .takes_value(true))
    }

    pub fn arg_names() -> Vec<&'static str> {
        vec![
            Runtime::arg_verbosity_name(),
            Runtime::arg_debugging_name(),
            Runtime::arg_no_color_output_name(),
            Runtime::arg_config_name(),
            Runtime::arg_config_override_name(),
            Runtime::arg_runtimepath_name(),
            Runtime::arg_storepath_name(),
            Runtime::arg_editor_name(),
        ]
    }

    pub fn arg_verbosity_name() -> &'static str {
        "verbosity"
    }

    pub fn arg_debugging_name() -> &'static str {
        "debugging"
    }

    pub fn arg_no_color_output_name() -> &'static str {
        "no-color-output"
    }

    pub fn arg_config_name() -> &'static str {
        "config"
    }

    pub fn arg_config_override_name() -> &'static str {
        "config-override"
    }

    pub fn arg_runtimepath_name() -> &'static str {
        "runtimepath"
    }

    pub fn arg_storepath_name() -> &'static str {
        "storepath"
    }

    pub fn arg_editor_name() -> &'static str {
        "editor"
    }

    /**
     * Initialize the internal logger
     */
    fn init_logger(is_debugging: bool, is_verbose: bool, colored: bool) {
        use std::env::var as env_var;
        use env_logger;

        if env_var("IMAG_LOG_ENV").is_ok() {
            env_logger::init().unwrap();
        } else {
            let lvl = if is_debugging {
                LogLevelFilter::Debug
            } else if is_verbose {
                LogLevelFilter::Info
            } else {
                LogLevelFilter::Warn
            };

            log::set_logger(|max_log_lvl| {
                max_log_lvl.set(lvl);
                debug!("Init logger with {}", lvl);
                Box::new(ImagLogger::new(lvl.to_log_level().unwrap()).with_color(colored))
            })
            .map_err(|_| {
                panic!("Could not setup logger");
            })
            .ok();
        }
    }

    /**
     * Get the verbosity flag value
     */
    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbosity")
    }

    /**
     * Get the debugging flag value
     */
    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debugging")
    }

    /**
     * Get the runtimepath
     */
    pub fn rtp(&self) -> &PathBuf {
        &self.rtp
    }

    /**
     * Get the commandline interface matches
     */
    pub fn cli(&self) -> &ArgMatches {
        &self.cli_matches
    }

    /**
     * Get the configuration object
     */
    pub fn config(&self) -> Option<&Configuration> {
        self.configuration.as_ref()
    }

    /**
     * Get the store object
     */
    pub fn store(&self) -> &Store {
        &self.store
    }

    pub fn editor(&self) -> Option<Command> {
        self.cli()
            .value_of("editor")
            .map(String::from)
            .or({
                match self.configuration {
                    Some(ref c) => c.editor().cloned(),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

fn get_override_specs(matches: &ArgMatches) -> Vec<String> {
    matches
        .values_of("config-override")
        .map(|values| {
             values
             .filter(|s| {
                 let b = s.contains("=");
                 if !b { warn!("override '{}' does not contain '=' - will be ignored!", s); }
                 b
             })
             .map(String::from)
             .collect()
        })
        .unwrap_or(vec![])
}

<commit_msg>DeleteHook should be executed after the delete action<commit_after>use std::path::PathBuf;
use std::process::Command;
use std::env;
use std::io::stderr;
use std::io::Write;

pub use clap::App;

use clap::{Arg, ArgMatches};
use log;
use log::LogLevelFilter;

use configuration::Configuration;
use error::RuntimeError;
use error::RuntimeErrorKind;
use error::MapErrInto;
use logger::ImagLogger;

use libimagstore::store::Store;

#[derive(Debug)]
pub struct Runtime<'a> {
    rtp: PathBuf,
    configuration: Option<Configuration>,
    cli_matches: ArgMatches<'a>,
    store: Store,
}

impl<'a> Runtime<'a> {

    /**
     * Gets the CLI spec for the program and retreives the config file path (or uses the default on
     * in $HOME/.imag/config, $XDG_CONFIG_DIR/imag/config or from env("$IMAG_CONFIG")
     * and builds the Runtime object with it.
     *
     * The cli_spec object should be initially build with the ::get_default_cli_builder() function.
     *
     */
    pub fn new(cli_spec: App<'a, 'a>) -> Result<Runtime<'a>, RuntimeError> {
        use std::env;

        use libimagstore::hook::position::HookPosition as HP;
        use libimagstore::hook::Hook;
        use libimagstore::error::StoreErrorKind;
        use libimagstorestdhook::debug::DebugHook;
        use libimagstorestdhook::vcs::git::delete::DeleteHook as GitDeleteHook;
        use libimagstorestdhook::vcs::git::update::UpdateHook as GitUpdateHook;
        use libimagerror::trace::trace_error;
        use libimagerror::trace::trace_error_dbg;
        use libimagerror::into::IntoError;

        use configuration::error::ConfigErrorKind;

        let matches = cli_spec.get_matches();

        let is_debugging = matches.is_present("debugging");
        let is_verbose   = matches.is_present("verbosity");
        let colored      = !matches.is_present("no-color-output");

        Runtime::init_logger(is_debugging, is_verbose, colored);

        let rtp : PathBuf = matches.value_of("runtimepath")
            .map_or_else(|| {
                env::var("HOME")
                    .map(PathBuf::from)
                    .map(|mut p| { p.push(".imag"); p})
                    .unwrap_or_else(|_| {
                        panic!("You seem to be $HOME-less. Please get a $HOME before using this software. We are sorry for you and hope you have some accommodation anyways.");
                    })
            }, PathBuf::from);
        let storepath = matches.value_of("storepath")
                                .map_or_else(|| {
                                    let mut spath = rtp.clone();
                                    spath.push("store");
                                    spath
                                }, PathBuf::from);

        let configpath = matches.value_of("config")
                                .map_or_else(|| rtp.clone(), PathBuf::from);

        let cfg = match Configuration::new(&configpath) {
            Err(e) => if e.err_type() != ConfigErrorKind::NoConfigFileFound {
                return Err(RuntimeErrorKind::Instantiate.into_error_with_cause(Box::new(e)));
            } else {
                warn!("No config file found.");
                warn!("Continuing without configuration file");
                None
            },

            Ok(mut cfg) => {
                if let Err(e) = cfg.override_config(get_override_specs(&matches)) {
                    error!("Could not apply config overrides");
                    trace_error(&e);

                    // TODO: continue question (interactive)
                }

                Some(cfg)
            }
        };

        let store_config = match cfg {
            Some(ref c) => c.store_config().cloned(),
            None        => None,
        };

        if is_debugging {
            write!(stderr(), "Config: {:?}\n", cfg).ok();
            write!(stderr(), "Store-config: {:?}\n", store_config).ok();
        }

        Store::new(storepath.clone(), store_config).map(|mut store| {
            // If we are debugging, generate hooks for all positions
            if is_debugging {
                let hooks : Vec<(Box<Hook>, &str, HP)> = vec![
                    (Box::new(DebugHook::new(HP::PreCreate))          , "debug", HP::PreCreate),
                    (Box::new(DebugHook::new(HP::PostCreate))         , "debug", HP::PostCreate),
                    (Box::new(DebugHook::new(HP::PreRetrieve))        , "debug", HP::PreRetrieve),
                    (Box::new(DebugHook::new(HP::PostRetrieve))       , "debug", HP::PostRetrieve),
                    (Box::new(DebugHook::new(HP::PreUpdate))          , "debug", HP::PreUpdate),
                    (Box::new(DebugHook::new(HP::PostUpdate))         , "debug", HP::PostUpdate),
                    (Box::new(DebugHook::new(HP::PreDelete))          , "debug", HP::PreDelete),
                    (Box::new(DebugHook::new(HP::PostDelete))         , "debug", HP::PostDelete),
                ];

                // If hook registration fails, trace the error and warn, but continue.
                for (hook, aspectname, position) in hooks {
                    if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) {
                        if e.err_type() == StoreErrorKind::HookRegisterError {
                            trace_error_dbg(&e);
                            warn!("Registering debug hook with store failed");
                        } else {
                            trace_error(&e);
                        };
                    }
                }
            }

            let sp = storepath;

            let hooks : Vec<(Box<Hook>, &str, HP)> = vec![
                (Box::new(GitDeleteHook::new(sp.clone(), HP::PostDelete))     , "vcs", HP::PostDelete),
                (Box::new(GitUpdateHook::new(sp, HP::PostUpdate))    , "vcs", HP::PostUpdate),
            ];

            for (hook, aspectname, position) in hooks {
                if let Err(e) = store.register_hook(position, &String::from(aspectname), hook) {
                    if e.err_type() == StoreErrorKind::HookRegisterError {
                        trace_error_dbg(&e);
                        warn!("Registering debug hook with store failed");
                    } else {
                        trace_error(&e);
                    };
                }
            }

            Runtime {
                cli_matches: matches,
                configuration: cfg,
                rtp: rtp,
                store: store,
            }
        })
        .map_err_into(RuntimeErrorKind::Instantiate)
    }

    /**
     * Get a commandline-interface builder object from `clap`
     *
     * This commandline interface builder object already contains some predefined interface flags:
     *   * -v | --verbose for verbosity
     *   * --debug for debugging
     *   * -c <file> | --config <file> for alternative configuration file
     *   * -r <path> | --rtp <path> for alternative runtimepath
     *   * --store <path> for alternative store path
     * Each has the appropriate help text included.
     *
     * The `appname` shall be "imag-<command>".
     */
    pub fn get_default_cli_builder(appname: &'a str,
                                   version: &'a str,
                                   about: &'a str)
        -> App<'a, 'a>
    {
        App::new(appname)
            .version(version)
            .author("Matthias Beyer <mail@beyermatthias.de>")
            .about(about)
            .arg(Arg::with_name(Runtime::arg_verbosity_name())
                .short("v")
                .long("verbose")
                .help("Enables verbosity")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_debugging_name())
                .long("debug")
                .help("Enables debugging output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_no_color_output_name())
                .long("no-color")
                .help("Disable color output")
                .required(false)
                .takes_value(false))

            .arg(Arg::with_name(Runtime::arg_config_name())
                .long("config")
                .help("Path to alternative config file")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_config_override_name())
                 .long("override-config")
                 .help("Override a configuration settings. Use 'key=value' pairs, where the key is a path in the TOML configuration. The value must be present in the configuration and be convertible to the type of the configuration setting. If the argument does not contain a '=', it gets ignored. Setting Arrays and Tables is not yet supported.")
                 .required(false)
                 .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_runtimepath_name())
                .long("rtp")
                .help("Alternative runtimepath")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_storepath_name())
                .long("store")
                .help("Alternative storepath. Must be specified as full path, can be outside of the RTP")
                .required(false)
                .takes_value(true))

            .arg(Arg::with_name(Runtime::arg_editor_name())
                .long("editor")
                .help("Set editor")
                .required(false)
                .takes_value(true))
    }

    pub fn arg_names() -> Vec<&'static str> {
        vec![
            Runtime::arg_verbosity_name(),
            Runtime::arg_debugging_name(),
            Runtime::arg_no_color_output_name(),
            Runtime::arg_config_name(),
            Runtime::arg_config_override_name(),
            Runtime::arg_runtimepath_name(),
            Runtime::arg_storepath_name(),
            Runtime::arg_editor_name(),
        ]
    }

    pub fn arg_verbosity_name() -> &'static str {
        "verbosity"
    }

    pub fn arg_debugging_name() -> &'static str {
        "debugging"
    }

    pub fn arg_no_color_output_name() -> &'static str {
        "no-color-output"
    }

    pub fn arg_config_name() -> &'static str {
        "config"
    }

    pub fn arg_config_override_name() -> &'static str {
        "config-override"
    }

    pub fn arg_runtimepath_name() -> &'static str {
        "runtimepath"
    }

    pub fn arg_storepath_name() -> &'static str {
        "storepath"
    }

    pub fn arg_editor_name() -> &'static str {
        "editor"
    }

    /**
     * Initialize the internal logger
     */
    fn init_logger(is_debugging: bool, is_verbose: bool, colored: bool) {
        use std::env::var as env_var;
        use env_logger;

        if env_var("IMAG_LOG_ENV").is_ok() {
            env_logger::init().unwrap();
        } else {
            let lvl = if is_debugging {
                LogLevelFilter::Debug
            } else if is_verbose {
                LogLevelFilter::Info
            } else {
                LogLevelFilter::Warn
            };

            log::set_logger(|max_log_lvl| {
                max_log_lvl.set(lvl);
                debug!("Init logger with {}", lvl);
                Box::new(ImagLogger::new(lvl.to_log_level().unwrap()).with_color(colored))
            })
            .map_err(|_| {
                panic!("Could not setup logger");
            })
            .ok();
        }
    }

    /**
     * Get the verbosity flag value
     */
    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbosity")
    }

    /**
     * Get the debugging flag value
     */
    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debugging")
    }

    /**
     * Get the runtimepath
     */
    pub fn rtp(&self) -> &PathBuf {
        &self.rtp
    }

    /**
     * Get the commandline interface matches
     */
    pub fn cli(&self) -> &ArgMatches {
        &self.cli_matches
    }

    /**
     * Get the configuration object
     */
    pub fn config(&self) -> Option<&Configuration> {
        self.configuration.as_ref()
    }

    /**
     * Get the store object
     */
    pub fn store(&self) -> &Store {
        &self.store
    }

    pub fn editor(&self) -> Option<Command> {
        self.cli()
            .value_of("editor")
            .map(String::from)
            .or({
                match self.configuration {
                    Some(ref c) => c.editor().cloned(),
                    _ => None,
                }
            })
            .or(env::var("EDITOR").ok())
            .map(Command::new)
    }
}

fn get_override_specs(matches: &ArgMatches) -> Vec<String> {
    matches
        .values_of("config-override")
        .map(|values| {
             values
             .filter(|s| {
                 let b = s.contains("=");
                 if !b { warn!("override '{}' does not contain '=' - will be ignored!", s); }
                 b
             })
             .map(String::from)
             .collect()
        })
        .unwrap_or(vec![])
}

<|endoftext|>


<commit_before><commit_msg>Use Command::spawn() instead of exec() on Windows<commit_after><|endoftext|>


<commit_before><commit_msg>Set the step pin to low after a step<commit_after><|endoftext|>


<commit_before><commit_msg>Added `remove_item` to `Store`<commit_after><|endoftext|>


<commit_before><commit_msg>use aliases for users.report request<commit_after><|endoftext|>


<commit_before><commit_msg>run all samples through the parser and look for no errors<commit_after>extern crate warbot;

use std::fs::File;
use std::io::Read;
use std::path::Path;

include!(concat!(env!("OUT_DIR"), "/tests.rs"));

fn run_file(name: &str) {
    let mut file_path = Path::new("tests/fodder").join(name);
    file_path.set_extension("txt");

    let mut file = match File::open(&file_path) {
        Err(e) => {
            println!("Couldn't open {}: {}", file_path.display(), e);
            panic!(e);
        },
        Ok(f) => f
    };

    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    for raw_line in contents.split('\n') {
        let line = raw_line.trim().to_owned();
        if line.len() == 0 {
            continue;
        }
        if line.starts_with("Output") {
            continue;
        }
        if line.starts_with("Round") {
            continue;
        }
        if line.starts_with("#") {
            continue;
        }
        match warbot::parser::parse(line) {
            Ok(_) => {},
            Err(e) => panic!("{:?}", e)
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>chore(doctests): remove unnecessary `rust` marker<commit_after><|endoftext|>


<commit_before><commit_msg>tests: Unit test Kind::from_bytes<commit_after><|endoftext|>


<commit_before><commit_msg>html_root_url.<commit_after><|endoftext|>


<commit_before><commit_msg>Implement Cursor's next method<commit_after><|endoftext|>


<commit_before><commit_msg>clean old movie pictures<commit_after><|endoftext|>


<commit_before><commit_msg>git work<commit_after><|endoftext|>


<commit_before>#![crate_id = "piston"]
#![deny(missing_doc)]
#![deny(dead_code)]
#![feature(globs)]
#![feature(macro_rules)]
#![feature(phase)]

//! A user friendly graphics engine.

extern crate time;
extern crate graphics;
extern crate log;
extern crate collections;
extern crate gl;
extern crate glfw;
extern crate sdl2;
extern crate sdl2_mixer;
extern crate image;
extern crate libc;
extern crate debug;

pub use Game = game::Game;

pub use Render = game_iterator::Render;
pub use Update = game_iterator::Update;
pub use KeyPress = game_iterator::KeyPress;
pub use KeyRelease = game_iterator::KeyRelease;
pub use MousePress = game_iterator::MousePress;
pub use MouseRelease = game_iterator::MouseRelease;
pub use MouseMove = game_iterator::MouseMove;
pub use MouseRelativeMove = game_iterator::MouseRelativeMove;

pub use GameEvent = game_iterator::GameEvent;
pub use GameIterator = game_iterator::GameIterator;
pub use GameIteratorSettings = game_iterator::GameIteratorSettings;
pub use RenderArgs = game_iterator::RenderArgs;
pub use UpdateArgs = game_iterator::UpdateArgs;
pub use KeyPressArgs = game_iterator::KeyPressArgs;
pub use KeyReleaseArgs = game_iterator::KeyReleaseArgs;
pub use MousePressArgs = game_iterator::MousePressArgs;
pub use MouseReleaseArgs = game_iterator::MouseReleaseArgs;
pub use MouseMoveArgs = game_iterator::MouseMoveArgs;
pub use MouseRelativeMoveArgs = game_iterator::MouseRelativeMoveArgs;

pub use GameWindow = game_window::GameWindow;
pub use GameWindowSDL2 = game_window_sdl2::GameWindowSDL2;
pub use GameWindowGLFW = game_window_glfw::GameWindowGLFW;
pub use GameWindowSettings = game_window_settings::GameWindowSettings;
pub use Gl = gl_back_end::Gl;
pub use AssetStore = asset_store::AssetStore;
pub use Texture = texture::Texture;

pub use Music = music::Music;
pub use Sound = sound::Sound;
pub use AudioBackEnd = audio_back_end::AudioBackEnd;
pub use AudioSDL2 = sdl2_audio_back_end::AudioSDL2;
pub use MusicSDL2 = sdl2_audio_back_end::MusicSDL2;
pub use SoundSDL2 = sdl2_audio_back_end::SoundSDL2;

pub mod shader_utils;
pub mod game_window;
pub mod keyboard;
pub mod event;
pub mod mouse;

mod game;
mod game_iterator;
mod game_window_sdl2;
mod game_window_glfw;
mod game_window_settings;
mod gl_back_end;
mod asset_store;
mod texture;

mod music;
mod sound;
mod audio_back_end;
mod sdl2_audio_back_end;<commit_msg>Replaced `#[deny(dead_code)]` with `#[warn(dead_code)]`<commit_after>#![crate_id = "piston"]
#![deny(missing_doc)]
#![warn(dead_code)]
#![feature(globs)]
#![feature(macro_rules)]
#![feature(phase)]

//! A user friendly graphics engine.

extern crate time;
extern crate graphics;
extern crate log;
extern crate collections;
extern crate gl;
extern crate glfw;
extern crate sdl2;
extern crate sdl2_mixer;
extern crate image;
extern crate libc;
extern crate debug;

pub use Game = game::Game;

pub use Render = game_iterator::Render;
pub use Update = game_iterator::Update;
pub use KeyPress = game_iterator::KeyPress;
pub use KeyRelease = game_iterator::KeyRelease;
pub use MousePress = game_iterator::MousePress;
pub use MouseRelease = game_iterator::MouseRelease;
pub use MouseMove = game_iterator::MouseMove;
pub use MouseRelativeMove = game_iterator::MouseRelativeMove;

pub use GameEvent = game_iterator::GameEvent;
pub use GameIterator = game_iterator::GameIterator;
pub use GameIteratorSettings = game_iterator::GameIteratorSettings;
pub use RenderArgs = game_iterator::RenderArgs;
pub use UpdateArgs = game_iterator::UpdateArgs;
pub use KeyPressArgs = game_iterator::KeyPressArgs;
pub use KeyReleaseArgs = game_iterator::KeyReleaseArgs;
pub use MousePressArgs = game_iterator::MousePressArgs;
pub use MouseReleaseArgs = game_iterator::MouseReleaseArgs;
pub use MouseMoveArgs = game_iterator::MouseMoveArgs;
pub use MouseRelativeMoveArgs = game_iterator::MouseRelativeMoveArgs;

pub use GameWindow = game_window::GameWindow;
pub use GameWindowSDL2 = game_window_sdl2::GameWindowSDL2;
pub use GameWindowGLFW = game_window_glfw::GameWindowGLFW;
pub use GameWindowSettings = game_window_settings::GameWindowSettings;
pub use Gl = gl_back_end::Gl;
pub use AssetStore = asset_store::AssetStore;
pub use Texture = texture::Texture;

pub use Music = music::Music;
pub use Sound = sound::Sound;
pub use AudioBackEnd = audio_back_end::AudioBackEnd;
pub use AudioSDL2 = sdl2_audio_back_end::AudioSDL2;
pub use MusicSDL2 = sdl2_audio_back_end::MusicSDL2;
pub use SoundSDL2 = sdl2_audio_back_end::SoundSDL2;

pub mod shader_utils;
pub mod game_window;
pub mod keyboard;
pub mod event;
pub mod mouse;

mod game;
mod game_iterator;
mod game_window_sdl2;
mod game_window_glfw;
mod game_window_settings;
mod gl_back_end;
mod asset_store;
mod texture;

mod music;
mod sound;
mod audio_back_end;
mod sdl2_audio_back_end;
<|endoftext|>


<commit_before><commit_msg>Update to the last rust-nightly.<commit_after><|endoftext|>


<commit_before>#![feature(macro_rules)]

use std::cmp::Ordering::{Greater, Equal, Less};

pub struct Slide<T: Iterator<Item=A>, A> {
  iter: T,
  n: usize,
  window: Vec
}

macro_rules! return_if(
  ($cond:expr, $value:expr) => (
    if $cond {
      return $value;
    }
  );
);

impl<A: Clone, T: Iterator<Item=A>> Slide<T, A> {
  fn push_window(&mut self) -> bool {
    let iter_next = self.iter.next();
    let is_some = iter_next.is_some();

    if is_some {
      self.window.push(iter_next.unwrap());
    }

    is_some
  }

  fn new(iter: T, n: usize) -> Slide<T, A> {
    Slide{
      iter: iter,
      n: n,
      window: Vec::with_capacity(n + 1)
    }
  }
}

impl<A: Clone, T: Iterator<Item=A>> Iterator for Slide<T, A> {
  type Item = Vec;

  fn next(&mut self) -> Option<Vec> {
    return_if!(self.n == 0, None);
    return_if!(!self.push_window(), None);

    loop {
      let window_status = self.window.len().cmp(&self.n);

      match window_status {
        Greater => { self.window.remove(0); }
        Equal => { return Some(self.window.clone()); }
        Less => { return_if!(!self.push_window(), None); }
      }
    }
  }
}

pub trait SlideIterator<T: Iterator<Item=A>, A> {
  fn slide(self, n: usize) -> Slide<T, A>;
}

impl<A: Clone, T: Iterator<Item=A>> SlideIterator<T, A> for T {
  fn slide(self, n: usize) -> Slide<T, A> {
    Slide::new(self, n)
  }
}

#[test]
fn test_slide() {
  let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(3);
  assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3]);
  assert_eq!(slide_iter.next().unwrap(), vec![2, 3, 4]);
  assert_eq!(slide_iter.next().unwrap(), vec![3, 4, 5]);
  assert!(slide_iter.next().is_none());
}

#[test]
fn test_slide_equal_window() {
  let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(5);
  assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3, 4, 5]);
  assert!(slide_iter.next().is_none());
}

#[test]
fn test_slide_zero_window() {
  let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(0);
  assert!(slide_iter.next().is_none());
}

#[test]
fn test_slide_overlong_window() {
  let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(7);
  assert!(slide_iter.next().is_none());
}
<commit_msg>Remove #![feature(macro_rules)] annotation<commit_after>use std::cmp::Ordering::{Greater, Equal, Less};

pub struct Slide<T: Iterator<Item=A>, A> {
  iter: T,
  n: usize,
  window: Vec
}

macro_rules! return_if(
  ($cond:expr, $value:expr) => (
    if $cond {
      return $value;
    }
  );
);

impl<A: Clone, T: Iterator<Item=A>> Slide<T, A> {
  fn push_window(&mut self) -> bool {
    let iter_next = self.iter.next();
    let is_some = iter_next.is_some();

    if is_some {
      self.window.push(iter_next.unwrap());
    }

    is_some
  }

  fn new(iter: T, n: usize) -> Slide<T, A> {
    Slide{
      iter: iter,
      n: n,
      window: Vec::with_capacity(n + 1)
    }
  }
}

impl<A: Clone, T: Iterator<Item=A>> Iterator for Slide<T, A> {
  type Item = Vec;

  fn next(&mut self) -> Option<Vec> {
    return_if!(self.n == 0, None);
    return_if!(!self.push_window(), None);

    loop {
      let window_status = self.window.len().cmp(&self.n);

      match window_status {
        Greater => { self.window.remove(0); }
        Equal => { return Some(self.window.clone()); }
        Less => { return_if!(!self.push_window(), None); }
      }
    }
  }
}

pub trait SlideIterator<T: Iterator<Item=A>, A> {
  fn slide(self, n: usize) -> Slide<T, A>;
}

impl<A: Clone, T: Iterator<Item=A>> SlideIterator<T, A> for T {
  fn slide(self, n: usize) -> Slide<T, A> {
    Slide::new(self, n)
  }
}

#[test]
fn test_slide() {
  let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(3);
  assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3]);
  assert_eq!(slide_iter.next().unwrap(), vec![2, 3, 4]);
  assert_eq!(slide_iter.next().unwrap(), vec![3, 4, 5]);
  assert!(slide_iter.next().is_none());
}

#[test]
fn test_slide_equal_window() {
  let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(5);
  assert_eq!(slide_iter.next().unwrap(), vec![1, 2, 3, 4, 5]);
  assert!(slide_iter.next().is_none());
}

#[test]
fn test_slide_zero_window() {
  let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(0);
  assert!(slide_iter.next().is_none());
}

#[test]
fn test_slide_overlong_window() {
  let mut slide_iter = vec![1i8, 2, 3, 4, 5].into_iter().slide(7);
  assert!(slide_iter.next().is_none());
}
<|endoftext|>


<commit_before><commit_msg>tests: Unit test Archive::read_entry_metadata_table<commit_after><|endoftext|>


<commit_before>// Copyright 2014-2015 Sam Doshi (sam@metal-fish.co.uk)
// Copyright 2013-2014 Philippe Delrieu (philippe.delrieu@free.fr)
//
// Licensed under the MIT License <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

extern crate libc;

use std::fmt;
use std::ptr;
use libc::c_char;

mod ffi;

// Types
// -----
/// Used by PortMidi to refer to a Midi device
pub type PortMidiDeviceId = i32;
pub type PortMidiResult<T> = Result<T, PortMidiError>;

// Errors
// ------
#[derive(Copy, Debug, PartialEq, Eq)]
pub enum PortMidiError {
    HostError,
    InvalidDeviceId,
    InsufficientMemory,
    BufferTooSmall,
    BufferOverflow,
    BadPtr,
    BadData,
    InternalError,
    BufferMaxSize
}

fn from_pm_error(pm_error: ffi::PmError) -> PortMidiResult<()> {
    match pm_error {
        ffi::PmError::PmNoError => Ok(()),
        ffi::PmError::PmGotData => Ok(()),
        ffi::PmError::PmHostError => Err(PortMidiError::HostError),
        ffi::PmError::PmInvalidDeviceId => Err(PortMidiError::InvalidDeviceId),
        ffi::PmError::PmInsufficientMemory => Err(PortMidiError::InsufficientMemory),
        ffi::PmError::PmBufferTooSmall => Err(PortMidiError::BufferTooSmall),
        ffi::PmError::PmBufferOverflow => Err(PortMidiError::BufferOverflow),
        ffi::PmError::PmBadPtr => Err(PortMidiError::BadPtr),
        ffi::PmError::PmBadData => Err(PortMidiError::BadData),
        ffi::PmError::PmInternalError => Err(PortMidiError::InternalError),
        ffi::PmError::PmBufferMaxSize => Err(PortMidiError::BufferMaxSize),
    }
}

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

// Global fns
// ----------
/// `initialize` initalizes the underlying PortMidi C library, call this
/// before using the library.
///
/// Once initialized, PortMidi will no longer pickup any new Midi devices that are
/// connected, i.e. it does not support hot plugging.
pub fn initialize() -> PortMidiResult<()> {
    from_pm_error(unsafe {
        ffi::Pm_Initialize()
    })
}

/// `terminate` terminates the underlying PortMidi C library, call this
/// after using the library.
pub fn terminate() -> PortMidiResult<()> {
    from_pm_error(unsafe {
        ffi::Pm_Terminate()
    })
}

/// Return the number of devices. This number will not change during the lifetime
/// of the program.
pub fn count_devices() -> PortMidiDeviceId {
    unsafe {
        ffi::Pm_CountDevices()
    }
}

/// Gets the `PortMidiDeviceId` for the default input, or `None` if
/// there isn't one
///
/// See the PortMidi documentation for details of how to set the default device
pub fn get_default_input_device_id() -> Option<PortMidiDeviceId> {
    let id = unsafe { ffi::Pm_GetDefaultInputDeviceID() };
    if id == ffi::PM_NO_DEVICE {
        None
    }
    else {
        Some(id)
    }
}

/// Gets the `PortMidiDeviceId` for the default output, or `None` if
/// there isn't one
///
/// See the PortMidi documentation for details of how to set the default device
pub fn get_default_output_device_id() -> Option<PortMidiDeviceId> {
    let id = unsafe { ffi::Pm_GetDefaultOutputDeviceID() };
    if id == ffi::PM_NO_DEVICE {
        None
    }
    else {
        Some(id)
    }
}

// DeviceInfo
// ----------
/// Represents what we know about a device
#[derive(Clone, Debug)]
pub struct DeviceInfo {
    /// The `PortMidiDeviceId` used with `OutputPort::new` and `InputPort::new`
    pub device_id: PortMidiDeviceId,
    /// The name of the device
    pub name: String,
    /// Is the device an input
    pub input: bool,
    /// Is the device an output
    pub output: bool
}

impl DeviceInfo {
    fn wrap(device_id: PortMidiDeviceId, device_info: *const ffi::PmDeviceInfo) -> DeviceInfo {
        let name = unsafe {
            let bytes = std::ffi::CStr::from_ptr((*device_info).name).to_bytes();
            std::str::from_utf8_unchecked(bytes).to_string()
        };
        let input = unsafe { (*device_info).input };
        let output = unsafe { (*device_info).output };

        DeviceInfo {
            device_id: device_id,
            name: name,
            input: input > 0,
            output: output > 0
        }
    }
}

/// Returns a `DeviceInfo` with information about a device, or `None` if
/// it does not exist
pub fn get_device_info(device_id: PortMidiDeviceId) -> Option<DeviceInfo> {
    let info = unsafe { ffi::Pm_GetDeviceInfo(device_id) };
    if info.is_null() {
        None
    }
    else {
        Some(DeviceInfo::wrap(device_id, info))
    }
}

// Midi events
// -----------
/// Represents a single midi message, see also `MidiEvent`
///
/// TODO: should we use u8?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: i8,
    pub data1: i8,
    pub data2: i8,
}

impl MidiMessage {
    fn wrap(cmessage : ffi::PmMessage) -> MidiMessage {
        MidiMessage {
            status:  ((cmessage) & 0xFF) as i8,
            data1 : (((cmessage) >> 8) & 0xFF) as i8,
            data2 : (((cmessage) >> 16) & 0xFF) as i8,
        }
    }

    fn unwrap(&self) -> ffi::PmMessage {
        ((((self.data2 as i32) << 16) & 0xFF0000) |
          (((self.data1 as i32) << 8) & 0xFF00) |
          ((self.status as i32) & 0xFF)) as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
///
/// TODO: what to do about the timestamp?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub  struct MidiEvent {
    pub message : MidiMessage,
    pub timestamp : ffi::PmTimestamp,
}

impl MidiEvent {
    fn wrap(event: ffi::PmEvent) -> MidiEvent {
        MidiEvent {
            message:  MidiMessage::wrap(event.message),
            timestamp : event.timestamp,
        }
    }

    fn unwrap(&self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: self.message.unwrap(),
            timestamp: self.timestamp,
        }
    }
}

// Input
// -----
/// Representation of an input midi port
#[allow(missing_copy_implementations)]
pub struct InputPort {
    pm_stream : *const ffi::PortMidiStream,
    input_device : ffi::PmDeviceId,
    buffer_size : i32,
}

impl InputPort {
    /// Construct a new `InputPort` for `input_device`
    pub fn new(input_device : PortMidiDeviceId, buffer_size: i32) -> InputPort {
        InputPort {
            pm_stream : ptr::null(),
            input_device : input_device,
            buffer_size : buffer_size,
        }
    }

    /// Open the port returning an error if there is a problem
    pub fn open(&mut self)  -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_OpenInput(&self.pm_stream, self.input_device, ptr::null(),
                              self.buffer_size, ptr::null(), ptr::null())
        })
    }

    /// Reads a single `MidiEvent` if one is avaible
    ///
    /// A `Result` of `None` means no event was available.
    ///
    /// See the PortMidi documentation for information on how it deals with input
    /// overflows
    pub fn read(&mut self) -> PortMidiResult<Option<MidiEvent>> {
        use std::num::FromPrimitive;
        //get one note a the time
        let mut event = ffi::PmEvent { message : 0, timestamp : 0 };
        let no_of_notes = unsafe { ffi::Pm_Read(self.pm_stream, &mut event, 1) };
        match no_of_notes {
            y if y == 0 => Ok(None),
            y if y > 0 => Ok(Some(MidiEvent::wrap(event))),
            _ => {
                // if it's negative it's an error, convert it
                let maybe_pm_error: Option<ffi::PmError> = FromPrimitive::from_i32(no_of_notes);
                if let Some(pm_error) = maybe_pm_error {
                    from_pm_error(pm_error).map(|_| None)
                }
                else {
                    // what should we do, if we can't convert the error no?
                    // should we panic?
                    Ok(None)
                }
            }
        }
    }

    /// `poll` tests if there is input available, either returing a bool or an error
    pub fn poll(&self) -> PortMidiResult<bool> {
        let pm_error = unsafe { ffi::Pm_Poll(self.pm_stream) };
        match pm_error {
            ffi::PmError::PmNoError => Ok(false),
            ffi::PmError::PmGotData => Ok(true),
            other => from_pm_error(other).map(|_| false)
        }
    }

    /// Closes the input, flushing any pending buffers
    ///
    /// PortMidi attempts to close open streams when the application
    /// exits, but this can be difficult under Windows
    /// (according to the PortMidi documentation).
    pub fn close(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Close(self.pm_stream)
        })
    }

    /*
    *    Test whether stream has a pending host error. Normally, the client finds
    *    out about errors through returned error codes, but some errors can occur
    *    asynchronously where the client does not
    *    explicitly call a function, and therefore cannot receive an error code.
    *    The client can test for a pending error using has_host_error(). If true,
    *    the error can be accessed and cleared by calling get_Error_text().
    *    Errors are also cleared by calling other functions that can return
    *    errors, e.g. open_input(), open_output(), read(), write(). The
    *    client does not need to call Pm_HasHostError(). Any pending error will be
    *    reported the next time the client performs an explicit function call on
    *    the stream, e.g. an input or output operation. Until the error is cleared,
    *    no new error codes will be obtained, even for a different stream.
    */
    pub fn has_host_error(&self) -> bool {
        unsafe {
            ffi::Pm_HasHostError(self.pm_stream) > 0
        }
    }
}

// Output
// ------
/// Representation of an output midi port
#[allow(missing_copy_implementations)]
pub struct OutputPort {
    pm_stream: *const ffi::PortMidiStream,
    output_device: ffi::PmDeviceId,
    buffer_size: i32,
}

impl OutputPort {
    /// Construct a new `InputPort` for `input_device`
    pub fn new(output_device: PortMidiDeviceId, buffer_size: i32) -> OutputPort {
        OutputPort {
            pm_stream: ptr::null(),
            output_device: output_device,
            buffer_size: buffer_size,
        }
    }

    /// Open the port returning an error if there is a problem
    pub fn open(&mut self)  -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_OpenOutput(&self.pm_stream, self.output_device, ptr::null(),
                               self.buffer_size, ptr::null(), ptr::null(), 0)
        })
    }

    /// Terminates outgoing messages immediately
    ///
    /// The caller should immediately close the output port, this may
    /// result in transmission of a partial midi message. Note, not all platforms
    /// support abort.
    pub fn abort(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Abort(self.pm_stream)
        })
    }

    /// Closes the midi stream, flushing any pending buffers
    ///
    /// PortMidi attempts to close open streams when the application
    /// exits, but this can be difficult under Windows
    /// (according to the PortMidi documentation).
    pub fn close(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Close(self.pm_stream)
        })
    }

    /// Write a single `MidiEvent`
    pub fn write_event(&mut self, midi_event: MidiEvent) -> PortMidiResult<()> {
        let event = midi_event.unwrap();
        from_pm_error(unsafe {
            ffi::Pm_Write(self.pm_stream, &event, 1)
        })
    }

    /// Write a single `MidiMessage` immediately
    pub fn write_message(&mut self, midi_message: MidiMessage) -> PortMidiResult<()> {
        let message = midi_message.unwrap();
        from_pm_error(unsafe {
            ffi::Pm_WriteShort(self.pm_stream, 0, message)
        })
    }

    /*
    *    Test whether stream has a pending host error. Normally, the client finds
    *    out about errors through returned error codes, but some errors can occur
    *    asynchronously where the client does not
    *    explicitly call a function, and therefore cannot receive an error code.
    *    The client can test for a pending error using has_host_error(). If true,
    *    the error can be accessed and cleared by calling get_Error_text().
    *    Errors are also cleared by calling other functions that can return
    *    errors, e.g. open_input(), open_output(), read(), write(). The
    *    client does not need to call Pm_HasHostError(). Any pending error will be
    *    reported the next time the client performs an explicit function call on
    *    the stream, e.g. an input or output operation. Until the error is cleared,
    *    no new error codes will be obtained, even for a different stream.
    */
    pub fn has_host_error(&self) -> bool  {
        unsafe {
            ffi::Pm_HasHostError(self.pm_stream) > 0
        }
    }
}

// Old code
// --------
/**  Translate portmidi error number into human readable message.
*    These strings are constants (set at compile time) so client has
*    no need to allocate storage
*/
pub fn get_error_text(error_code: ffi::PmError) -> String {
    unsafe {
        let error_text = ffi::Pm_GetErrorText(error_code);
        let bytes = std::ffi::CStr::from_ptr(error_text).to_bytes();
        std::str::from_utf8_unchecked(bytes).to_string()
    }
}

/**  Translate portmidi host error into human readable message.
     These strings are computed at run time, so client has to allocate storage.
     After this routine executes, the host error is cleared.
*/
pub fn get_host_error_text(msg: *const c_char, len: i32) {
    unsafe {
        ffi::Pm_GetHostErrorText(msg, len);
    }
}

pub const HDRLENGTH: i32 = 50;
pub const PM_HOST_ERROR_MSG_LEN: i32 = 256;

<commit_msg>add features `core` and `std_misc`<commit_after>// Copyright 2014-2015 Sam Doshi (sam@metal-fish.co.uk)
// Copyright 2013-2014 Philippe Delrieu (philippe.delrieu@free.fr)
//
// Licensed under the MIT License <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.
#![feature(core, std_misc)]

extern crate libc;

use std::fmt;
use std::ptr;
use libc::c_char;

mod ffi;

// Types
// -----
/// Used by PortMidi to refer to a Midi device
pub type PortMidiDeviceId = i32;
pub type PortMidiResult<T> = Result<T, PortMidiError>;

// Errors
// ------
#[derive(Copy, Debug, PartialEq, Eq)]
pub enum PortMidiError {
    HostError,
    InvalidDeviceId,
    InsufficientMemory,
    BufferTooSmall,
    BufferOverflow,
    BadPtr,
    BadData,
    InternalError,
    BufferMaxSize
}

fn from_pm_error(pm_error: ffi::PmError) -> PortMidiResult<()> {
    match pm_error {
        ffi::PmError::PmNoError => Ok(()),
        ffi::PmError::PmGotData => Ok(()),
        ffi::PmError::PmHostError => Err(PortMidiError::HostError),
        ffi::PmError::PmInvalidDeviceId => Err(PortMidiError::InvalidDeviceId),
        ffi::PmError::PmInsufficientMemory => Err(PortMidiError::InsufficientMemory),
        ffi::PmError::PmBufferTooSmall => Err(PortMidiError::BufferTooSmall),
        ffi::PmError::PmBufferOverflow => Err(PortMidiError::BufferOverflow),
        ffi::PmError::PmBadPtr => Err(PortMidiError::BadPtr),
        ffi::PmError::PmBadData => Err(PortMidiError::BadData),
        ffi::PmError::PmInternalError => Err(PortMidiError::InternalError),
        ffi::PmError::PmBufferMaxSize => Err(PortMidiError::BufferMaxSize),
    }
}

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

// Global fns
// ----------
/// `initialize` initalizes the underlying PortMidi C library, call this
/// before using the library.
///
/// Once initialized, PortMidi will no longer pickup any new Midi devices that are
/// connected, i.e. it does not support hot plugging.
pub fn initialize() -> PortMidiResult<()> {
    from_pm_error(unsafe {
        ffi::Pm_Initialize()
    })
}

/// `terminate` terminates the underlying PortMidi C library, call this
/// after using the library.
pub fn terminate() -> PortMidiResult<()> {
    from_pm_error(unsafe {
        ffi::Pm_Terminate()
    })
}

/// Return the number of devices. This number will not change during the lifetime
/// of the program.
pub fn count_devices() -> PortMidiDeviceId {
    unsafe {
        ffi::Pm_CountDevices()
    }
}

/// Gets the `PortMidiDeviceId` for the default input, or `None` if
/// there isn't one
///
/// See the PortMidi documentation for details of how to set the default device
pub fn get_default_input_device_id() -> Option<PortMidiDeviceId> {
    let id = unsafe { ffi::Pm_GetDefaultInputDeviceID() };
    if id == ffi::PM_NO_DEVICE {
        None
    }
    else {
        Some(id)
    }
}

/// Gets the `PortMidiDeviceId` for the default output, or `None` if
/// there isn't one
///
/// See the PortMidi documentation for details of how to set the default device
pub fn get_default_output_device_id() -> Option<PortMidiDeviceId> {
    let id = unsafe { ffi::Pm_GetDefaultOutputDeviceID() };
    if id == ffi::PM_NO_DEVICE {
        None
    }
    else {
        Some(id)
    }
}

// DeviceInfo
// ----------
/// Represents what we know about a device
#[derive(Clone, Debug)]
pub struct DeviceInfo {
    /// The `PortMidiDeviceId` used with `OutputPort::new` and `InputPort::new`
    pub device_id: PortMidiDeviceId,
    /// The name of the device
    pub name: String,
    /// Is the device an input
    pub input: bool,
    /// Is the device an output
    pub output: bool
}

impl DeviceInfo {
    fn wrap(device_id: PortMidiDeviceId, device_info: *const ffi::PmDeviceInfo) -> DeviceInfo {
        let name = unsafe {
            let bytes = std::ffi::CStr::from_ptr((*device_info).name).to_bytes();
            std::str::from_utf8_unchecked(bytes).to_string()
        };
        let input = unsafe { (*device_info).input };
        let output = unsafe { (*device_info).output };

        DeviceInfo {
            device_id: device_id,
            name: name,
            input: input > 0,
            output: output > 0
        }
    }
}

/// Returns a `DeviceInfo` with information about a device, or `None` if
/// it does not exist
pub fn get_device_info(device_id: PortMidiDeviceId) -> Option<DeviceInfo> {
    let info = unsafe { ffi::Pm_GetDeviceInfo(device_id) };
    if info.is_null() {
        None
    }
    else {
        Some(DeviceInfo::wrap(device_id, info))
    }
}

// Midi events
// -----------
/// Represents a single midi message, see also `MidiEvent`
///
/// TODO: should we use u8?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: i8,
    pub data1: i8,
    pub data2: i8,
}

impl MidiMessage {
    fn wrap(cmessage : ffi::PmMessage) -> MidiMessage {
        MidiMessage {
            status:  ((cmessage) & 0xFF) as i8,
            data1 : (((cmessage) >> 8) & 0xFF) as i8,
            data2 : (((cmessage) >> 16) & 0xFF) as i8,
        }
    }

    fn unwrap(&self) -> ffi::PmMessage {
        ((((self.data2 as i32) << 16) & 0xFF0000) |
          (((self.data1 as i32) << 8) & 0xFF00) |
          ((self.status as i32) & 0xFF)) as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
///
/// TODO: what to do about the timestamp?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub  struct MidiEvent {
    pub message : MidiMessage,
    pub timestamp : ffi::PmTimestamp,
}

impl MidiEvent {
    fn wrap(event: ffi::PmEvent) -> MidiEvent {
        MidiEvent {
            message:  MidiMessage::wrap(event.message),
            timestamp : event.timestamp,
        }
    }

    fn unwrap(&self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: self.message.unwrap(),
            timestamp: self.timestamp,
        }
    }
}

// Input
// -----
/// Representation of an input midi port
#[allow(missing_copy_implementations)]
pub struct InputPort {
    pm_stream : *const ffi::PortMidiStream,
    input_device : ffi::PmDeviceId,
    buffer_size : i32,
}

impl InputPort {
    /// Construct a new `InputPort` for `input_device`
    pub fn new(input_device : PortMidiDeviceId, buffer_size: i32) -> InputPort {
        InputPort {
            pm_stream : ptr::null(),
            input_device : input_device,
            buffer_size : buffer_size,
        }
    }

    /// Open the port returning an error if there is a problem
    pub fn open(&mut self)  -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_OpenInput(&self.pm_stream, self.input_device, ptr::null(),
                              self.buffer_size, ptr::null(), ptr::null())
        })
    }

    /// Reads a single `MidiEvent` if one is avaible
    ///
    /// A `Result` of `None` means no event was available.
    ///
    /// See the PortMidi documentation for information on how it deals with input
    /// overflows
    pub fn read(&mut self) -> PortMidiResult<Option<MidiEvent>> {
        use std::num::FromPrimitive;
        //get one note a the time
        let mut event = ffi::PmEvent { message : 0, timestamp : 0 };
        let no_of_notes = unsafe { ffi::Pm_Read(self.pm_stream, &mut event, 1) };
        match no_of_notes {
            y if y == 0 => Ok(None),
            y if y > 0 => Ok(Some(MidiEvent::wrap(event))),
            _ => {
                // if it's negative it's an error, convert it
                let maybe_pm_error: Option<ffi::PmError> = FromPrimitive::from_i32(no_of_notes);
                if let Some(pm_error) = maybe_pm_error {
                    from_pm_error(pm_error).map(|_| None)
                }
                else {
                    // what should we do, if we can't convert the error no?
                    // should we panic?
                    Ok(None)
                }
            }
        }
    }

    /// `poll` tests if there is input available, either returing a bool or an error
    pub fn poll(&self) -> PortMidiResult<bool> {
        let pm_error = unsafe { ffi::Pm_Poll(self.pm_stream) };
        match pm_error {
            ffi::PmError::PmNoError => Ok(false),
            ffi::PmError::PmGotData => Ok(true),
            other => from_pm_error(other).map(|_| false)
        }
    }

    /// Closes the input, flushing any pending buffers
    ///
    /// PortMidi attempts to close open streams when the application
    /// exits, but this can be difficult under Windows
    /// (according to the PortMidi documentation).
    pub fn close(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Close(self.pm_stream)
        })
    }

    /*
    *    Test whether stream has a pending host error. Normally, the client finds
    *    out about errors through returned error codes, but some errors can occur
    *    asynchronously where the client does not
    *    explicitly call a function, and therefore cannot receive an error code.
    *    The client can test for a pending error using has_host_error(). If true,
    *    the error can be accessed and cleared by calling get_Error_text().
    *    Errors are also cleared by calling other functions that can return
    *    errors, e.g. open_input(), open_output(), read(), write(). The
    *    client does not need to call Pm_HasHostError(). Any pending error will be
    *    reported the next time the client performs an explicit function call on
    *    the stream, e.g. an input or output operation. Until the error is cleared,
    *    no new error codes will be obtained, even for a different stream.
    */
    pub fn has_host_error(&self) -> bool {
        unsafe {
            ffi::Pm_HasHostError(self.pm_stream) > 0
        }
    }
}

// Output
// ------
/// Representation of an output midi port
#[allow(missing_copy_implementations)]
pub struct OutputPort {
    pm_stream: *const ffi::PortMidiStream,
    output_device: ffi::PmDeviceId,
    buffer_size: i32,
}

impl OutputPort {
    /// Construct a new `InputPort` for `input_device`
    pub fn new(output_device: PortMidiDeviceId, buffer_size: i32) -> OutputPort {
        OutputPort {
            pm_stream: ptr::null(),
            output_device: output_device,
            buffer_size: buffer_size,
        }
    }

    /// Open the port returning an error if there is a problem
    pub fn open(&mut self)  -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_OpenOutput(&self.pm_stream, self.output_device, ptr::null(),
                               self.buffer_size, ptr::null(), ptr::null(), 0)
        })
    }

    /// Terminates outgoing messages immediately
    ///
    /// The caller should immediately close the output port, this may
    /// result in transmission of a partial midi message. Note, not all platforms
    /// support abort.
    pub fn abort(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Abort(self.pm_stream)
        })
    }

    /// Closes the midi stream, flushing any pending buffers
    ///
    /// PortMidi attempts to close open streams when the application
    /// exits, but this can be difficult under Windows
    /// (according to the PortMidi documentation).
    pub fn close(&mut self) -> PortMidiResult<()> {
        from_pm_error(unsafe {
            ffi::Pm_Close(self.pm_stream)
        })
    }

    /// Write a single `MidiEvent`
    pub fn write_event(&mut self, midi_event: MidiEvent) -> PortMidiResult<()> {
        let event = midi_event.unwrap();
        from_pm_error(unsafe {
            ffi::Pm_Write(self.pm_stream, &event, 1)
        })
    }

    /// Write a single `MidiMessage` immediately
    pub fn write_message(&mut self, midi_message: MidiMessage) -> PortMidiResult<()> {
        let message = midi_message.unwrap();
        from_pm_error(unsafe {
            ffi::Pm_WriteShort(self.pm_stream, 0, message)
        })
    }

    /*
    *    Test whether stream has a pending host error. Normally, the client finds
    *    out about errors through returned error codes, but some errors can occur
    *    asynchronously where the client does not
    *    explicitly call a function, and therefore cannot receive an error code.
    *    The client can test for a pending error using has_host_error(). If true,
    *    the error can be accessed and cleared by calling get_Error_text().
    *    Errors are also cleared by calling other functions that can return
    *    errors, e.g. open_input(), open_output(), read(), write(). The
    *    client does not need to call Pm_HasHostError(). Any pending error will be
    *    reported the next time the client performs an explicit function call on
    *    the stream, e.g. an input or output operation. Until the error is cleared,
    *    no new error codes will be obtained, even for a different stream.
    */
    pub fn has_host_error(&self) -> bool  {
        unsafe {
            ffi::Pm_HasHostError(self.pm_stream) > 0
        }
    }
}

// Old code
// --------
/**  Translate portmidi error number into human readable message.
*    These strings are constants (set at compile time) so client has
*    no need to allocate storage
*/
pub fn get_error_text(error_code: ffi::PmError) -> String {
    unsafe {
        let error_text = ffi::Pm_GetErrorText(error_code);
        let bytes = std::ffi::CStr::from_ptr(error_text).to_bytes();
        std::str::from_utf8_unchecked(bytes).to_string()
    }
}

/**  Translate portmidi host error into human readable message.
     These strings are computed at run time, so client has to allocate storage.
     After this routine executes, the host error is cleared.
*/
pub fn get_host_error_text(msg: *const c_char, len: i32) {
    unsafe {
        ffi::Pm_GetHostErrorText(msg, len);
    }
}

pub const HDRLENGTH: i32 = 50;
pub const PM_HOST_ERROR_MSG_LEN: i32 = 256;

<|endoftext|>


<commit_before><commit_msg>I'm sorry<commit_after>pub mod build;
pub mod bundle;
pub mod util;
<|endoftext|>


<commit_before><commit_msg>12 - use import<commit_after>// Bind the `deeply::nested::function` path to `other_function`
use deeply::nested::function as other_function;

fn function() {
    println!("called `function()`");
}

mod deeply {
    pub mod nested {
        pub fn function() {
            println!("called `deeply::nested::function()`")
        }
    }
}

fn main() {
    // Easier access to `deeply::nested::function`
    other_function();

    println!("Entering block");
    {
        // This is equivalent to `use deeply::nested::function as function`
        // This `function` will shadow the outer one
        use deeply::nested::function;

        function();

        println!("Leaving block");

        // `use` bindings have a local scope, in this case the `function`
        // shadowing is only available in this scope
    }

    function();
}
<|endoftext|>


<commit_before><commit_msg>add new<commit_after>fn add_strings(nums1:) -> i32 {}
<|endoftext|>


<commit_before><commit_msg>add a publisher_confirms example<commit_after>use futures_executor::LocalPool;
use lapin::{
    message::DeliveryResult, options::*, publisher_confirm::Confirmation, types::FieldTable,
    BasicProperties, Connection, ConnectionProperties,
};
use log::info;

fn main() {
    std::env::set_var("RUST_LOG", "trace");

    env_logger::init();

    let addr = std::env::var("AMQP_ADDR").unwrap_or_else(|_| "amqp://127.0.0.1:5672/%2f".into());
    let mut executor = LocalPool::new();

    executor.run_until(async {
        let conn = Connection::connect(&addr, ConnectionProperties::default())
            .await
            .expect("connection error");

        info!("CONNECTED");

        //send channel
        let channel_a = conn.create_channel().await.expect("create_channel");
        //receive channel
        let channel_b = conn.create_channel().await.expect("create_channel");
        info!("[{}] state: {:?}", line!(), conn.status().state());

        //create the hello queue
        let queue = channel_a
            .queue_declare(
                "hello",
                QueueDeclareOptions::default(),
                FieldTable::default(),
            )
            .await
            .expect("queue_declare");
        info!("[{}] state: {:?}", line!(), conn.status().state());
        info!("[{}] declared queue: {:?}", line!(), queue);

        let queue = channel_a
            .confirm_select(ConfirmSelectOptions::default())
            .await
            .expect("confirm_select");
        info!("[{}] state: {:?}", line!(), conn.status().state());
        info!("Enabled publisher-confirms: {:?}", queue);

        let chan = channel_b.clone();
        info!("will consume");
        channel_b
            .basic_consume(
                "hello",
                "my_consumer",
                BasicConsumeOptions::default(),
                FieldTable::default(),
            )
            .await
            .expect("basic_consume")
            .set_delegate(Box::new(move |delivery: DeliveryResult| {
                info!("received message: {:?}", delivery);
                if let Ok(Some(delivery)) = delivery {
                    chan.basic_ack(delivery.delivery_tag, BasicAckOptions::default())
                        .wait() // await is hard to handle here
                        .expect("basic_ack");
                }
            }));
        info!("[{}] state: {:?}", line!(), conn.status().state());

        info!("will publish");
        let payload = b"Hello world!";
        let confirm = channel_a
            .basic_publish(
                "",
                "hello",
                BasicPublishOptions::default(),
                payload.to_vec(),
                BasicProperties::default(),
            )
            .await
            .expect("basic_publish")
            .await; // Wait for this specific ack/nack
        assert_eq!(confirm, Confirmation::Ack);
        info!("[{}] state: {:?}", line!(), conn.status().state());

        for _ in 1..=2 {
            channel_a
                .basic_publish(
                    "",
                    "hello",
                    BasicPublishOptions::default(),
                    payload.to_vec(),
                    BasicProperties::default(),
                )
                .await
                .expect("basic_publish"); // Drop the PublisherConfirm instead for waiting for it ...
        }

        // ... and wait for all pending ack/nack afterwards instead of individually in the above loop
        let returned = channel_a
            .wait_for_confirms()
            .await
            .expect("wait for confirms");
        assert!(returned.is_empty());

        std::thread::sleep(std::time::Duration::from_millis(2000));
        conn.close(200, "OK").await.expect("connection close");
    })
}
<|endoftext|>


<commit_before><commit_msg>Renamed example.rs from src/<commit_after>extern crate orbclient;

use std::cmp::max;
use std::env;

use orbclient::{BmpFile, Color, EventOption, Window};

fn main() {
    let path = match env::args().nth(1) {
        Some(arg) => arg,
        None => "res/redox.bmp".to_string(),
    };

    let bmp = BmpFile::from_path(&path);
    let mut window = Window::new(-1,
                                 -1,
                                 max(32, bmp.width() as u32),
                                 max(32, bmp.height() as u32),
                                 &path)
                         .unwrap();
    window.set(Color::rgb(0, 0, 0));
    window.image(0, 0, bmp.width() as u32, bmp.height() as u32, &bmp);
    window.sync();

    loop {
        for event in window.events() {
            println!("{:?}", event.to_option());
            if let EventOption::Quit(_) = event.to_option() {
                return;
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>writer mod: rename Entry::name to Entry::path<commit_after><|endoftext|>


<commit_before><commit_msg>Do Problem 08 with cheat<commit_after>fn main() {
    let mut list =
        ~['a', 'a', 'a', 'a', 'b', 'c', 'c', 'a', 'a', 'd', 'e', 'e', 'e', 'e'];

    list.dedup(); // Cheat
    println!("{:?}", list);
}
<|endoftext|>


<commit_before><commit_msg>Fix: Editor commands should be split at whitespace<commit_after><|endoftext|>


<commit_before><commit_msg>Add simple utility to show frontend properties.<commit_after>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate linuxdvb;

use std::error::Error;
use std::path::Path;

use linuxdvb::{Frontend,ReadWriteMode,BlockMode};
use linuxdvb::properties::GetProperty as GP;

type SimpleResult<T> = Result<T, Box<Error>>;

fn show_frontend_properties(path: &Path) -> SimpleResult<()> {
    let frontend = try!(Frontend::open(path, ReadWriteMode::ReadOnly, BlockMode::NonBlocking));
    let get_properties = [
        GP::DtvApiVersion,
        GP::DtvAtscmhFicVer,
        GP::DtvAtscmhNog,
        GP::DtvAtscmhParadeId,
        GP::DtvAtscmhPrc,
        GP::DtvAtscmhRsCodeModePri,
        GP::DtvAtscmhRsCodeModeSec,
        GP::DtvAtscmhRsFrameEnsemble,
        GP::DtvAtscmhRsFrameMode,
        GP::DtvAtscmhScccBlockMode,
        GP::DtvAtscmhScccCodeModeA,
        GP::DtvAtscmhScccCodeModeB,
        GP::DtvAtscmhScccCodeModeC,
        GP::DtvAtscmhScccCodeModeD,
        GP::DtvAtscmhSgn,
        GP::DtvAtscmhTnog,
        GP::DtvBandwidthHz,
        GP::DtvCodeRateHp,
        GP::DtvCodeRateLp,
        GP::DtvDeliverySystem,
        GP::DtvFrequency,
        GP::DtvGuardInterval,
        GP::DtvHierarchy,
        GP::DtvInnerFec,
        GP::DtvInterleaving,
        GP::DtvInversion,
        GP::DtvIsdbtLayerEnabled,
        GP::DtvIsdbtLayeraFec,
        GP::DtvIsdbtLayeraModulation,
        GP::DtvIsdbtLayeraSegmentCount,
        GP::DtvIsdbtLayeraTimeInterleaving,
        GP::DtvIsdbtLayerbFec,
        GP::DtvIsdbtLayerbModulation,
        GP::DtvIsdbtLayerbSegmentCount,
        GP::DtvIsdbtLayerbTimeInterleaving,
        GP::DtvIsdbtLayercFec,
        GP::DtvIsdbtLayercModulation,
        GP::DtvIsdbtLayercSegmentCount,
        GP::DtvIsdbtLayercTimeInterleaving,
        GP::DtvIsdbtPartialReception,
        GP::DtvIsdbtSbSegmentCount,
        GP::DtvIsdbtSbSegmentIdx,
        GP::DtvIsdbtSbSubchannelId,
        GP::DtvIsdbtSoundBroadcasting,
        GP::DtvLna,
        GP::DtvModulation,
        GP::DtvPilot,
        GP::DtvRolloff,
        GP::DtvStatCnr,
        GP::DtvStatErrorBlockCount,
        GP::DtvStatPostErrorBitCount,
        GP::DtvStatPostTotalBitCount,
        GP::DtvStatPreErrorBitCount,
        GP::DtvStatPreTotalBitCount,
        GP::DtvStatSignalStrength,
        GP::DtvStatTotalBlockCount,
        GP::DtvStreamId,
        GP::DtvSymbolRate,
        GP::DtvTone,
        GP::DtvTransmissionMode,
        GP::DtvVoltage,
        GP::DtvEnumDelsys,
    ];
    let properties = try!(frontend.get_properties(&get_properties));
    println!("{:#?}", properties);
    Ok(())
}

fn main() {
    let string_path = match std::env::args().nth(1) {
        Some(string_path) => string_path,
        None => {
            println!("Specify frontend device");
            return;
        }
    };
    if let Err(error) = show_frontend_properties(Path::new(&string_path)) {
        println!("Error: {:?}", error);
    };
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::ErrorKind;
use std::io::{Seek, Write, SeekFrom};
use std::fs::{OpenOptions, read_dir};
use std::os::unix::prelude::AsRawFd;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::thread;
use std::time::Duration;

use devicemapper::consts::SECTOR_SIZE;

use devicemapper::Device;
use devicemapper::types::{Bytes, Sectors};
use time::Timespec;
use uuid::Uuid;

use consts::IEC;
use engine::{DevUuid, EngineResult, EngineError, ErrorEnum, PoolUuid};
use super::metadata::{StaticHeader, BDA, validate_mda_size};
use super::engine::DevOwnership;
pub use super::BlockDevSave;

const MIN_DEV_SIZE: Bytes = Bytes(IEC::Gi as u64);

ioctl!(read blkgetsize64 with 0x12, 114; u64);

pub fn blkdev_size(file: &File) -> EngineResult<Bytes> {
    let mut val: u64 = 0;

    match unsafe { blkgetsize64(file.as_raw_fd(), &mut val) } {
        Err(x) => Err(EngineError::Nix(x)),
        Ok(_) => Ok(Bytes(val)),
    }
}

/// Resolve a list of Paths of some sort to a set of unique Devices.
/// Return an IOError if there was a problem resolving any particular device.
pub fn resolve_devices(paths: &[&Path]) -> io::Result<HashSet<Device>> {
    let mut devices = HashSet::new();
    for path in paths {
        let dev = try!(Device::from_str(&path.to_string_lossy()));
        devices.insert(dev);
    }
    Ok(devices)
}

/// Find all Stratis Blockdevs.
///
/// Returns a map of pool uuids to maps of blockdev uuids to blockdevs.
pub fn find_all() -> EngineResult<HashMap<PoolUuid, HashMap<DevUuid, BlockDev>>> {

    /// If a Path refers to a valid Stratis blockdev, return a BlockDev
    /// struct. Otherwise, return None. Return an error if there was
    /// a problem inspecting the device.
    fn setup(devnode: &Path) -> EngineResult<Option<BlockDev>> {
        let mut f = try!(OpenOptions::new()
            .read(true)
            .open(devnode));

        if let Some(bda) = BDA::load(&mut f).ok() {
            let dev = try!(Device::from_str(&devnode.to_string_lossy()));
            Ok(Some(BlockDev {
                dev: dev,
                devnode: devnode.to_owned(),
                bda: bda,
            }))
        } else {
            Ok(None)
        }
    }

    let mut pool_map = HashMap::new();
    for dir_e in try!(read_dir("/dev")) {
        let devnode = match dir_e {
            Ok(d) => d.path(),
            Err(_) => continue,
        };

        match setup(&devnode) {
            Ok(Some(blockdev)) => {
                pool_map.entry(blockdev.pool_uuid().clone())
                    .or_insert_with(HashMap::new)
                    .insert(blockdev.uuid().clone(), blockdev);
            }
            _ => continue,
        };
    }

    Ok(pool_map)
}

/// Write buf at offset length times.
pub fn write_sectors(path: &Path,
                     offset: Sectors,
                     length: Sectors,
                     buf: &[u8; SECTOR_SIZE])
                     -> EngineResult<()> {
    let mut f = try!(OpenOptions::new().write(true).open(path));

    try!(f.seek(SeekFrom::Start(*offset)));
    for _ in 0..*length {
        try!(f.write_all(buf));
    }

    try!(f.flush());
    Ok(())
}

/// Zero sectors at the given offset for length sectors.
pub fn wipe_sectors(path: &Path, offset: Sectors, length: Sectors) -> EngineResult<()> {
    write_sectors(path, offset, length, &[0u8; SECTOR_SIZE])
}

/// Initialize multiple blockdevs at once. This allows all of them
/// to be checked for usability before writing to any of them.
pub fn initialize(pool_uuid: &PoolUuid,
                  devices: HashSet<Device>,
                  mda_size: Sectors,
                  force: bool)
                  -> EngineResult<Vec<BlockDev>> {
    /// Gets device information, returns an error if problem with obtaining
    /// that information.
    /// Returns a tuple with the blockdev's path, its size in bytes,
    /// its ownership as determined by calling determine_ownership(),
    /// and an open File handle, all of which are needed later.
    fn dev_info(dev: &Device) -> EngineResult<(PathBuf, Bytes, DevOwnership, File)> {
        let devnode = try!(dev.path().ok_or_else(|| {
            io::Error::new(ErrorKind::InvalidInput,
                           format!("could not get device node from dev {}", dev.dstr()))
        }));
        let mut f = try!(OpenOptions::new()
            .read(true)
            .write(true)
            .open(&devnode)
            .map_err(|_| {
                io::Error::new(ErrorKind::PermissionDenied,
                               format!("Could not open {}", devnode.display()))
            }));

        let dev_size = try!(blkdev_size(&f));

        let ownership = match StaticHeader::determine_ownership(&mut f) {
            Ok(ownership) => ownership,
            Err(err) => {
                let error_message = format!("{} for device {}", err, devnode.display());
                return Err(EngineError::Engine(ErrorEnum::Invalid, error_message));
            }
        };

        Ok((devnode, dev_size, ownership, f))
    }

    /// Filter devices for admission to pool based on dev_infos.
    /// If there is an error finding out the info, return that error.
    /// Also, return an error if a device is not appropriate for this pool.
    fn filter_devs<I>(dev_infos: I,
                      pool_uuid: &PoolUuid,
                      force: bool)
                      -> EngineResult<Vec<(Device, (PathBuf, Bytes, File))>>
        where I: Iterator<Item = (Device, EngineResult<(PathBuf, Bytes, DevOwnership, File)>)>
    {
        let mut add_devs = Vec::new();
        for (dev, dev_result) in dev_infos {
            let (devnode, dev_size, ownership, f) = try!(dev_result);
            if dev_size < MIN_DEV_SIZE {
                let error_message = format!("{} too small, minimum {} bytes",
                                            devnode.display(),
                                            MIN_DEV_SIZE);
                return Err(EngineError::Engine(ErrorEnum::Invalid, error_message));
            };
            match ownership {
                DevOwnership::Unowned => add_devs.push((dev, (devnode, dev_size, f))),
                DevOwnership::Theirs => {
                    if !force {
                        let error_str = format!("First 8K of {} not zeroed", devnode.display());
                        return Err(EngineError::Engine(ErrorEnum::Invalid, error_str));
                    } else {
                        add_devs.push((dev, (devnode, dev_size, f)))
                    }
                }
                DevOwnership::Ours(uuid) => {
                    if *pool_uuid != uuid {
                        let error_str = format!("Device {} already belongs to Stratis pool {}",
                                                devnode.display(),
                                                uuid);
                        return Err(EngineError::Engine(ErrorEnum::Invalid, error_str));
                    }
                }
            }
        }
        Ok(add_devs)
    }

    try!(validate_mda_size(mda_size));

    let dev_infos = devices.into_iter().map(|d: Device| (d, dev_info(&d)));

    let add_devs = try!(filter_devs(dev_infos, pool_uuid, force));

    // TODO: Fix this code.  We should deal with any number of blockdevs
    //
    if add_devs.len() < 2 {
        return Err(EngineError::Engine(ErrorEnum::Error,
                                       "Need at least 2 blockdevs to create a pool".into()));
    }

    let mut bds = Vec::new();
    for (dev, (devnode, dev_size, mut f)) in add_devs {

        let bda = try!(BDA::initialize(&mut f,
                                       pool_uuid,
                                       &Uuid::new_v4(),
                                       mda_size,
                                       dev_size.sectors()));

        let bd = BlockDev {
            dev: dev,
            devnode: devnode.clone(),
            bda: bda,
        };
        bds.push(bd);
    }
    Ok(bds)
}

#[derive(Debug)]
pub struct BlockDev {
    dev: Device,
    pub devnode: PathBuf,
    bda: BDA,
}

impl BlockDev {
    pub fn to_save(&self) -> BlockDevSave {
        BlockDevSave {
            devnode: self.devnode.clone(),
            total_size: self.size(),
        }
    }

    pub fn wipe_metadata(self) -> EngineResult<()> {
        let mut f = try!(OpenOptions::new().write(true).open(&self.devnode));
        BDA::wipe(&mut f)
    }

    /// Get the "x:y" device string for this blockdev
    pub fn dstr(&self) -> String {
        self.dev.dstr()
    }

    pub fn save_state(&mut self, time: &Timespec, metadata: &[u8]) -> EngineResult<()> {
        let mut f = try!(OpenOptions::new().write(true).open(&self.devnode));
        self.bda.save_state(time, metadata, &mut f)
    }

    pub fn load_state(&self) -> EngineResult<Option<Vec<u8>>> {
        let mut f = try!(OpenOptions::new().read(true).open(&self.devnode));
        self.bda.load_state(&mut f)
    }

    /// List the available-for-upper-layer-use range in this blockdev.
    pub fn avail_range(&self) -> (Sectors, Sectors) {
        let start = self.bda.size();
        let size = self.size();
        // Blockdev size is at least MIN_DEV_SIZE, so this can fail only if
        // size of metadata area exceeds 1 GiB. Initial metadata area size
        // is 4 MiB.
        assert!(start <= size);
        (start, size - start)
    }

    /// The /dev/mapper/<name> device is not immediately available for use.
    /// TODO: Implement wait for event or poll.
    pub fn wait_for_dm() {
        thread::sleep(Duration::from_millis(500))
    }

    /// The device's UUID.
    pub fn uuid(&self) -> &DevUuid {
        self.bda.dev_uuid()
    }

    /// The device's pool's UUID.
    pub fn pool_uuid(&self) -> &PoolUuid {
        self.bda.pool_uuid()
    }

    /// The device's size.
    pub fn size(&self) -> Sectors {
        self.bda.dev_size()
    }

    /// Last time metadata was written to this device.
    pub fn last_update_time(&self) -> Option<&Timespec> {
        self.bda.last_update_time()
    }
}
<commit_msg>Add function to get the available range as a segment<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::ErrorKind;
use std::io::{Seek, Write, SeekFrom};
use std::fs::{OpenOptions, read_dir};
use std::os::unix::prelude::AsRawFd;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::thread;
use std::time::Duration;

use devicemapper::consts::SECTOR_SIZE;
use devicemapper::Device;
use devicemapper::segment::Segment;
use devicemapper::types::{Bytes, Sectors};
use time::Timespec;
use uuid::Uuid;

use consts::IEC;
use engine::{DevUuid, EngineResult, EngineError, ErrorEnum, PoolUuid};
use super::metadata::{StaticHeader, BDA, validate_mda_size};
use super::engine::DevOwnership;
pub use super::BlockDevSave;

const MIN_DEV_SIZE: Bytes = Bytes(IEC::Gi as u64);

ioctl!(read blkgetsize64 with 0x12, 114; u64);

pub fn blkdev_size(file: &File) -> EngineResult<Bytes> {
    let mut val: u64 = 0;

    match unsafe { blkgetsize64(file.as_raw_fd(), &mut val) } {
        Err(x) => Err(EngineError::Nix(x)),
        Ok(_) => Ok(Bytes(val)),
    }
}

/// Resolve a list of Paths of some sort to a set of unique Devices.
/// Return an IOError if there was a problem resolving any particular device.
pub fn resolve_devices(paths: &[&Path]) -> io::Result<HashSet<Device>> {
    let mut devices = HashSet::new();
    for path in paths {
        let dev = try!(Device::from_str(&path.to_string_lossy()));
        devices.insert(dev);
    }
    Ok(devices)
}

/// Find all Stratis Blockdevs.
///
/// Returns a map of pool uuids to maps of blockdev uuids to blockdevs.
pub fn find_all() -> EngineResult<HashMap<PoolUuid, HashMap<DevUuid, BlockDev>>> {

    /// If a Path refers to a valid Stratis blockdev, return a BlockDev
    /// struct. Otherwise, return None. Return an error if there was
    /// a problem inspecting the device.
    fn setup(devnode: &Path) -> EngineResult<Option<BlockDev>> {
        let mut f = try!(OpenOptions::new()
            .read(true)
            .open(devnode));

        if let Some(bda) = BDA::load(&mut f).ok() {
            let dev = try!(Device::from_str(&devnode.to_string_lossy()));
            Ok(Some(BlockDev {
                dev: dev,
                devnode: devnode.to_owned(),
                bda: bda,
            }))
        } else {
            Ok(None)
        }
    }

    let mut pool_map = HashMap::new();
    for dir_e in try!(read_dir("/dev")) {
        let devnode = match dir_e {
            Ok(d) => d.path(),
            Err(_) => continue,
        };

        match setup(&devnode) {
            Ok(Some(blockdev)) => {
                pool_map.entry(blockdev.pool_uuid().clone())
                    .or_insert_with(HashMap::new)
                    .insert(blockdev.uuid().clone(), blockdev);
            }
            _ => continue,
        };
    }

    Ok(pool_map)
}

/// Write buf at offset length times.
pub fn write_sectors(path: &Path,
                     offset: Sectors,
                     length: Sectors,
                     buf: &[u8; SECTOR_SIZE])
                     -> EngineResult<()> {
    let mut f = try!(OpenOptions::new().write(true).open(path));

    try!(f.seek(SeekFrom::Start(*offset)));
    for _ in 0..*length {
        try!(f.write_all(buf));
    }

    try!(f.flush());
    Ok(())
}

/// Zero sectors at the given offset for length sectors.
pub fn wipe_sectors(path: &Path, offset: Sectors, length: Sectors) -> EngineResult<()> {
    write_sectors(path, offset, length, &[0u8; SECTOR_SIZE])
}

/// Initialize multiple blockdevs at once. This allows all of them
/// to be checked for usability before writing to any of them.
pub fn initialize(pool_uuid: &PoolUuid,
                  devices: HashSet<Device>,
                  mda_size: Sectors,
                  force: bool)
                  -> EngineResult<Vec<BlockDev>> {
    /// Gets device information, returns an error if problem with obtaining
    /// that information.
    /// Returns a tuple with the blockdev's path, its size in bytes,
    /// its ownership as determined by calling determine_ownership(),
    /// and an open File handle, all of which are needed later.
    fn dev_info(dev: &Device) -> EngineResult<(PathBuf, Bytes, DevOwnership, File)> {
        let devnode = try!(dev.path().ok_or_else(|| {
            io::Error::new(ErrorKind::InvalidInput,
                           format!("could not get device node from dev {}", dev.dstr()))
        }));
        let mut f = try!(OpenOptions::new()
            .read(true)
            .write(true)
            .open(&devnode)
            .map_err(|_| {
                io::Error::new(ErrorKind::PermissionDenied,
                               format!("Could not open {}", devnode.display()))
            }));

        let dev_size = try!(blkdev_size(&f));

        let ownership = match StaticHeader::determine_ownership(&mut f) {
            Ok(ownership) => ownership,
            Err(err) => {
                let error_message = format!("{} for device {}", err, devnode.display());
                return Err(EngineError::Engine(ErrorEnum::Invalid, error_message));
            }
        };

        Ok((devnode, dev_size, ownership, f))
    }

    /// Filter devices for admission to pool based on dev_infos.
    /// If there is an error finding out the info, return that error.
    /// Also, return an error if a device is not appropriate for this pool.
    fn filter_devs<I>(dev_infos: I,
                      pool_uuid: &PoolUuid,
                      force: bool)
                      -> EngineResult<Vec<(Device, (PathBuf, Bytes, File))>>
        where I: Iterator<Item = (Device, EngineResult<(PathBuf, Bytes, DevOwnership, File)>)>
    {
        let mut add_devs = Vec::new();
        for (dev, dev_result) in dev_infos {
            let (devnode, dev_size, ownership, f) = try!(dev_result);
            if dev_size < MIN_DEV_SIZE {
                let error_message = format!("{} too small, minimum {} bytes",
                                            devnode.display(),
                                            MIN_DEV_SIZE);
                return Err(EngineError::Engine(ErrorEnum::Invalid, error_message));
            };
            match ownership {
                DevOwnership::Unowned => add_devs.push((dev, (devnode, dev_size, f))),
                DevOwnership::Theirs => {
                    if !force {
                        let error_str = format!("First 8K of {} not zeroed", devnode.display());
                        return Err(EngineError::Engine(ErrorEnum::Invalid, error_str));
                    } else {
                        add_devs.push((dev, (devnode, dev_size, f)))
                    }
                }
                DevOwnership::Ours(uuid) => {
                    if *pool_uuid != uuid {
                        let error_str = format!("Device {} already belongs to Stratis pool {}",
                                                devnode.display(),
                                                uuid);
                        return Err(EngineError::Engine(ErrorEnum::Invalid, error_str));
                    }
                }
            }
        }
        Ok(add_devs)
    }

    try!(validate_mda_size(mda_size));

    let dev_infos = devices.into_iter().map(|d: Device| (d, dev_info(&d)));

    let add_devs = try!(filter_devs(dev_infos, pool_uuid, force));

    // TODO: Fix this code.  We should deal with any number of blockdevs
    //
    if add_devs.len() < 2 {
        return Err(EngineError::Engine(ErrorEnum::Error,
                                       "Need at least 2 blockdevs to create a pool".into()));
    }

    let mut bds = Vec::new();
    for (dev, (devnode, dev_size, mut f)) in add_devs {

        let bda = try!(BDA::initialize(&mut f,
                                       pool_uuid,
                                       &Uuid::new_v4(),
                                       mda_size,
                                       dev_size.sectors()));

        let bd = BlockDev {
            dev: dev,
            devnode: devnode.clone(),
            bda: bda,
        };
        bds.push(bd);
    }
    Ok(bds)
}

#[derive(Debug)]
pub struct BlockDev {
    dev: Device,
    pub devnode: PathBuf,
    bda: BDA,
}

impl BlockDev {
    pub fn to_save(&self) -> BlockDevSave {
        BlockDevSave {
            devnode: self.devnode.clone(),
            total_size: self.size(),
        }
    }

    pub fn wipe_metadata(self) -> EngineResult<()> {
        let mut f = try!(OpenOptions::new().write(true).open(&self.devnode));
        BDA::wipe(&mut f)
    }

    /// Get the "x:y" device string for this blockdev
    pub fn dstr(&self) -> String {
        self.dev.dstr()
    }

    pub fn save_state(&mut self, time: &Timespec, metadata: &[u8]) -> EngineResult<()> {
        let mut f = try!(OpenOptions::new().write(true).open(&self.devnode));
        self.bda.save_state(time, metadata, &mut f)
    }

    pub fn load_state(&self) -> EngineResult<Option<Vec<u8>>> {
        let mut f = try!(OpenOptions::new().read(true).open(&self.devnode));
        self.bda.load_state(&mut f)
    }

    /// List the available-for-upper-layer-use range in this blockdev.
    fn avail_range(&self) -> (Sectors, Sectors) {
        let start = self.bda.size();
        let size = self.size();
        // Blockdev size is at least MIN_DEV_SIZE, so this can fail only if
        // size of metadata area exceeds 1 GiB. Initial metadata area size
        // is 4 MiB.
        assert!(start <= size);
        (start, size - start)
    }

    /// Return the available range as a segment
    pub fn avail_range_segment(&self) -> Segment {
        let (start, length) = self.avail_range();
        Segment::new(self.dev, start, length)
    }

    /// The /dev/mapper/<name> device is not immediately available for use.
    /// TODO: Implement wait for event or poll.
    pub fn wait_for_dm() {
        thread::sleep(Duration::from_millis(500))
    }

    /// The device's UUID.
    pub fn uuid(&self) -> &DevUuid {
        self.bda.dev_uuid()
    }

    /// The device's pool's UUID.
    pub fn pool_uuid(&self) -> &PoolUuid {
        self.bda.pool_uuid()
    }

    /// The device's size.
    pub fn size(&self) -> Sectors {
        self.bda.dev_size()
    }

    /// Last time metadata was written to this device.
    pub fn last_update_time(&self) -> Option<&Timespec> {
        self.bda.last_update_time()
    }
}
<|endoftext|>