<commit_before>use image::RgbImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;
use codec::Codec;

pub struct RgbCodec;

impl Codec for RgbCodec
{
    type Input = RgbImage;
    type Mode = RgbMode;

    fn encode<R: Rng>(
        source: &mut RgbImage,
        payload: &[u8],
        _mode: RgbMode,
        mut rng: R)
    {
        // iterate over pixels mutably
        for (mut pixels, bytes) in source.pixels_mut()
            // ~2.7 pixels per byte, so instead by use 24-pixel
            // and 3-byte chunks
            .chunks(8).into_iter()
            // make them vectors so we can check their lengths
            .map(|ch| ch.collect::<Vec<_>>())
            // give each chunk 3 bytes
            .zip(payload.iter().map(|x| *x)
                 .chunks(3).into_iter()
                 // make them also vectors
                 .map(|ch| ch.collect::<Vec<_>>()))
        {
            // if any of the chunks are short, abort
            if pixels.len() != 8 || bytes.len() != 3
            {
                return;
            }

            let rng = &mut rng;
            // i looked for a better way...
            fix_u8(&mut pixels[0].data[0], get_bit(bytes[0], 0), rng);
            fix_u8(&mut pixels[0].data[1], get_bit(bytes[0], 1), rng);
            fix_u8(&mut pixels[0].data[2], get_bit(bytes[0], 2), rng);
            fix_u8(&mut pixels[1].data[0], get_bit(bytes[0], 3), rng);
            fix_u8(&mut pixels[1].data[1], get_bit(bytes[0], 4), rng);
            fix_u8(&mut pixels[1].data[2], get_bit(bytes[0], 5), rng);
            fix_u8(&mut pixels[2].data[0], get_bit(bytes[0], 6), rng);
            fix_u8(&mut pixels[2].data[1], get_bit(bytes[0], 7), rng);

            fix_u8(&mut pixels[2].data[2], get_bit(bytes[1], 0), rng);
            fix_u8(&mut pixels[3].data[0], get_bit(bytes[1], 1), rng);
            fix_u8(&mut pixels[3].data[1], get_bit(bytes[1], 2), rng);
            fix_u8(&mut pixels[3].data[2], get_bit(bytes[1], 3), rng);
            fix_u8(&mut pixels[4].data[0], get_bit(bytes[1], 4), rng);
            fix_u8(&mut pixels[4].data[1], get_bit(bytes[1], 5), rng);
            fix_u8(&mut pixels[4].data[2], get_bit(bytes[1], 6), rng);
            fix_u8(&mut pixels[5].data[0], get_bit(bytes[1], 7), rng);

            fix_u8(&mut pixels[5].data[1], get_bit(bytes[2], 0), rng);
            fix_u8(&mut pixels[5].data[2], get_bit(bytes[2], 1), rng);
            fix_u8(&mut pixels[6].data[0], get_bit(bytes[2], 2), rng);
            fix_u8(&mut pixels[6].data[1], get_bit(bytes[2], 3), rng);
            fix_u8(&mut pixels[6].data[2], get_bit(bytes[2], 4), rng);
            fix_u8(&mut pixels[7].data[0], get_bit(bytes[2], 5), rng);
            fix_u8(&mut pixels[7].data[1], get_bit(bytes[2], 6), rng);
            fix_u8(&mut pixels[7].data[2], get_bit(bytes[2], 7), rng);
        }
    }

    fn decode(
        source: &RgbImage,
        payload: &mut [u8],
        len: usize,
        _mode: RgbMode)
    {
        assert!(len <= payload.len());

        let exlen = len + (len % 3);

        // iterate over the pixels
        for (index, pixels) in source.pixels()
            // grab them in chunks of 8
            .chunks(8).into_iter()
            // make them vectors
            .map(|ch| ch.collect::<Vec<_>>())
            .take(exlen / 3) // exlen is always exactly divisible by 3
            .enumerate()
        {
            if pixels.len() != 8
            {
                return;
            }

            let mut byte = 0u8;
            byte = set_bit(byte, 0, pixels[0].data[0] % 2 == 1);
            byte = set_bit(byte, 1, pixels[0].data[1] % 2 == 1);
            byte = set_bit(byte, 2, pixels[0].data[2] % 2 == 1);
            byte = set_bit(byte, 3, pixels[1].data[0] % 2 == 1);
            byte = set_bit(byte, 4, pixels[1].data[1] % 2 == 1);
            byte = set_bit(byte, 5, pixels[1].data[2] % 2 == 1);
            byte = set_bit(byte, 6, pixels[2].data[0] % 2 == 1);
            byte = set_bit(byte, 7, pixels[2].data[1] % 2 == 1);

            if index * 3 < len
            {
                payload[index * 3] = byte;
            }

            byte = set_bit(byte, 0, pixels[2].data[2] % 2 == 1);
            byte = set_bit(byte, 1, pixels[3].data[0] % 2 == 1);
            byte = set_bit(byte, 2, pixels[3].data[1] % 2 == 1);
            byte = set_bit(byte, 3, pixels[3].data[2] % 2 == 1);
            byte = set_bit(byte, 4, pixels[4].data[0] % 2 == 1);
            byte = set_bit(byte, 5, pixels[4].data[1] % 2 == 1);
            byte = set_bit(byte, 6, pixels[4].data[2] % 2 == 1);
            byte = set_bit(byte, 7, pixels[5].data[0] % 2 == 1);

            if index * 3 + 1 < len
            {
                payload[index * 3 + 1] = byte;
            }

            byte = set_bit(byte, 0, pixels[5].data[1] % 2 == 1);
            byte = set_bit(byte, 1, pixels[5].data[2] % 2 == 1);
            byte = set_bit(byte, 2, pixels[6].data[0] % 2 == 1);
            byte = set_bit(byte, 3, pixels[6].data[1] % 2 == 1);
            byte = set_bit(byte, 4, pixels[6].data[2] % 2 == 1);
            byte = set_bit(byte, 5, pixels[7].data[0] % 2 == 1);
            byte = set_bit(byte, 6, pixels[7].data[1] % 2 == 1);
            byte = set_bit(byte, 7, pixels[7].data[2] % 2 == 1);

            if index * 3 + 2 < len
            {
                payload[index * 3 + 2] = byte;
            }
        }
    }

    fn estimate(
        source: &RgbImage,
        mode: RgbMode) -> Option<usize>
    {
        Some(match mode
        {
            RgbMode::All =>
                source.width() as usize * source.height() as usize / 3
        })
    }

}

#[derive(Copy, Clone)]
pub enum RgbMode
{
    All,
}

use std::default::Default;

impl Default for RgbMode
{
    fn default() -> RgbMode
    {
        RgbMode::All
    }
}

use std::str::FromStr;

impl FromStr for RgbMode
{
    type Err = ();

    fn from_str(s: &str) -> Result<RgbMode, ()>
    {
        if s == "all"
        {
            Ok(RgbMode::All)
        }
        else
        {
            Err(())
        }
    }
}
<commit_msg>Added test for Rgb codec<commit_after>use image::RgbImage;
use rand::Rng;
use itertools::Itertools;

use utils::*;
use codec::Codec;

pub struct RgbCodec;

impl Codec for RgbCodec
{
    type Input = RgbImage;
    type Mode = RgbMode;

    fn encode<R: Rng>(
        source: &mut RgbImage,
        payload: &[u8],
        _mode: RgbMode,
        mut rng: R)
    {
        // iterate over pixels mutably
        for (mut pixels, bytes) in source.pixels_mut()
            // ~2.7 pixels per byte, so instead by use 24-pixel
            // and 3-byte chunks
            .chunks(8).into_iter()
            // make them vectors so we can check their lengths
            .map(|ch| ch.collect::<Vec<_>>())
            // give each chunk 3 bytes
            .zip(payload.iter().map(|x| *x)
                 .chunks(3).into_iter()
                 // make them also vectors
                 .map(|ch| ch.collect::<Vec<_>>()))
        {
            // if any of the chunks are short, abort
            if pixels.len() != 8 || bytes.len() != 3
            {
                return;
            }

            let rng = &mut rng;
            // i looked for a better way...
            fix_u8(&mut pixels[0].data[0], get_bit(bytes[0], 0), rng);
            fix_u8(&mut pixels[0].data[1], get_bit(bytes[0], 1), rng);
            fix_u8(&mut pixels[0].data[2], get_bit(bytes[0], 2), rng);
            fix_u8(&mut pixels[1].data[0], get_bit(bytes[0], 3), rng);
            fix_u8(&mut pixels[1].data[1], get_bit(bytes[0], 4), rng);
            fix_u8(&mut pixels[1].data[2], get_bit(bytes[0], 5), rng);
            fix_u8(&mut pixels[2].data[0], get_bit(bytes[0], 6), rng);
            fix_u8(&mut pixels[2].data[1], get_bit(bytes[0], 7), rng);

            fix_u8(&mut pixels[2].data[2], get_bit(bytes[1], 0), rng);
            fix_u8(&mut pixels[3].data[0], get_bit(bytes[1], 1), rng);
            fix_u8(&mut pixels[3].data[1], get_bit(bytes[1], 2), rng);
            fix_u8(&mut pixels[3].data[2], get_bit(bytes[1], 3), rng);
            fix_u8(&mut pixels[4].data[0], get_bit(bytes[1], 4), rng);
            fix_u8(&mut pixels[4].data[1], get_bit(bytes[1], 5), rng);
            fix_u8(&mut pixels[4].data[2], get_bit(bytes[1], 6), rng);
            fix_u8(&mut pixels[5].data[0], get_bit(bytes[1], 7), rng);

            fix_u8(&mut pixels[5].data[1], get_bit(bytes[2], 0), rng);
            fix_u8(&mut pixels[5].data[2], get_bit(bytes[2], 1), rng);
            fix_u8(&mut pixels[6].data[0], get_bit(bytes[2], 2), rng);
            fix_u8(&mut pixels[6].data[1], get_bit(bytes[2], 3), rng);
            fix_u8(&mut pixels[6].data[2], get_bit(bytes[2], 4), rng);
            fix_u8(&mut pixels[7].data[0], get_bit(bytes[2], 5), rng);
            fix_u8(&mut pixels[7].data[1], get_bit(bytes[2], 6), rng);
            fix_u8(&mut pixels[7].data[2], get_bit(bytes[2], 7), rng);
        }
    }

    fn decode(
        source: &RgbImage,
        payload: &mut [u8],
        len: usize,
        _mode: RgbMode)
    {
        assert!(len <= payload.len());

        let exlen = len + (len % 3);

        // iterate over the pixels
        for (index, pixels) in source.pixels()
            // grab them in chunks of 8
            .chunks(8).into_iter()
            // make them vectors
            .map(|ch| ch.collect::<Vec<_>>())
            .take(exlen / 3) // exlen is always exactly divisible by 3
            .enumerate()
        {
            if pixels.len() != 8
            {
                return;
            }

            let mut byte = 0u8;
            byte = set_bit(byte, 0, pixels[0].data[0] % 2 == 1);
            byte = set_bit(byte, 1, pixels[0].data[1] % 2 == 1);
            byte = set_bit(byte, 2, pixels[0].data[2] % 2 == 1);
            byte = set_bit(byte, 3, pixels[1].data[0] % 2 == 1);
            byte = set_bit(byte, 4, pixels[1].data[1] % 2 == 1);
            byte = set_bit(byte, 5, pixels[1].data[2] % 2 == 1);
            byte = set_bit(byte, 6, pixels[2].data[0] % 2 == 1);
            byte = set_bit(byte, 7, pixels[2].data[1] % 2 == 1);

            if index * 3 < len
            {
                payload[index * 3] = byte;
            }

            byte = set_bit(byte, 0, pixels[2].data[2] % 2 == 1);
            byte = set_bit(byte, 1, pixels[3].data[0] % 2 == 1);
            byte = set_bit(byte, 2, pixels[3].data[1] % 2 == 1);
            byte = set_bit(byte, 3, pixels[3].data[2] % 2 == 1);
            byte = set_bit(byte, 4, pixels[4].data[0] % 2 == 1);
            byte = set_bit(byte, 5, pixels[4].data[1] % 2 == 1);
            byte = set_bit(byte, 6, pixels[4].data[2] % 2 == 1);
            byte = set_bit(byte, 7, pixels[5].data[0] % 2 == 1);

            if index * 3 + 1 < len
            {
                payload[index * 3 + 1] = byte;
            }

            byte = set_bit(byte, 0, pixels[5].data[1] % 2 == 1);
            byte = set_bit(byte, 1, pixels[5].data[2] % 2 == 1);
            byte = set_bit(byte, 2, pixels[6].data[0] % 2 == 1);
            byte = set_bit(byte, 3, pixels[6].data[1] % 2 == 1);
            byte = set_bit(byte, 4, pixels[6].data[2] % 2 == 1);
            byte = set_bit(byte, 5, pixels[7].data[0] % 2 == 1);
            byte = set_bit(byte, 6, pixels[7].data[1] % 2 == 1);
            byte = set_bit(byte, 7, pixels[7].data[2] % 2 == 1);

            if index * 3 + 2 < len
            {
                payload[index * 3 + 2] = byte;
            }
        }
    }

    fn estimate(
        source: &RgbImage,
        mode: RgbMode) -> Option<usize>
    {
        Some(match mode
        {
            RgbMode::All =>
                source.width() as usize * source.height() as usize / 3
        })
    }

}

#[derive(Copy, Clone)]
pub enum RgbMode
{
    All,
}

use std::default::Default;

impl Default for RgbMode
{
    fn default() -> RgbMode
    {
        RgbMode::All
    }
}

use std::str::FromStr;

impl FromStr for RgbMode
{
    type Err = ();

    fn from_str(s: &str) -> Result<RgbMode, ()>
    {
        if s == "all"
        {
            Ok(RgbMode::All)
        }
        else
        {
            Err(())
        }
    }
}

#[cfg(test)]
mod test
{
    use image::{ImageBuffer, Rgb};
    use rand::StdRng;

    use codec::Codec;
    use super::*;

    #[test]
    fn all()
    {
        let mut image = ImageBuffer::from_pixel(
            30,
            8,
            Rgb
            {
                data: [127u8; 3],
            });

        let payload = vec![
            1,2, 3, 4, 5, 6, 7, 8, 9, 10,
            11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
            21, 22, 23, 24, 25, 26, 27, 28, 29, 30
        ];

        let mut buf = vec![0; 30];

        let rng = StdRng::new().unwrap();

        RgbCodec::encode(&mut image, &payload, RgbMode::All, rng);

        RgbCodec::decode(&image, &mut buf, 30, RgbMode::All);

        assert_eq!(payload, buf);
    }
}
<|endoftext|>


<commit_before>#![deny(trivial_numeric_casts)]
#![warn(
    unused_import_braces,
    unstable_features,
    unused_extern_crates
)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        float_arithmetic,
        mut_mut,
        nonminimal_bool,
        option_map_unwrap_or,
        option_map_unwrap_or_else,
        unicode_not_nfc,
        use_self
    )
)]

extern crate file_per_thread_logger;
#[macro_use]
extern crate cfg_if;
#[cfg(feature = "disas")]
extern crate capstone;
extern crate clap;
extern crate cranelift_codegen;
extern crate cranelift_entity;
extern crate cranelift_filetests;
extern crate cranelift_reader;
extern crate pretty_env_logger;

cfg_if! {
    if #[cfg(feature = "wasm")] {
        extern crate cranelift_wasm;
        extern crate term;
        extern crate wabt;
        mod wasm;
    }
}
extern crate target_lexicon;

use clap::{App, Arg, SubCommand};
use cranelift_codegen::dbg::LOG_FILENAME_PREFIX;
use cranelift_codegen::VERSION;
use std::io::{self, Write};
use std::option::Option;
use std::process;

mod cat;
mod compile;
mod print_cfg;
mod utils;

/// A command either succeeds or fails with an error message.
pub type CommandResult = Result<(), String>;

fn add_input_file_arg<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("file")
        .default_value("-")
        .multiple(true)
        .value_name("file")
        .help("Specify file(s) to be used for test. Defaults to reading from stdin.")
}

fn add_single_input_file_arg<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("single-file")
        .required(true)
        .value_name("single-file")
        .help("Specify a file to be used. Use '-' for stdin.")
}

fn add_pass_arg<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("pass")
        .required(true)
        .multiple(true)
        .value_name("pass")
        .help("Specify pass(s) to be run on test file")
}

fn add_verbose_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("verbose").short("v").help("Be more verbose")
}

fn add_time_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("time-passes")
        .short("T")
        .help("Print pass timing report for test")
}

fn add_set_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("set")
        .long("set")
        .takes_value(true)
        .multiple(true)
        .help("Configure Cranelift settings")
}

fn add_target_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("target")
        .takes_value(true)
        .long("target")
        .help("Specify the Cranelift target")
}

fn add_print_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("print")
        .short("p")
        .help("Print the resulting Cranelift IR")
}

fn add_debug_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("debug")
        .short("d")
        .help("enable debug output on stderr/stdout")
}

/// Returns a vector of clap value options and changes these options into a vector of strings
fn get_vec<'a>(argument_vec: Option<clap::Values<'a>>) -> Vec<String> {
    let mut ret_vec: Vec<String> = Vec::new();
    if let Some(clap_vec) = argument_vec {
        for val in clap_vec {
            ret_vec.push(val.to_string());
        }
    }

    ret_vec
}

fn add_wasm_or_compile<'a>(cmd: &str) -> clap::App<'a, 'a> {
    let about_str = match cmd {
        "wasm" => "Compiles Cranelift IR into target language",
        "compile" => "Compiles Cranelift IR into target language",
        _ => panic!("Invalid command"),
    };

    SubCommand::with_name(cmd)
        .about(about_str)
        .arg(add_verbose_flag())
        .arg(add_print_flag())
        .arg(add_time_flag())
        .arg(add_set_flag())
        .arg(add_target_flag())
        .arg(add_input_file_arg())
        .arg(add_debug_flag())
}

fn handle_debug_flag(debug: bool) {
    if debug {
        pretty_env_logger::init();
    } else {
        file_per_thread_logger::initialize(LOG_FILENAME_PREFIX);
    }
}

fn main() {
    let app_cmds = App::new("Cranelift code generator utility")
        .version(VERSION)
        .subcommand(
            SubCommand::with_name("test")
                .about("Run Cranelift tests")
                .arg(add_verbose_flag())
                .arg(add_time_flag())
                .arg(add_input_file_arg())
                .arg(add_debug_flag()),
        ).subcommand(
            SubCommand::with_name("cat")
                .about("Outputs .clif file")
                .arg(add_input_file_arg())
                .arg(add_debug_flag()),
        ).subcommand(
            SubCommand::with_name("print-cfg")
                .about("Prints out cfg in dot format")
                .arg(add_input_file_arg())
                .arg(add_debug_flag()),
        ).subcommand(
            add_wasm_or_compile("compile")
                .arg(
                    Arg::with_name("just-decode")
                        .short("t")
                        .help("Just decode WebAssembly to Cranelift IR"),
                ).arg(Arg::with_name("check-translation").short("c").help(
                    "Just checks the correctness of Cranelift IR translated from WebAssembly",
                )),
        ).subcommand(add_wasm_or_compile("wasm"))
        .subcommand(
            SubCommand::with_name("pass")
                .about("Run specified pass(s) on an input file.")
                .arg(add_single_input_file_arg())
                .arg(add_target_flag())
                .arg(add_pass_arg())
                .arg(add_debug_flag())
                .arg(add_time_flag()),
        );

    let res_util = match app_cmds.get_matches().subcommand() {
        ("cat", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));
            cat::run(&get_vec(rest_cmd.values_of("file")))
        }
        ("test", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));
            cranelift_filetests::run(
                rest_cmd.is_present("verbose"),
                &get_vec(rest_cmd.values_of("file")),
            ).map(|_time| ())
        }
        ("pass", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));

            let mut target_val: &str = "";
            if let Some(clap_target) = rest_cmd.value_of("target") {
                target_val = clap_target;
            }

            // Can be unwrapped because 'single-file' is required
            cranelift_filetests::run_passes(
                rest_cmd.is_present("verbose"),
                &get_vec(rest_cmd.values_of("pass")),
                target_val,
                rest_cmd.value_of("single-file").unwrap(),
            ).map(|_time| ())
        }
        ("print-cfg", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));
            print_cfg::run(&get_vec(rest_cmd.values_of("file")))
        }
        ("compile", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));

            let mut target_val: &str = "";
            if let Some(clap_target) = rest_cmd.value_of("target") {
                target_val = clap_target;
            }

            compile::run(
                get_vec(rest_cmd.values_of("file")),
                rest_cmd.is_present("print"),
                &get_vec(rest_cmd.values_of("set")),
                target_val,
            )
        }
        ("wasm", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));

            let mut target_val: &str = "";
            if let Some(clap_target) = rest_cmd.value_of("target") {
                target_val = clap_target;
            }

            #[cfg(feature = "wasm")]
            let result = wasm::run(
                get_vec(rest_cmd.values_of("file")),
                rest_cmd.is_present("verbose"),
                rest_cmd.is_present("just-decode"),
                rest_cmd.is_present("check-translation"),
                rest_cmd.is_present("print"),
                &get_vec(rest_cmd.values_of("set")),
                target_val,
                rest_cmd.is_present("print-size"),
            );

            #[cfg(not(feature = "wasm"))]
            let result = Err("Error: clif-util was compiled without wasm support.".to_owned());

            result
        }
        _ => Err(format!("Invalid subcommand.")),
    };

    if let Err(mut msg) = res_util {
        if !msg.ends_with('\n') {
            msg.push('\n');
        }
        io::stdout().flush().expect("flushing stdout");
        io::stderr().write_all(msg.as_bytes()).unwrap();
        process::exit(1);
    }
}
<commit_msg>clippy: Remove useless format call.<commit_after>#![deny(trivial_numeric_casts)]
#![warn(
    unused_import_braces,
    unstable_features,
    unused_extern_crates
)]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        float_arithmetic,
        mut_mut,
        nonminimal_bool,
        option_map_unwrap_or,
        option_map_unwrap_or_else,
        unicode_not_nfc,
        use_self
    )
)]

extern crate file_per_thread_logger;
#[macro_use]
extern crate cfg_if;
#[cfg(feature = "disas")]
extern crate capstone;
extern crate clap;
extern crate cranelift_codegen;
extern crate cranelift_entity;
extern crate cranelift_filetests;
extern crate cranelift_reader;
extern crate pretty_env_logger;

cfg_if! {
    if #[cfg(feature = "wasm")] {
        extern crate cranelift_wasm;
        extern crate term;
        extern crate wabt;
        mod wasm;
    }
}
extern crate target_lexicon;

use clap::{App, Arg, SubCommand};
use cranelift_codegen::dbg::LOG_FILENAME_PREFIX;
use cranelift_codegen::VERSION;
use std::io::{self, Write};
use std::option::Option;
use std::process;

mod cat;
mod compile;
mod print_cfg;
mod utils;

/// A command either succeeds or fails with an error message.
pub type CommandResult = Result<(), String>;

fn add_input_file_arg<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("file")
        .default_value("-")
        .multiple(true)
        .value_name("file")
        .help("Specify file(s) to be used for test. Defaults to reading from stdin.")
}

fn add_single_input_file_arg<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("single-file")
        .required(true)
        .value_name("single-file")
        .help("Specify a file to be used. Use '-' for stdin.")
}

fn add_pass_arg<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("pass")
        .required(true)
        .multiple(true)
        .value_name("pass")
        .help("Specify pass(s) to be run on test file")
}

fn add_verbose_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("verbose").short("v").help("Be more verbose")
}

fn add_time_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("time-passes")
        .short("T")
        .help("Print pass timing report for test")
}

fn add_set_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("set")
        .long("set")
        .takes_value(true)
        .multiple(true)
        .help("Configure Cranelift settings")
}

fn add_target_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("target")
        .takes_value(true)
        .long("target")
        .help("Specify the Cranelift target")
}

fn add_print_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("print")
        .short("p")
        .help("Print the resulting Cranelift IR")
}

fn add_debug_flag<'a>() -> clap::Arg<'a, 'a> {
    Arg::with_name("debug")
        .short("d")
        .help("enable debug output on stderr/stdout")
}

/// Returns a vector of clap value options and changes these options into a vector of strings
fn get_vec<'a>(argument_vec: Option<clap::Values<'a>>) -> Vec<String> {
    let mut ret_vec: Vec<String> = Vec::new();
    if let Some(clap_vec) = argument_vec {
        for val in clap_vec {
            ret_vec.push(val.to_string());
        }
    }

    ret_vec
}

fn add_wasm_or_compile<'a>(cmd: &str) -> clap::App<'a, 'a> {
    let about_str = match cmd {
        "wasm" => "Compiles Cranelift IR into target language",
        "compile" => "Compiles Cranelift IR into target language",
        _ => panic!("Invalid command"),
    };

    SubCommand::with_name(cmd)
        .about(about_str)
        .arg(add_verbose_flag())
        .arg(add_print_flag())
        .arg(add_time_flag())
        .arg(add_set_flag())
        .arg(add_target_flag())
        .arg(add_input_file_arg())
        .arg(add_debug_flag())
}

fn handle_debug_flag(debug: bool) {
    if debug {
        pretty_env_logger::init();
    } else {
        file_per_thread_logger::initialize(LOG_FILENAME_PREFIX);
    }
}

fn main() {
    let app_cmds = App::new("Cranelift code generator utility")
        .version(VERSION)
        .subcommand(
            SubCommand::with_name("test")
                .about("Run Cranelift tests")
                .arg(add_verbose_flag())
                .arg(add_time_flag())
                .arg(add_input_file_arg())
                .arg(add_debug_flag()),
        ).subcommand(
            SubCommand::with_name("cat")
                .about("Outputs .clif file")
                .arg(add_input_file_arg())
                .arg(add_debug_flag()),
        ).subcommand(
            SubCommand::with_name("print-cfg")
                .about("Prints out cfg in dot format")
                .arg(add_input_file_arg())
                .arg(add_debug_flag()),
        ).subcommand(
            add_wasm_or_compile("compile")
                .arg(
                    Arg::with_name("just-decode")
                        .short("t")
                        .help("Just decode WebAssembly to Cranelift IR"),
                ).arg(Arg::with_name("check-translation").short("c").help(
                    "Just checks the correctness of Cranelift IR translated from WebAssembly",
                )),
        ).subcommand(add_wasm_or_compile("wasm"))
        .subcommand(
            SubCommand::with_name("pass")
                .about("Run specified pass(s) on an input file.")
                .arg(add_single_input_file_arg())
                .arg(add_target_flag())
                .arg(add_pass_arg())
                .arg(add_debug_flag())
                .arg(add_time_flag()),
        );

    let res_util = match app_cmds.get_matches().subcommand() {
        ("cat", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));
            cat::run(&get_vec(rest_cmd.values_of("file")))
        }
        ("test", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));
            cranelift_filetests::run(
                rest_cmd.is_present("verbose"),
                &get_vec(rest_cmd.values_of("file")),
            ).map(|_time| ())
        }
        ("pass", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));

            let mut target_val: &str = "";
            if let Some(clap_target) = rest_cmd.value_of("target") {
                target_val = clap_target;
            }

            // Can be unwrapped because 'single-file' is required
            cranelift_filetests::run_passes(
                rest_cmd.is_present("verbose"),
                &get_vec(rest_cmd.values_of("pass")),
                target_val,
                rest_cmd.value_of("single-file").unwrap(),
            ).map(|_time| ())
        }
        ("print-cfg", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));
            print_cfg::run(&get_vec(rest_cmd.values_of("file")))
        }
        ("compile", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));

            let mut target_val: &str = "";
            if let Some(clap_target) = rest_cmd.value_of("target") {
                target_val = clap_target;
            }

            compile::run(
                get_vec(rest_cmd.values_of("file")),
                rest_cmd.is_present("print"),
                &get_vec(rest_cmd.values_of("set")),
                target_val,
            )
        }
        ("wasm", Some(rest_cmd)) => {
            handle_debug_flag(rest_cmd.is_present("debug"));

            let mut target_val: &str = "";
            if let Some(clap_target) = rest_cmd.value_of("target") {
                target_val = clap_target;
            }

            #[cfg(feature = "wasm")]
            let result = wasm::run(
                get_vec(rest_cmd.values_of("file")),
                rest_cmd.is_present("verbose"),
                rest_cmd.is_present("just-decode"),
                rest_cmd.is_present("check-translation"),
                rest_cmd.is_present("print"),
                &get_vec(rest_cmd.values_of("set")),
                target_val,
                rest_cmd.is_present("print-size"),
            );

            #[cfg(not(feature = "wasm"))]
            let result = Err("Error: clif-util was compiled without wasm support.".to_owned());

            result
        }
        _ => Err("Invalid subcommand.".to_owned()),
    };

    if let Err(mut msg) = res_util {
        if !msg.ends_with('\n') {
            msg.push('\n');
        }
        io::stdout().flush().expect("flushing stdout");
        io::stderr().write_all(msg.as_bytes()).unwrap();
        process::exit(1);
    }
}
<|endoftext|>


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

#![allow(missing_doc)]

/// A task pool abstraction. Useful for achieving predictable CPU
/// parallelism.

use core::prelude::*;

use task;
use task::spawn;
use vec::Vec;
use comm::{channel, Sender};

enum Msg<T> {
    Execute(proc(&T):Send),
    Quit
}

pub struct TaskPool<T> {
    channels: Vec<Sender<Msg<T>>>,
    next_index: uint,
}

#[unsafe_destructor]
impl<T> Drop for TaskPool<T> {
    fn drop(&mut self) {
        for channel in self.channels.mut_iter() {
            channel.send(Quit);
        }
    }
}

impl<T> TaskPool<T> {
    /// Spawns a new task pool with `n_tasks` tasks. If the `sched_mode`
    /// is None, the tasks run on this scheduler; otherwise, they run on a
    /// new scheduler with the given mode. The provided `init_fn_factory`
    /// returns a function which, given the index of the task, should return
    /// local data to be kept around in that task.
    pub fn new(n_tasks: uint,
               init_fn_factory: || -> proc(uint):Send -> T)
               -> TaskPool<T> {
        assert!(n_tasks >= 1);

        let channels = Vec::from_fn(n_tasks, |i| {
            let (tx, rx) = channel::<Msg<T>>();
            let init_fn = init_fn_factory();

            let task_body = proc() {
                let local_data = init_fn(i);
                loop {
                    match rx.recv() {
                        Execute(f) => f(&local_data),
                        Quit => break
                    }
                }
            };

            // Run on this scheduler.
            task::spawn(task_body);

            tx
        });

        return TaskPool {
            channels: channels,
            next_index: 0,
        };
    }

    /// Executes the function `f` on a task in the pool. The function
    /// receives a reference to the local data returned by the `init_fn`.
    pub fn execute(&mut self, f: proc(&T):Send) {
        self.channels.get(self.next_index).send(Execute(f));
        self.next_index += 1;
        if self.next_index == self.channels.len() { self.next_index = 0; }
    }
}

#[test]
fn test_task_pool() {
    let f: || -> proc(uint):Send -> uint = || {
        let g: proc(uint):Send -> uint = proc(i) i;
        g
    };
    let mut pool = TaskPool::new(4, f);
    for _ in range(0, 8) {
        pool.execute(proc(i) println!("Hello from thread {}!", *i));
    }
}
<commit_msg>std::sync::TaskPool: Improve module documentation<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Abstraction of a task pool for basic parallelism.

use core::prelude::*;

use task;
use task::spawn;
use vec::Vec;
use comm::{channel, Sender};

enum Msg<T> {
    Execute(proc(&T):Send),
    Quit
}

/// A task pool used to execute functions in parallel.
pub struct TaskPool<T> {
    channels: Vec<Sender<Msg<T>>>,
    next_index: uint,
}

#[unsafe_destructor]
impl<T> Drop for TaskPool<T> {
    fn drop(&mut self) {
        for channel in self.channels.mut_iter() {
            channel.send(Quit);
        }
    }
}

impl<T> TaskPool<T> {
    /// Spawns a new task pool with `n_tasks` tasks. The provided
    /// `init_fn_factory` returns a function which, given the index of the
    /// task, should return local data to be kept around in that task.
    ///
    /// # Failure
    ///
    /// This function will fail if `n_tasks` is less than 1.
    pub fn new(n_tasks: uint,
               init_fn_factory: || -> proc(uint):Send -> T)
               -> TaskPool<T> {
        assert!(n_tasks >= 1);

        let channels = Vec::from_fn(n_tasks, |i| {
            let (tx, rx) = channel::<Msg<T>>();
            let init_fn = init_fn_factory();

            let task_body = proc() {
                let local_data = init_fn(i);
                loop {
                    match rx.recv() {
                        Execute(f) => f(&local_data),
                        Quit => break
                    }
                }
            };

            // Run on this scheduler.
            task::spawn(task_body);

            tx
        });

        return TaskPool {
            channels: channels,
            next_index: 0,
        };
    }

    /// Executes the function `f` on a task in the pool. The function
    /// receives a reference to the local data returned by the `init_fn`.
    pub fn execute(&mut self, f: proc(&T):Send) {
        self.channels.get(self.next_index).send(Execute(f));
        self.next_index += 1;
        if self.next_index == self.channels.len() { self.next_index = 0; }
    }
}

#[test]
fn test_task_pool() {
    let f: || -> proc(uint):Send -> uint = || { proc(i) i };
    let mut pool = TaskPool::new(4, f);
    for _ in range(0, 8) {
        pool.execute(proc(i) println!("Hello from thread {}!", *i));
    }
}

#[test]
#[should_fail]
fn test_zero_tasks_failure() {
    let f: || -> proc(uint):Send -> uint = || { proc(i) i };
    TaskPool::new(0, f);
}
<|endoftext|>


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

use std::fmt;
use std::default::Default;
use std::hash;
use std::{mem, raw, ptr, slice};
use serialize::{Encodable, Decodable, Encoder, Decoder};

/// A non-growable owned slice. This would preferably become `~[T]`
/// under DST.
#[unsafe_no_drop_flag] // data is set to null on destruction
pub struct OwnedSlice<T> {
    /// null iff len == 0
    data: *mut T,
    len: uint,
}

impl<T:fmt::Show> fmt::Show for OwnedSlice<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!("OwnedSlice {{".fmt(fmt));
        for i in self.iter() {
            try!(i.fmt(fmt));
        }
        try!("}}".fmt(fmt));
        Ok(())
    }
}

#[unsafe_destructor]
impl<T> Drop for OwnedSlice<T> {
    fn drop(&mut self) {
        if self.data.is_null() { return }

        // extract the vector
        let v = mem::replace(self, OwnedSlice::empty());
        // free via the Vec destructor
        v.into_vec();
    }
}

impl<T> OwnedSlice<T> {
    pub fn empty() -> OwnedSlice<T> {
        OwnedSlice  { data: ptr::mut_null(), len: 0 }
    }

    #[inline(never)]
    pub fn from_vec(mut v: Vec<T>) -> OwnedSlice<T> {
        let len = v.len();

        if len == 0 {
            OwnedSlice::empty()
        } else {
            let p = v.as_mut_ptr();
            // we own the allocation now
            unsafe {mem::forget(v)}

            OwnedSlice { data: p, len: len }
        }
    }

    #[inline(never)]
    pub fn into_vec(self) -> Vec<T> {
        // null is ok, because len == 0 in that case, as required by Vec.
        unsafe {
            let ret = Vec::from_raw_parts(self.len, self.len, self.data);
            // the vector owns the allocation now
            mem::forget(self);
            ret
        }
    }

    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        static PTR_MARKER: u8 = 0;
        let ptr = if self.data.is_null() {
            // length zero, i.e. this will never be read as a T.
            &PTR_MARKER as *const u8 as *const T
        } else {
            self.data as *const T
        };

        let slice: &[T] = unsafe {mem::transmute(raw::Slice {
            data: ptr,
            len: self.len
        })};

        slice
    }

    pub fn get<'a>(&'a self, i: uint) -> &'a T {
        self.as_slice().get(i).expect("OwnedSlice: index out of bounds")
    }

    pub fn iter<'r>(&'r self) -> slice::Items<'r, T> {
        self.as_slice().iter()
    }

    pub fn map<U>(&self, f: |&T| -> U) -> OwnedSlice<U> {
        self.iter().map(f).collect()
    }
}

impl<T> Default for OwnedSlice<T> {
    fn default() -> OwnedSlice<T> {
        OwnedSlice::empty()
    }
}

impl<T: Clone> Clone for OwnedSlice<T> {
    fn clone(&self) -> OwnedSlice<T> {
        OwnedSlice::from_vec(Vec::from_slice(self.as_slice()))
    }
}

impl<S: hash::Writer, T: hash::Hash<S>> hash::Hash<S> for OwnedSlice<T> {
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state)
    }
}

impl<T: PartialEq> PartialEq for OwnedSlice<T> {
    fn eq(&self, other: &OwnedSlice<T>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<T: Eq> Eq for OwnedSlice<T> {}

impl<T> Collection for OwnedSlice<T> {
    fn len(&self) -> uint { self.len }
}

impl<T> FromIterator<T> for OwnedSlice<T> {
    fn from_iter<I: Iterator<T>>(mut iter: I) -> OwnedSlice<T> {
        OwnedSlice::from_vec(iter.collect())
    }
}

impl<S: Encoder<E>, T: Encodable<S, E>, E> Encodable<S, E> for OwnedSlice<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
       self.as_slice().encode(s)
    }
}

impl<D: Decoder<E>, T: Decodable<D, E>, E> Decodable<D, E> for OwnedSlice<T> {
    fn decode(d: &mut D) -> Result<OwnedSlice<T>, E> {
        Ok(OwnedSlice::from_vec(match Decodable::decode(d) {
            Ok(t) => t,
            Err(e) => return Err(e)
        }))
    }
}
<commit_msg>fix sized deallocation for OwnedSlice<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;
use std::default::Default;
use std::hash;
use std::{mem, raw, ptr, slice};
use serialize::{Encodable, Decodable, Encoder, Decoder};

/// A non-growable owned slice. This would preferably become `~[T]`
/// under DST.
#[unsafe_no_drop_flag] // data is set to null on destruction
pub struct OwnedSlice<T> {
    /// null iff len == 0
    data: *mut T,
    len: uint,
}

impl<T:fmt::Show> fmt::Show for OwnedSlice<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!("OwnedSlice {{".fmt(fmt));
        for i in self.iter() {
            try!(i.fmt(fmt));
        }
        try!("}}".fmt(fmt));
        Ok(())
    }
}

#[unsafe_destructor]
impl<T> Drop for OwnedSlice<T> {
    fn drop(&mut self) {
        if self.data.is_null() { return }

        // extract the vector
        let v = mem::replace(self, OwnedSlice::empty());
        // free via the Vec destructor
        v.into_vec();
    }
}

impl<T> OwnedSlice<T> {
    pub fn empty() -> OwnedSlice<T> {
        OwnedSlice  { data: ptr::mut_null(), len: 0 }
    }

    #[inline(never)]
    pub fn from_vec(mut v: Vec<T>) -> OwnedSlice<T> {
        let len = v.len();

        if len == 0 {
            OwnedSlice::empty()
        } else {
            // drop excess capacity to avoid breaking sized deallocation
            v.shrink_to_fit();

            let p = v.as_mut_ptr();
            // we own the allocation now
            unsafe { mem::forget(v) }

            OwnedSlice { data: p, len: len }
        }
    }

    #[inline(never)]
    pub fn into_vec(self) -> Vec<T> {
        // null is ok, because len == 0 in that case, as required by Vec.
        unsafe {
            let ret = Vec::from_raw_parts(self.len, self.len, self.data);
            // the vector owns the allocation now
            mem::forget(self);
            ret
        }
    }

    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        static PTR_MARKER: u8 = 0;
        let ptr = if self.data.is_null() {
            // length zero, i.e. this will never be read as a T.
            &PTR_MARKER as *const u8 as *const T
        } else {
            self.data as *const T
        };

        let slice: &[T] = unsafe {mem::transmute(raw::Slice {
            data: ptr,
            len: self.len
        })};

        slice
    }

    pub fn get<'a>(&'a self, i: uint) -> &'a T {
        self.as_slice().get(i).expect("OwnedSlice: index out of bounds")
    }

    pub fn iter<'r>(&'r self) -> slice::Items<'r, T> {
        self.as_slice().iter()
    }

    pub fn map<U>(&self, f: |&T| -> U) -> OwnedSlice<U> {
        self.iter().map(f).collect()
    }
}

impl<T> Default for OwnedSlice<T> {
    fn default() -> OwnedSlice<T> {
        OwnedSlice::empty()
    }
}

impl<T: Clone> Clone for OwnedSlice<T> {
    fn clone(&self) -> OwnedSlice<T> {
        OwnedSlice::from_vec(Vec::from_slice(self.as_slice()))
    }
}

impl<S: hash::Writer, T: hash::Hash<S>> hash::Hash<S> for OwnedSlice<T> {
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state)
    }
}

impl<T: PartialEq> PartialEq for OwnedSlice<T> {
    fn eq(&self, other: &OwnedSlice<T>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<T: Eq> Eq for OwnedSlice<T> {}

impl<T> Collection for OwnedSlice<T> {
    fn len(&self) -> uint { self.len }
}

impl<T> FromIterator<T> for OwnedSlice<T> {
    fn from_iter<I: Iterator<T>>(mut iter: I) -> OwnedSlice<T> {
        OwnedSlice::from_vec(iter.collect())
    }
}

impl<S: Encoder<E>, T: Encodable<S, E>, E> Encodable<S, E> for OwnedSlice<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
       self.as_slice().encode(s)
    }
}

impl<D: Decoder<E>, T: Decodable<D, E>, E> Decodable<D, E> for OwnedSlice<T> {
    fn decode(d: &mut D) -> Result<OwnedSlice<T>, E> {
        Ok(OwnedSlice::from_vec(match Decodable::decode(d) {
            Ok(t) => t,
            Err(e) => return Err(e)
        }))
    }
}
<|endoftext|>


<commit_before>use crate::config::{Config, EnvConfig};
use crate::error::{Error, ErrorKind, Result};
use crate::page::parse_page;
use crate::service;
use std::process::{Command, Stdio};

pub fn build_url(cfg: &Config) -> Result<String> {
    let page = parse_page(&cfg)?;
    service::build_page_url(&page, &cfg)
}

fn browse_with_cmd(url: &str, cmd: &str) -> Result<()> {
    let out = Command::new(cmd)
        .arg(url)
        .stdout(Stdio::inherit())
        .output()?;
    if out.status.success() {
        Ok(())
    } else {
        Error::err(ErrorKind::UserBrowseCommandFailed {
            cmd: cmd.to_string(),
            url: url.to_string(),
            msg: String::from_utf8_lossy(&out.stderr)
                .trim()
                .replace('\n', " "),
        })
    }
}

pub fn browse(url: &str, env: &EnvConfig) -> Result<()> {
    if let Some(ref cmd) = env.browse_command {
        return browse_with_cmd(url, cmd);
    }

    match open::that(url) {
        Ok(status) if status.success() => Ok(()),
        Ok(status) => {
            let url = url.to_string();
            let msg = if let Some(code) = status.code() {
                format!("Command exited with non-zero status {}", code)
            } else {
                "Error on opening URL {}: Command terminated by signal".to_string()
            };
            Error::err(ErrorKind::OpenUrlFailure { url, msg })
        }
        Err(e) => Error::err(ErrorKind::OpenUrlFailure {
            url: url.to_string(),
            msg: format!("{}", e),
        }),
    }
}
<commit_msg>fix error message on command failure with signals<commit_after>use crate::config::{Config, EnvConfig};
use crate::error::{Error, ErrorKind, Result};
use crate::page::parse_page;
use crate::service;
use std::process::{Command, Stdio};

pub fn build_url(cfg: &Config) -> Result<String> {
    let page = parse_page(&cfg)?;
    service::build_page_url(&page, &cfg)
}

fn browse_with_cmd(url: &str, cmd: &str) -> Result<()> {
    let out = Command::new(cmd)
        .arg(url)
        .stdout(Stdio::inherit())
        .output()?;
    if out.status.success() {
        Ok(())
    } else {
        Error::err(ErrorKind::UserBrowseCommandFailed {
            cmd: cmd.to_string(),
            url: url.to_string(),
            msg: String::from_utf8_lossy(&out.stderr)
                .trim()
                .replace('\n', " "),
        })
    }
}

pub fn browse(url: &str, env: &EnvConfig) -> Result<()> {
    if let Some(ref cmd) = env.browse_command {
        return browse_with_cmd(url, cmd);
    }

    match open::that(url) {
        Ok(status) if status.success() => Ok(()),
        Ok(status) => {
            let url = url.to_string();
            let msg = if let Some(code) = status.code() {
                format!("Command exited with non-zero status {}", code)
            } else {
                // TODO: Add signal on target == *nix using ExitStatusExt
                "Command terminated by signal".to_string()
            };
            Error::err(ErrorKind::OpenUrlFailure { url, msg })
        }
        Err(e) => Error::err(ErrorKind::OpenUrlFailure {
            url: url.to_string(),
            msg: format!("{}", e),
        }),
    }
}
<|endoftext|>


<commit_before>use std::num::Wrapping;
use number_types::d8_type::d8;

#[allow(warnings)]
#[derive(Copy, Clone, Debug)]
pub struct d16(pub Wrapping<u16>);

impl d16 {
    pub fn lsb(self) -> d8 {
        // remember, on little-endian systems, the lsb has index 0!
        let array: [d8; 2] = unsafe {
            ::std::mem::transmute::<d16, [d8; 2]>(self)
        };
        array[0]
    }

    pub const HIGHEST_BIT_MASK: d16 = d16(Wrapping(0b1000000000000000));
    pub const LOWEST_BIT_MASK: d16 = d16(Wrapping(0b0000000000000001));
    pub const ZERO: d16 = d16(Wrapping(0));
}

impl ::std::cmp::PartialEq for d16 {
    fn eq(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me == other
    }
}

impl ::std::cmp::Eq for d16 {}

impl ::std::cmp::PartialEq<u16> for d16 {
    fn eq(&self, &other: &u16) -> bool {
        let d16(Wrapping(me)) = *self;
        me == other
    }
}

impl ::std::cmp::PartialOrd for d16 {
    fn partial_cmp(&self, &d16(other): &Self) -> Option<::std::cmp::Ordering> {
        let d16(me) = *self;
        if me < other {
            Some(::std::cmp::Ordering::Less)
        } else if me > other {
            Some(::std::cmp::Ordering::Greater)
        } else {
            Some(::std::cmp::Ordering::Equal)
        }
    }

    fn lt(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me < other
    }

    fn gt(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me > other
    }

    fn le(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me <= other
    }

    fn ge(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me >= other
    }
}

impl ::std::cmp::Ord for d16 {
    fn cmp(&self, &d16(other): &Self) -> ::std::cmp::Ordering {
        let d16(me) = *self;
        if me < other {
            ::std::cmp::Ordering::Less
        } else if me > other {
            ::std::cmp::Ordering::Greater
        } else {
            ::std::cmp::Ordering::Equal
        }
    }
}

impl ::std::convert::AsRef<[d8; 2]> for d16 {
    fn as_ref(&self) -> &[d8; 2] {
        use std::mem::transmute;

        unsafe {
            transmute(&self)
        }
    }
}

impl ::std::convert::From<[d8; 2]> for d16 {
    fn from(this: [d8; 2]) -> Self {
        unsafe {
            ::std::mem::transmute(this)
        }
    }
}

impl ::std::convert::From<d16> for [d8; 2] {
    fn from(this: d16) -> Self {
        unsafe {
            ::std::mem::transmute(this)
        }
    }
}

impl ::std::ops::Add for d16 {
    type Output = Self;
    fn add(self, d16(other): Self) -> <Self as ::std::ops::Add<Self>>::Output {
        let d16(me) = self;
        d16(me + other)
    }
}

impl ::std::ops::AddAssign for d16 {
    fn add_assign(&mut self, d16(other): Self) {
        self.0 = self.0 + other;
    }
}

impl ::std::ops::Add<u16> for d16 {
    type Output = Self;
    fn add(self, other: u16) -> <Self as ::std::ops::Add<u16>>::Output {
        let d16(me) = self;
        d16(me + Wrapping(other))
    }
}

impl ::std::ops::AddAssign<u16> for d16 {
    fn add_assign(&mut self, other: u16) {
        self.0 = self.0 + Wrapping(other);
    }
}

impl ::std::ops::Sub for d16 {
    type Output = Self;
    fn sub(self, d16(other): Self) -> <Self as ::std::ops::Sub<Self>>::Output {
        let d16(me) = self;
        d16(me - other)
    }
}

impl ::std::ops::SubAssign for d16 {
    fn sub_assign(&mut self, d16(other): Self) {
        self.0 = self.0 - other;
    }
}

impl ::std::ops::SubAssign<u16> for d16 {
    fn sub_assign(&mut self, other: u16) {
        self.0 = self.0 - Wrapping(other);
    }
}

impl ::std::ops::BitAnd for d16 {
    type Output = Self;
    fn bitand(self, d16(other): Self) -> <Self as ::std::ops::BitAnd>::Output {
        let d16(me) = self;
        d16(me & other)
    }
}

impl ::std::ops::BitAndAssign for d16 {
    fn bitand_assign(&mut self, d16(other): Self) {
        self.0 &= other;
    }
}
<commit_msg>Wrote some AsRef & AsMut implementations for d16 <=> [d8; 2]<commit_after>use std::num::Wrapping;
use number_types::d8_type::d8;

#[allow(warnings)]
#[derive(Copy, Clone, Debug)]
pub struct d16(pub Wrapping<u16>);

impl d16 {
    pub fn lsb(self) -> d8 {
        // remember, on little-endian systems, the lsb has index 0!
        let array: [d8; 2] = unsafe {
            ::std::mem::transmute::<d16, [d8; 2]>(self)
        };
        array[0]
    }

    pub const HIGHEST_BIT_MASK: d16 = d16(Wrapping(0b1000000000000000));
    pub const LOWEST_BIT_MASK: d16 = d16(Wrapping(0b0000000000000001));
    pub const ZERO: d16 = d16(Wrapping(0));
}

impl ::std::cmp::PartialEq for d16 {
    fn eq(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me == other
    }
}

impl ::std::cmp::Eq for d16 {}

impl ::std::cmp::PartialEq<u16> for d16 {
    fn eq(&self, &other: &u16) -> bool {
        let d16(Wrapping(me)) = *self;
        me == other
    }
}

impl ::std::cmp::PartialOrd for d16 {
    fn partial_cmp(&self, &d16(other): &Self) -> Option<::std::cmp::Ordering> {
        let d16(me) = *self;
        if me < other {
            Some(::std::cmp::Ordering::Less)
        } else if me > other {
            Some(::std::cmp::Ordering::Greater)
        } else {
            Some(::std::cmp::Ordering::Equal)
        }
    }

    fn lt(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me < other
    }

    fn gt(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me > other
    }

    fn le(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me <= other
    }

    fn ge(&self, &d16(other): &Self) -> bool {
        let d16(me) = *self;
        me >= other
    }
}

impl ::std::cmp::Ord for d16 {
    fn cmp(&self, &d16(other): &Self) -> ::std::cmp::Ordering {
        let d16(me) = *self;
        if me < other {
            ::std::cmp::Ordering::Less
        } else if me > other {
            ::std::cmp::Ordering::Greater
        } else {
            ::std::cmp::Ordering::Equal
        }
    }
}

impl ::std::convert::AsRef<[d8; 2]> for d16 {
    fn as_ref(&self) -> &[d8; 2] {
        unsafe {
            ::std::mem::transmute(&self)
        }
    }
}

impl ::std::convert::AsRef<d16> for [d8; 2] {
    fn as_ref(&self) -> &d16 {
        unsafe {
            ::std::mem::transmute(&self)
        }
    }
}

impl ::std::convert::AsMut<[d8; 2]> for d16 {
    fn as_mut(&mut self) -> &mut [d8; 2] {
        unsafe {
            ::std::mem::transmute(self)
        }
    }
}

impl ::std::convert::AsMut<d16> for [d8; 2] {
    fn as_mut(&mut self) -> &mut d16 {
        unsafe {
            ::std::mem::transmute(self)
        }
    }
}

impl ::std::convert::From<[d8; 2]> for d16 {
    fn from(this: [d8; 2]) -> Self {
        unsafe {
            ::std::mem::transmute(this)
        }
    }
}

impl ::std::convert::From<d16> for [d8; 2] {
    fn from(this: d16) -> Self {
        unsafe {
            ::std::mem::transmute(this)
        }
    }
}

impl ::std::ops::Add for d16 {
    type Output = Self;
    fn add(self, d16(other): Self) -> <Self as ::std::ops::Add<Self>>::Output {
        let d16(me) = self;
        d16(me + other)
    }
}

impl ::std::ops::AddAssign for d16 {
    fn add_assign(&mut self, d16(other): Self) {
        self.0 = self.0 + other;
    }
}

impl ::std::ops::Add<u16> for d16 {
    type Output = Self;
    fn add(self, other: u16) -> <Self as ::std::ops::Add<u16>>::Output {
        let d16(me) = self;
        d16(me + Wrapping(other))
    }
}

impl ::std::ops::AddAssign<u16> for d16 {
    fn add_assign(&mut self, other: u16) {
        self.0 = self.0 + Wrapping(other);
    }
}

impl ::std::ops::Sub for d16 {
    type Output = Self;
    fn sub(self, d16(other): Self) -> <Self as ::std::ops::Sub<Self>>::Output {
        let d16(me) = self;
        d16(me - other)
    }
}

impl ::std::ops::SubAssign for d16 {
    fn sub_assign(&mut self, d16(other): Self) {
        self.0 = self.0 - other;
    }
}

impl ::std::ops::SubAssign<u16> for d16 {
    fn sub_assign(&mut self, other: u16) {
        self.0 = self.0 - Wrapping(other);
    }
}

impl ::std::ops::BitAnd for d16 {
    type Output = Self;
    fn bitand(self, d16(other): Self) -> <Self as ::std::ops::BitAnd>::Output {
        let d16(me) = self;
        d16(me & other)
    }
}

impl ::std::ops::BitAndAssign for d16 {
    fn bitand_assign(&mut self, d16(other): Self) {
        self.0 &= other;
    }
}
<|endoftext|>


<commit_before>//!
//! Support mapping based Cone geometry.
//!

use std::num::Zero;
use nalgebra::traits::indexable::Indexable;
use nalgebra::traits::rotation::Rotate;
use nalgebra::traits::transformation::Transform;
use nalgebra::traits::vector::AlgebraicVecExt;
use bounding_volume::aabb::{HasAABB, AABB};
use bounding_volume::aabb;
use geom::implicit::Implicit;

/// Implicit description of a cylinder geometry with its principal axis aligned with the `x` axis.
#[deriving(Eq, ToStr, Clone)]
pub struct Cone<N> {
    priv half_height: N,
    priv radius: N
}

impl<N: Signed> Cone<N> {
    /// Creates a new cone.
    ///
    /// # Arguments:
    ///     * `half_height` - the half length of the cone along the `x` axis.
    ///     * `radius` - the length of the cone along all other axis.
    pub fn new(half_height: N, radius: N) -> Cone<N> {
        assert!(half_height.is_positive() && radius.is_positive());

        Cone {
            half_height: half_height,
            radius: radius
        }
    }
}

impl<N: Clone> Cone<N> {
    /// The cone half length along the `x` axis.
    pub fn half_height(&self) -> N {
        self.half_height.clone()
    }

    /// The radius of the cone along all but the `x` axis.
    pub fn radius(&self) -> N {
        self.radius.clone()
    }
}

impl<N: Clone + Signed + Algebraic,
     V: Clone + AlgebraicVecExt<N>,
     M: Transform<V> + Rotate<V>>
Implicit<V, M> for Cone<N> {
    fn support_point(&self, m: &M, dir: &V) -> V {
        let local_dir = m.inv_rotate(dir);

        if local_dir.at(0).is_negative() { // points toward the base
            let mut vres = local_dir.clone();

            vres.set(0, Zero::zero());

            if vres.normalize().is_zero() {
                vres = Zero::zero()
            }
            else {
                vres = vres * self.radius
            }

            vres.set(0, -self.half_height);

            m.transform(&vres)
        }
        else { // points toward the pointy thing
            let mut vres = Zero::zero::<V>();

            vres.set(0, self.half_height.clone());

            m.transform(&vres)
        }
    }
}

impl<N: Signed + Algebraic + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Rotate<V> + Transform<V>>
HasAABB<N, V, M> for Cone<N> {
    fn aabb(&self, m: &M) -> AABB<N, V> {
        aabb::implicit_shape_aabb(m, self)
    }
}
<commit_msg>Fix cone support function.<commit_after>//!
//! Support mapping based Cone geometry.
//!

use std::num::Zero;
use nalgebra::traits::indexable::Indexable;
use nalgebra::traits::rotation::Rotate;
use nalgebra::traits::transformation::Transform;
use nalgebra::traits::vector::AlgebraicVecExt;
use bounding_volume::aabb::{HasAABB, AABB};
use bounding_volume::aabb;
use geom::implicit::Implicit;

/// Implicit description of a cylinder geometry with its principal axis aligned with the `x` axis.
#[deriving(Eq, ToStr, Clone)]
pub struct Cone<N> {
    priv half_height: N,
    priv radius: N
}

impl<N: Signed> Cone<N> {
    /// Creates a new cone.
    ///
    /// # Arguments:
    ///     * `half_height` - the half length of the cone along the `x` axis.
    ///     * `radius` - the length of the cone along all other axis.
    pub fn new(half_height: N, radius: N) -> Cone<N> {
        assert!(half_height.is_positive() && radius.is_positive());

        Cone {
            half_height: half_height,
            radius: radius
        }
    }
}

impl<N: Clone> Cone<N> {
    /// The cone half length along the `x` axis.
    pub fn half_height(&self) -> N {
        self.half_height.clone()
    }

    /// The radius of the cone along all but the `x` axis.
    pub fn radius(&self) -> N {
        self.radius.clone()
    }
}

impl<N: Clone + Signed + Algebraic + Ord,
     V: Clone + AlgebraicVecExt<N>,
     M: Transform<V> + Rotate<V>>
Implicit<V, M> for Cone<N> {
    fn support_point(&self, m: &M, dir: &V) -> V {
        let local_dir = m.inv_rotate(dir);

        let mut vres = local_dir.clone();

        vres.set(0, Zero::zero());

        if vres.normalize().is_zero() {
            vres = Zero::zero();

            if local_dir.at(0).is_negative() {
                vres.set(0, -self.half_height)
            }
            else {
                vres.set(0, self.half_height.clone())
            }
        }
        else {
            vres = vres * self.radius;
            vres.set(0, -self.half_height);

            if local_dir.dot(&vres) < local_dir.at(0) * self.half_height {
                vres = Zero::zero();
                vres.set(0, self.half_height.clone())
            }
        }

        m.transform(&vres)
    }
}

impl<N: Signed + Algebraic + Ord + Clone,
     V: AlgebraicVecExt<N> + Clone,
     M: Rotate<V> + Transform<V>>
HasAABB<N, V, M> for Cone<N> {
    fn aabb(&self, m: &M) -> AABB<N, V> {
        aabb::implicit_shape_aabb(m, self)
    }
}
<|endoftext|>


<commit_before>use bytes::{alloc, Buf, MutBuf, Bytes, BlockBuf, BlockBufCursor};

/// Buffer abstraction
pub trait Buffer<'a> : MutBuf {
    /// Type of Buf returned
    type Cursor: Buf;

    /// Returns a `Buf` over buffered bytes.
    fn buf(&'a self) -> Self::Cursor;

    /// Return the number of buffered bytes
    fn len(&self) -> usize;

    /// Drain the first `n` buffered bytes, returning them as a `Bytes` value.
    fn shift(&mut self, n: usize) -> Bytes;

    /// Move all buffered bytes into a sequential memory
    ///
    /// # Panics
    ///
    /// Panics if the `Buffer` is unable to allocate sequential memory large
    /// enough to contain the buffered bytes.
    fn compact(&mut self);

    /// Returns a byte slice if all bytes are located in sequential memory
    fn bytes(&self) -> Option<&[u8]>;
}

impl<'a, A: alloc::FixedSize> Buffer<'a> for BlockBuf<A> {
    type Cursor = BlockBufCursor<'a>;

    fn buf(&'a self) -> BlockBufCursor<'a> {
        BlockBuf::buf(self)
    }

    fn len(&self) -> usize {
        BlockBuf::len(self)
    }

    fn shift(&mut self, n: usize) -> Bytes {
        BlockBuf::shift(self, n)
    }

    fn compact(&mut self) {
        BlockBuf::compact(self)
    }

    fn bytes(&self) -> Option<&[u8]> {
        BlockBuf::bytes(self)
    }
}
<commit_msg>Remove a dead file<commit_after><|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Serial port driver
//!
//! Create new serial ports by calling `PortNum::new()`. If the system supports
//! that port, `Some(SerialPort)` will be returned. Otherwise, if the system
//! does not have that port number (such as `COM3` and `COM4`) on many machines,
//! `PortNum::new()` returns `None`.
//!
//! See [the OS Dev wiki](http://wiki.osdev.org/Serial_Ports) for more
//! information.

use super::{Read, Write, Port};
use ::util;

/// Available serial ports.
///
/// These are used to create new serial ports, so that serial ports
/// cannot be created for an arbitrary memory location.
///
#[derive(Debug, Copy, Clone)]
#[repr(usize)]
pub enum PortNum { Com1 = 0
                , Com2 = 1
                , Com3 = 2
                , Com4 = 3
                }

impl PortNum {
    #[inline]
    fn get_port_addr(&self) -> Option<u16> {
        match BDA_SERIAL_INFO[*self as usize] {
            n if n > 0 => Some(n)
          , _ => None
        }
    }

    /// Returns `Some(SerialPort)` if this port exists, `None` if it does not
    pub fn new(&self) -> Option<SerialPort> {
        self.get_port_addr().map(|port| {
             // Disable all interrupts
            Port::<u8>::new(port + 1).write(0x00);
            // Enable DLAB (set baud rate divisor)
            Port::<u8>::new(port + 3).write(0x80);
            // Set divisor to 38400 baud
            Port::<u8>::new(port + 0).write(0x03); // divisor hi byte
            Port::<u8>::new(port + 1).write(0x00); // divisor lo byte
            // 8 bits, no parity, one stop bit
            Port::<u8>::new(port + 3).write(0x03);
            // Enable FIFO, clear them, with 14-byte threshold
            Port::<u8>::new(port + 2).write(0xC7);
            // IRQs enabled, RTS/DSR set
            Port::<u8>::new(port + 4).write(0x0B);
            Port::<u8>::new(port + 1).write(0x01);

            SerialPort { data_port: Port::<u8>::new(port)
                       , status_port: Port::<u8>::new(port + 5)
                       }
        })
    }
}

/// Address of the BIOS Data Area (BDA)
/// where the serial port addresses are stored.
const BDA_ADDR: usize = 0x400;

lazy_static! {
    static ref BDA_SERIAL_INFO: [u16; 4]
        = unsafe { *(BDA_ADDR as *const [u16; 4]) };

}

/// A serial port
pub struct SerialPort { data_port: Port<u8>
                      , status_port: Port<u8>
                      }

impl SerialPort {
    /// Returns true if the serial port has recieved data
    #[inline]
    pub fn has_byte(&self) -> bool {
        self.status_port.read() & 1 != 0
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.status_port.read() & 0x20 == 0x20
    }

    #[inline]
    pub fn read_byte(&self) -> u8 {
        while !self.has_byte() {};
        self.data_port.read()
    }

    #[inline]
    pub fn write_byte(&self, byte: u8) {
        while !self.is_empty() {};
        self.data_port.write(byte)
    }
}

impl Read for SerialPort {
    type Error = util::Void;

    /// Reads a single byte into the given buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        Ok(match &mut *buf {
            // if the length of the buffer is 0, then obviously
            // no bytes were read
            &mut []                  => 0
            // otherwise, read one byte into the head of the buffer
          , &mut [ref mut head, _..] => { *head = self.read_byte(); 1 }
        })
    }

    /// Reads a new byte into each position in the buffer.
    fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        let mut read_bytes = 0;
        for idx in buf.iter_mut() {
            // for each index in the buffer, read another byte from the port
            *idx = self.read_byte();
            // and increment the number of bytes read (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            read_bytes += 1;
        }
        Ok(read_bytes)
    }
}

impl Write for SerialPort {
    type Error = util::Void;

    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
        let mut written_bytes = 0;
        for byte in buf {
            // write each byte in the buffer to the port
            self.write_byte(*byte);
            // and increment the number of bytes written (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            written_bytes += 1;
        }
        Ok(written_bytes)
    }
}
<commit_msg>[kernel] Only initialize serial ports once<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Serial port driver
//!
//! Create new serial ports by calling `PortNum::new()`. If the system supports
//! that port, `Some(SerialPort)` will be returned. Otherwise, if the system
//! does not have that port number (such as `COM3` and `COM4`) on many machines,
//! `PortNum::new()` returns `None`.
//!
//! See [the OS Dev wiki](http://wiki.osdev.org/Serial_Ports) for more
//! information.

use super::{Read, Write, Port};

use core::ops;
use spin::Mutex;

use ::util;

/// Address of the BIOS Data Area (BDA)
/// where the serial port addresses are stored.
const BDA_ADDR: usize = 0x400;

lazy_static! {
    static ref BDA_SERIAL_INFO: [u16; 4]
        = unsafe { *(BDA_ADDR as *const [u16; 4]) };

    pub static ref COM1: Option<Mutex<SerialPort>>
        = PortNum::Com1.initialize().map(Mutex::new);

    pub static ref COM2: Option<Mutex<SerialPort>>
        = PortNum::Com2.initialize().map(Mutex::new);

    pub static ref COM3: Option<Mutex<SerialPort>>
        = PortNum::Com3.initialize().map(Mutex::new);

    pub static ref COM4: Option<Mutex<SerialPort>>
        = PortNum::Com4.initialize().map(Mutex::new);
}

/// Available serial ports.
///
/// These are used to create new serial ports, so that serial ports
/// cannot be created for an arbitrary memory location.
///
#[derive(Debug, Copy, Clone)]
#[repr(usize)]
enum PortNum { Com1 = 0
             , Com2 = 1
             , Com3 = 2
             , Com4 = 3
             }

impl PortNum {
    #[inline]
    fn get_port_addr(&self) -> Option<u16> {
        match BDA_SERIAL_INFO[*self as usize] {
            n if n > 0 => Some(n)
          , _ => None
        }
    }

    /// Returns `Some(SerialPort)` if this port exists, `None` if it does not
    fn initialize(&self) -> Option<SerialPort> {
        self.get_port_addr().map(|port| {
             // Disable all interrupts
            Port::<u8>::new(port + 1).write(0x00);
            // Enable DLAB (set baud rate divisor)
            Port::<u8>::new(port + 3).write(0x80);
            // Set divisor to 38400 baud
            Port::<u8>::new(port + 0).write(0x03); // divisor hi byte
            Port::<u8>::new(port + 1).write(0x00); // divisor lo byte
            // 8 bits, no parity, one stop bit
            Port::<u8>::new(port + 3).write(0x03);
            // Enable FIFO, clear them, with 14-byte threshold
            Port::<u8>::new(port + 2).write(0xC7);
            // IRQs enabled, RTS/DSR set
            Port::<u8>::new(port + 4).write(0x0B);
            Port::<u8>::new(port + 1).write(0x01);

            SerialPort { data_port: Port::<u8>::new(port)
                       , status_port: Port::<u8>::new(port + 5)
                       }
        })
    }
}

/// A serial port
pub struct SerialPort { data_port: Port<u8>
                      , status_port: Port<u8>
                      }

impl SerialPort {
    /// Returns true if the serial port has recieved data
    #[inline]
    pub fn has_byte(&self) -> bool {
        self.status_port.read() & 1 != 0
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.status_port.read() & 0x20 == 0x20
    }

    #[inline]
    pub fn read_byte(&self) -> u8 {
        while !self.has_byte() {};
        self.data_port.read()
    }

    #[inline]
    pub fn write_byte(&self, byte: u8) {
        while !self.is_empty() {};
        self.data_port.write(byte)
    }
}

impl Read for SerialPort {
    type Error = util::Void;

    /// Reads a single byte into the given buffer
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        Ok(match &mut *buf {
            // if the length of the buffer is 0, then obviously
            // no bytes were read
            &mut []                  => 0
            // otherwise, read one byte into the head of the buffer
          , &mut [ref mut head, _..] => { *head = self.read_byte(); 1 }
        })
    }

    /// Reads a new byte into each position in the buffer.
    fn read_all(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
        let mut read_bytes = 0;
        for idx in buf.iter_mut() {
            // for each index in the buffer, read another byte from the port
            *idx = self.read_byte();
            // and increment the number of bytes read (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            read_bytes += 1;
        }
        Ok(read_bytes)
    }
}

impl Write for SerialPort {
    type Error = util::Void;

    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
        let mut written_bytes = 0;
        for byte in buf {
            // write each byte in the buffer to the port
            self.write_byte(*byte);
            // and increment the number of bytes written (this should be faster
            // than calling `buf.len()` later; as we only need 1 loop)
            written_bytes += 1;
        }
        Ok(written_bytes)
    }
}
<|endoftext|>


<commit_before>/// This modules define the logic used to search for a doc in a given
/// block. (at most 128 docs)
///
/// Searching within a block is a hotspot when running intersection.
/// so it was worth defining it in its own module.

#[cfg(target_arch = "x86_64")]
mod sse2 {
    use postings::compression::COMPRESSION_BLOCK_SIZE;
    use std::arch::x86_64::__m128i as DataType;
    use std::arch::x86_64::_mm_add_epi32 as op_add;
    use std::arch::x86_64::_mm_cmplt_epi32 as op_lt;
    use std::arch::x86_64::_mm_load_si128 as op_load; // requires 128-bits alignment
    use std::arch::x86_64::_mm_set1_epi32 as set1;
    use std::arch::x86_64::_mm_setzero_si128 as set0;
    use std::arch::x86_64::_mm_sub_epi32 as op_sub;
    use std::arch::x86_64::{_mm_cvtsi128_si32, _mm_shuffle_epi32};

    const MASK1: i32 = 78;
    const MASK2: i32 = 177;

    /// Performs an exhaustive linear search over the
    ///
    /// There is no early exit here. We simply count the
    /// number of elements that are `< target`.
    pub fn linear_search_sse2_128(arr: &[u32], target: u32) -> usize {
        unsafe {
            let ptr = arr.as_ptr() as *const DataType;
            let vkey = set1(target as i32);
            let mut cnt = set0();
            // We work over 4 `__m128i` at a time.
            // A single `__m128i` actual contains 4 `u32`.
            for i in 0..(COMPRESSION_BLOCK_SIZE as isize) / (4 * 4) {
                let cmp1 = op_lt(op_load(ptr.offset(i * 4)), vkey);
                let cmp2 = op_lt(op_load(ptr.offset(i * 4 + 1)), vkey);
                let cmp3 = op_lt(op_load(ptr.offset(i * 4 + 2)), vkey);
                let cmp4 = op_lt(op_load(ptr.offset(i * 4 + 3)), vkey);
                let sum = op_add(op_add(cmp1, cmp2), op_add(cmp3, cmp4));
                cnt = op_sub(cnt, sum);
            }
            cnt = op_add(cnt, _mm_shuffle_epi32(cnt, MASK1));
            cnt = op_add(cnt, _mm_shuffle_epi32(cnt, MASK2));
            _mm_cvtsi128_si32(cnt) as usize
        }
    }

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

        #[test]
        fn test_linear_search_sse2_128_u32() {
            for i in 0..23 {
                dbg!(i);
                let arr: Vec<u32> = (0..128).map(|el| el * 2 + 1 << 18).collect();
                assert_eq!(linear_search_sse2_128(&arr, arr[64] + 1), 65);
            }
        }
    }
}

/// This `linear search` browser exhaustively through the array.
/// but the early exit is very difficult to predict.
///
/// Coupled with `exponential search` this function is likely
/// to be called with the same `len`
fn linear_search(arr: &[u32], target: u32) -> usize {
    arr.iter().map(|&el| if el < target { 1 } else { 0 }).sum()
}

fn exponential_search(arr: &[u32], target: u32) -> (usize, usize) {
    let end = arr.len();
    let mut begin = 0;
    for &pivot in &[1, 3, 7, 15, 31, 63] {
        if pivot >= end {
            break;
        }
        if arr[pivot] > target {
            return (begin, pivot);
        }
        begin = pivot;
    }
    (begin, end)
}

fn galloping(block_docs: &[u32], target: u32) -> usize {
    let (start, end) = exponential_search(&block_docs, target);
    start + linear_search(&block_docs[start..end], target)
}

/// Tantivy may rely on SIMD instructions to search for a specific document within
/// a given block.
#[derive(Clone, Copy, PartialEq)]
pub enum BlockSearcher {
    #[cfg(target_arch = "x86_64")]
    SSE2,
    Scalar,
}

impl BlockSearcher {
    /// Search the first index containing an element greater or equal to
    /// the target.
    ///
    /// The results should be equivalent to
    /// ```ignore
    /// block[..]
    //       .iter()
    //       .take_while(|&&val| val < target)
    //       .count()
    /// ```
    ///
    /// The `start` argument is just used to hint that the response is
    /// greater than beyond `start`. The implementation may or may not use
    /// it for optimization.
    ///
    /// # Assumption
    ///
    /// The array len is > start.
    /// The block is sorted
    /// The target is assumed greater or equal to the `arr[start]`.
    /// The target is assumed smaller or equal to the last element of the block.
    ///
    /// Currently the scalar implementation starts by an exponential search, and
    /// then operates a linear search in the result subarray.
    ///
    /// If SSE2 instructions are available in the `(platform, running CPU)`,
    /// then we use a different implementation that does an exhaustive linear search over
    /// the full block whenever the block is full (`len == 128`). It is surprisingly faster, most likely because of the lack
    /// of branch.
    pub fn search_in_block(&self, block_docs: &[u32], start: usize, target: u32) -> usize {
        #[cfg(target_arch = "x86_64")]
        {
            use postings::compression::COMPRESSION_BLOCK_SIZE;
            if *self == BlockSearcher::SSE2 {
                if block_docs.len() == COMPRESSION_BLOCK_SIZE {
                    return sse2::linear_search_sse2_128(block_docs, target);
                }
            }
        }
        start + galloping(&block_docs[start..], target)
    }
}

impl Default for BlockSearcher {
    fn default() -> BlockSearcher {
        #[cfg(target_arch = "x86_64")]
        {
            if is_x86_feature_detected!("sse2") {
                return BlockSearcher::SSE2;
            }
        }
        BlockSearcher::Scalar
    }
}

#[cfg(test)]
mod tests {
    use super::exponential_search;
    use super::linear_search;
    use super::BlockSearcher;

    #[test]
    fn test_linear_search() {
        let len: usize = 50;
        let arr: Vec<u32> = (0..len).map(|el| 1u32 + (el as u32) * 2).collect();
        for target in 1..*arr.last().unwrap() {
            let res = linear_search(&arr[..], target);
            if res > 0 {
                assert!(arr[res - 1] < target);
            }
            if res < len {
                assert!(arr[res] >= target);
            }
        }
    }

    #[test]
    fn test_exponentiel_search() {
        assert_eq!(exponential_search(&[1, 2], 0), (0, 1));
        assert_eq!(exponential_search(&[1, 2], 1), (0, 1));
        assert_eq!(
            exponential_search(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 7),
            (3, 7)
        );
    }

    fn util_test_search_in_block(block_searcher: BlockSearcher, block: &[u32], target: u32) {
        let cursor = search_in_block_trivial_but_slow(block, target);
        for i in 0..cursor {
            assert_eq!(block_searcher.search_in_block(block, i, target), cursor);
        }
    }

    fn util_test_search_in_block_all(block_searcher: BlockSearcher, block: &[u32]) {
        use std::collections::HashSet;
        let mut targets = HashSet::new();
        for (i, val) in block.iter().cloned().enumerate() {
            if i > 0 {
                targets.insert(val - 1);
            }
            targets.insert(val);
        }
        for target in targets {
            util_test_search_in_block(block_searcher, block, target);
        }
    }

    fn search_in_block_trivial_but_slow(block: &[u32], target: u32) -> usize {
        block.iter().take_while(|&&val| val < target).count()
    }

    fn test_search_in_block_util(block_searcher: BlockSearcher) {
        for len in 1u32..128u32 {
            let v: Vec<u32> = (0..len).map(|i| i * 2).collect();
            util_test_search_in_block_all(block_searcher, &v[..]);
        }
    }

    #[test]
    fn test_search_in_block_scalar() {
        test_search_in_block_util(BlockSearcher::Scalar);
    }

    #[cfg(target_arch = "x86_64")]
    #[test]
    fn test_search_in_block_sse2() {
        test_search_in_block_util(BlockSearcher::SSE2);
    }
}
<commit_msg>Clippy comments (#532)<commit_after>/// This modules define the logic used to search for a doc in a given
/// block. (at most 128 docs)
///
/// Searching within a block is a hotspot when running intersection.
/// so it was worth defining it in its own module.

#[cfg(target_arch = "x86_64")]
mod sse2 {
    use postings::compression::COMPRESSION_BLOCK_SIZE;
    use std::arch::x86_64::__m128i as DataType;
    use std::arch::x86_64::_mm_add_epi32 as op_add;
    use std::arch::x86_64::_mm_cmplt_epi32 as op_lt;
    use std::arch::x86_64::_mm_load_si128 as op_load; // requires 128-bits alignment
    use std::arch::x86_64::_mm_set1_epi32 as set1;
    use std::arch::x86_64::_mm_setzero_si128 as set0;
    use std::arch::x86_64::_mm_sub_epi32 as op_sub;
    use std::arch::x86_64::{_mm_cvtsi128_si32, _mm_shuffle_epi32};

    const MASK1: i32 = 78;
    const MASK2: i32 = 177;

    /// Performs an exhaustive linear search over the
    ///
    /// There is no early exit here. We simply count the
    /// number of elements that are `< target`.
    pub fn linear_search_sse2_128(arr: &[u32], target: u32) -> usize {
        unsafe {
            let ptr = arr.as_ptr() as *const DataType;
            let vkey = set1(target as i32);
            let mut cnt = set0();
            // We work over 4 `__m128i` at a time.
            // A single `__m128i` actual contains 4 `u32`.
            for i in 0..(COMPRESSION_BLOCK_SIZE as isize) / (4 * 4) {
                let cmp1 = op_lt(op_load(ptr.offset(i * 4)), vkey);
                let cmp2 = op_lt(op_load(ptr.offset(i * 4 + 1)), vkey);
                let cmp3 = op_lt(op_load(ptr.offset(i * 4 + 2)), vkey);
                let cmp4 = op_lt(op_load(ptr.offset(i * 4 + 3)), vkey);
                let sum = op_add(op_add(cmp1, cmp2), op_add(cmp3, cmp4));
                cnt = op_sub(cnt, sum);
            }
            cnt = op_add(cnt, _mm_shuffle_epi32(cnt, MASK1));
            cnt = op_add(cnt, _mm_shuffle_epi32(cnt, MASK2));
            _mm_cvtsi128_si32(cnt) as usize
        }
    }

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

        #[test]
        fn test_linear_search_sse2_128_u32() {
            for i in 0..23 {
                dbg!(i);
                let arr: Vec<u32> = (0..128).map(|el| el * 2 + 1 << 18).collect();
                assert_eq!(linear_search_sse2_128(&arr, arr[64] + 1), 65);
            }
        }
    }
}

/// This `linear search` browser exhaustively through the array.
/// but the early exit is very difficult to predict.
///
/// Coupled with `exponential search` this function is likely
/// to be called with the same `len`
fn linear_search(arr: &[u32], target: u32) -> usize {
    arr.iter().map(|&el| if el < target { 1 } else { 0 }).sum()
}

fn exponential_search(arr: &[u32], target: u32) -> (usize, usize) {
    let end = arr.len();
    let mut begin = 0;
    for &pivot in &[1, 3, 7, 15, 31, 63] {
        if pivot >= end {
            break;
        }
        if arr[pivot] > target {
            return (begin, pivot);
        }
        begin = pivot;
    }
    (begin, end)
}

fn galloping(block_docs: &[u32], target: u32) -> usize {
    let (start, end) = exponential_search(&block_docs, target);
    start + linear_search(&block_docs[start..end], target)
}

/// Tantivy may rely on SIMD instructions to search for a specific document within
/// a given block.
#[derive(Clone, Copy, PartialEq)]
pub enum BlockSearcher {
    #[cfg(target_arch = "x86_64")]
    SSE2,
    Scalar,
}

impl BlockSearcher {
    /// Search the first index containing an element greater or equal to
    /// the target.
    ///
    /// The results should be equivalent to
    /// ```ignore
    /// block[..]
    //       .iter()
    //       .take_while(|&&val| val < target)
    //       .count()
    /// ```
    ///
    /// The `start` argument is just used to hint that the response is
    /// greater than beyond `start`. The implementation may or may not use
    /// it for optimization.
    ///
    /// # Assumption
    ///
    /// The array len is > start.
    /// The block is sorted
    /// The target is assumed greater or equal to the `arr[start]`.
    /// The target is assumed smaller or equal to the last element of the block.
    ///
    /// Currently the scalar implementation starts by an exponential search, and
    /// then operates a linear search in the result subarray.
    ///
    /// If SSE2 instructions are available in the `(platform, running CPU)`,
    /// then we use a different implementation that does an exhaustive linear search over
    /// the full block whenever the block is full (`len == 128`). It is surprisingly faster, most likely because of the lack
    /// of branch.
    pub fn search_in_block(self, block_docs: &[u32], start: usize, target: u32) -> usize {
        #[cfg(target_arch = "x86_64")]
        {
            use postings::compression::COMPRESSION_BLOCK_SIZE;
            if self == BlockSearcher::SSE2 && block_docs.len() == COMPRESSION_BLOCK_SIZE {
                return sse2::linear_search_sse2_128(block_docs, target);
            }
        }
        start + galloping(&block_docs[start..], target)
    }
}

impl Default for BlockSearcher {
    fn default() -> BlockSearcher {
        #[cfg(target_arch = "x86_64")]
        {
            if is_x86_feature_detected!("sse2") {
                return BlockSearcher::SSE2;
            }
        }
        BlockSearcher::Scalar
    }
}

#[cfg(test)]
mod tests {
    use super::exponential_search;
    use super::linear_search;
    use super::BlockSearcher;

    #[test]
    fn test_linear_search() {
        let len: usize = 50;
        let arr: Vec<u32> = (0..len).map(|el| 1u32 + (el as u32) * 2).collect();
        for target in 1..*arr.last().unwrap() {
            let res = linear_search(&arr[..], target);
            if res > 0 {
                assert!(arr[res - 1] < target);
            }
            if res < len {
                assert!(arr[res] >= target);
            }
        }
    }

    #[test]
    fn test_exponentiel_search() {
        assert_eq!(exponential_search(&[1, 2], 0), (0, 1));
        assert_eq!(exponential_search(&[1, 2], 1), (0, 1));
        assert_eq!(
            exponential_search(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 7),
            (3, 7)
        );
    }

    fn util_test_search_in_block(block_searcher: BlockSearcher, block: &[u32], target: u32) {
        let cursor = search_in_block_trivial_but_slow(block, target);
        for i in 0..cursor {
            assert_eq!(block_searcher.search_in_block(block, i, target), cursor);
        }
    }

    fn util_test_search_in_block_all(block_searcher: BlockSearcher, block: &[u32]) {
        use std::collections::HashSet;
        let mut targets = HashSet::new();
        for (i, val) in block.iter().cloned().enumerate() {
            if i > 0 {
                targets.insert(val - 1);
            }
            targets.insert(val);
        }
        for target in targets {
            util_test_search_in_block(block_searcher, block, target);
        }
    }

    fn search_in_block_trivial_but_slow(block: &[u32], target: u32) -> usize {
        block.iter().take_while(|&&val| val < target).count()
    }

    fn test_search_in_block_util(block_searcher: BlockSearcher) {
        for len in 1u32..128u32 {
            let v: Vec<u32> = (0..len).map(|i| i * 2).collect();
            util_test_search_in_block_all(block_searcher, &v[..]);
        }
    }

    #[test]
    fn test_search_in_block_scalar() {
        test_search_in_block_util(BlockSearcher::Scalar);
    }

    #[cfg(target_arch = "x86_64")]
    #[test]
    fn test_search_in_block_sse2() {
        test_search_in_block_util(BlockSearcher::SSE2);
    }
}
<|endoftext|>


<commit_before>use libc::{c_char, c_void, c_uint};
use prodbg_api::{CMenuFuncs1, PDMenuItem};
use std::mem::transmute;

static mut MENU_FUNCS: CMenuFuncs1 = CMenuFuncs1 {
    create_menu: create_menu,
    destroy_menu: destroy_menu,
    add_menu_item: add_menu_item,
    remove_menu_item: remove_menu_item,
    set_flags: set_flags,
    set_shortcut_key: set_shortcut_key,
};

fn create_menu(_title: *const c_char) -> u64 {
    0
}

fn destroy_menu(_handle: u64) {

}

fn add_menu_item(_menu: u64, _name: *const c_char, _id: c_uint) -> PDMenuItem {
    PDMenuItem(0)
}

fn remove_menu_item(_item: u64) {

}

fn set_flags(_item: u64, _flags: c_uint) {

}

fn set_shortcut_key(_item: u64, _accel_key: c_uint, _modifier: c_uint) {

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
    create_menu: extern "C" fn(title: *const c_char) -> u64,
    destroy_menu: extern "C" fn(handle: u64),

    add_menu_item: extern "C" fn(menu: u64, name: *const c_char, id: c_uint) -> PDMenuItem,
    remove_menu_item: extern "C" fn(item: u64),

    set_flags: extern "C" fn(item: u64, flags: c_uint),
    set_shortcut_key: extern "C" fn(item: u64, accel_key: c_uint, modifier: c_uint),
*/

pub fn get_menu_funcs1() -> *mut c_void {
    unsafe {
        let funcs: *mut c_void = transmute(&mut MENU_FUNCS);
        funcs
    }
    //ptr::null_mut()
}
<commit_msg>Working on menus<commit_after>use libc::{c_char, c_void, c_uint};
use prodbg_api::{CMenuFuncs1, PDMenuItem};
//use prodbg_api::CFixedString;
use std::mem::transmute;
use std::ptr;
//use minifb;

static mut MENU_FUNCS: CMenuFuncs1 = CMenuFuncs1 {
    create_menu: create_menu,
    destroy_menu: destroy_menu,
    add_menu_item: add_menu_item,
    remove_menu_item: remove_menu_item,
    set_flags: set_flags,
    set_shortcut_key: set_shortcut_key,
};

//fn create_menu(title: *const c_char) -> *mut c_void {
fn create_menu(title: *const c_char) -> u64 {
    unsafe {
        //let name = CStr::from_ptr(title);
        //let menu = minfb::Menu::new(name.to_str().unwrap());
        //menu.0
        //let menu_ptr = transmute(Box::new(menu));

    }

    0

    //ptr::null_mut();
}

//fn destroy_menu(_handle: *mut c_void) {
fn destroy_menu(_handle: u64) {
    //let _: Box<minifb::Menu> = unsafe { transmute(handle) };
    // implicitly dropped
}

fn add_menu_item(_menu: u64, _name: *const c_char, _id: c_uint) -> u64 {
    /*
    let menu: &mut minifb::Menu = unsafe { &mut *(ptr as *mut minifb::Menu) };
    let name = CStr::from_ptr(title);
    menu.add_item(name.as_str().unwrap(), id).build().0
    */
    0
}

fn remove_menu_item(_item: u64) {

}

fn set_flags(_item: u64, _flags: c_uint) {

}

fn set_shortcut_key(_item: u64, _accel_key: c_uint, _modifier: c_uint) {

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

pub fn get_menu_funcs1() -> *mut c_void {
    unsafe {
        let funcs: *mut c_void = transmute(&mut MENU_FUNCS);
        funcs
    }
    //ptr::null_mut()
}
<|endoftext|>


<commit_before><commit_msg>remove empty src/iter/misc.rs<commit_after><|endoftext|>