<commit_before>//! This module implements the root command of the CLI tool.

use std::io;
use std::io::Write;
use std::env;
use std::process;

use log;
use clap::{Arg, App, AppSettings};

use prelude::*;
use constants::VERSION;
use utils::{make_subcommand, Logger};
use config::{Config, Auth};

const ABOUT: &'static str = "
Command line utility for Sentry.

This tool helps you managing remote resources on a Sentry server like
sourcemaps, debug symbols, releases or similar.  Use `--help` on the
subcommands to learn more about them.";

macro_rules! each_subcommand {
    ($mac:ident) => {
        $mac!(upload_dsym);
        $mac!(releases);
        $mac!(issues);
        $mac!(update);
        $mac!(uninstall);
        $mac!(info);
        $mac!(login);
        $mac!(send_event);
        $mac!(react_native_xcode);
    }
}

// it would be great if this could be a macro expansion as well
// but rust bug #37663 breaks location information then.
pub mod upload_dsym;
pub mod releases;
pub mod issues;
pub mod update;
pub mod uninstall;
pub mod info;
pub mod login;
pub mod send_event;
pub mod react_native_xcode;

/// Given an argument vector and a `Config` this executes the
/// command line and returns the result.
pub fn execute(args: Vec<String>, config: &mut Config) -> Result<()> {
    // special case for the xcode integration for react native.  For more
    // information see commands/react_native_xcode.rs
    if let Ok(val) = env::var("__SENTRY_RN_WRAP_XCODE_CALL") {
        env::remove_var("__SENTRY_RN_WRAP_XCODE_CALL");
        if &val == "1" {
            return react_native_xcode::wrap_call();
        }
    }

    let mut app = App::new("sentry-cli")
        .version(VERSION)
        .about(ABOUT)
        .max_term_width(100)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::UnifiedHelpMessage)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .arg(Arg::with_name("url")
            .value_name("URL")
            .long("url")
            .help("The sentry API URL{n}defaults to https://sentry.io/"))
        .arg(Arg::with_name("auth_token")
            .value_name("AUTH_TOKEN")
            .long("auth-token")
            .help("The sentry auth token to use"))
        .arg(Arg::with_name("api_key")
            .value_name("API_KEY")
            .long("api-key")
            .help("The sentry API key to use"))
        .arg(Arg::with_name("log_level")
            .value_name("LOG_LEVEL")
            .long("log-level")
            .help("The log level for sentry-cli{n}\
                   (valid levels: TRACE, DEBUG, INFO, WARN, ERROR)"));

    macro_rules! add_subcommand {
        ($name:ident) => {{
            app = app.subcommand($name::make_app(
                make_subcommand(&stringify!($name).replace("_", "-"))));
        }}
    }
    each_subcommand!(add_subcommand);

    let matches = app.get_matches_from_safe(args)?;

    if let Some(url) = matches.value_of("url") {
        config.url = url.to_owned();
    }
    if let Some(api_key) = matches.value_of("api_key") {
        config.auth = Some(Auth::Key(api_key.to_owned()));
    }
    if let Some(auth_token) = matches.value_of("auth_token") {
        config.auth = Some(Auth::Token(auth_token.to_owned()));
    }
    if let Some(level_str) = matches.value_of("log_level") {
        match level_str.parse() {
            Ok(level) => {
                config.log_level = level;
            }
            Err(_) => {
                fail!("Unknown log level: {}", level_str);
            }
        }
    }

    log::set_logger(|max_log_level| {
            max_log_level.set(config.log_level);
            Box::new(Logger)
        })
        .ok();

    macro_rules! execute_subcommand {
        ($name:ident) => {{
            let cmd = stringify!($name).replace("_", "-");
            if let Some(sub_matches) = matches.subcommand_matches(cmd) {
                return Ok($name::execute(&sub_matches, &config)?);
            }
        }}
    }
    each_subcommand!(execute_subcommand);
    unreachable!();
}

fn run() -> Result<()> {
    execute(env::args().collect(), &mut Config::from_cli_config()?)
}

/// Executes the command line application and exists the process.
pub fn main() {
    match run() {
        Ok(()) => process::exit(0),
        Err(err) => {
            if let &ErrorKind::Clap(ref clap_err) = err.kind() {
                clap_err.exit();
            }

            writeln!(&mut io::stderr(), "error: {}", err).ok();

            if env::var("RUST_BACKTRACE") == Ok("1".into()) {
                writeln!(&mut io::stderr(), "").ok();
                writeln!(&mut io::stderr(), "{:?}", err.backtrace()).ok();
            }

            process::exit(1);
        }
    }
}
<commit_msg>Do not provide the react-native-xcode command on non mac versions<commit_after>//! This module implements the root command of the CLI tool.

use std::io;
use std::io::Write;
use std::env;
use std::process;

use log;
use clap::{Arg, App, AppSettings};

use prelude::*;
use constants::VERSION;
use utils::{make_subcommand, Logger};
use config::{Config, Auth};

const ABOUT: &'static str = "
Command line utility for Sentry.

This tool helps you managing remote resources on a Sentry server like
sourcemaps, debug symbols, releases or similar.  Use `--help` on the
subcommands to learn more about them.";

macro_rules! each_subcommand {
    ($mac:ident) => {
        $mac!(upload_dsym);
        $mac!(releases);
        $mac!(issues);
        $mac!(update);
        $mac!(uninstall);
        $mac!(info);
        $mac!(login);
        $mac!(send_event);
        #[cfg(target_os="macos")]
        $mac!(react_native_xcode);
    }
}

// it would be great if this could be a macro expansion as well
// but rust bug #37663 breaks location information then.
pub mod upload_dsym;
pub mod releases;
pub mod issues;
pub mod update;
pub mod uninstall;
pub mod info;
pub mod login;
pub mod send_event;

#[cfg(target_os="macos")]
pub mod react_native_xcode;

/// Given an argument vector and a `Config` this executes the
/// command line and returns the result.
pub fn execute(args: Vec<String>, config: &mut Config) -> Result<()> {
    // special case for the xcode integration for react native.  For more
    // information see commands/react_native_xcode.rs
    if let Ok(val) = env::var("__SENTRY_RN_WRAP_XCODE_CALL") {
        env::remove_var("__SENTRY_RN_WRAP_XCODE_CALL");
        if &val == "1" {
            return react_native_xcode::wrap_call();
        }
    }

    let mut app = App::new("sentry-cli")
        .version(VERSION)
        .about(ABOUT)
        .max_term_width(100)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::UnifiedHelpMessage)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .arg(Arg::with_name("url")
            .value_name("URL")
            .long("url")
            .help("The sentry API URL{n}defaults to https://sentry.io/"))
        .arg(Arg::with_name("auth_token")
            .value_name("AUTH_TOKEN")
            .long("auth-token")
            .help("The sentry auth token to use"))
        .arg(Arg::with_name("api_key")
            .value_name("API_KEY")
            .long("api-key")
            .help("The sentry API key to use"))
        .arg(Arg::with_name("log_level")
            .value_name("LOG_LEVEL")
            .long("log-level")
            .help("The log level for sentry-cli{n}\
                   (valid levels: TRACE, DEBUG, INFO, WARN, ERROR)"));

    macro_rules! add_subcommand {
        ($name:ident) => {{
            app = app.subcommand($name::make_app(
                make_subcommand(&stringify!($name).replace("_", "-"))));
        }}
    }
    each_subcommand!(add_subcommand);

    let matches = app.get_matches_from_safe(args)?;

    if let Some(url) = matches.value_of("url") {
        config.url = url.to_owned();
    }
    if let Some(api_key) = matches.value_of("api_key") {
        config.auth = Some(Auth::Key(api_key.to_owned()));
    }
    if let Some(auth_token) = matches.value_of("auth_token") {
        config.auth = Some(Auth::Token(auth_token.to_owned()));
    }
    if let Some(level_str) = matches.value_of("log_level") {
        match level_str.parse() {
            Ok(level) => {
                config.log_level = level;
            }
            Err(_) => {
                fail!("Unknown log level: {}", level_str);
            }
        }
    }

    log::set_logger(|max_log_level| {
            max_log_level.set(config.log_level);
            Box::new(Logger)
        })
        .ok();

    macro_rules! execute_subcommand {
        ($name:ident) => {{
            let cmd = stringify!($name).replace("_", "-");
            if let Some(sub_matches) = matches.subcommand_matches(cmd) {
                return Ok($name::execute(&sub_matches, &config)?);
            }
        }}
    }
    each_subcommand!(execute_subcommand);
    unreachable!();
}

fn run() -> Result<()> {
    execute(env::args().collect(), &mut Config::from_cli_config()?)
}

/// Executes the command line application and exists the process.
pub fn main() {
    match run() {
        Ok(()) => process::exit(0),
        Err(err) => {
            if let &ErrorKind::Clap(ref clap_err) = err.kind() {
                clap_err.exit();
            }

            writeln!(&mut io::stderr(), "error: {}", err).ok();

            if env::var("RUST_BACKTRACE") == Ok("1".into()) {
                writeln!(&mut io::stderr(), "").ok();
                writeln!(&mut io::stderr(), "{:?}", err.backtrace()).ok();
            }

            process::exit(1);
        }
    }
}
<|endoftext|>


<commit_before>#[link(name="echo", vers="1.0.0", author="Derek Chiang")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Derek Chiang <derekchiang93@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::stderr;
use std::uint;
use extra::getopts::groups;

static VERSION: &'static str = "1.0.0";

fn print_char(c: char) {
    print!("{}", c);
}

fn to_char(bytes: &[u8], base: uint) -> char {
    uint::parse_bytes(bytes, base).unwrap() as u8 as char
}

fn isxdigit(c: u8) -> bool {
    match c as char {
        '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |
        '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' => true,
        _ => false
    }
}

fn isodigit(c: u8) -> bool {
    match c as char {
        '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => true,
        _ => false
    }
}

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        groups::optflag("n", "", "do not output the trailing newline"),
        groups::optflag("e", "", "enable interpretation of backslash escapes"),
        groups::optflag("E", "", "disable interpretation of backslash escapes (default)"),
        groups::optflag("h", "help", "display this help and exit"),
        groups::optflag("V", "version", "output version information and exit"),
    ];

    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer,
                "Invalid options\n{}", f.to_err_msg());
            os::set_exit_status(1);
            return
        }
    };

    if matches.opt_present("help") {
        println("echo " + VERSION + " - display a line of text");
        println("");
        println("Usage:");
        println!("  {0:s} [SHORT-OPTION]... [STRING]...", program);
        println!("  {0:s} LONG-OPTION", program);
        println("");
        print(groups::usage("Echo the STRING(s) to standard output.", opts));
        print("\nIf -e is in effect, the following sequences are recognized:\n\
\n\
  \\\\      backslash\n\
  \\a      alert (BEL)\n\
  \\b      backspace\n\
  \\c      produce no further output\n\
  \\e      escape\n\
  \\f      form feed\n\
  \\n      new line\n\
  \\r      carriage return\n\
  \\t      horizontal tab\n\
  \\v      vertical tab\n\
  \\0NNN   byte with octal value NNN (1 to 3 digits)\n\
  \\xHH    byte with hexadecimal value HH (1 to 2 digits)\n\
");
        return;
    }

    if matches.opt_present("version") {
        return println("echo version: " + VERSION);
    }

    if matches.free.is_empty() {
        print("");
    } else {
        let string = matches.free.connect(" ");
        if matches.opt_present("e") {
            let mut prev_was_slash = false;
            let mut iter = string.chars().enumerate();
            loop {
                match iter.next() {
                    Some((index, c)) => {
                        if !prev_was_slash {
                            if c != '\\' {
                                print_char(c);
                            } else {
                                prev_was_slash = true;
                            }
                        } else {
                            prev_was_slash = false;
                            match c {
                                '\\' => print_char('\\'),
                                'a' => print_char('\x07'),
                                'b' => print_char('\x08'),
                                'c' => break,
                                'e' => print_char('\x1B'),
                                'f' => print_char('\x0C'),
                                'n' => print_char('\n'),
                                'r' => print_char('\r'),
                                't' => print_char('\t'),
                                'v' => print_char('\x0B'),
                                'x' => {
                                    if index == string.len() - 1 {
                                        print_char('\\');
                                        print_char('x');
                                    } else if index == string.len() - 2 {
                                        let next_char = string[index + 1];
                                        if isxdigit(next_char) {
                                            print_char(to_char([next_char as u8], 16u));
                                            iter.next();
                                        } else {
                                            print_char('\\');
                                            print_char('x');
                                        }
                                    } else {
                                        let next_char = string[index + 1];
                                        let next_next_char = string[index + 2];
                                        match (isxdigit(next_char), isxdigit(next_next_char)) {
                                            (true, true) => {
                                                print_char(to_char([next_char as u8, next_next_char as u8], 16u));
                                                iter.next(); iter.next();
                                            }
                                            (true, false) => {
                                                print_char(to_char([next_char as u8], 16u));
                                                iter.next();
                                            }
                                            _ => {
                                                print_char('\\');
                                                print_char('x');
                                            }
                                        };
                                    }
                                },
                                '0' => {
                                    if index == string.len() - 1 {
                                        print_char('\\');
                                        print_char('0');
                                    } else if index == string.len() - 2 {
                                        let next_char = string[index + 1];
                                        if isodigit(next_char) {
                                            print_char(to_char([next_char as u8], 8u));
                                            iter.next();
                                        } else {
                                            print_char('\\');
                                            print_char('0');
                                        }
                                    } else if index == string.len() - 3 {
                                        let next_char = string[index + 1];
                                        let next_next_char = string[index + 2];
                                        match (isodigit(next_char), isodigit(next_next_char)) {
                                            (true, true) => {
                                                print_char(to_char([next_char as u8, next_next_char as u8], 8u));
                                                iter.next(); iter.next();
                                            }
                                            (true, false) => {
                                                print_char(to_char([next_char as u8], 8u));
                                                iter.next();
                                            }
                                            _ => {
                                                print_char('\\');
                                                print_char('x');
                                            }
                                        };
                                    } else {
                                        let next_char = string[index + 1];
                                        let next_next_char = string[index + 2];
                                        let next_next_next_char = string[index + 3];
                                        match (isodigit(next_char), isodigit(next_next_char),
                                            isodigit(next_next_next_char)) {
                                            (true, true, true) => {
                                                print_char(to_char([next_char as u8, next_next_char as u8, next_next_next_char as u8], 8u));
                                                iter.next(); iter.next(); iter.next();
                                            }
                                            (true, true, false) => {
                                                print_char(to_char([next_char as u8, next_next_char as u8], 8u));
                                                iter.next(); iter.next();
                                            }
                                            (true, false, false) => {
                                                print_char(to_char([next_char as u8], 8u));
                                                iter.next();
                                            }
                                            _ => {
                                                print_char('\\');
                                                print_char('x');
                                            }
                                        };
                                    }
                                }
                                _ => {
                                    print_char('\\');
                                    print_char(c);
                                }
                            }
                        }
                    }
                    None => break
                }
            }
        } else {
            print(string);
        }
    }

    if !matches.opt_present("n") {
        println("")
    }
}
<commit_msg>Refactoring<commit_after>#[link(name="echo", vers="1.0.0", author="Derek Chiang")];

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Derek Chiang <derekchiang93@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern mod extra;

use std::os;
use std::io::stderr;
use std::uint;
use extra::getopts::groups;

static VERSION: &'static str = "1.0.0";

fn print_char(c: char) {
    print!("{}", c);
}

fn to_char(bytes: &[u8], base: uint) -> char {
    uint::parse_bytes(bytes, base).unwrap() as u8 as char
}

fn isxdigit(c: u8) -> bool {
    match c as char {
        '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |
        '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' => true,
        _ => false
    }
}

fn isodigit(c: u8) -> bool {
    match c as char {
        '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => true,
        _ => false
    }
}

fn main() {
    let args = os::args();
    let program = args[0].clone();
    let opts = ~[
        groups::optflag("n", "", "do not output the trailing newline"),
        groups::optflag("e", "", "enable interpretation of backslash escapes"),
        groups::optflag("E", "", "disable interpretation of backslash escapes (default)"),
        groups::optflag("h", "help", "display this help and exit"),
        groups::optflag("V", "version", "output version information and exit"),
    ];

    let matches = match groups::getopts(args.tail(), opts) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut stderr() as &mut Writer,
                "Invalid options\n{}", f.to_err_msg());
            os::set_exit_status(1);
            return
        }
    };

    if matches.opt_present("help") {
        println("echo " + VERSION + " - display a line of text");
        println("");
        println("Usage:");
        println!("  {0:s} [SHORT-OPTION]... [STRING]...", program);
        println!("  {0:s} LONG-OPTION", program);
        println("");
        print(groups::usage("Echo the STRING(s) to standard output.", opts));
        print("\nIf -e is in effect, the following sequences are recognized:\n\
\n\
  \\\\      backslash\n\
  \\a      alert (BEL)\n\
  \\b      backspace\n\
  \\c      produce no further output\n\
  \\e      escape\n\
  \\f      form feed\n\
  \\n      new line\n\
  \\r      carriage return\n\
  \\t      horizontal tab\n\
  \\v      vertical tab\n\
  \\0NNN   byte with octal value NNN (1 to 3 digits)\n\
  \\xHH    byte with hexadecimal value HH (1 to 2 digits)\n\
");
        return;
    }

    if matches.opt_present("version") {
        return println("echo version: " + VERSION);
    }

    if !matches.free.is_empty() {
        let string = matches.free.connect(" ");
        if matches.opt_present("e") {
            let mut prev_was_slash = false;
            let mut iter = string.chars().enumerate();
            loop {
                match iter.next() {
                    Some((index, c)) => {
                        if !prev_was_slash {
                            if c != '\\' {
                                print_char(c);
                            } else {
                                prev_was_slash = true;
                            }
                        } else {
                            prev_was_slash = false;
                            match c {
                                '\\' => print_char('\\'),
                                'a' => print_char('\x07'),
                                'b' => print_char('\x08'),
                                'c' => break,
                                'e' => print_char('\x1B'),
                                'f' => print_char('\x0C'),
                                'n' => print_char('\n'),
                                'r' => print_char('\r'),
                                't' => print_char('\t'),
                                'v' => print_char('\x0B'),
                                'x' => {
                                    if index == string.len() - 1 {
                                        print_char('\\');
                                        print_char('x');
                                    } else if index == string.len() - 2 {
                                        let next_char = string[index + 1];
                                        if isxdigit(next_char) {
                                            print_char(to_char([next_char as u8], 16u));
                                            iter.next();
                                        } else {
                                            print_char('\\');
                                            print_char('x');
                                        }
                                    } else {
                                        let next_char = string[index + 1];
                                        let next_next_char = string[index + 2];
                                        match (isxdigit(next_char), isxdigit(next_next_char)) {
                                            (true, true) => {
                                                print_char(to_char([next_char as u8, next_next_char as u8], 16u));
                                                iter.next(); iter.next();
                                            }
                                            (true, false) => {
                                                print_char(to_char([next_char as u8], 16u));
                                                iter.next();
                                            }
                                            _ => {
                                                print_char('\\');
                                                print_char('x');
                                            }
                                        };
                                    }
                                },
                                '0' => {
                                    if index == string.len() - 1 {
                                        print_char('\\');
                                        print_char('0');
                                    } else if index == string.len() - 2 {
                                        let next_char = string[index + 1];
                                        if isodigit(next_char) {
                                            print_char(to_char([next_char as u8], 8u));
                                            iter.next();
                                        } else {
                                            print_char('\\');
                                            print_char('0');
                                        }
                                    } else if index == string.len() - 3 {
                                        let next_char = string[index + 1];
                                        let next_next_char = string[index + 2];
                                        match (isodigit(next_char), isodigit(next_next_char)) {
                                            (true, true) => {
                                                print_char(to_char([next_char as u8, next_next_char as u8], 8u));
                                                iter.next(); iter.next();
                                            }
                                            (true, false) => {
                                                print_char(to_char([next_char as u8], 8u));
                                                iter.next();
                                            }
                                            _ => {
                                                print_char('\\');
                                                print_char('x');
                                            }
                                        };
                                    } else {
                                        let next_char = string[index + 1];
                                        let next_next_char = string[index + 2];
                                        let next_next_next_char = string[index + 3];
                                        match (isodigit(next_char), isodigit(next_next_char),
                                            isodigit(next_next_next_char)) {
                                            (true, true, true) => {
                                                print_char(to_char([next_char as u8, next_next_char as u8, next_next_next_char as u8], 8u));
                                                iter.next(); iter.next(); iter.next();
                                            }
                                            (true, true, false) => {
                                                print_char(to_char([next_char as u8, next_next_char as u8], 8u));
                                                iter.next(); iter.next();
                                            }
                                            (true, false, false) => {
                                                print_char(to_char([next_char as u8], 8u));
                                                iter.next();
                                            }
                                            _ => {
                                                print_char('\\');
                                                print_char('x');
                                            }
                                        };
                                    }
                                }
                                _ => {
                                    print_char('\\');
                                    print_char(c);
                                }
                            }
                        }
                    }
                    None => break
                }
            }
        } else {
            print(string);
        }
    }

    if !matches.opt_present("n") {
        println("")
    }
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#![feature(path_ext)]

extern crate claxon;
extern crate hound;

use std::fs;
use std::io;
use std::path;

fn run_metaflac(fname: &path::Path) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all streaminfo data.
    let output = Command::new("metaflac")
                         .arg("--show-min-blocksize")
                         .arg("--show-max-blocksize")
                         .arg("--show-min-framesize")
                         .arg("--show-max-framesize")
                         .arg("--show-sample-rate")
                         .arg("--show-channels")
                         .arg("--show-bps")
                         .arg("--show-total-samples")
                         .arg("--show-md5sum")
                         .arg(fname.to_str().expect("unsupported filename"))
                         .output().ok().expect("failed to run metaflac");
    String::from_utf8(output.stdout).ok().expect("metaflac wrote invalid UTF-8")
}

fn decode_file(fname: &path::Path) {
    use std::process::Command;

    // Run the the reference flac decoder on the file.
    let success = Command::new("flac")
                          .arg("--decode")
                          .arg(fname.to_str().expect("unsupported filename"))
                          .status().ok().expect("failed to run flac")
                          .success();
    assert!(success);
}

fn print_hex(seq: &[u8]) -> String {
    let vec: Vec<String> = seq.iter().map(|x| format!("{:0>2x}", *x)).collect();
    vec.concat()
}

fn read_streaminfo(fname: &path::Path) -> String {
    use claxon::FlacStream;

    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let reader = io::BufReader::new(file);
    let stream = FlacStream::new(reader).unwrap();
    let streaminfo = stream.streaminfo();

    // Format the streaminfo in the same way that metaflac prints it.
    format!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
            streaminfo.min_block_size,
            streaminfo.max_block_size,
            streaminfo.min_frame_size.unwrap_or(0),
            streaminfo.max_frame_size.unwrap_or(0),
            streaminfo.sample_rate,
            streaminfo.channels,
            streaminfo.bits_per_sample,
            streaminfo.samples.unwrap_or(0),
            print_hex(&streaminfo.md5sum)) // TODO implement LowerHex for &[u8] and submit a PR.
}

fn compare_metaflac(fname: &path::Path) {
    let metaflac = run_metaflac(fname);
    let streaminfo = read_streaminfo(fname);
    let mut mf_lines = metaflac.lines_any();
    let mut si_lines = streaminfo.lines_any();
    while let (Some(mf), Some(si)) = (mf_lines.next(), si_lines.next()) {
        if mf != si {
            println!("metaflac\n--------\n{}", metaflac);
            println!("streaminfo\n----------\n{}", streaminfo);
            panic!("metaflac disagrees on parsed streaminfo");
        }
    };
}

fn compare_decoded_stream(fname: &path::Path) {
    use std::fs::PathExt;

    let ref_fname = fname.with_extension("wav");
    if !ref_fname.exists() {
        // TODO: actually, we might only want to run the test for files that
        // do exist already. It is fine to run streaminfo or decode-only tests
        // on thousands of files, but decoding thousands of files to wav before
        // running the tests will take a lot of space. For now, while the
        // number of samples is closer to 10 than to 100, this is fine.
        decode_file(fname);
    }

    // If the reference file does exist after decoding, we can compare it to
    // how Claxon decodes it, sample by sample.
    if ref_fname.exists() {
        let mut ref_stream = hound::WavReader::open(ref_fname).unwrap();

        let try_file = fs::File::open(fname).unwrap();
        let try_reader = io::BufReader::new(try_file);
        let mut try_stream = claxon::FlacStream::new(try_reader).unwrap();

        // The streaminfo test will ensure that things like bit depth and
        // sample rate match, only the actual samples are compared here.

        let mut ref_samples = ref_stream.samples::<i32>();

        let samples = try_stream.streaminfo().samples.unwrap();
        let n_channels = try_stream.streaminfo().channels;
        let mut blocks = try_stream.blocks::<i32>();
        let mut sample = 0u64;
        let mut b = 0u64;

        while sample < samples {
            let block = blocks.read_next().unwrap();
            let mut channels: Vec<_> = (0 .. n_channels)
                                       .map(|i| block.channel(i).iter().cloned())
                                       .collect();
            for i in (0 .. block.len()) {
                for ch in (0 .. n_channels as usize) {
                    let ref_sample = ref_samples.next().map(|r| r.ok().unwrap());
                    let try_sample = channels[ch].next();
                    if ref_sample != try_sample {
                        println!("disagreement at sample {} of block {} in channel {}: reference is {} but decoded is {}",
                                 i, b, ch, ref_sample.unwrap(), try_sample.unwrap());
                        panic!("decoding differs from reference decoder");
                    }
                }
            }
            sample = sample + block.len() as u64;
            b = b + 1;
        }
    }
}

// Hard-coded tests for the test samples added py populate.sh.
// This allows us to run these tests in parallel and follow progress without
// enabling --nocapture.

#[test]
fn verify_streaminfo_p0() {
    compare_metaflac(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_streaminfo_p1() {
    compare_metaflac(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_streaminfo_p2() {
    compare_metaflac(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_streaminfo_p3() {
    compare_metaflac(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_streaminfo_p4() {
    compare_metaflac(path::Path::new("testsamples/p4.flac"));
}

#[test]
fn verify_decoded_stream_p0() {
    compare_decoded_stream(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_decoded_stream_p1() {
    compare_decoded_stream(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_decoded_stream_p2() {
    compare_decoded_stream(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_decoded_stream_p3() {
    compare_decoded_stream(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_decoded_stream_p4() {
    compare_decoded_stream(path::Path::new("testsamples/p4.flac"));
}
<commit_msg>use .lines() instead of deprecated .lines_any()<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#![feature(path_ext)]

extern crate claxon;
extern crate hound;

use std::fs;
use std::io;
use std::path;

fn run_metaflac(fname: &path::Path) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all streaminfo data.
    let output = Command::new("metaflac")
                         .arg("--show-min-blocksize")
                         .arg("--show-max-blocksize")
                         .arg("--show-min-framesize")
                         .arg("--show-max-framesize")
                         .arg("--show-sample-rate")
                         .arg("--show-channels")
                         .arg("--show-bps")
                         .arg("--show-total-samples")
                         .arg("--show-md5sum")
                         .arg(fname.to_str().expect("unsupported filename"))
                         .output().ok().expect("failed to run metaflac");
    String::from_utf8(output.stdout).ok().expect("metaflac wrote invalid UTF-8")
}

fn decode_file(fname: &path::Path) {
    use std::process::Command;

    // Run the the reference flac decoder on the file.
    let success = Command::new("flac")
                          .arg("--decode")
                          .arg(fname.to_str().expect("unsupported filename"))
                          .status().ok().expect("failed to run flac")
                          .success();
    assert!(success);
}

fn print_hex(seq: &[u8]) -> String {
    let vec: Vec<String> = seq.iter().map(|x| format!("{:0>2x}", *x)).collect();
    vec.concat()
}

fn read_streaminfo(fname: &path::Path) -> String {
    use claxon::FlacStream;

    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let reader = io::BufReader::new(file);
    let stream = FlacStream::new(reader).unwrap();
    let streaminfo = stream.streaminfo();

    // Format the streaminfo in the same way that metaflac prints it.
    format!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
            streaminfo.min_block_size,
            streaminfo.max_block_size,
            streaminfo.min_frame_size.unwrap_or(0),
            streaminfo.max_frame_size.unwrap_or(0),
            streaminfo.sample_rate,
            streaminfo.channels,
            streaminfo.bits_per_sample,
            streaminfo.samples.unwrap_or(0),
            print_hex(&streaminfo.md5sum)) // TODO implement LowerHex for &[u8] and submit a PR.
}

fn compare_metaflac(fname: &path::Path) {
    let metaflac = run_metaflac(fname);
    let streaminfo = read_streaminfo(fname);
    let mut mf_lines = metaflac.lines();
    let mut si_lines = streaminfo.lines();
    while let (Some(mf), Some(si)) = (mf_lines.next(), si_lines.next()) {
        if mf != si {
            println!("metaflac\n--------\n{}", metaflac);
            println!("streaminfo\n----------\n{}", streaminfo);
            panic!("metaflac disagrees on parsed streaminfo");
        }
    };
}

fn compare_decoded_stream(fname: &path::Path) {
    use std::fs::PathExt;

    let ref_fname = fname.with_extension("wav");
    if !ref_fname.exists() {
        // TODO: actually, we might only want to run the test for files that
        // do exist already. It is fine to run streaminfo or decode-only tests
        // on thousands of files, but decoding thousands of files to wav before
        // running the tests will take a lot of space. For now, while the
        // number of samples is closer to 10 than to 100, this is fine.
        decode_file(fname);
    }

    // If the reference file does exist after decoding, we can compare it to
    // how Claxon decodes it, sample by sample.
    if ref_fname.exists() {
        let mut ref_stream = hound::WavReader::open(ref_fname).unwrap();

        let try_file = fs::File::open(fname).unwrap();
        let try_reader = io::BufReader::new(try_file);
        let mut try_stream = claxon::FlacStream::new(try_reader).unwrap();

        // The streaminfo test will ensure that things like bit depth and
        // sample rate match, only the actual samples are compared here.

        let mut ref_samples = ref_stream.samples::<i32>();

        let samples = try_stream.streaminfo().samples.unwrap();
        let n_channels = try_stream.streaminfo().channels;
        let mut blocks = try_stream.blocks::<i32>();
        let mut sample = 0u64;
        let mut b = 0u64;

        while sample < samples {
            let block = blocks.read_next().unwrap();
            let mut channels: Vec<_> = (0 .. n_channels)
                                       .map(|i| block.channel(i).iter().cloned())
                                       .collect();
            for i in (0 .. block.len()) {
                for ch in (0 .. n_channels as usize) {
                    let ref_sample = ref_samples.next().map(|r| r.ok().unwrap());
                    let try_sample = channels[ch].next();
                    if ref_sample != try_sample {
                        println!("disagreement at sample {} of block {} in channel {}: reference is {} but decoded is {}",
                                 i, b, ch, ref_sample.unwrap(), try_sample.unwrap());
                        panic!("decoding differs from reference decoder");
                    }
                }
            }
            sample = sample + block.len() as u64;
            b = b + 1;
        }
    }
}

// Hard-coded tests for the test samples added py populate.sh.
// This allows us to run these tests in parallel and follow progress without
// enabling --nocapture.

#[test]
fn verify_streaminfo_p0() {
    compare_metaflac(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_streaminfo_p1() {
    compare_metaflac(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_streaminfo_p2() {
    compare_metaflac(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_streaminfo_p3() {
    compare_metaflac(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_streaminfo_p4() {
    compare_metaflac(path::Path::new("testsamples/p4.flac"));
}

#[test]
fn verify_decoded_stream_p0() {
    compare_decoded_stream(path::Path::new("testsamples/p0.flac"));
}

#[test]
fn verify_decoded_stream_p1() {
    compare_decoded_stream(path::Path::new("testsamples/p1.flac"));
}

#[test]
fn verify_decoded_stream_p2() {
    compare_decoded_stream(path::Path::new("testsamples/p2.flac"));
}

#[test]
fn verify_decoded_stream_p3() {
    compare_decoded_stream(path::Path::new("testsamples/p3.flac"));
}

#[test]
fn verify_decoded_stream_p4() {
    compare_decoded_stream(path::Path::new("testsamples/p4.flac"));
}
<|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::str;

use encoding::label::encoding_from_whatwg_label;
use encoding::all::UTF_8;
use encoding::Encoding;
use encoding::DecodeReplace;
use encoding::decode;

use tokenizer::{tokenize, Tokenizer};
use parser::{parse_stylesheet_rules, StylesheetParser};

/// Determine the character encoding of a CSS stylesheet and decode it.
///
/// This is based on the presence of a :abbr:`BOM (Byte Order Mark)`,
/// an `@charset` rule,
/// and encoding meta-information.
///
/// :param css_bytes: A byte string.
/// :param protocol_encoding:
///     The encoding label, if any, defined by HTTP or equivalent protocol.
///     (e.g. via the `charset` parameter of the `Content-Type` header.)
/// :param environment_encoding:
///     An optional `Encoding` object
///     for the `environment encoding
///     <http://www.w3.org/TR/css-syntax/#environment-encoding>`_,
///     if any.
/// :returns:
///     A 2-tuple of a decoded Unicode string
///     and the `Encoding` object that was used.
pub fn decode_stylesheet_bytes(css: &[u8], protocol_encoding_label: Option<&str>,
                               environment_encoding: Option<&'static Encoding>)
                            -> (~str, &'static Encoding) {
    // http://dev.w3.org/csswg/css-syntax/#the-input-byte-stream
    match protocol_encoding_label {
        None => (),
        Some(label) => match encoding_from_whatwg_label(label) {
            None => (),
            Some(fallback) => return decode_replace(css, fallback)
        }
    }
    if css.starts_with("@charset \"".as_bytes()) {
        // 10 is "@charset \"".len()
        // 100 is arbitrary so that no encoding label is more than 100-10 bytes.
        match css.slice(10, css.len().min(&100)).position_elem(&('"' as u8)) {
            None => (),
            Some(label_length)
            => if css.slice_from(10 + label_length).starts_with("\";".as_bytes()) {
                let label = css.slice(10, 10 + label_length);
                let label = str::from_chars(label.iter().map(|&b| b as char).to_owned_vec());
                match encoding_from_whatwg_label(label) {
                    None => (),
                    Some(fallback) => match fallback.name() {
                        "utf-16be" | "utf-16le"
                        => return decode_replace(css, UTF_8 as &'static Encoding),
                        _ => return decode_replace(css, fallback),
                    }
                }
            }
        }
    }
    match environment_encoding {
        None => (),
        Some(fallback) => return decode_replace(css, fallback)
    }
    return decode_replace(css, UTF_8 as &'static Encoding)
}

#[inline]
fn decode_replace(input: &[u8], fallback_encoding: &'static Encoding)-> (~str, &'static Encoding) {
    let (result, used_encoding) = decode(input, DecodeReplace, fallback_encoding);
    (result.unwrap(), used_encoding)
}

/// Parse stylesheet from bytes.
///
/// :param css_bytes: A byte string.
/// :param protocol_encoding:
///     The encoding label, if any, defined by HTTP or equivalent protocol.
///     (e.g. via the `charset` parameter of the `Content-Type` header.)
/// :param environment_encoding:
///     An optional `Encoding` object
///     for the `environment encoding
///     <http://www.w3.org/TR/css-syntax/#environment-encoding>`_,
///     if any.
/// :returns:
///     A 2-tuple of a Iterator<Result<Rule, SyntaxError>>
///     and the `Encoding` object that was used.
pub fn parse_stylesheet_rules_from_bytes(
        css_bytes: &[u8], protocol_encoding_label: Option<&str>,
        environment_encoding: Option<&'static Encoding>)
     -> (StylesheetParser<Tokenizer>, &'static Encoding) {
    let (css_unicode, encoding) = decode_stylesheet_bytes(
        css_bytes, protocol_encoding_label, environment_encoding);
    (parse_stylesheet_rules(tokenize(css_unicode)), encoding)
}
<commit_msg>Use rust-encoding’s new EncodeObj type.<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::str;

use encoding::label::encoding_from_whatwg_label;
use encoding::all::UTF_8;
use encoding::{EncodingObj, DecodeReplace, decode};

use tokenizer::{tokenize, Tokenizer};
use parser::{parse_stylesheet_rules, StylesheetParser};

/// Determine the character encoding of a CSS stylesheet and decode it.
///
/// This is based on the presence of a :abbr:`BOM (Byte Order Mark)`,
/// an `@charset` rule,
/// and encoding meta-information.
///
/// :param css_bytes: A byte string.
/// :param protocol_encoding:
///     The encoding label, if any, defined by HTTP or equivalent protocol.
///     (e.g. via the `charset` parameter of the `Content-Type` header.)
/// :param environment_encoding:
///     An optional `Encoding` object
///     for the `environment encoding
///     <http://www.w3.org/TR/css-syntax/#environment-encoding>`_,
///     if any.
/// :returns:
///     A 2-tuple of a decoded Unicode string
///     and the `Encoding` object that was used.
pub fn decode_stylesheet_bytes(css: &[u8], protocol_encoding_label: Option<&str>,
                               environment_encoding: Option<EncodingObj>)
                            -> (~str, EncodingObj) {
    // http://dev.w3.org/csswg/css-syntax/#the-input-byte-stream
    match protocol_encoding_label {
        None => (),
        Some(label) => match encoding_from_whatwg_label(label) {
            None => (),
            Some(fallback) => return decode_replace(css, fallback)
        }
    }
    if css.starts_with("@charset \"".as_bytes()) {
        // 10 is "@charset \"".len()
        // 100 is arbitrary so that no encoding label is more than 100-10 bytes.
        match css.slice(10, css.len().min(&100)).position_elem(&('"' as u8)) {
            None => (),
            Some(label_length)
            => if css.slice_from(10 + label_length).starts_with("\";".as_bytes()) {
                let label = css.slice(10, 10 + label_length);
                let label = str::from_chars(label.iter().map(|&b| b as char).to_owned_vec());
                match encoding_from_whatwg_label(label) {
                    None => (),
                    Some(fallback) => match fallback.name() {
                        "utf-16be" | "utf-16le"
                        => return decode_replace(css, UTF_8 as EncodingObj),
                        _ => return decode_replace(css, fallback),
                    }
                }
            }
        }
    }
    match environment_encoding {
        None => (),
        Some(fallback) => return decode_replace(css, fallback)
    }
    return decode_replace(css, UTF_8 as EncodingObj)
}

#[inline]
fn decode_replace(input: &[u8], fallback_encoding: EncodingObj)-> (~str, EncodingObj) {
    let (result, used_encoding) = decode(input, DecodeReplace, fallback_encoding);
    (result.unwrap(), used_encoding)
}

/// Parse stylesheet from bytes.
///
/// :param css_bytes: A byte string.
/// :param protocol_encoding:
///     The encoding label, if any, defined by HTTP or equivalent protocol.
///     (e.g. via the `charset` parameter of the `Content-Type` header.)
/// :param environment_encoding:
///     An optional `Encoding` object
///     for the `environment encoding
///     <http://www.w3.org/TR/css-syntax/#environment-encoding>`_,
///     if any.
/// :returns:
///     A 2-tuple of a Iterator<Result<Rule, SyntaxError>>
///     and the `Encoding` object that was used.
pub fn parse_stylesheet_rules_from_bytes(
        css_bytes: &[u8], protocol_encoding_label: Option<&str>,
        environment_encoding: Option<EncodingObj>)
     -> (StylesheetParser<Tokenizer>, EncodingObj) {
    let (css_unicode, encoding) = decode_stylesheet_bytes(
        css_bytes, protocol_encoding_label, environment_encoding);
    (parse_stylesheet_rules(tokenize(css_unicode)), encoding)
}
<|endoftext|>


<commit_before>extern crate std;
extern crate libc;

use std::io::Command;
use std::str;
use std::option::Option;
use std::collections::TrieSet;
use libc::{execvp, perror};
//use std::c_str::ptr;
use std::ptr;
use std::os;

fn detached_session_number(line: &str) -> Option<uint> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split(':').next().and_then(|s| from_str(s))
    }
}

fn detached_sessions(output: &str) -> TrieSet {
    output.lines().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

fn exec_program(program: &str, args: &[&str]) {
    program.with_c_str(|c_program| {
            // I don't much care about the ownership of the strings here
            // at this point, so let's just fail if execvp isn't working.
            unsafe {
                let mut c_args = vec![];
                for &arg in args.iter() {
                    c_args.push(arg.to_c_str().unwrap());
                }
                c_args.push(ptr::null());
                execvp(c_program, c_args.as_ptr());
                perror("Running tmux failed:".to_c_str().unwrap());
            }
        });
    fail!("Couldn't exec {:s}", program);
}

fn prepare_environment() {
    let path = match os::getenv("PATH") {
        Some(path) => path + ":/usr/local/bin",
        _ => "/bin:/usr/bin:/usr/local/bin".to_str()
    };
    os::setenv("PATH", path.as_slice());
}

fn start_server() {
    match Command::new("tmux").arg("start-server").status() {
        Ok(status) => status,
        Err(e) => fail!("Could not start tmux server: exited with an error status: {}", e),
    };
}

fn main() {
    prepare_environment();

    start_server();
    let session_output = Command::new("tmux").arg("list-sessions").output();
    match session_output {
        Ok(o) => {
            match str::from_utf8(o.output.as_slice()) {
                Some(output) => {
                    let sessions = detached_sessions(output);
                    match sessions.iter().next() {
                        Some(n) => {
                            let my_str = n.to_str();
                            let session = my_str.as_slice();
                            let mut args: Vec<&str> = vec!["tmux", "attach-session", "-t"];
                            args.push(session);
                            exec_program("tmux", args.as_slice());
                        }
                        _ => { exec_program("tmux", ["tmux"]); }
                    }
                },
                None => fail!("Could not parse the utf-8 returned by tmux!"),
            }
        },
        Err(e) => fail!("Tmux exited with an error status: {}", e),
    };
}

#[test]
fn test_session_number_with_numbers(){
    match(detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(11) => (),
        Some(n) => fail!(format!("Should have returned 11, got {:u}!", n)),
        None => fail!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match(detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(n) => fail!(format!("Should have returned None, got {:u}!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match(detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(n) => fail!(format!("Should have returned None, got {:u}!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions("3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<commit_msg>Use ok() and expect() to reduce match depths in start_server<commit_after>extern crate std;
extern crate libc;

use std::io::Command;
use std::str;
use std::option::Option;
use std::collections::TrieSet;
use libc::{execvp, perror};
//use std::c_str::ptr;
use std::ptr;
use std::os;

fn detached_session_number(line: &str) -> Option<uint> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split(':').next().and_then(|s| from_str(s))
    }
}

fn detached_sessions(output: &str) -> TrieSet {
    output.lines().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

fn exec_program(program: &str, args: &[&str]) {
    program.with_c_str(|c_program| {
            // I don't much care about the ownership of the strings here
            // at this point, so let's just fail if execvp isn't working.
            unsafe {
                let mut c_args = vec![];
                for &arg in args.iter() {
                    c_args.push(arg.to_c_str().unwrap());
                }
                c_args.push(ptr::null());
                execvp(c_program, c_args.as_ptr());
                perror("Running tmux failed:".to_c_str().unwrap());
            }
        });
    fail!("Couldn't exec {:s}", program);
}

fn prepare_environment() {
    let path = match os::getenv("PATH") {
        Some(path) => path + ":/usr/local/bin",
        _ => "/bin:/usr/bin:/usr/local/bin".to_str()
    };
    os::setenv("PATH", path.as_slice());
}

fn start_server() {
    Command::new("tmux").arg("start-server").status().ok().
        expect("Could not start tmux server: it exited with an error status.");
}

fn main() {
    prepare_environment();

    start_server();
    let session_output = Command::new("tmux").arg("list-sessions").output();
    match session_output {
        Ok(o) => {
            match str::from_utf8(o.output.as_slice()) {
                Some(output) => {
                    let sessions = detached_sessions(output);
                    match sessions.iter().next() {
                        Some(n) => {
                            let my_str = n.to_str();
                            let session = my_str.as_slice();
                            let mut args: Vec<&str> = vec!["tmux", "attach-session", "-t"];
                            args.push(session);
                            exec_program("tmux", args.as_slice());
                        }
                        _ => { exec_program("tmux", ["tmux"]); }
                    }
                },
                None => fail!("Could not parse the utf-8 returned by tmux!"),
            }
        },
        Err(e) => fail!("Tmux exited with an error status: {}", e),
    };
}

#[test]
fn test_session_number_with_numbers(){
    match(detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(11) => (),
        Some(n) => fail!(format!("Should have returned 11, got {:u}!", n)),
        None => fail!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match(detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(n) => fail!(format!("Should have returned None, got {:u}!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match(detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(n) => fail!(format!("Should have returned None, got {:u}!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions("3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;

use std::collections::{VecDeque};
use std::cmp;
use std::ffi::CString;
use std::old_io::{IoResult, IoError};
use std::iter::repeat;
use std::mem;
use std::sync::Arc;

use bindings::bpf;
use old_packet::Packet;
use old_packet::ethernet::{EthernetHeader, MutableEthernetHeader};
use datalink::DataLinkChannelType;
use datalink::DataLinkChannelType::{Layer2, Layer3};
use internal;
use util::NetworkInterface;

// NOTE buffer must be word aligned.
pub fn datalink_channel(network_interface: &NetworkInterface,
                        write_buffer_size: usize,
                        read_buffer_size: usize,
                        channel_type: DataLinkChannelType)
    -> IoResult<(DataLinkSenderImpl, DataLinkReceiverImpl)> {
    #[cfg(target_os = "freebsd")]
    fn get_fd() -> libc::c_int {
        unsafe {
            libc::open(CString::from_slice("/dev/bpf").as_ptr(), libc::O_RDWR, 0)
        }
    }

    #[cfg(target_os = "macos")]
    fn get_fd() -> libc::c_int {
        // FIXME This is an arbitrary number of attempts
        for i in (0..1_000is) {
            let fd = unsafe {
                let file_name = format!("/dev/bpf{}", i);
                libc::open(CString::from_slice(file_name.as_bytes()).as_ptr(), libc::O_RDWR, 0)
            };
            if fd != -1 {
                return fd;
            }
        }
        return -1;
    }

    #[cfg(target_os = "freebsd")]
    fn set_feedback(fd: libc::c_int) -> Result<(), IoError> {
        let one: libc::c_uint = 1;
        if unsafe { bpf::ioctl(fd, bpf::BIOCFEEDBACK, &one) } == -1 {
            let err = IoError::last_error();
            unsafe { libc::close(fd); }
            return Err(err);
        }
        Ok(())
    }

    #[cfg(target_os = "macos")]
    fn set_feedback(_fd: libc::c_int) -> Result<(), IoError> {
        Ok(())
    }

    match channel_type {
        Layer2 => (),
        Layer3(_) => unimplemented!(),
    }

    let fd = get_fd();
    if fd == -1 {
        return Err(IoError::last_error());
    }
    let mut iface: bpf::ifreq = unsafe { mem::zeroed() };
    let mut i = 0;
    for c in network_interface.name.as_slice().bytes() {
        iface.ifr_name[i] = c as i8;
        i += 1;
    }

    let buflen = read_buffer_size as libc::c_uint;
    // NOTE Buffer length must be set before binding to an interface
    //      otherwise this will return Invalid Argument
    if unsafe { bpf::ioctl(fd, bpf::BIOCSBLEN, &buflen) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // Set the interface to use
    if unsafe { bpf::ioctl(fd, bpf::BIOCSETIF, &iface) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // Return from read as soon as packets are available - don't wait to fill the buffer
    let one: libc::c_uint = 1;
    if unsafe { bpf::ioctl(fd, bpf::BIOCIMMEDIATE, &one) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    let mut header_size = 0;

    // Get the device type
    let mut dlt: libc::c_uint = 0;
    if unsafe { bpf::ioctl(fd, bpf::BIOCGDLT, &mut dlt) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // The loopback IoError::last_error()device does weird things
    // FIXME This should really just be another L2 packet header type
    if dlt == bpf::DLT_NULL {
        header_size = 4;

        // Allow packets to be read back after they are written
        match set_feedback(fd) {
            Err(e) => return Err(e),
            _ => ()
        }

    } else {
        // Don't fill in source MAC
        if unsafe { bpf::ioctl(fd, bpf::BIOCSHDRCMPLT, &one) } == -1 {
            let err = IoError::last_error();
            unsafe { libc::close(fd); }
            return Err(err);
        }
    }

    let fd = Arc::new(internal::FileDesc { fd: fd });
    let sender = DataLinkSenderImpl {
        fd: fd.clone(),
        write_buffer: repeat(0u8).take(write_buffer_size).collect(),
        header_size: header_size,
    };
    let receiver = DataLinkReceiverImpl {
        fd: fd,
        read_buffer: repeat(0u8).take(read_buffer_size).collect(),
        header_size: header_size,
    };

    Ok((sender, receiver))
}

pub struct DataLinkSenderImpl {
    fd: Arc<internal::FileDesc>,
    write_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkSenderImpl {
    pub fn build_and_send<F>(&mut self, num_packets: usize, packet_size: usize,
                          func: &mut F) -> Option<IoResult<()>>
        where F : FnMut(MutableEthernetHeader)
    {
        let len = num_packets * (packet_size + self.header_size);
        if len >= self.write_buffer.len() {
            None
        } else {
            let min = cmp::min(self.write_buffer.len(), len);
            for chunk in self.write_buffer[..min]
                                          .chunks_mut(packet_size + self.header_size) {
                // If we're sending on the loopback device, the first 4 bytes must be set to
                // AF_INET
                if self.header_size == 4 {
                    unsafe {
                        *(chunk.as_mut_ptr() as *mut u32) = libc::AF_INET as u32;
                    }
                }
                {
                    let eh = MutableEthernetHeader::new(&mut chunk[self.header_size..]);
                    func(eh);
                }
                match unsafe { libc::write(self.fd.fd,
                                           chunk.as_ptr() as *const libc::c_void,
                                           chunk.len() as libc::size_t) } {
                    len if len == -1 => return Some(Err(IoError::last_error())),
                    _ => ()
                }
            }
            Some(Ok(()))
        }
    }

    pub fn send_to(&mut self, packet: EthernetHeader, _dst: Option<NetworkInterface>)
        -> Option<IoResult<()>> {
        match unsafe { libc::write(self.fd.fd,
                                   packet.packet().as_ptr() as *const libc::c_void,
                                   packet.packet().len() as libc::size_t) } {
            len if len == -1 => Some(Err(IoError::last_error())),
            _ => Some(Ok(()))
        }
    }
}

pub struct DataLinkReceiverImpl {
    fd: Arc<internal::FileDesc>,
    read_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkReceiverImpl {
    pub fn iter<'a>(&'a mut self) -> DataLinkChannelIteratorImpl<'a> {
        let buflen = self.read_buffer.len();
        DataLinkChannelIteratorImpl {
            pc: self,
            // Enough room for minimally sized packets without reallocating
            packets: VecDeque::with_capacity(buflen / 64)
        }
    }
}

pub struct DataLinkChannelIteratorImpl<'a> {
    pc: &'a mut DataLinkReceiverImpl,
    packets: VecDeque<(usize, usize)>,
}

impl<'a> DataLinkChannelIteratorImpl<'a> {
    pub fn next<'c>(&'c mut self) -> IoResult<EthernetHeader<'c>> {
        if self.packets.is_empty() {
            let buflen = match unsafe {
                libc::read(self.pc.fd.fd,
                           self.pc.read_buffer.as_ptr() as *mut libc::c_void,
                           self.pc.read_buffer.len() as libc::size_t)
            } {
                len if len > 0 => len,
                _ => return Err(IoError::last_error())
            };
            let mut ptr = self.pc.read_buffer.as_mut_ptr();
            let end = unsafe { self.pc.read_buffer.as_ptr().offset(buflen as isize) };
            while (ptr as *const u8) < end {
                unsafe {
                    let packet: *const bpf::bpf_hdr = mem::transmute(ptr);
                    let start = ptr as isize +
                                (*packet).bh_hdrlen as isize -
                                self.pc.read_buffer.as_ptr() as isize;
                    self.packets.push_back((start as usize + self.pc.header_size,
                                      (*packet).bh_caplen as usize - self.pc.header_size));
                    let offset = (*packet).bh_hdrlen as isize + (*packet).bh_caplen as isize;
                    ptr = ptr.offset(bpf::BPF_WORDALIGN(offset));
                }
            }
        }
        let (start, len) = self.packets.pop_front().unwrap();
        Ok(EthernetHeader::new(&self.pc.read_buffer[start .. start + len]))
    }
}

<commit_msg>Hopefully fix OS X build on latest master.<commit_after>// Copyright (c) 2014 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;

use std::collections::{VecDeque};
use std::cmp;
use std::ffi::CString;
use std::old_io::{IoResult, IoError};
use std::iter::repeat;
use std::mem;
use std::sync::Arc;

use bindings::bpf;
use old_packet::Packet;
use old_packet::ethernet::{EthernetHeader, MutableEthernetHeader};
use datalink::DataLinkChannelType;
use datalink::DataLinkChannelType::{Layer2, Layer3};
use internal;
use util::NetworkInterface;

// NOTE buffer must be word aligned.
pub fn datalink_channel(network_interface: &NetworkInterface,
                        write_buffer_size: usize,
                        read_buffer_size: usize,
                        channel_type: DataLinkChannelType)
    -> IoResult<(DataLinkSenderImpl, DataLinkReceiverImpl)> {
    #[cfg(target_os = "freebsd")]
    fn get_fd() -> libc::c_int {
        unsafe {
            libc::open(CString::new(&b"/dev/bpf"[..]).unwrap().as_ptr(), libc::O_RDWR, 0)
        }
    }

    #[cfg(target_os = "macos")]
    fn get_fd() -> libc::c_int {
        // FIXME This is an arbitrary number of attempts
        for i in (0..1_000is) {
            let fd = unsafe {
                let file_name = format!("/dev/bpf{}", i);
                libc::open(CString::new(file_name.as_bytes()).unwrap().as_ptr(), libc::O_RDWR, 0)
            };
            if fd != -1 {
                return fd;
            }
        }
        return -1;
    }

    #[cfg(target_os = "freebsd")]
    fn set_feedback(fd: libc::c_int) -> Result<(), IoError> {
        let one: libc::c_uint = 1;
        if unsafe { bpf::ioctl(fd, bpf::BIOCFEEDBACK, &one) } == -1 {
            let err = IoError::last_error();
            unsafe { libc::close(fd); }
            return Err(err);
        }
        Ok(())
    }

    #[cfg(target_os = "macos")]
    fn set_feedback(_fd: libc::c_int) -> Result<(), IoError> {
        Ok(())
    }

    match channel_type {
        Layer2 => (),
        Layer3(_) => unimplemented!(),
    }

    let fd = get_fd();
    if fd == -1 {
        return Err(IoError::last_error());
    }
    let mut iface: bpf::ifreq = unsafe { mem::zeroed() };
    let mut i = 0;
    for c in network_interface.name.as_slice().bytes() {
        iface.ifr_name[i] = c as i8;
        i += 1;
    }

    let buflen = read_buffer_size as libc::c_uint;
    // NOTE Buffer length must be set before binding to an interface
    //      otherwise this will return Invalid Argument
    if unsafe { bpf::ioctl(fd, bpf::BIOCSBLEN, &buflen) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // Set the interface to use
    if unsafe { bpf::ioctl(fd, bpf::BIOCSETIF, &iface) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // Return from read as soon as packets are available - don't wait to fill the buffer
    let one: libc::c_uint = 1;
    if unsafe { bpf::ioctl(fd, bpf::BIOCIMMEDIATE, &one) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    let mut header_size = 0;

    // Get the device type
    let mut dlt: libc::c_uint = 0;
    if unsafe { bpf::ioctl(fd, bpf::BIOCGDLT, &mut dlt) } == -1 {
        let err = IoError::last_error();
        unsafe { libc::close(fd); }
        return Err(err);
    }

    // The loopback IoError::last_error()device does weird things
    // FIXME This should really just be another L2 packet header type
    if dlt == bpf::DLT_NULL {
        header_size = 4;

        // Allow packets to be read back after they are written
        match set_feedback(fd) {
            Err(e) => return Err(e),
            _ => ()
        }

    } else {
        // Don't fill in source MAC
        if unsafe { bpf::ioctl(fd, bpf::BIOCSHDRCMPLT, &one) } == -1 {
            let err = IoError::last_error();
            unsafe { libc::close(fd); }
            return Err(err);
        }
    }

    let fd = Arc::new(internal::FileDesc { fd: fd });
    let sender = DataLinkSenderImpl {
        fd: fd.clone(),
        write_buffer: repeat(0u8).take(write_buffer_size).collect(),
        header_size: header_size,
    };
    let receiver = DataLinkReceiverImpl {
        fd: fd,
        read_buffer: repeat(0u8).take(read_buffer_size).collect(),
        header_size: header_size,
    };

    Ok((sender, receiver))
}

pub struct DataLinkSenderImpl {
    fd: Arc<internal::FileDesc>,
    write_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkSenderImpl {
    pub fn build_and_send<F>(&mut self, num_packets: usize, packet_size: usize,
                          func: &mut F) -> Option<IoResult<()>>
        where F : FnMut(MutableEthernetHeader)
    {
        let len = num_packets * (packet_size + self.header_size);
        if len >= self.write_buffer.len() {
            None
        } else {
            let min = cmp::min(self.write_buffer.len(), len);
            for chunk in self.write_buffer[..min]
                                          .chunks_mut(packet_size + self.header_size) {
                // If we're sending on the loopback device, the first 4 bytes must be set to
                // AF_INET
                if self.header_size == 4 {
                    unsafe {
                        *(chunk.as_mut_ptr() as *mut u32) = libc::AF_INET as u32;
                    }
                }
                {
                    let eh = MutableEthernetHeader::new(&mut chunk[self.header_size..]);
                    func(eh);
                }
                match unsafe { libc::write(self.fd.fd,
                                           chunk.as_ptr() as *const libc::c_void,
                                           chunk.len() as libc::size_t) } {
                    len if len == -1 => return Some(Err(IoError::last_error())),
                    _ => ()
                }
            }
            Some(Ok(()))
        }
    }

    pub fn send_to(&mut self, packet: EthernetHeader, _dst: Option<NetworkInterface>)
        -> Option<IoResult<()>> {
        match unsafe { libc::write(self.fd.fd,
                                   packet.packet().as_ptr() as *const libc::c_void,
                                   packet.packet().len() as libc::size_t) } {
            len if len == -1 => Some(Err(IoError::last_error())),
            _ => Some(Ok(()))
        }
    }
}

pub struct DataLinkReceiverImpl {
    fd: Arc<internal::FileDesc>,
    read_buffer: Vec<u8>,
    header_size: usize,
}

impl DataLinkReceiverImpl {
    pub fn iter<'a>(&'a mut self) -> DataLinkChannelIteratorImpl<'a> {
        let buflen = self.read_buffer.len();
        DataLinkChannelIteratorImpl {
            pc: self,
            // Enough room for minimally sized packets without reallocating
            packets: VecDeque::with_capacity(buflen / 64)
        }
    }
}

pub struct DataLinkChannelIteratorImpl<'a> {
    pc: &'a mut DataLinkReceiverImpl,
    packets: VecDeque<(usize, usize)>,
}

impl<'a> DataLinkChannelIteratorImpl<'a> {
    pub fn next<'c>(&'c mut self) -> IoResult<EthernetHeader<'c>> {
        if self.packets.is_empty() {
            let buflen = match unsafe {
                libc::read(self.pc.fd.fd,
                           self.pc.read_buffer.as_ptr() as *mut libc::c_void,
                           self.pc.read_buffer.len() as libc::size_t)
            } {
                len if len > 0 => len,
                _ => return Err(IoError::last_error())
            };
            let mut ptr = self.pc.read_buffer.as_mut_ptr();
            let end = unsafe { self.pc.read_buffer.as_ptr().offset(buflen as isize) };
            while (ptr as *const u8) < end {
                unsafe {
                    let packet: *const bpf::bpf_hdr = mem::transmute(ptr);
                    let start = ptr as isize +
                                (*packet).bh_hdrlen as isize -
                                self.pc.read_buffer.as_ptr() as isize;
                    self.packets.push_back((start as usize + self.pc.header_size,
                                      (*packet).bh_caplen as usize - self.pc.header_size));
                    let offset = (*packet).bh_hdrlen as isize + (*packet).bh_caplen as isize;
                    ptr = ptr.offset(bpf::BPF_WORDALIGN(offset));
                }
            }
        }
        let (start, len) = self.packets.pop_front().unwrap();
        Ok(EthernetHeader::new(&self.pc.read_buffer[start .. start + len]))
    }
}

<|endoftext|>


<commit_before>#![feature(test)]
#![allow(unused_imports)]

extern crate test;
#[macro_use(s)]
extern crate ndarray;
#[cfg(feature = "rblas")]
extern crate rblas;
#[cfg(feature = "rblas")]
use rblas::matrix::Matrix;

use ndarray::{
    OwnedArray,
    zeros,
};
use ndarray::{arr0, arr1, arr2};

use test::black_box;

#[bench]
fn bench_std_add_shared(bench: &mut test::Bencher)
{
    let mut a = arr2::<f32, _>(&[[1., 2., 2.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [5., 6., 6.]]);
    let b = a.clone();
    bench.iter(|| a.iadd(&b));
}

#[bench]
fn bench_std_add_owned(bench: &mut test::Bencher)
{
    let a = arr2::<f32, _>(&[[1., 2., 2.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [5., 6., 6.]]);
    let mut a = a.to_owned();
    let b = a.clone();
    bench.iter(|| a.iadd(&b));
}

#[bench]
fn small_iter_1d(bench: &mut test::Bencher)
{
    let a = arr1::<f32>(&[1., 2., 2.,
                         3., 4., 4.,
                         3., 4., 4.,
                         3., 4., 4.,
                         5., 6., 6.]);
    bench.iter(|| for &elt in a.iter() { black_box(elt); })
}

#[bench]
fn small_iter_1d_raw(bench: &mut test::Bencher)
{
    let a = arr1::<f32>(&[1., 2., 2.,
                         3., 4., 4.,
                         3., 4., 4.,
                         3., 4., 4.,
                         5., 6., 6.]);
    bench.iter(|| for &elt in a.raw_data().iter() { black_box(elt); })
}

#[bench]
fn small_iter_2d(bench: &mut test::Bencher)
{
    let a = arr2::<f32, _>(&[[1., 2., 2.],
                          [3., 4., 4.],
                          [3., 4., 4.],
                          [3., 4., 4.],
                          [5., 6., 6.]]);
    bench.iter(|| for &elt in a.iter() { black_box(elt); })
}

#[bench]
fn bench_std_iter_1d_large(bench: &mut test::Bencher)
{
    let a = OwnedArray::<i32, _>::zeros(64 * 64);
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.iter() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn bench_std_iter_1d_raw_large(bench: &mut test::Bencher)
{
    // this is autovectorized to death (= great performance)
    let a = OwnedArray::<i32, _>::zeros(64 * 64);
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.raw_data() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn bench_std_iter_2d_large(bench: &mut test::Bencher)
{
    let a = OwnedArray::<i32, _>::zeros((64, 64));
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.iter() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn bench_std_iter_2d_raw_large(bench: &mut test::Bencher)
{
    // this is autovectorized to death (= great performance)
    let a = OwnedArray::<i32, _>::zeros((64, 64));
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.raw_data() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn bench_std_iter_2d_cutout(bench: &mut test::Bencher)
{
    let a = OwnedArray::<i32, _>::zeros((66, 66));
    let av = a.view().slice(s![1..-1, 1..-1]);
    let a = black_box(av);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.iter() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn bench_std_iter_2d_by_row_cutout(bench: &mut test::Bencher)
{
    let a = OwnedArray::<i32, _>::zeros((66, 66));
    let av = a.view().slice(s![1..-1, 1..-1]);
    let a = black_box(av);
    bench.iter(|| {
        let mut sum = 0;
        for row in 0..a.shape()[0] {
            for &elt in a.row_iter(row) {
                sum += elt;
            }
        }
        sum
    });
}

#[bench]
fn bench_std_iter_2d_transpose_large(bench: &mut test::Bencher)
{
    let mut a = OwnedArray::<i32, _>::zeros((64, 64));
    a.swap_axes(0, 1);
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.iter() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn bench_std_iter_2d_transpose_by_row_large(bench: &mut test::Bencher)
{
    let mut a = OwnedArray::<i32, _>::zeros((64, 64));
    a.swap_axes(0, 1);
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for row in 0..a.shape()[0] {
            for &elt in a.row_iter(row) {
                sum += elt;
            }
        }
        sum
    });
}

#[bench]
fn assign_scalar_2d_transposed(bench: &mut test::Bencher)
{
    let mut a = arr2::<f32, _>(&[[1., 2., 2.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [5., 6., 6.]]);
    a.swap_axes(0, 1);
    bench.iter(|| a.assign_scalar(&3.))
}

#[bench]
fn assign_scalar_2d(bench: &mut test::Bencher)
{
    let mut a = arr2::<f32, _>(&[[1., 2., 2.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [5., 6., 6.]]);
    bench.iter(|| a.assign_scalar(&3.))
}

#[bench]
fn assign_scalar_2d_large(bench: &mut test::Bencher)
{
    let a = OwnedArray::zeros((64, 64));
    let mut a = black_box(a);
    let s = black_box(3.);
    bench.iter(|| a.assign_scalar(&s))
}

#[bench]
fn assign_scalar_2d_transposed_large(bench: &mut test::Bencher)
{
    let mut a = OwnedArray::zeros((64, 64));
    a.swap_axes(0, 1);
    let mut a = black_box(a);
    let s = black_box(3.);
    bench.iter(|| a.assign_scalar(&s))
}

#[bench]
fn assign_scalar_2d_raw_large(bench: &mut test::Bencher)
{
    let a = OwnedArray::zeros((64, 64));
    let mut a = black_box(a);
    let s = black_box(3.);
    bench.iter(|| for elt in a.raw_data_mut() { *elt = s; });
}

#[bench]
fn bench_iter_diag(bench: &mut test::Bencher)
{
    let a = OwnedArray::<f32, _>::zeros((1024, 1024));
    bench.iter(|| for elt in a.diag_iter() { black_box(elt); })
}

#[bench]
fn bench_row_iter(bench: &mut test::Bencher)
{
    let a = OwnedArray::<f32, _>::zeros((1024, 1024));
    let it = a.row_iter(17);
    bench.iter(|| for elt in it.clone() { black_box(elt); })
}

#[bench]
fn bench_col_iter(bench: &mut test::Bencher)
{
    let a = OwnedArray::<f32, _>::zeros((1024, 1024));
    let it = a.col_iter(17);
    bench.iter(|| for elt in it.clone() { black_box(elt); })
}

#[bench]
fn bench_mat_mul(bench: &mut test::Bencher)
{
    let a = arr2::<f32, _>(&[[1., 2., 2.],
                          [3., 4., 4.],
                          [3., 4., 4.],
                          [3., 4., 4.],
                          [5., 6., 6.]]);
    let mut at = a.clone();
    at.swap_axes(0, 1);
    bench.iter(|| at.mat_mul(&a));
}

#[bench]
fn bench_mat_mul_large(bench: &mut test::Bencher)
{
    let a = OwnedArray::<f32, _>::zeros((64, 64));
    let b = OwnedArray::<f32, _>::zeros((64, 64));
    let a = black_box(a.view());
    let b = black_box(b.view());
    bench.iter(|| a.mat_mul(&b));
}

#[cfg(feature = "rblas")]
#[bench]
fn bench_mat_mul_rblas_large(bench: &mut test::Bencher)
{
    use rblas::Gemm;
    use rblas::attribute::Transpose;
    use ndarray::blas::AsBlas;

    let mut a = OwnedArray::<f32, _>::zeros((64, 64));
    let mut b = OwnedArray::<f32, _>::zeros((64, 64));
    let mut c = OwnedArray::<f32, _>::zeros((64, 64));
    bench.iter(|| {
        // C ← α AB + β C
        f32::gemm(&1.,
                  Transpose::NoTrans, &a.blas(),
                  Transpose::NoTrans, &b.blas(),
                  &1., &mut c.blas());
    });
}

#[bench]
fn bench_create_iter(bench: &mut test::Bencher)
{
    let a = arr2(&[[1., 2., 2.],
                   [3., 4., 4.],
                   [3., 4., 4.],
                   [3., 4., 4.],
                   [5., 6., 6.]]);
    let mut at = a.clone();
    at.swap_axes(0, 1);
    let v = black_box(at.view());

    bench.iter(|| {
        let v = black_box(v);
        v.into_iter()
    });
}

#[bench]
fn lst_squares(bench: &mut test::Bencher)
{
    let xs = arr2::<f32, _>(&[[ 2.,  3.],
                           [-2., -1.],
                           [ 1.,  5.],
                           [-1.,  2.]]);
    let b = arr1(&[1., -1., 2., 1.]);
    bench.iter(|| ndarray::linalg::least_squares(&xs, &b));
}

#[bench]
fn bench_to_owned_n(bench: &mut test::Bencher)
{
    let a = zeros::<f32, _>((32, 32));
    bench.iter(|| a.to_owned());
}

#[bench]
fn bench_to_owned_t(bench: &mut test::Bencher)
{
    let mut a = zeros::<f32, _>((32, 32));
    a.swap_axes(0, 1);
    bench.iter(|| a.to_owned());
}
<commit_msg>Add benchmarks for 2d iteration & operations<commit_after>#![feature(test)]
#![allow(unused_imports)]

extern crate test;
#[macro_use(s)]
extern crate ndarray;
#[cfg(feature = "rblas")]
extern crate rblas;
#[cfg(feature = "rblas")]
use rblas::matrix::Matrix;

use ndarray::{
    OwnedArray,
    zeros,
};
use ndarray::{arr0, arr1, arr2};

use test::black_box;

#[bench]
fn bench_std_add_shared(bench: &mut test::Bencher)
{
    let mut a = arr2::<f32, _>(&[[1., 2., 2.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [5., 6., 6.]]);
    let b = a.clone();
    bench.iter(|| a.iadd(&b));
}

#[bench]
fn bench_std_add_owned(bench: &mut test::Bencher)
{
    let a = arr2::<f32, _>(&[[1., 2., 2.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [5., 6., 6.]]);
    let mut a = a.to_owned();
    let b = a.clone();
    bench.iter(|| a.iadd(&b));
}

#[bench]
fn small_iter_1d(bench: &mut test::Bencher)
{
    let a = arr1::<f32>(&[1., 2., 2.,
                         3., 4., 4.,
                         3., 4., 4.,
                         3., 4., 4.,
                         5., 6., 6.]);
    bench.iter(|| for &elt in a.iter() { black_box(elt); })
}

#[bench]
fn small_iter_1d_raw(bench: &mut test::Bencher)
{
    let a = arr1::<f32>(&[1., 2., 2.,
                         3., 4., 4.,
                         3., 4., 4.,
                         3., 4., 4.,
                         5., 6., 6.]);
    bench.iter(|| for &elt in a.raw_data().iter() { black_box(elt); })
}

#[bench]
fn small_iter_2d(bench: &mut test::Bencher)
{
    let a = arr2::<f32, _>(&[[1., 2., 2.],
                          [3., 4., 4.],
                          [3., 4., 4.],
                          [3., 4., 4.],
                          [5., 6., 6.]]);
    bench.iter(|| for &elt in a.iter() { black_box(elt); })
}

#[bench]
fn add_1d_regular(bench: &mut test::Bencher)
{
    let a = OwnedArray::<i32, _>::zeros(64 * 64);
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.iter() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn add_1d_raw(bench: &mut test::Bencher)
{
    // this is autovectorized to death (= great performance)
    let a = OwnedArray::<i32, _>::zeros(64 * 64);
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.raw_data() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn add_2d_regular(bench: &mut test::Bencher)
{
    let a = OwnedArray::<i32, _>::zeros((64, 64));
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.iter() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn bench_std_iter_2d_raw_large(bench: &mut test::Bencher)
{
    // this is autovectorized to death (= great performance)
    let a = OwnedArray::<i32, _>::zeros((64, 64));
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.raw_data() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn add_2d_cutout(bench: &mut test::Bencher)
{
    let a = OwnedArray::<i32, _>::zeros((66, 66));
    let av = a.view().slice(s![1..-1, 1..-1]);
    let a = black_box(av);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.iter() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn add_2d_cutout_by_row(bench: &mut test::Bencher)
{
    let a = OwnedArray::<i32, _>::zeros((66, 66));
    let av = a.view().slice(s![1..-1, 1..-1]);
    let a = black_box(av);
    bench.iter(|| {
        let mut sum = 0;
        for row in 0..a.shape()[0] {
            for &elt in a.row_iter(row) {
                sum += elt;
            }
        }
        sum
    });
}

#[bench]
fn bench_std_iter_2d_transpose_large(bench: &mut test::Bencher)
{
    let mut a = OwnedArray::<i32, _>::zeros((64, 64));
    a.swap_axes(0, 1);
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for &elt in a.iter() {
            sum += elt;
        }
        sum
    });
}

#[bench]
fn add_2d_transpose_by_row(bench: &mut test::Bencher)
{
    let mut a = OwnedArray::<i32, _>::zeros((64, 64));
    a.swap_axes(0, 1);
    let a = black_box(a);
    bench.iter(|| {
        let mut sum = 0;
        for row in 0..a.shape()[0] {
            for &elt in a.row_iter(row) {
                sum += elt;
            }
        }
        sum
    });
}

#[bench]
fn assign_scalar_2d_transposed(bench: &mut test::Bencher)
{
    let mut a = arr2::<f32, _>(&[[1., 2., 2.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [5., 6., 6.]]);
    a.swap_axes(0, 1);
    bench.iter(|| a.assign_scalar(&3.))
}

#[bench]
fn assign_scalar_2d(bench: &mut test::Bencher)
{
    let mut a = arr2::<f32, _>(&[[1., 2., 2.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [3., 4., 4.],
                              [5., 6., 6.]]);
    bench.iter(|| a.assign_scalar(&3.))
}

#[bench]
fn assign_scalar_2d_large(bench: &mut test::Bencher)
{
    let a = OwnedArray::zeros((64, 64));
    let mut a = black_box(a);
    let s = 3.;
    bench.iter(|| a.assign_scalar(&s))
}

#[bench]
fn assign_scalar_2d_cutout(bench: &mut test::Bencher)
{
    let mut a = OwnedArray::zeros((66, 66));
    let mut a = a.slice_mut(s![1..-1, 1..-1]);
    let mut a = black_box(a);
    let s = 3.;
    bench.iter(|| a.assign_scalar(&s))
}

#[bench]
fn assign_scalar_2d_transposed_large(bench: &mut test::Bencher)
{
    let mut a = OwnedArray::zeros((64, 64));
    a.swap_axes(0, 1);
    let mut a = black_box(a);
    let s = 3.;
    bench.iter(|| a.assign_scalar(&s))
}

#[bench]
fn assign_scalar_2d_raw_large(bench: &mut test::Bencher)
{
    let a = OwnedArray::zeros((64, 64));
    let mut a = black_box(a);
    let s = 3.;
    bench.iter(|| for elt in a.raw_data_mut() { *elt = s; });
}

#[bench]
fn bench_iter_diag(bench: &mut test::Bencher)
{
    let a = OwnedArray::<f32, _>::zeros((1024, 1024));
    bench.iter(|| for elt in a.diag_iter() { black_box(elt); })
}

#[bench]
fn bench_row_iter(bench: &mut test::Bencher)
{
    let a = OwnedArray::<f32, _>::zeros((1024, 1024));
    let it = a.row_iter(17);
    bench.iter(|| for elt in it.clone() { black_box(elt); })
}

#[bench]
fn bench_col_iter(bench: &mut test::Bencher)
{
    let a = OwnedArray::<f32, _>::zeros((1024, 1024));
    let it = a.col_iter(17);
    bench.iter(|| for elt in it.clone() { black_box(elt); })
}

#[bench]
fn bench_mat_mul(bench: &mut test::Bencher)
{
    let a = arr2::<f32, _>(&[[1., 2., 2.],
                          [3., 4., 4.],
                          [3., 4., 4.],
                          [3., 4., 4.],
                          [5., 6., 6.]]);
    let mut at = a.clone();
    at.swap_axes(0, 1);
    bench.iter(|| at.mat_mul(&a));
}

#[bench]
fn bench_mat_mul_large(bench: &mut test::Bencher)
{
    let a = OwnedArray::<f32, _>::zeros((64, 64));
    let b = OwnedArray::<f32, _>::zeros((64, 64));
    let a = black_box(a.view());
    let b = black_box(b.view());
    bench.iter(|| a.mat_mul(&b));
}

#[cfg(feature = "rblas")]
#[bench]
fn bench_mat_mul_rblas_large(bench: &mut test::Bencher)
{
    use rblas::Gemm;
    use rblas::attribute::Transpose;
    use ndarray::blas::AsBlas;

    let mut a = OwnedArray::<f32, _>::zeros((64, 64));
    let mut b = OwnedArray::<f32, _>::zeros((64, 64));
    let mut c = OwnedArray::<f32, _>::zeros((64, 64));
    bench.iter(|| {
        // C ← α AB + β C
        f32::gemm(&1.,
                  Transpose::NoTrans, &a.blas(),
                  Transpose::NoTrans, &b.blas(),
                  &1., &mut c.blas());
    });
}

#[bench]
fn bench_create_iter(bench: &mut test::Bencher)
{
    let a = arr2(&[[1., 2., 2.],
                   [3., 4., 4.],
                   [3., 4., 4.],
                   [3., 4., 4.],
                   [5., 6., 6.]]);
    let mut at = a.clone();
    at.swap_axes(0, 1);
    let v = black_box(at.view());

    bench.iter(|| {
        let v = black_box(v);
        v.into_iter()
    });
}

#[bench]
fn lst_squares(bench: &mut test::Bencher)
{
    let xs = arr2::<f32, _>(&[[ 2.,  3.],
                           [-2., -1.],
                           [ 1.,  5.],
                           [-1.,  2.]]);
    let b = arr1(&[1., -1., 2., 1.]);
    bench.iter(|| ndarray::linalg::least_squares(&xs, &b));
}

#[bench]
fn bench_to_owned_n(bench: &mut test::Bencher)
{
    let a = zeros::<f32, _>((32, 32));
    bench.iter(|| a.to_owned());
}

#[bench]
fn bench_to_owned_t(bench: &mut test::Bencher)
{
    let mut a = zeros::<f32, _>((32, 32));
    a.swap_axes(0, 1);
    bench.iter(|| a.to_owned());
}
<|endoftext|>