<commit_before>//! Runtime support needed for testing the stdarch crate.
//!
//! This basically just disassembles the current executable and then parses the
//! output once globally and then provides the `assert` function which makes
//! assertions about the disassembly of a function.
#![feature(bench_black_box)] // For black_box
#![deny(rust_2018_idioms)]
#![allow(clippy::missing_docs_in_private_items, clippy::print_stdout)]

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate cfg_if;

pub use assert_instr_macro::*;
pub use simd_test_macro::*;
use std::{cmp, collections::HashSet, env, hash, hint::black_box, str, sync::atomic::AtomicPtr};

cfg_if! {
    if #[cfg(target_arch = "wasm32")] {
        pub mod wasm;
        use wasm::disassemble_myself;
    } else {
        mod disassembly;
        use crate::disassembly::disassemble_myself;
    }
}

lazy_static! {
    static ref DISASSEMBLY: HashSet<Function> = disassemble_myself();
}

#[derive(Debug)]
struct Function {
    name: String,
    instrs: Vec<String>,
}
impl Function {
    fn new(n: &str) -> Self {
        Self {
            name: n.to_string(),
            instrs: Vec::new(),
        }
    }
}

impl cmp::PartialEq for Function {
    fn eq(&self, other: &Self) -> bool {
        self.name == other.name
    }
}
impl cmp::Eq for Function {}

impl hash::Hash for Function {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.name.hash(state)
    }
}

/// Main entry point for this crate, called by the `#[assert_instr]` macro.
///
/// This asserts that the function at `fnptr` contains the instruction
/// `expected` provided.
pub fn assert(shim_addr: usize, fnname: &str, expected: &str) {
    // Make sure that the shim is not removed
    black_box(shim_addr);

    //eprintln!("shim name: {}", fnname);
    let function = &DISASSEMBLY
        .get(&Function::new(fnname))
        .unwrap_or_else(|| panic!("function \"{}\" not found in the disassembly", fnname));
    //eprintln!("  function: {:?}", function);

    let mut instrs = &function.instrs[..];
    while instrs.last().map_or(false, |s| s == "nop") {
        instrs = &instrs[..instrs.len() - 1];
    }

    // There are two cases when the expected instruction is nop:
    // 1. The expected intrinsic is compiled away so we can't
    // check for it - aka the intrinsic is not generating any code.
    // 2. It is a mark, indicating that the instruction will be
    // compiled into other instructions - mainly because of llvm
    // optimization.
    if expected == "nop" {
        return;
    }

    // Look for `expected` as the first part of any instruction in this
    // function, e.g., tzcntl in tzcntl %rax,%rax.
    let found = instrs.iter().any(|s| s.starts_with(expected));

    // Look for `call` instructions in the disassembly to detect whether
    // inlining failed: all intrinsics are `#[inline(always)]`, so
    // calling one intrinsic from another should not generate `call`
    // instructions.
    let inlining_failed = instrs.windows(2).any(|s| {
        // On 32-bit x86 position independent code will call itself and be
        // immediately followed by a `pop` to learn about the current address.
        // Let's not take that into account when considering whether a function
        // failed inlining something.
        s[0].contains("call") && (!cfg!(target_arch = "x86") || s[1].contains("pop"))
    });

    let instruction_limit = std::env::var("STDARCH_ASSERT_INSTR_LIMIT")
        .ok()
        .map_or_else(
            || match expected {
                // `cpuid` returns a pretty big aggregate structure, so exempt
                // it from the slightly more restrictive 22 instructions below.
                "cpuid" => 30,

                // Apparently, on Windows, LLVM generates a bunch of
                // saves/restores of xmm registers around these intstructions,
                // which exceeds the limit of 20 below. As it seems dictated by
                // Windows's ABI (I believe?), we probably can't do much
                // about it.
                "vzeroall" | "vzeroupper" if cfg!(windows) => 30,

                // Intrinsics using `cvtpi2ps` are typically "composites" and
                // in some cases exceed the limit.
                "cvtpi2ps" => 25,
                // core_arch/src/arm_shared/simd32
                // vfmaq_n_f32_vfma : #instructions = 26 >= 22 (limit)
                "usad8" | "vfma" | "vfms" => 27,
                "qadd8" | "qsub8" | "sadd8" | "sel" | "shadd8" | "shsub8" | "usub8" | "ssub8" => 29,
                // core_arch/src/arm_shared/simd32
                // vst1q_s64_x4_vst1 : #instructions = 40 >= 22 (limit)
                "vst1" => 41,

                // Temporary, currently the fptosi.sat and fptoui.sat LLVM
                // intrinsics emit unnecessary code on arm. This can be
                // removed once it has been addressed in LLVM.
                "fcvtzu" | "fcvtzs" | "vcvt" => 64,

                // Original limit was 20 instructions, but ARM DSP Intrinsics
                // are exactly 20 instructions long. So, bump the limit to 22
                // instead of adding here a long list of exceptions.
                _ => 22,
            },
            |v| v.parse().unwrap(),
        );
    let probably_only_one_instruction = instrs.len() < instruction_limit;

    if found && probably_only_one_instruction && !inlining_failed {
        return;
    }

    // Help debug by printing out the found disassembly, and then panic as we
    // didn't find the instruction.
    println!("disassembly for {}: ", fnname,);
    for (i, instr) in instrs.iter().enumerate() {
        println!("\t{:2}: {}", i, instr);
    }

    if !found {
        panic!(
            "failed to find instruction `{}` in the disassembly",
            expected
        );
    } else if !probably_only_one_instruction {
        panic!(
            "instruction found, but the disassembly contains too many \
             instructions: #instructions = {} >= {} (limit)",
            instrs.len(),
            instruction_limit
        );
    } else if inlining_failed {
        panic!(
            "instruction found, but the disassembly contains `call` \
             instructions, which hint that inlining failed"
        );
    }
}

pub fn assert_skip_test_ok(name: &str) {
    if env::var("STDARCH_TEST_EVERYTHING").is_err() {
        return;
    }
    panic!("skipped test `{}` when it shouldn't be skipped", name);
}

// See comment in `assert-instr-macro` crate for why this exists
pub static _DONT_DEDUP: AtomicPtr<u8> = AtomicPtr::new(b"".as_ptr() as *mut _);
<commit_msg>Implement proper subroutine call detection for x86, x86_64, aarch64 and wasm32.<commit_after>//! Runtime support needed for testing the stdarch crate.
//!
//! This basically just disassembles the current executable and then parses the
//! output once globally and then provides the `assert` function which makes
//! assertions about the disassembly of a function.
#![feature(bench_black_box)] // For black_box
#![deny(rust_2018_idioms)]
#![allow(clippy::missing_docs_in_private_items, clippy::print_stdout)]

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate cfg_if;

pub use assert_instr_macro::*;
pub use simd_test_macro::*;
use std::{cmp, collections::HashSet, env, hash, hint::black_box, str, sync::atomic::AtomicPtr};

cfg_if! {
    if #[cfg(target_arch = "wasm32")] {
        pub mod wasm;
        use wasm::disassemble_myself;
    } else {
        mod disassembly;
        use crate::disassembly::disassemble_myself;
    }
}

lazy_static! {
    static ref DISASSEMBLY: HashSet<Function> = disassemble_myself();
}

#[derive(Debug)]
struct Function {
    name: String,
    instrs: Vec<String>,
}
impl Function {
    fn new(n: &str) -> Self {
        Self {
            name: n.to_string(),
            instrs: Vec::new(),
        }
    }
}

impl cmp::PartialEq for Function {
    fn eq(&self, other: &Self) -> bool {
        self.name == other.name
    }
}
impl cmp::Eq for Function {}

impl hash::Hash for Function {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.name.hash(state)
    }
}

/// Main entry point for this crate, called by the `#[assert_instr]` macro.
///
/// This asserts that the function at `fnptr` contains the instruction
/// `expected` provided.
pub fn assert(shim_addr: usize, fnname: &str, expected: &str) {
    // Make sure that the shim is not removed
    black_box(shim_addr);

    //eprintln!("shim name: {}", fnname);
    let function = &DISASSEMBLY
        .get(&Function::new(fnname))
        .unwrap_or_else(|| panic!("function \"{}\" not found in the disassembly", fnname));
    //eprintln!("  function: {:?}", function);

    let mut instrs = &function.instrs[..];
    while instrs.last().map_or(false, |s| s == "nop") {
        instrs = &instrs[..instrs.len() - 1];
    }

    // There are two cases when the expected instruction is nop:
    // 1. The expected intrinsic is compiled away so we can't
    // check for it - aka the intrinsic is not generating any code.
    // 2. It is a mark, indicating that the instruction will be
    // compiled into other instructions - mainly because of llvm
    // optimization.
    if expected == "nop" {
        return;
    }

    // Look for `expected` as the first part of any instruction in this
    // function, e.g., tzcntl in tzcntl %rax,%rax.
    let found = instrs.iter().any(|s| s.starts_with(expected));

    // Look for subroutine call instructions in the disassembly to detect whether
    // inlining failed: all intrinsics are `#[inline(always)]`, so calling one
    // intrinsic from another should not generate subroutine call instructions.
    let inlining_failed = if cfg!(target_arch = "x86_64") || cfg!(target_arch = "wasm32") {
        instrs.iter().any(|s| s.starts_with("call "))
    } else if cfg!(target_arch = "x86") {
        instrs.windows(2).any(|s| {
            // On 32-bit x86 position independent code will call itself and be
            // immediately followed by a `pop` to learn about the current address.
            // Let's not take that into account when considering whether a function
            // failed inlining something.
            s[0].starts_with("call ") && s[1].starts_with("pop") // FIXME: original logic but does not match comment
        })
    } else if cfg!(target_arch = "aarch64") {
        instrs.iter().any(|s| s.starts_with("bl "))
    } else {
        // FIXME: Add detection for other archs
        false
    };

    let instruction_limit = std::env::var("STDARCH_ASSERT_INSTR_LIMIT")
        .ok()
        .map_or_else(
            || match expected {
                // `cpuid` returns a pretty big aggregate structure, so exempt
                // it from the slightly more restrictive 22 instructions below.
                "cpuid" => 30,

                // Apparently, on Windows, LLVM generates a bunch of
                // saves/restores of xmm registers around these intstructions,
                // which exceeds the limit of 20 below. As it seems dictated by
                // Windows's ABI (I believe?), we probably can't do much
                // about it.
                "vzeroall" | "vzeroupper" if cfg!(windows) => 30,

                // Intrinsics using `cvtpi2ps` are typically "composites" and
                // in some cases exceed the limit.
                "cvtpi2ps" => 25,
                // core_arch/src/arm_shared/simd32
                // vfmaq_n_f32_vfma : #instructions = 26 >= 22 (limit)
                "usad8" | "vfma" | "vfms" => 27,
                "qadd8" | "qsub8" | "sadd8" | "sel" | "shadd8" | "shsub8" | "usub8" | "ssub8" => 29,
                // core_arch/src/arm_shared/simd32
                // vst1q_s64_x4_vst1 : #instructions = 40 >= 22 (limit)
                "vst1" => 41,

                // Temporary, currently the fptosi.sat and fptoui.sat LLVM
                // intrinsics emit unnecessary code on arm. This can be
                // removed once it has been addressed in LLVM.
                "fcvtzu" | "fcvtzs" | "vcvt" => 64,

                // Original limit was 20 instructions, but ARM DSP Intrinsics
                // are exactly 20 instructions long. So, bump the limit to 22
                // instead of adding here a long list of exceptions.
                _ => 22,
            },
            |v| v.parse().unwrap(),
        );
    let probably_only_one_instruction = instrs.len() < instruction_limit;

    if found && probably_only_one_instruction && !inlining_failed {
        return;
    }

    // Help debug by printing out the found disassembly, and then panic as we
    // didn't find the instruction.
    println!("disassembly for {}: ", fnname,);
    for (i, instr) in instrs.iter().enumerate() {
        println!("\t{:2}: {}", i, instr);
    }

    if !found {
        panic!(
            "failed to find instruction `{}` in the disassembly",
            expected
        );
    } else if !probably_only_one_instruction {
        panic!(
            "instruction found, but the disassembly contains too many \
             instructions: #instructions = {} >= {} (limit)",
            instrs.len(),
            instruction_limit
        );
    } else if inlining_failed {
        panic!(
            "instruction found, but the disassembly contains subroutine \
             call instructions, which hint that inlining failed"
        );
    }
}

pub fn assert_skip_test_ok(name: &str) {
    if env::var("STDARCH_TEST_EVERYTHING").is_err() {
        return;
    }
    panic!("skipped test `{}` when it shouldn't be skipped", name);
}

// See comment in `assert-instr-macro` crate for why this exists
pub static _DONT_DEDUP: AtomicPtr<u8> = AtomicPtr::new(b"".as_ptr() as *mut _);
<|endoftext|>


<commit_before>//! The integration suite for inspecting sessions.

extern crate libc;
extern crate rand;
extern crate regex;

mod helpers;

mod open {
    use rand::{random};
    use std::fs::File;
    use std::fs;
    use std::path::PathBuf;
    use std::io::prelude::*;
    use helpers::*;

    fn setup(contents: &'static [u8]) -> (String, PathBuf) {
        let project_name = format!("muxed_int_test_{}", random::<u16>());
        let project_file = format!("/tmp/muxed_{}/{}.yml", random::<u16>(), project_name);
        let project_path = PathBuf::from(&project_file);

        let muxed_path = project_path.parent().unwrap();
        if !muxed_path.exists() { println!("{:?}", fs::create_dir(muxed_path)) };

        let mut buffer = File::create(&project_path).unwrap();
        let _ = buffer.write(contents);

        (project_name, project_path.clone())
    }

    fn cleanup(project_name: &String, config_path: &PathBuf) -> () {
        let _ = fs::remove_file(config_path);
        let _ = fs::remove_dir(config_path.parent().unwrap());
        kill_session(&project_name);
    }

    fn test_with_contents(contents: &'static [u8]) -> TmuxSession {
        let (project_name, config_path) = setup(contents);
        open_muxed(&project_name, config_path.parent().unwrap());
        let completed = PathBuf::from(format!("/tmp/{}.complete", project_name));
        let exec = format!("touch {}", completed.display());
        send_keys(&project_name, &exec);
        wait_on(&completed);
        let session = TmuxSession::from_string(&list_windows(&project_name.to_string()));
        cleanup(&project_name, &config_path);
        session
    }

    #[test]
    fn opens_3_windows_from_array() {
        let contents = b"---
windows: ['ls', 'vi', 'git']
";
        let session = test_with_contents(contents);
        assert_eq!(session.num_of_windows, 3)
    }

    #[test]
    fn opens_2_windows() {
        let contents = b"---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['ls', 'vi']
  - stuff: ''
";
        let session = test_with_contents(contents);
        assert_eq!(session.num_of_windows, 2)
    }

    #[test]
    fn opens_3_windows_with_integer_names() {
        let contents = b"---
windows: [1, 'ls', 3]
";
        let session = test_with_contents(contents);
        assert_eq!(session.num_of_windows, 3)
    }

    #[test]
    fn single_window_has_2_panes() {
        let contents = b"---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['ls', 'vi']
";
        let session = test_with_contents(contents);
        let num = session.windows.get("editor").unwrap().panes.as_usize().unwrap();
        assert_eq!(num, 2)
    }

    #[test]
    fn multiple_windows_with_panes() {
        let contents = b"---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['ls', 'vi']
  - tests:
      layout: 'main-vertical'
      panes: ['ls', 'vi', 'ls']
";
        let session = test_with_contents(contents);
        let num = session.windows.get("editor").unwrap().panes.as_usize().unwrap();
        let num1 = session.windows.get("tests").unwrap().panes.as_usize().unwrap();
        assert_eq!(num, 2);
        assert_eq!(num1, 3)
    }

    #[test]
    fn window_with_empty_command_is_valid() {
        let contents = b"---
windows:
  - editor:
";
        let session = test_with_contents(contents);
        assert_eq!(session.num_of_windows, 1)
    }

    #[test]
    fn panes_with_empty_commands_are_valid() {
        let contents = b"---
windows:
  - editor:
      layout: 'main-vertical'
      panes:
        -
        -
";
        let session = test_with_contents(contents);
        let num = session.windows.get("editor").unwrap().panes.as_usize().unwrap();
        assert_eq!(num, 2)
    }

    #[test]
    fn expect_to_open_in_directory_containing_spaces() {
        let dir = PathBuf::from("/tmp/Directory With Spaces/");
        if !dir.exists() { println!("{:?}", fs::create_dir(&dir)) };
        let contents = b"---
root: /tmp/Directory With Spaces/
windows:
  - editor: ''
";
        let session = test_with_contents(contents);
        let pane_current_path = session.windows.get("editor").unwrap().pane_current_path.as_str().unwrap();
        let _ = fs::remove_dir(dir);
        assert_eq!(pane_current_path, "/tmp/Directory With Spaces");
    }

    #[test]
    fn expect_focus_on_the_first_window() {
        let contents = b"---
windows: ['ssh', 'git']
";
        let session = test_with_contents(contents);
        let window_active = session.window_active.as_str().unwrap();
        assert_eq!(window_active, "ssh")
    }

// This test should exist but we currently don't do anything to list panes.
//    #[test]
//    fn expect_focus_on_the_top_pane() {
//        let contents = b"---
//windows:
//  - ssh:
//    layout: main-horizontal
//    panes:
//      - ''
//      - ''
//  - git: ''
//";
//        let session = test_with_contents(contents);
//        assert_eq!(session.pane_active, "ssh.0")
//    }
}
<commit_msg>test(tests/open.rs) OSX Travis compatible<commit_after>//! The integration suite for inspecting sessions.

extern crate libc;
extern crate rand;
extern crate regex;

mod helpers;

mod open {
    use rand::{random};
    use std::fs::File;
    use std::fs;
    use std::path::PathBuf;
    use std::io::prelude::*;
    use helpers::*;

    fn setup(contents: &'static [u8]) -> (String, PathBuf) {
        let project_name = format!("muxed_int_test_{}", random::<u16>());
        let project_file = format!("/tmp/muxed_{}/{}.yml", random::<u16>(), project_name);
        let project_path = PathBuf::from(&project_file);

        let muxed_path = project_path.parent().unwrap();
        if !muxed_path.exists() { println!("{:?}", fs::create_dir(muxed_path)) };

        let mut buffer = File::create(&project_path).unwrap();
        let _ = buffer.write(contents);

        (project_name, project_path.clone())
    }

    fn cleanup(project_name: &String, config_path: &PathBuf) -> () {
        let _ = fs::remove_file(config_path);
        let _ = fs::remove_dir(config_path.parent().unwrap());
        kill_session(&project_name);
    }

    fn test_with_contents(contents: &'static [u8]) -> TmuxSession {
        let (project_name, config_path) = setup(contents);
        open_muxed(&project_name, config_path.parent().unwrap());
        let completed = PathBuf::from(format!("/tmp/{}.complete", project_name));
        let exec = format!("touch {}", completed.display());
        send_keys(&project_name, &exec);
        wait_on(&completed);
        let session = TmuxSession::from_string(&list_windows(&project_name.to_string()));
        cleanup(&project_name, &config_path);
        session
    }

    #[test]
    fn opens_3_windows_from_array() {
        let contents = b"---
windows: ['ls', 'vi', 'git']
";
        let session = test_with_contents(contents);
        assert_eq!(session.num_of_windows, 3)
    }

    #[test]
    fn opens_2_windows() {
        let contents = b"---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['ls', 'vi']
  - stuff: ''
";
        let session = test_with_contents(contents);
        assert_eq!(session.num_of_windows, 2)
    }

    #[test]
    fn opens_3_windows_with_integer_names() {
        let contents = b"---
windows: [1, 'ls', 3]
";
        let session = test_with_contents(contents);
        assert_eq!(session.num_of_windows, 3)
    }

    #[test]
    fn single_window_has_2_panes() {
        let contents = b"---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['ls', 'vi']
";
        let session = test_with_contents(contents);
        let num = session.windows.get("editor").unwrap().panes.as_usize().unwrap();
        assert_eq!(num, 2)
    }

    #[test]
    fn multiple_windows_with_panes() {
        let contents = b"---
windows:
  - editor:
      layout: 'main-vertical'
      panes: ['ls', 'vi']
  - tests:
      layout: 'main-vertical'
      panes: ['ls', 'vi', 'ls']
";
        let session = test_with_contents(contents);
        let num = session.windows.get("editor").unwrap().panes.as_usize().unwrap();
        let num1 = session.windows.get("tests").unwrap().panes.as_usize().unwrap();
        assert_eq!(num, 2);
        assert_eq!(num1, 3)
    }

    #[test]
    fn window_with_empty_command_is_valid() {
        let contents = b"---
windows:
  - editor:
";
        let session = test_with_contents(contents);
        assert_eq!(session.num_of_windows, 1)
    }

    #[test]
    fn panes_with_empty_commands_are_valid() {
        let contents = b"---
windows:
  - editor:
      layout: 'main-vertical'
      panes:
        -
        -
";
        let session = test_with_contents(contents);
        let num = session.windows.get("editor").unwrap().panes.as_usize().unwrap();
        assert_eq!(num, 2)
    }

    #[test]
    fn expect_to_open_in_directory_containing_spaces() {
        let dir = PathBuf::from("/tmp/Directory With Spaces/");
        if !dir.exists() { println!("{:?}", fs::create_dir(&dir)) };
        let contents = b"---
root: /tmp/Directory With Spaces/
windows:
  - editor: ''
";
        let session = test_with_contents(contents);
        let pane_current_path = session.windows.get("editor").unwrap().pane_current_path.as_str().unwrap();
        let _ = fs::remove_dir(dir);
        // Use contains because OSX on travis ci symlinks /tmp/ to /private/tmp/
        // resulting in `pane_current_path` being `/private/tmp/Direct…`
        assert!(pane_current_path.contains("/tmp/Directory With Spaces"));
    }

    #[test]
    fn expect_focus_on_the_first_window() {
        let contents = b"---
windows: ['ssh', 'git']
";
        let session = test_with_contents(contents);
        let window_active = session.window_active.as_str().unwrap();
        assert_eq!(window_active, "ssh")
    }

// This test should exist but we currently don't do anything to list panes.
//    #[test]
//    fn expect_focus_on_the_top_pane() {
//        let contents = b"---
//windows:
//  - ssh:
//    layout: main-horizontal
//    panes:
//      - ''
//      - ''
//  - git: ''
//";
//        let session = test_with_contents(contents);
//        assert_eq!(session.pane_active, "ssh.0")
//    }
}
<|endoftext|>


<commit_before>use js::exec::{Executor, Interpreter};
use syntax::Lexer;
use syntax::Parser;
use getopts::Matches;
use std::io::stdio::stdin;
use std::io::{BufReader, BufferedReader};
/// An interactive command-line mode
pub struct Interactive {
	m: Matches
}
impl Interactive {
	/// Create a new interactive mode info
	pub fn new(m: Matches) -> Interactive {
		Interactive {
			m: m
		}
	}
	/// Run the interactive mode
	pub fn run(&self) {
		print!("> ");
		let mut engine : Interpreter = Executor::new();
		let verbose = self.m.opt_present("v");
		let mut input = stdin();
		loop {
			let line = input.read_line().unwrap();
			let line_bytes = line.as_bytes();
			if verbose {
				println!("Lexing");
			}
			let mut lexer = Lexer::new(BufferedReader::new(BufReader::new(line_bytes)));
			lexer.lex().unwrap();
			let tokens = lexer.tokens;
			if verbose {
				println!("Tokens: {}", tokens);
				println!("Parsing");
			}
			let expr = Parser::new(tokens).parse_all().unwrap();
			println!("Expression: {}", expr);
			let result = engine.run(&expr);
			match result {
				Ok(v) =>
					println!("{}", v.borrow()),
				Err(v) =>
					println!("Failed with {}", v.borrow())
			}
			print!("> ");
		}
	}
}<commit_msg>Move verbose output into condition<commit_after>use js::exec::{Executor, Interpreter};
use syntax::Lexer;
use syntax::Parser;
use getopts::Matches;
use std::io::stdio::stdin;
use std::io::{BufReader, BufferedReader};
/// An interactive command-line mode
pub struct Interactive {
	m: Matches
}
impl Interactive {
	/// Create a new interactive mode info
	pub fn new(m: Matches) -> Interactive {
		Interactive {
			m: m
		}
	}
	/// Run the interactive mode
	pub fn run(&self) {
		print!("> ");
		let mut engine : Interpreter = Executor::new();
		let verbose = self.m.opt_present("v");
		let mut input = stdin();
		loop {
			let line = input.read_line().unwrap();
			let line_bytes = line.as_bytes();
			if verbose {
				println!("Lexing");
			}
			let mut lexer = Lexer::new(BufferedReader::new(BufReader::new(line_bytes)));
			lexer.lex().unwrap();
			let tokens = lexer.tokens;
			if verbose {
				println!("Tokens: {}", tokens);
				println!("Parsing");
			}
			let expr = Parser::new(tokens).parse_all().unwrap();
			if verbose {
				println!("Expression: {}", expr);
			}
			let result = engine.run(&expr);
			match result {
				Ok(v) =>
					println!("{}", v.borrow()),
				Err(v) =>
					println!("Failed with {}", v.borrow())
			}
			print!("> ");
		}
	}
}<|endoftext|>


<commit_before>use rand::os::OsRng;
use rand::XorShiftRng;
use rand::Rand;
use rand::Rng;

use tile::Faction;

use util::{Error, Direction};

use level::{Level, add_isize_to_usize};

pub struct FactionGen {
    rand: XorShiftRng,
}

impl FactionGen {
    pub fn new() -> FactionGen {
        FactionGen {
            rand: XorShiftRng::rand(&mut OsRng::new().unwrap()),
        }
    }

    pub fn generate(&mut self, level: &mut Level<Faction>) {
        let mut delta = Vec::new();
        for x in 0..level.get_width() {
            for y in 0..level.get_height() {
                let mut deck = Vec::new();
                match level.get_mut_tile(x, y) {
                    Ok(tile) => {
                        match *tile {
                            Faction::Faction(_) => {
                                deck.push(tile.clone());
                            },
                            Faction::Void => continue,
                            _ => {},
                        }

                    },
                    Err(Error::IndexOutOfBounds) => {
                        panic!("Generate method indexed out of bounds while simulating a step. This should never happen unless the programmer is not very bright.");
                    }
                }
                Self::get_faction_neighbours(x, y, &mut deck, level);
                match self.rand.choose(&deck) {
                    Some(f) => {
                        delta.push(((x,y), f.clone()));
                    },
                    None => continue,
                }
            }
        }
        Self::apply_changes(level, delta);
    }

    fn get_faction_neighbours(x: usize, y: usize, deck: &mut Vec<Faction>, level: &mut Level<Faction>) {
        for d in Direction::get_dirs() {
            let (ix, iy) = d.get_tuple();
            let coord = match (add_isize_to_usize(ix, x), add_isize_to_usize(iy, y)) {
                (Some(x), Some(y)) => (x,y),
                _ => continue,
            };
            match level.get_tile_with_tuple(coord) {
                Ok(f @ &Faction::Faction(_)) => deck.push(f.clone()),
                _ => {},
            }
        }
    }

    fn apply_changes(level: &mut Level<Faction>, delta: Vec<((usize, usize), Faction)>) {
        for ((x, y), f) in delta {
            if let Ok(tile) = level.get_mut_tile(x, y) {
                *tile = f;
            }
        }
    }
}
<commit_msg>refactored some things mentioned in delmas review<commit_after>use rand::os::OsRng;
use rand::XorShiftRng;
use rand::Rand;
use rand::Rng;

use tile::Faction;

use util::{Error, Direction};

use level::{Level, add_isize_to_usize};

pub struct FactionGen {
    rand: XorShiftRng,
}

impl FactionGen {
    pub fn new() -> FactionGen {
        FactionGen {
            rand: XorShiftRng::rand(&mut OsRng::new().unwrap()),
        }
    }

    pub fn generate(&mut self, level: &mut Level<Faction>) {
        let mut delta = Vec::with_capacity(level.get_width() * level.get_height());
        for x in 0..level.get_width() {
            for y in 0..level.get_height() {
                let mut deck = Vec::with_capacity(9);
                match level.get_mut_tile(x, y) {
                    Ok(tile) => {
                        match *tile {
                            Faction::Faction(_) => {
                                deck.push(tile.clone());
                            },
                            Faction::Void => continue,
                            _ => {},
                        }

                    },
                    Err(Error::IndexOutOfBounds) => {
                        unreachable!("Generate method indexed out of bounds while simulating a step. This should never happen unless the programmer is not very bright.");
                    }
                }
                Self::get_faction_neighbours(x, y, &mut deck, level);
                match self.rand.choose(&deck) {
                    Some(f) => {
                        delta.push(((x,y), f.clone()));
                    },
                    None => continue,
                }
            }
        }
        Self::apply_changes(level, delta);
    }

    fn get_faction_neighbours(x: usize, y: usize, deck: &mut Vec<Faction>, level: &mut Level<Faction>) {
        for d in Direction::get_dirs() {
            let (ix, iy) = d.get_tuple();
            let coord = match (add_isize_to_usize(ix, x), add_isize_to_usize(iy, y)) {
                (Some(x), Some(y)) => (x,y),
                _ => continue,
            };
            match level.get_tile_with_tuple(coord) {
                Ok(f @ &Faction::Faction(_)) => deck.push(f.clone()),
                _ => {},
            }
        }
    }

    fn apply_changes(level: &mut Level<Faction>, delta: Vec<((usize, usize), Faction)>) {
        for ((x, y), f) in delta {
            if let Ok(tile) = level.get_mut_tile(x, y) {
                *tile = f;
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 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.

extern crate rustfmt;

use std::collections::HashMap;
use std::fs;
use std::io::Read;
use std::sync::atomic;
use rustfmt::*;

// For now, the only supported regression tests are idempotent tests - the input and
// output must match exactly.
// FIXME(#28) would be good to check for error messages and fail on them, or at least report.
#[test]
fn idempotent_tests() {
    println!("Idempotent tests:");
    FAILURES.store(0, atomic::Ordering::Relaxed);

    // Get all files in the tests/idem directory
    let files = fs::read_dir("tests/idem").unwrap();
    // For each file, run rustfmt and collect the output
    let mut count = 0;
    for entry in files {
        let path = entry.unwrap().path();
        let file_name = path.to_str().unwrap();
        println!("Testing '{}'...", file_name);
        run(vec!["rustfmt".to_owned(), file_name.to_owned()], WriteMode::Return(HANDLE_RESULT));
        count += 1;
    }
    // And also dogfood ourselves!
    println!("Testing 'src/lib.rs'...");
    run(vec!["rustfmt".to_string(), "src/lib.rs".to_string()],
        WriteMode::Return(HANDLE_RESULT));
    count += 1;

    // Display results
    let fails = FAILURES.load(atomic::Ordering::Relaxed);
    println!("Ran {} idempotent tests; {} failures.", count, fails);
    assert!(fails == 0, "{} idempotent tests failed", fails);
}

// 'global' used by sys_tests and handle_result.
static FAILURES: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
// Ick, just needed to get a &'static to handle_result.
static HANDLE_RESULT: &'static Fn(HashMap<String, String>) = &handle_result;

// Compare output to input.
fn handle_result(result: HashMap<String, String>) {
    let mut fails = 0;

    for file_name in result.keys() {
        let mut f = fs::File::open(file_name).unwrap();
        let mut text = String::new();
        f.read_to_string(&mut text).unwrap();
        if result[file_name] != text {
            fails += 1;
            println!("Mismatch in {}.", file_name);
            println!("{}", result[file_name]);
        }
    }

    if fails > 0 {
        FAILURES.fetch_add(1, atomic::Ordering::Relaxed);
    }
}<commit_msg>first step to a non-panicking idem_check function<commit_after>// Copyright 2015 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.

#![feature(std_misc)]

extern crate rustfmt;

use std::collections::HashMap;
use std::fs;
use std::io::Read;
use rustfmt::*;

// For now, the only supported regression tests are idempotent tests - the input and
// output must match exactly.
// FIXME(#28) would be good to check for error messages and fail on them, or at least report.
#[test]
fn idempotent_tests() {
    println!("Idempotent tests:");

    // Get all files in the tests/idem directory
    let files = fs::read_dir("tests/idem").unwrap();
    let files2 = fs::read_dir("tests").unwrap();
    let files3 = fs::read_dir("src/bin").unwrap();
    // For each file, run rustfmt and collect the output

    let mut count = 0;
    let mut fails = 0;
    for entry in files.chain(files2).chain(files3) {
        let path = entry.unwrap().path();
        let file_name = path.to_str().unwrap();
        if !file_name.ends_with(".rs") {
            continue;
        }
        println!("Testing '{}'...", file_name);
        match idempotent_check(vec!["rustfmt".to_owned(), file_name.to_owned()]) {
            Ok(()) => {},
            Err(m) => {
                print_mismatches(m);
                fails += 1;
            },
        }
        count += 1;
    }
    // And also dogfood rustfmt!
    println!("Testing 'src/lib.rs'...");
    match idempotent_check(vec!["rustfmt".to_owned(), "src/lib.rs".to_owned()]) {
        Ok(()) => {},
        Err(m) => {
            print_mismatches(m);
            fails += 1;
        },
    }
    count += 1;

    // Display results
    println!("Ran {} idempotent tests; {} failures.", count, fails);
    assert!(fails == 0, "{} idempotent tests failed", fails);
}

// Compare output to input.
fn print_mismatches(result: HashMap<String, String>) {
    for (file_name, fmt_text) in result {
        println!("Mismatch in {}.", file_name);
        println!("{}", fmt_text);
    }
}

// Ick, just needed to get a &'static to handle_result.
static HANDLE_RESULT: &'static Fn(HashMap<String, String>) = &handle_result;

pub fn idempotent_check(args: Vec<String>) -> Result<(), HashMap<String, String>> {
    use std::thread;
    use std::fs;
    use std::io::Read;
    thread::spawn(move || {
        run(args, WriteMode::Return(HANDLE_RESULT));
    }).join().map_err(|mut any|
        any.downcast_mut::<HashMap<String, String>>()
           .unwrap() // i know it is a hashmap
           .drain() // i only get a reference :(
           .collect() // so i need to turn it into an iter and then back
    )
}

// Compare output to input.
fn handle_result(result: HashMap<String, String>) {
    let mut failures = HashMap::new();

    for (file_name, fmt_text) in result {
        let mut f = fs::File::open(&file_name).unwrap();
        let mut text = String::new();
        // TODO: speedup by running through bytes iterator
        f.read_to_string(&mut text).unwrap();
        if fmt_text != text {
            failures.insert(file_name, fmt_text);
        }
    }
    if !failures.is_empty() {
        panic!(failures);
    }
}<|endoftext|>


<commit_before>use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, quote_spanned};
use std::fmt;
use syn::spanned::Spanned;

#[cfg(any(feature = "std", test))]
#[macro_use]
extern crate std;

#[cfg(all(not(feature = "std"), not(test)))]
#[macro_use]
extern crate core as std;

#[path = "../../shared/error.rs"]
mod error;

#[path = "../../shared/parser.rs"]
mod parser;

#[proc_macro]
pub fn parse_lit(input: TokenStream) -> TokenStream {
    build_uuid(input.clone()).unwrap_or_else(|e| {
        let msg = e.to_string();
        let ts = TokenStream2::from(input);
        let span = match e {
            Error::UuidParse(error::Error(
                error::ErrorKind::InvalidCharacter { index, .. },
            )) => {
                let mut s = proc_macro2::Literal::string("");
                s.set_span(ts.span());
                s.subspan(index + 1..=index + 1).unwrap()
            }
            Error::UuidParse(error::Error(
                error::ErrorKind::InvalidGroupLength { found, group, .. },
            )) => {
                let start =
                    parser::GROUP_LENS.iter().take(group).sum::<usize>()
                        + group
                        + 1;
                let mut s = proc_macro2::Literal::string("");
                s.set_span(ts.span());
                s.subspan(start..start + found).unwrap()
            }
            _ => ts.span(),
        };
        TokenStream::from(quote_spanned! {span=>
            compile_error!(#msg)
        })
    })
}

enum Error {
    NonStringLiteral,
    UuidParse(error::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::NonStringLiteral => f.write_str("expected string literal"),
            Error::UuidParse(ref e) => write!(f, "{}", e),
        }
    }
}

fn build_uuid(input: TokenStream) -> Result<TokenStream, Error> {
    let literal = match syn::parse::<syn::Lit>(input) {
        Ok(syn::Lit::Str(literal)) => literal,
        _ => return Err(Error::NonStringLiteral),
    };

    // steps:
    // get Literal
    // do Literal::subspan
    // pass that into quote_spanned

    let literal = literal.value();

    let bytes = parser::parse_str(&literal).map_err(Error::UuidParse)?;

    let tokens = bytes
        .iter()
        .map(|byte| quote! { #byte, })
        .collect::<TokenStream2>();

    Ok(quote! {[#tokens]}.into())
}
<commit_msg>Micro refactor<commit_after>use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, quote_spanned};
use std::fmt;
use syn::spanned::Spanned;

#[cfg(any(feature = "std", test))]
#[macro_use]
extern crate std;

#[cfg(all(not(feature = "std"), not(test)))]
#[macro_use]
extern crate core as std;

#[path = "../../shared/error.rs"]
mod error;

#[path = "../../shared/parser.rs"]
mod parser;

#[proc_macro]
pub fn parse_lit(input: TokenStream) -> TokenStream {
    build_uuid(input.clone()).unwrap_or_else(|e| {
        let msg = e.to_string();
        let ts = TokenStream2::from(input);
        let span = match e {
            Error::UuidParse(error::Error(
                error::ErrorKind::InvalidCharacter { index, .. },
            )) => {
                let mut s = proc_macro2::Literal::string("");
                s.set_span(ts.span());
                s.subspan(index + 1..=index + 1).unwrap()
            }
            Error::UuidParse(error::Error(
                error::ErrorKind::InvalidGroupLength { found, group, .. },
            )) => {
                let start =
                    parser::GROUP_LENS.iter().take(group).sum::<usize>()
                        + group
                        + 1;
                let mut s = proc_macro2::Literal::string("");
                s.set_span(ts.span());
                s.subspan(start..start + found).unwrap()
            }
            _ => ts.span(),
        };
        TokenStream::from(quote_spanned! {span=>
            compile_error!(#msg)
        })
    })
}

enum Error {
    NonStringLiteral,
    UuidParse(error::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::NonStringLiteral => f.write_str("expected string literal"),
            Error::UuidParse(ref e) => write!(f, "{}", e),
        }
    }
}

fn build_uuid(input: TokenStream) -> Result<TokenStream, Error> {
    let string = match syn::parse::<syn::Lit>(input) {
        Ok(syn::Lit::Str(literal)) => literal.value(),
        _ => return Err(Error::NonStringLiteral),
    };

    let bytes = parser::parse_str(&string).map_err(Error::UuidParse)?;

    let tokens = bytes
        .iter()
        .map(|byte| quote! { #byte, })
        .collect::<TokenStream2>();

    Ok(quote! {[#tokens]}.into())
}
<|endoftext|>


<commit_before>#![crate_type="dylib"]
#![feature(plugin_registrar, slice_patterns)]
#![feature(rustc_private, core)]
#![deny(warnings)]
#![allow(unused_features)]

extern crate syntax;
extern crate rustc;
extern crate glassful;

use syntax::ast;
use syntax::parse::token;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacEager, MacResult, DummyResult};
use syntax::ext::build::AstBuilder;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("glassful", expand);
}

fn expand(cx: &mut ExtCtxt, outer_span: Span, toks: &[ast::TokenTree])
    -> Box<MacResult + 'static>
{
    let inner_span = match toks {
        [] => {
            cx.span_err(outer_span, "empty invocation");
            return DummyResult::expr(outer_span);
        }
        [ref first, ..] => {
            let first = first.get_span();
            let last = toks.iter().rev().next().unwrap().get_span();
            if first.expn_id != last.expn_id {
                cx.span_err(first, "invocation is split between expansion contexts??");
                cx.span_note(last, "last token is here");
                return DummyResult::expr(outer_span);
            }

            Span {
                lo: first.lo,
                hi: last.hi,
                expn_id: first.expn_id,
            }
        }
    };

    let src = match cx.codemap().span_to_snippet(inner_span) {
        Err(e) => {
            cx.span_err(inner_span, &format!("can't extract source snippet: {:?}", e)[..]);
            return DummyResult::expr(inner_span);
        }
        Ok(src) => src,
    };

    match glassful::try_translate(src) {
        None => {
            cx.span_err(outer_span, "translation failed");
            DummyResult::expr(outer_span)
        }
        Some(res) => {
            let interned = token::intern_and_get_ident(&res[..]);
            MacEager::expr(cx.expr_str(inner_span, interned))
        }
    }
}
<commit_msg>Fix the macros crate<commit_after>#![crate_type="dylib"]
#![feature(plugin_registrar, slice_patterns)]
#![feature(rustc_private, core)]
#![deny(warnings)]
#![allow(unused_features)]

extern crate syntax;
extern crate glassful;
extern crate rustc_plugin;

use syntax::ast;
use syntax::parse::token;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacEager, MacResult, DummyResult};
use syntax::ext::build::AstBuilder;
use rustc_plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("glassful", expand);
}

fn expand(cx: &mut ExtCtxt, outer_span: Span, toks: &[ast::TokenTree])
    -> Box<MacResult + 'static>
{
    let inner_span = match toks {
        [] => {
            cx.span_err(outer_span, "empty invocation");
            return DummyResult::expr(outer_span);
        }
        [ref first, ..] => {
            let first = first.get_span();
            let last = toks.iter().rev().next().unwrap().get_span();
            if first.expn_id != last.expn_id {
                cx.struct_span_err(first, "invocation is split between expansion contexts?").span_note(last, "last token is here");
                return DummyResult::expr(outer_span);
            }

            Span {
                lo: first.lo,
                hi: last.hi,
                expn_id: first.expn_id,
            }
        }
    };

    let src = match cx.codemap().span_to_snippet(inner_span) {
        Err(e) => {
            cx.span_err(inner_span, &format!("can't extract source snippet: {:?}", e)[..]);
            return DummyResult::expr(inner_span);
        }
        Ok(src) => src,
    };

    match glassful::try_translate(src) {
        None => {
            cx.span_err(outer_span, "translation failed");
            DummyResult::expr(outer_span)
        }
        Some(res) => {
            let interned = token::intern_and_get_ident(&res[..]);
            MacEager::expr(cx.expr_str(inner_span, interned))
        }
    }
}
<|endoftext|>


<commit_before>use codespan::Files;
use std::io;
use std::str::FromStr;
use termcolor::{Color, ColorSpec, ColorChoice, WriteColor};

use crate::diagnostic::{Diagnostic, Severity};

pub use termcolor;

mod views;

/// The display style to use when rendering diagnostics.
#[derive(Clone, Debug)]
pub enum DisplayStyle {
    /// Output a richly formatted diagnostic, with source code previews.
    ///
    /// ```text
    /// error[E0001]: unexpected type in `+` application
    ///
    ///    ┌── test:2:9 ───
    ///    │
    ///  2 │ (+ test "")
    ///    │         ^^ expected `Int` but found `String`
    ///    │
    ///    = expected type `Int`
    ///         found type `String`
    /// ```
    Rich,
    /// Output a short diagnostic, with a line number, severity, and message.
    ///
    /// ```text
    /// test:2:9: error[E0001]: unexpected type in `+` application
    /// ```
    Short,
}

/// Configures how a diagnostic is rendered.
#[derive(Clone, Debug)]
pub struct Config {
    /// The display style to use when rendering diagnostics.
    /// Defaults to: `DisplayStyle::Rich`.
    pub display_style: DisplayStyle,
    /// Column width of tabs.
    /// Defaults to: `4`.
    pub tab_width: usize,
    /// Styles to use when rendering the diagnostic.
    pub styles: Styles,
    /// The character to use when marking the top-left corner of the source.
    /// Defaults to: `'┌'`.
    pub border_top_left_char: char,
    /// The character to use when marking the top border of the source.
    /// Defaults to: `'─'`.
    pub border_top_char: char,
    /// The character to use when marking the left border of the source.
    /// Defaults to: `'│'`.
    pub border_left_char: char,
    /// The character to use when underlining a primary label.
    /// Defaults to: `'^'`.
    pub primary_underline_char: char,
    /// The character to use when underlining a secondary label.
    /// Defaults to: `'-'`.
    pub secondary_underline_char: char,
    /// The character to use for the note bullet.
    /// Defaults to: `'='`.
    pub note_bullet_char: char,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            display_style: DisplayStyle::Rich,
            tab_width: 4,
            styles: Styles::default(),
            border_top_left_char: '┌',
            border_top_char: '─',
            border_left_char: '│',
            primary_underline_char: '^',
            secondary_underline_char: '-',
            note_bullet_char: '=',
        }
    }
}

impl Config {
    /// Measure the width of a string, taking into account the tab width.
    pub fn width(&self, s: &str) -> usize {
        use unicode_width::UnicodeWidthChar;

        s.chars()
            .map(|ch| match ch {
                '\t' => self.tab_width,
                _ => ch.width().unwrap_or(0),
            })
            .sum()
    }

    /// Get the amount of spaces we should use for printing tabs.
    pub fn tab_padding(&self) -> String {
        (0..self.tab_width).map(|_| ' ').collect()
    }
}

/// Styles to use when rendering the diagnostic.
#[derive(Clone, Debug)]
pub struct Styles {
    /// The style to use when rendering bug headers.
    /// Defaults to `fg:red bold intense`.
    pub header_bug: ColorSpec,
    /// The style to use when rendering error headers.
    /// Defaults to `fg:red bold intense`.
    pub header_error: ColorSpec,
    /// The style to use when rendering warning headers.
    /// Defaults to `fg:yellow bold intense`.
    pub header_warning: ColorSpec,
    /// The style to use when rendering note headers.
    /// Defaults to `fg:green bold intense`.
    pub header_note: ColorSpec,
    /// The style to use when rendering help headers.
    /// Defaults to `fg:cyan bold intense`.
    pub header_help: ColorSpec,
    /// The style to use when the main diagnostic message.
    /// Defaults to `bold intense`.
    pub header_message: ColorSpec,

    /// The style to use when rendering bug labels.
    /// Defaults to `fg:red`.
    pub primary_label_bug: ColorSpec,
    /// The style to use when rendering error labels.
    /// Defaults to `fg:red`.
    pub primary_label_error: ColorSpec,
    /// The style to use when rendering warning labels.
    /// Defaults to `fg:yellow`.
    pub primary_label_warning: ColorSpec,
    /// The style to use when rendering note labels.
    /// Defaults to `fg:green`.
    pub primary_label_note: ColorSpec,
    /// The style to use when rendering help labels.
    /// Defaults to `fg:cyan`.
    pub primary_label_help: ColorSpec,
    /// The style to use when rendering secondary labels.
    /// Defaults `fg:blue` (or `fg:cyan` on windows).
    pub secondary_label: ColorSpec,

    /// The style to use when rendering the line numbers.
    /// Defaults `fg:blue` (or `fg:cyan` on windows).
    pub line_number: ColorSpec,
    /// The style to use when rendering the source code borders.
    /// Defaults `fg:blue` (or `fg:cyan` on windows).
    pub border: ColorSpec,
    /// The style to use when rendering the note bullets.
    /// Defaults `fg:blue` (or `fg:cyan` on windows).
    pub note_bullet: ColorSpec,
}

impl Styles {
    /// The style used to mark a header at a given severity.
    pub fn header(&self, severity: Severity) -> &ColorSpec {
        match severity {
            Severity::Bug => &self.header_bug,
            Severity::Error => &self.header_error,
            Severity::Warning => &self.header_warning,
            Severity::Note => &self.header_note,
            Severity::Help => &self.header_help,
        }
    }

    /// The style used to mark a primary label at a given severity.
    pub fn primary_label(&self, severity: Severity) -> &ColorSpec {
        match severity {
            Severity::Bug => &self.primary_label_bug,
            Severity::Error => &self.primary_label_error,
            Severity::Warning => &self.primary_label_warning,
            Severity::Note => &self.primary_label_note,
            Severity::Help => &self.primary_label_help,
        }
    }
}

impl Default for Styles {
    fn default() -> Styles {
        // Blue is really difficult to see on the standard windows command line
        #[cfg(windows)]
        const BLUE: Color = Color::Cyan;
        #[cfg(not(windows))]
        const BLUE: Color = Color::Blue;

        let header = ColorSpec::new().set_bold(true).set_intense(true).clone();

        Styles {
            header_bug: header.clone().set_fg(Some(Color::Red)).clone(),
            header_error: header.clone().set_fg(Some(Color::Red)).clone(),
            header_warning: header.clone().set_fg(Some(Color::Yellow)).clone(),
            header_note: header.clone().set_fg(Some(Color::Green)).clone(),
            header_help: header.clone().set_fg(Some(Color::Cyan)).clone(),
            header_message: header.clone(),

            primary_label_bug: ColorSpec::new().set_fg(Some(Color::Red)).clone(),
            primary_label_error: ColorSpec::new().set_fg(Some(Color::Red)).clone(),
            primary_label_warning: ColorSpec::new().set_fg(Some(Color::Yellow)).clone(),
            primary_label_note: ColorSpec::new().set_fg(Some(Color::Green)).clone(),
            primary_label_help: ColorSpec::new().set_fg(Some(Color::Cyan)).clone(),
            secondary_label: ColorSpec::new().set_fg(Some(BLUE)).clone(),

            line_number: ColorSpec::new().set_fg(Some(BLUE)).clone(),
            border: ColorSpec::new().set_fg(Some(BLUE)).clone(),
            note_bullet: ColorSpec::new().set_fg(Some(BLUE)).clone(),
        }
    }
}

pub fn emit(
    writer: &mut impl WriteColor,
    config: &Config,
    files: &Files,
    diagnostic: &Diagnostic,
) -> io::Result<()> {
    use self::views::{RichDiagnostic, ShortDiagnostic};

    match config.display_style {
        DisplayStyle::Rich => RichDiagnostic::new(files, diagnostic).emit(writer, config),
        DisplayStyle::Short => ShortDiagnostic::new(files, diagnostic).emit(writer, config),
    }
}

/// A command line argument that configures the coloring of the output.
///
/// This can be used with command line argument parsers like `clap` or `structopt`.
///
/// # Example
///
/// ```rust
/// use structopt::StructOpt;
/// use codespan_reporting::emitter::termcolor::StandardStream;
/// use codespan_reporting::emitter::ColorArg;
///
/// #[derive(Debug, StructOpt)]
/// #[structopt(name = "groovey-app")]
/// pub struct Opts {
///     /// Configure coloring of output
///     #[structopt(
///         long = "color",
///         parse(try_from_str),
///         default_value = "auto",
///         raw(possible_values = "ColorArg::VARIANTS", case_insensitive = "true")
///     )]
///     pub color: ColorArg,
/// }
///
/// fn main() {
///     let opts = Opts::from_args();
///     let writer = StandardStream::stderr(opts.color.into());
/// }
/// ```
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ColorArg(pub ColorChoice);

impl ColorArg {
    /// Allowed values the argument.
    ///
    /// This is useful for generating documentation via `clap` or `structopt`'s
    /// `possible_values` configuration.
    pub const VARIANTS: &'static [&'static str] = &["auto", "always", "ansi", "never"];
}

impl FromStr for ColorArg {
    type Err = &'static str;

    fn from_str(src: &str) -> Result<ColorArg, &'static str> {
        match src {
            _ if src.eq_ignore_ascii_case("auto") => Ok(ColorArg(ColorChoice::Auto)),
            _ if src.eq_ignore_ascii_case("always") => Ok(ColorArg(ColorChoice::Always)),
            _ if src.eq_ignore_ascii_case("ansi") => Ok(ColorArg(ColorChoice::AlwaysAnsi)),
            _ if src.eq_ignore_ascii_case("never") => Ok(ColorArg(ColorChoice::Never)),
            _ => Err("valid values: auto, always, ansi, never"),
        }
    }
}

impl Into<ColorChoice> for ColorArg {
    fn into(self) -> ColorChoice {
        self.0
    }
}
<commit_msg>Topologically sort emitter module<commit_after>use codespan::Files;
use std::io;
use std::str::FromStr;
use termcolor::{Color, ColorChoice, ColorSpec, WriteColor};

use crate::diagnostic::{Diagnostic, Severity};

pub use termcolor;

mod views;

/// Emit a diagnostic using the given writer, context, config, and files.
pub fn emit(
    writer: &mut impl WriteColor,
    config: &Config,
    files: &Files,
    diagnostic: &Diagnostic,
) -> io::Result<()> {
    use self::views::{RichDiagnostic, ShortDiagnostic};

    match config.display_style {
        DisplayStyle::Rich => RichDiagnostic::new(files, diagnostic).emit(writer, config),
        DisplayStyle::Short => ShortDiagnostic::new(files, diagnostic).emit(writer, config),
    }
}

/// Configures how a diagnostic is rendered.
#[derive(Clone, Debug)]
pub struct Config {
    /// The display style to use when rendering diagnostics.
    /// Defaults to: `DisplayStyle::Rich`.
    pub display_style: DisplayStyle,
    /// Column width of tabs.
    /// Defaults to: `4`.
    pub tab_width: usize,
    /// Styles to use when rendering the diagnostic.
    pub styles: Styles,
    /// The character to use when marking the top-left corner of the source.
    /// Defaults to: `'┌'`.
    pub border_top_left_char: char,
    /// The character to use when marking the top border of the source.
    /// Defaults to: `'─'`.
    pub border_top_char: char,
    /// The character to use when marking the left border of the source.
    /// Defaults to: `'│'`.
    pub border_left_char: char,
    /// The character to use when underlining a primary label.
    /// Defaults to: `'^'`.
    pub primary_underline_char: char,
    /// The character to use when underlining a secondary label.
    /// Defaults to: `'-'`.
    pub secondary_underline_char: char,
    /// The character to use for the note bullet.
    /// Defaults to: `'='`.
    pub note_bullet_char: char,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            display_style: DisplayStyle::Rich,
            tab_width: 4,
            styles: Styles::default(),
            border_top_left_char: '┌',
            border_top_char: '─',
            border_left_char: '│',
            primary_underline_char: '^',
            secondary_underline_char: '-',
            note_bullet_char: '=',
        }
    }
}

impl Config {
    /// Measure the width of a string, taking into account the tab width.
    pub fn width(&self, s: &str) -> usize {
        use unicode_width::UnicodeWidthChar;

        s.chars()
            .map(|ch| match ch {
                '\t' => self.tab_width,
                _ => ch.width().unwrap_or(0),
            })
            .sum()
    }

    /// Get the amount of spaces we should use for printing tabs.
    pub fn tab_padding(&self) -> String {
        (0..self.tab_width).map(|_| ' ').collect()
    }
}

/// The display style to use when rendering diagnostics.
#[derive(Clone, Debug)]
pub enum DisplayStyle {
    /// Output a richly formatted diagnostic, with source code previews.
    ///
    /// ```text
    /// error[E0001]: unexpected type in `+` application
    ///
    ///    ┌── test:2:9 ───
    ///    │
    ///  2 │ (+ test "")
    ///    │         ^^ expected `Int` but found `String`
    ///    │
    ///    = expected type `Int`
    ///         found type `String`
    /// ```
    Rich,
    /// Output a short diagnostic, with a line number, severity, and message.
    ///
    /// ```text
    /// test:2:9: error[E0001]: unexpected type in `+` application
    /// ```
    Short,
}

/// Styles to use when rendering the diagnostic.
#[derive(Clone, Debug)]
pub struct Styles {
    /// The style to use when rendering bug headers.
    /// Defaults to `fg:red bold intense`.
    pub header_bug: ColorSpec,
    /// The style to use when rendering error headers.
    /// Defaults to `fg:red bold intense`.
    pub header_error: ColorSpec,
    /// The style to use when rendering warning headers.
    /// Defaults to `fg:yellow bold intense`.
    pub header_warning: ColorSpec,
    /// The style to use when rendering note headers.
    /// Defaults to `fg:green bold intense`.
    pub header_note: ColorSpec,
    /// The style to use when rendering help headers.
    /// Defaults to `fg:cyan bold intense`.
    pub header_help: ColorSpec,
    /// The style to use when the main diagnostic message.
    /// Defaults to `bold intense`.
    pub header_message: ColorSpec,

    /// The style to use when rendering bug labels.
    /// Defaults to `fg:red`.
    pub primary_label_bug: ColorSpec,
    /// The style to use when rendering error labels.
    /// Defaults to `fg:red`.
    pub primary_label_error: ColorSpec,
    /// The style to use when rendering warning labels.
    /// Defaults to `fg:yellow`.
    pub primary_label_warning: ColorSpec,
    /// The style to use when rendering note labels.
    /// Defaults to `fg:green`.
    pub primary_label_note: ColorSpec,
    /// The style to use when rendering help labels.
    /// Defaults to `fg:cyan`.
    pub primary_label_help: ColorSpec,
    /// The style to use when rendering secondary labels.
    /// Defaults `fg:blue` (or `fg:cyan` on windows).
    pub secondary_label: ColorSpec,

    /// The style to use when rendering the line numbers.
    /// Defaults `fg:blue` (or `fg:cyan` on windows).
    pub line_number: ColorSpec,
    /// The style to use when rendering the source code borders.
    /// Defaults `fg:blue` (or `fg:cyan` on windows).
    pub border: ColorSpec,
    /// The style to use when rendering the note bullets.
    /// Defaults `fg:blue` (or `fg:cyan` on windows).
    pub note_bullet: ColorSpec,
}

impl Styles {
    /// The style used to mark a header at a given severity.
    pub fn header(&self, severity: Severity) -> &ColorSpec {
        match severity {
            Severity::Bug => &self.header_bug,
            Severity::Error => &self.header_error,
            Severity::Warning => &self.header_warning,
            Severity::Note => &self.header_note,
            Severity::Help => &self.header_help,
        }
    }

    /// The style used to mark a primary label at a given severity.
    pub fn primary_label(&self, severity: Severity) -> &ColorSpec {
        match severity {
            Severity::Bug => &self.primary_label_bug,
            Severity::Error => &self.primary_label_error,
            Severity::Warning => &self.primary_label_warning,
            Severity::Note => &self.primary_label_note,
            Severity::Help => &self.primary_label_help,
        }
    }
}

impl Default for Styles {
    fn default() -> Styles {
        // Blue is really difficult to see on the standard windows command line
        #[cfg(windows)]
        const BLUE: Color = Color::Cyan;
        #[cfg(not(windows))]
        const BLUE: Color = Color::Blue;

        let header = ColorSpec::new().set_bold(true).set_intense(true).clone();

        Styles {
            header_bug: header.clone().set_fg(Some(Color::Red)).clone(),
            header_error: header.clone().set_fg(Some(Color::Red)).clone(),
            header_warning: header.clone().set_fg(Some(Color::Yellow)).clone(),
            header_note: header.clone().set_fg(Some(Color::Green)).clone(),
            header_help: header.clone().set_fg(Some(Color::Cyan)).clone(),
            header_message: header.clone(),

            primary_label_bug: ColorSpec::new().set_fg(Some(Color::Red)).clone(),
            primary_label_error: ColorSpec::new().set_fg(Some(Color::Red)).clone(),
            primary_label_warning: ColorSpec::new().set_fg(Some(Color::Yellow)).clone(),
            primary_label_note: ColorSpec::new().set_fg(Some(Color::Green)).clone(),
            primary_label_help: ColorSpec::new().set_fg(Some(Color::Cyan)).clone(),
            secondary_label: ColorSpec::new().set_fg(Some(BLUE)).clone(),

            line_number: ColorSpec::new().set_fg(Some(BLUE)).clone(),
            border: ColorSpec::new().set_fg(Some(BLUE)).clone(),
            note_bullet: ColorSpec::new().set_fg(Some(BLUE)).clone(),
        }
    }
}

/// A command line argument that configures the coloring of the output.
///
/// This can be used with command line argument parsers like `clap` or `structopt`.
///
/// # Example
///
/// ```rust
/// use structopt::StructOpt;
/// use codespan_reporting::emitter::termcolor::StandardStream;
/// use codespan_reporting::emitter::ColorArg;
///
/// #[derive(Debug, StructOpt)]
/// #[structopt(name = "groovey-app")]
/// pub struct Opts {
///     /// Configure coloring of output
///     #[structopt(
///         long = "color",
///         parse(try_from_str),
///         default_value = "auto",
///         raw(possible_values = "ColorArg::VARIANTS", case_insensitive = "true")
///     )]
///     pub color: ColorArg,
/// }
///
/// fn main() {
///     let opts = Opts::from_args();
///     let writer = StandardStream::stderr(opts.color.into());
/// }
/// ```
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ColorArg(pub ColorChoice);

impl ColorArg {
    /// Allowed values the argument.
    ///
    /// This is useful for generating documentation via `clap` or `structopt`'s
    /// `possible_values` configuration.
    pub const VARIANTS: &'static [&'static str] = &["auto", "always", "ansi", "never"];
}

impl FromStr for ColorArg {
    type Err = &'static str;

    fn from_str(src: &str) -> Result<ColorArg, &'static str> {
        match src {
            _ if src.eq_ignore_ascii_case("auto") => Ok(ColorArg(ColorChoice::Auto)),
            _ if src.eq_ignore_ascii_case("always") => Ok(ColorArg(ColorChoice::Always)),
            _ if src.eq_ignore_ascii_case("ansi") => Ok(ColorArg(ColorChoice::AlwaysAnsi)),
            _ if src.eq_ignore_ascii_case("never") => Ok(ColorArg(ColorChoice::Never)),
            _ => Err("valid values: auto, always, ansi, never"),
        }
    }
}

impl Into<ColorChoice> for ColorArg {
    fn into(self) -> ColorChoice {
        self.0
    }
}
<|endoftext|>


<commit_before>extern crate zombie_shooter_lib;
extern crate cgmath;

#[test]
fn direction_test() {
  use cgmath::Point2;
  assert_eq!(0, zombie_shooter_lib::graphics::direction(Point2 {
    x: 1.0,
    y: 0.0,
  }, Point2 {
    x: 2.0,
    y: 0.0,
  }), "(1,0) to (2,0) should be 0deg");

  assert_eq!(90, zombie_shooter_lib::graphics::direction(Point2 {
    x: 0.0,
    y: 1.0,
  }, Point2 {
    x: 0.0,
    y: 2.0,
  }), "(0,1) to (0,2) should be 90deg");

  assert_eq!(26, zombie_shooter_lib::graphics::direction(Point2 {
    x: -2.0,
    y: 1.0,
  }, Point2 {
    x: 2.0,
    y: 3.0,
  }), "(-2,1) to (2,3) should be 26deg");

  assert_eq!(45, zombie_shooter_lib::graphics::direction(Point2 {
    x: -2.0,
    y: -2.0,
  }, Point2 {
    x: -1.0,
    y: -1.0,
  }), "(-2,-2) to (-1,-1) should be 45deg");

  assert_eq!(225, zombie_shooter_lib::graphics::direction(Point2 {
    x: -1.0,
    y: -2.0,
  }, Point2 {
    x: -3.0,
    y: -4.0,
  }), "(-1,-2) to (-3,-4) should be 225deg");

  assert_eq!(315, zombie_shooter_lib::graphics::direction(Point2 {
    x: -1.0,
    y: -2.0,
  }, Point2 {
    x: 1.0,
    y: -4.0,
  }), "(-1,-2) to (1,-4) should be 315deg");
}

#[test]
fn direction_movement_test() {
  use cgmath::Point2;

  assert_eq!(Point2 { x: 1.0, y: 0.0 },
             zombie_shooter_lib::graphics::direction_movement(
               zombie_shooter_lib::graphics::direction(Point2 {
                 x: 1.0,
                 y: 0.0,
               }, Point2 {
                 x: 2.0,
                 y: 0.0,
               })
             ), "(1,0) to (2,0) should be (1,0)");

  assert_eq!(Point2 { x: 0.0, y: 1.0 },
             zombie_shooter_lib::graphics::direction_movement(
               zombie_shooter_lib::graphics::direction(Point2 {
                 x: 0.0,
                 y: 1.0,
               }, Point2 {
                 x: 0.0,
                 y: 2.0,
               })
             ), "(0,1) to (0,2) should be (0,1)");

  assert_eq!(Point2 { x: 0.71, y: 0.71 }, // 0.71 = sqrt(2) / 2.0
             zombie_shooter_lib::graphics::direction_movement(
               zombie_shooter_lib::graphics::direction(Point2 {
                 x: -2.0,
                 y: -2.0,
               }, Point2 {
                 x: -1.0,
                 y: -1.0,
               })
             ), "(-2,-2) to (-1,-1) should be 45deg");
}
<commit_msg>Add new unit test case<commit_after>extern crate zombie_shooter_lib;
extern crate cgmath;

#[test]
fn direction_test() {
  use cgmath::Point2;
  assert_eq!(0, zombie_shooter_lib::graphics::direction(Point2 {
    x: 1.0,
    y: 0.0,
  }, Point2 {
    x: 2.0,
    y: 0.0,
  }), "(1,0) to (2,0) should be 0deg");

  assert_eq!(90, zombie_shooter_lib::graphics::direction(Point2 {
    x: 0.0,
    y: 1.0,
  }, Point2 {
    x: 0.0,
    y: 2.0,
  }), "(0,1) to (0,2) should be 90deg");

  assert_eq!(26, zombie_shooter_lib::graphics::direction(Point2 {
    x: -2.0,
    y: 1.0,
  }, Point2 {
    x: 2.0,
    y: 3.0,
  }), "(-2,1) to (2,3) should be 26deg");

  assert_eq!(45, zombie_shooter_lib::graphics::direction(Point2 {
    x: -2.0,
    y: -2.0,
  }, Point2 {
    x: -1.0,
    y: -1.0,
  }), "(-2,-2) to (-1,-1) should be 45deg");

  assert_eq!(225, zombie_shooter_lib::graphics::direction(Point2 {
    x: -1.0,
    y: -2.0,
  }, Point2 {
    x: -3.0,
    y: -4.0,
  }), "(-1,-2) to (-3,-4) should be 225deg");

  assert_eq!(315, zombie_shooter_lib::graphics::direction(Point2 {
    x: -1.0,
    y: -2.0,
  }, Point2 {
    x: 1.0,
    y: -4.0,
  }), "(-1,-2) to (1,-4) should be 315deg");
}

#[test]
fn direction_movement_test() {
  use cgmath::Point2;

  assert_eq!(Point2 { x: 1.0, y: 0.0 },
             zombie_shooter_lib::graphics::direction_movement(
               zombie_shooter_lib::graphics::direction(Point2 {
                 x: 1.0,
                 y: 0.0,
               }, Point2 {
                 x: 2.0,
                 y: 0.0,
               })
             ), "(1,0) to (2,0) should be (1,0)");

  assert_eq!(Point2 { x: 0.0, y: 1.0 },
             zombie_shooter_lib::graphics::direction_movement(
               zombie_shooter_lib::graphics::direction(Point2 {
                 x: 0.0,
                 y: 1.0,
               }, Point2 {
                 x: 0.0,
                 y: 2.0,
               })
             ), "(0,1) to (0,2) should be (0,1)");

  assert_eq!(Point2 { x: 0.71, y: 0.71 }, // 0.71 = sqrt(2) / 2.0
             zombie_shooter_lib::graphics::direction_movement(
               zombie_shooter_lib::graphics::direction(Point2 {
                 x: -2.0,
                 y: -2.0,
               }, Point2 {
                 x: -1.0,
                 y: -1.0,
               })
             ), "(-2,-2) to (-1,-1) should be 45deg");

  assert_eq!(Point2 { x: -0.71, y: -0.71 }, // 0.71 = sqrt(2) / 2.0
             zombie_shooter_lib::graphics::direction_movement(
               zombie_shooter_lib::graphics::direction(Point2 {
                 x: -1.0,
                 y: -1.0,
               }, Point2 {
                 x: -2.0,
                 y: -2.0,
               })
             ), "(-1,-1) to (-2,-2) should be 225deg");
}
<|endoftext|>


<commit_before>#[macro_use]
mod common;

#[cfg(unix)]
#[macro_use]
extern crate lazy_static;

#[cfg(unix)]
extern crate rust_users;

// For conditional compilation
macro_rules! unix_only {
    ($($fea:expr, $m:ident);+) => {
        $(
            #[cfg(unix)]
            #[cfg(feature = $fea)]
            mod $m;
         )+
    };
}
unix_only! {
    "chmod", test_chmod;
    "chown", test_chown;
    "chgrp", test_chgrp;
    "install", test_install;
    "mv", test_mv;
    "pathchk", test_pathchk;
    "pinky", test_pinky;
    "stdbuf", test_stdbuf;
    "touch", test_touch;
    "unlink", test_unlink;
    "who", test_who;
    // Be aware of the trailing semicolon after the last item
    "stat", test_stat
}

macro_rules! generic {
    ($($fea:expr, $m:ident);+) => {
        $(
            #[cfg(feature = $fea)]
            mod $m;
         )+
    };
}
generic! {
    "base32", test_base32;
    "base64", test_base64;
    "basename", test_basename;
    "cat", test_cat;
    "cksum", test_cksum;
    "comm", test_comm;
    "cp", test_cp;
    "cut", test_cut;
    "dircolors", test_dircolors;
    "dirname", test_dirname;
    "du", test_du;
    "echo", test_echo;
    "env", test_env;
    "expr", test_expr;
    "factor", test_factor;
    "false", test_false;
    "fold", test_fold;
    "hashsum", test_hashsum;
    "head", test_head;
    "join", test_join;
    "link", test_link;
    "ln", test_ln;
    "ls", test_ls;
    "mkdir", test_mkdir;
    "mktemp", test_mktemp;
    "numfmt", test_numfmt;
    "nl", test_nl;
    "od", test_od;
    "paste", test_paste;
    "printf", test_printf;
    "ptx", test_ptx;
    "pwd", test_pwd;
    "readlink", test_readlink;
    "realpath", test_realpath;
    "rm", test_rm;
    "rmdir", test_rmdir;
    "seq", test_seq;
    "sort", test_sort;
    "split", test_split;
    "sum", test_sum;
    "tac", test_tac;
    "tail", test_tail;
    "test", test_test;
    "tr", test_tr;
    "true", test_true;
    "truncate", test_truncate;
    "tsort", test_tsort;
    "unexpand", test_unexpand;
    "uniq", test_uniq;
    "wc", test_wc;
    // Be aware of the trailing semicolon after the last item
    "hostname", test_hostname
}
<commit_msg>touch: fix ~ activate tests on non-unix platforms<commit_after>#[macro_use]
mod common;

#[cfg(unix)]
#[macro_use]
extern crate lazy_static;

#[cfg(unix)]
extern crate rust_users;

// For conditional compilation
macro_rules! unix_only {
    ($($fea:expr, $m:ident);+) => {
        $(
            #[cfg(unix)]
            #[cfg(feature = $fea)]
            mod $m;
         )+
    };
}
unix_only! {
    "chmod", test_chmod;
    "chown", test_chown;
    "chgrp", test_chgrp;
    "install", test_install;
    "mv", test_mv;
    "pathchk", test_pathchk;
    "pinky", test_pinky;
    "stdbuf", test_stdbuf;
    "unlink", test_unlink;
    "who", test_who;
    // Be aware of the trailing semicolon after the last item
    "stat", test_stat
}

macro_rules! generic {
    ($($fea:expr, $m:ident);+) => {
        $(
            #[cfg(feature = $fea)]
            mod $m;
         )+
    };
}
generic! {
    "base32", test_base32;
    "base64", test_base64;
    "basename", test_basename;
    "cat", test_cat;
    "cksum", test_cksum;
    "comm", test_comm;
    "cp", test_cp;
    "cut", test_cut;
    "dircolors", test_dircolors;
    "dirname", test_dirname;
    "du", test_du;
    "echo", test_echo;
    "env", test_env;
    "expr", test_expr;
    "factor", test_factor;
    "false", test_false;
    "fold", test_fold;
    "hashsum", test_hashsum;
    "head", test_head;
    "join", test_join;
    "link", test_link;
    "ln", test_ln;
    "ls", test_ls;
    "mkdir", test_mkdir;
    "mktemp", test_mktemp;
    "numfmt", test_numfmt;
    "nl", test_nl;
    "od", test_od;
    "paste", test_paste;
    "printf", test_printf;
    "ptx", test_ptx;
    "pwd", test_pwd;
    "readlink", test_readlink;
    "realpath", test_realpath;
    "rm", test_rm;
    "rmdir", test_rmdir;
    "seq", test_seq;
    "sort", test_sort;
    "split", test_split;
    "sum", test_sum;
    "tac", test_tac;
    "tail", test_tail;
    "test", test_test;
    "touch", test_touch;
    "tr", test_tr;
    "true", test_true;
    "truncate", test_truncate;
    "tsort", test_tsort;
    "unexpand", test_unexpand;
    "uniq", test_uniq;
    "wc", test_wc;
    // Be aware of the trailing semicolon after the last item
    "hostname", test_hostname
}
<|endoftext|>


<commit_before>extern crate test;
extern crate ndarray;

use ndarray::Array;

#[bench]
fn time_matmul(b: &mut test::Bencher)
{
    b.iter(|| {
        let mut a: Array<uint, (uint, uint)> = Array::zeros((2u, 3u));
        for (i, elt) in a.iter_mut().enumerate() {
            *elt = i;
        }

        let mut b: Array<uint, (uint, uint)> = Array::zeros((3u, 4u));
        for (i, elt) in b.iter_mut().enumerate() {
            *elt = i;
        }

        let c = a.mat_mul(&b);
        unsafe {
            let result = Array::from_vec_dim((2u, 4u), vec![20u, 23, 26, 29, 56, 68, 80, 92]);
            assert!(c == result);
        }
    })
}
<commit_msg>Add test for Array of char<commit_after>extern crate test;
extern crate ndarray;

use ndarray::Array;

#[test]
fn char_array()
{
    // test compilation & basics of non-numerical array
    let cc = Array::from_iter("alphabet".chars()).reshape((4u, 2u));
    assert!(cc.at_sub(1, 0) == Array::from_iter("apae".chars()));
}

#[bench]
fn time_matmul(b: &mut test::Bencher)
{
    b.iter(|| {
        let mut a: Array<uint, (uint, uint)> = Array::zeros((2u, 3u));
        for (i, elt) in a.iter_mut().enumerate() {
            *elt = i;
        }

        let mut b: Array<uint, (uint, uint)> = Array::zeros((3u, 4u));
        for (i, elt) in b.iter_mut().enumerate() {
            *elt = i;
        }

        let c = a.mat_mul(&b);
        unsafe {
            let result = Array::from_vec_dim((2u, 4u), vec![20u, 23, 26, 29, 56, 68, 80, 92]);
            assert!(c == result);
        }
    })
}
<|endoftext|>


<commit_before>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// 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.

#![deny(missing_docs)]
#![allow(dead_code)]

//! Tinelli-style invariant generation.

extern crate term ;
extern crate system ;
extern crate common ;
extern crate unroll ;

use std::fmt ;
use std::cmp::Ord ;
use std::hash::{ Hash, Hasher } ;
use std::collections::{ HashSet, HashMap } ;
use std::marker::PhantomData ;

use term::{
  Offset2, Term, Operator,
  Factory,
  Bool, Int, Rat,
  Model
} ;

/// Key representing a node, corresponds to the key of its representant.
type Key = u64 ;

/// The value trait provides the operator encoding the ordering.
trait Val: Sized + Ord + Eq + Hash {
  /// The operator encording the ordering, e.g. `=>` for `Bool`.
  fn order_op() -> Operator ;
  /// Evaluates a term to some value given a model.
  fn eval(
    & Term, & Offset2, & Model, & Factory
  ) -> Result<Self, String> ;
}

impl Val for Bool {
  fn order_op() -> Operator { Operator::Impl }
  fn eval(
    term: & Term, offset: & Offset2, model: & Model, factory: & Factory
  ) -> Result<Bool, String> {
    factory.eval_bool(term, offset, model)
  }
}
impl Val for Int {
  fn order_op() -> Operator { Operator::Le }
  fn eval(
    term: & Term, offset: & Offset2, model: & Model, factory: & Factory
  ) -> Result<Int, String> {
    factory.eval_int(term, offset, model)
  }
}
impl Val for Rat {
  fn order_op() -> Operator { Operator::Le }
  fn eval(
    term: & Term, offset: & Offset2, model: & Model, factory: & Factory
  ) -> Result<Rat, String> {
    factory.eval_rat(term, offset, model)
  }
}

/// A node in the invariant generation graph.
struct Node<V> {
  /// Phantom data for the type the terms evaluate to.
  phantom: PhantomData<V>,
  /// Term representing the class.
  rep: Term,
  /// All terms of the node except `rep`.
  others: HashSet<Term>,
  /// The keys of the nodes directly above this one.
  above: HashSet<Key>,
  /// The keys of the nodes directly below this one.
  below: HashSet<Key>,
}
impl<V: Val> Node<V> {
  /// Creates a new node.
  #[inline(always)]
  pub fn mk(rep: Term, others: HashSet<Term>) -> Self {
    debug_assert!(
      ! others.contains(& rep)
    ) ;
    Node {
      phantom: PhantomData,
      rep: rep,
      others: others,
      above: HashSet::new(),
      below: HashSet::new(),
    }
  }
  /// Creates a new node with a representant and no other terms.
  #[inline(always)]
  pub fn of_rep(rep: Term) -> Self {
    Self::mk( rep, HashSet::new() )
  }

  /// Adds a term to the node.
  #[inline(always)]
  pub fn insert(& mut self, term: Term) -> bool {
    self.others.insert(term)
  }

  /// The nodes above this one.
  #[inline(always)]
  pub fn above(& self) -> & HashSet<Key> { & self.above }
  /// The nodes below this one.
  #[inline(always)]
  pub fn below(& self) -> & HashSet<Key> { & self.below }

  /// Adds a node above a node.
  #[inline(always)]
  pub fn add_above(& mut self, node: Key) -> bool {
    self.above.insert(node)
  }
  /// Adds a node below a node.
  #[inline(always)]
  pub fn add_below(& mut self, node: Key) -> bool {
    self.below.insert(node)
  }

  /// Removes a node above a node.
  #[inline(always)]
  pub fn rm_above(& mut self, node: Key) -> bool {
    self.above.remove(& node)
  }
  /// Removes a node below a node.
  #[inline(always)]
  pub fn rm_below(& mut self, node: Key) -> bool {
    self.below.remove(& node)
  }

  /** Returns the set of nodes below a node. Destroys the set `below` of the
  structure. */
  pub fn drain_below(& mut self) -> HashSet<Key> {
    let mut below = HashSet::new() ;
    ::std::mem::swap(& mut below, & mut self.below) ;
    below
  }

  /** Splits a node based on a model `mdl`.

  Returns the nodes `N_1`, ..., `N_n` such that

  * all elements of `N_i` are equal to some value `v_i` under `mdl`,
  * for `0 <= i < n`, `v_i \le v_{i+1}` where `\le` is the ordering on the
    values.

  Uses `insert_in_vec`. */
  pub fn split(
    self, model: & Model, offset: & Offset2, factory: & Factory
  ) -> Result<Vec<(V,Self)>, String> {
    debug_assert!( self.above.is_empty() ) ;
    debug_assert!( self.below.is_empty() ) ;
    let mut vec = vec![] ;
    match V::eval(& self.rep, offset, model, factory) {
      Ok(v) => vec.push( (v, Self::of_rep(self.rep)) ),
      Err(s) => return Err(s),
    } ;
    for term in self.others.into_iter() {
      match V::eval(& term, offset, model, factory) {
        Ok(v) => vec = insert_in_vec(vec, v, term),
        Err(s) => return Err(s),
      }
    } ;
    Ok(vec)
  }
}

/** Helper function for `split`, inserts a value / term pair in a sorted
value / node pair.

Inserts the term in the node corresponding to the value if any, otherwise
creates a new node with this term as representative. */
fn insert_in_vec<V: Val>(
  vec: Vec<(V, Node<V>)>, val: V, term: Term
) -> Vec<(V, Node<V>)> {
  use std::cmp::Ordering::* ;
  use std::iter::Extend ;
  let mut new = Vec::with_capacity(vec.len() + 1) ;
  let mut old = vec.into_iter() ;
  loop {
    if let Some( (v, mut node) ) = old.next() {
      match v.cmp(& val) {
        Less => new.push( (v, node) ),
        Equal => {
          node.insert(term) ;
          new.push( (v, node) ) ;
          break
        },
        Greater => {
          new.push( (v, node) ) ;
          new.push( (val, Node::of_rep(term)) ) ;
          break
        },
      }
    } else {
      new.push( (val, Node::of_rep(term)) ) ;
      break
    }
  }
  new.extend(old) ;
  new
}

impl<V> Hash for Node<V> {
  fn hash<H: Hasher>(& self, state: & mut H) {
    state.write_u64(self.rep.hkey())
  }
}

impl<V> fmt::Display for Node<V> {
  fn fmt(& self, fmt: & mut fmt::Formatter) -> fmt::Result {
    write!(
      fmt, "{}[{}]({}<{}<{})",
      self.rep.hkey(), self.rep.get(),
      self.above.len(), self.others.len(), self.below.len()
    )
  }
}

/// A graph is some roots and some nodes.
struct Graph<V> {
  /// Roots of the graph.
  roots: HashSet<Key>,
  /// Nodes of the graph.
  nodes: HashMap<Key, (Node<V>, V)>
}
impl<V> Graph<V> {
  #[inline(always)]
  pub fn node(& self, index: & Key) -> Option<& (Node<V>, V)> {
    self.nodes.get(index)
  }
  #[inline(always)]
  pub fn node_mut(
    & mut self, index: & Key
  ) -> Option<& mut (Node<V>, V)> {
    self.nodes.get_mut(index)
  }
  /// Extracts a root (removes it from the set of nodes).
  #[inline]
  pub fn root(& mut self) -> Option<Node<V>> {
    let root = match self.roots.iter().next() {
      Some(key) => * key,
      None => return None,
    } ;
    let was_there = self.roots.remove(& root) ;
    debug_assert!( was_there ) ;
    match self.nodes.remove(& root) {
      Some( (n, _) ) => Some(n),
      None => panic!(
        "node {} is registered as root but unknown to set of nodes",
        root
      )
    }
  }
}

<commit_msg>Basic stuff for the graph splitting algorithm<commit_after>// Copyright 2015 Adrien Champion. See the COPYRIGHT file at the top-level
// directory of this distribution.
//
// 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.

#![deny(missing_docs)]
#![allow(dead_code)]

//! Tinelli-style invariant generation.

extern crate term ;
extern crate system ;
extern crate common ;
extern crate unroll ;

use std::fmt ;
use std::cmp::Ord ;
use std::hash::{ Hash, Hasher } ;
use std::collections::{ HashSet, HashMap } ;
use std::marker::PhantomData ;

use term::{
  Offset2, Term, Operator,
  Factory,
  Bool, Int, Rat,
  Model
} ;

/// Key representing a node, corresponds to the key of its representant.
type Key = u64 ;

/// The value trait provides the operator encoding the ordering.
trait Val: Sized + Ord + Eq + Hash {
  /// The operator encording the ordering, e.g. `=>` for `Bool`.
  fn order_op() -> Operator ;
  /// Evaluates a term to some value given a model.
  fn eval(
    & Term, & Offset2, & Model, & Factory
  ) -> Result<Self, String> ;
}

impl Val for Bool {
  fn order_op() -> Operator { Operator::Impl }
  fn eval(
    term: & Term, offset: & Offset2, model: & Model, factory: & Factory
  ) -> Result<Bool, String> {
    factory.eval_bool(term, offset, model)
  }
}
impl Val for Int {
  fn order_op() -> Operator { Operator::Le }
  fn eval(
    term: & Term, offset: & Offset2, model: & Model, factory: & Factory
  ) -> Result<Int, String> {
    factory.eval_int(term, offset, model)
  }
}
impl Val for Rat {
  fn order_op() -> Operator { Operator::Le }
  fn eval(
    term: & Term, offset: & Offset2, model: & Model, factory: & Factory
  ) -> Result<Rat, String> {
    factory.eval_rat(term, offset, model)
  }
}

/// A node in the invariant generation graph.
struct Node<V> {
  /// Phantom data for the type the terms evaluate to.
  phantom: PhantomData<V>,
  /// Term representing the class.
  rep: Term,
  /// All terms of the node except `rep`.
  others: HashSet<Term>,
  /// The keys of the nodes directly above this one.
  above: HashSet<Key>,
  /// Stores the nodes potentially above this one after the split.
  above_transient: HashSet<Key>,
  /// The keys of the nodes directly below this one.
  below: HashSet<Key>,
}
impl<V: Val> Node<V> {
  /// Creates a new node.
  #[inline(always)]
  pub fn mk(rep: Term, others: HashSet<Term>) -> Self {
    debug_assert!(
      ! others.contains(& rep)
    ) ;
    Node {
      phantom: PhantomData,
      rep: rep,
      others: others,
      above: HashSet::new(),
      above_transient: HashSet::new(),
      below: HashSet::new(),
    }
  }
  /// Creates a new node with a representant and no other terms.
  #[inline(always)]
  pub fn of_rep(rep: Term) -> Self {
    Self::mk( rep, HashSet::new() )
  }

  /// The key of the node (hkey of the representant).
  #[inline(always)]
  pub fn key(& self) -> Key { self.rep.hkey() }

  /// Adds a term to the node.
  #[inline(always)]
  pub fn insert(& mut self, term: Term) -> bool {
    self.others.insert(term)
  }

  /// The nodes above this one.
  #[inline(always)]
  pub fn above(& self) -> & HashSet<Key> { & self.above }
  /// The nodes below this one.
  #[inline(always)]
  pub fn below(& self) -> & HashSet<Key> { & self.below }

  /// Adds a node above a node.
  #[inline(always)]
  pub fn add_above(& mut self, node: Key) -> bool {
    self.above.insert(node)
  }
  /// Adds a node below a node.
  #[inline(always)]
  pub fn add_below(& mut self, node: Key) -> bool {
    self.below.insert(node)
  }

  /// Removes a node above a node.
  #[inline(always)]
  pub fn rm_above(& mut self, node: Key) -> bool {
    self.above.remove(& node)
  }
  /// Removes a node below a node.
  #[inline(always)]
  pub fn rm_below(& mut self, node: Key) -> bool {
    self.below.remove(& node)
  }

  /** Returns the set of nodes below a node. Destroys the set `below` of the
  structure. */
  pub fn drain_below(& mut self) -> HashSet<Key> {
    let mut below = HashSet::new() ;
    ::std::mem::swap(& mut below, & mut self.below) ;
    below
  }

  /** Splits a node based on a model `mdl`.

  Returns the nodes `N_1`, ..., `N_n` such that

  * all elements of `N_i` are equal to some value `v_i` under `mdl`,
  * for `0 <= i < n`, `v_i \le v_{i+1}` where `\le` is the ordering on the
    values.

  Uses `insert_in_vec`. */
  pub fn split(
    self, model: & Model, offset: & Offset2, factory: & Factory
  ) -> Result<Vec<(V,Self)>, String> {
    debug_assert!( self.above.is_empty() ) ;
    debug_assert!( self.below.is_empty() ) ;
    let mut vec = vec![] ;
    match V::eval(& self.rep, offset, model, factory) {
      Ok(v) => vec.push( (v, Self::of_rep(self.rep)) ),
      Err(s) => return Err(s),
    } ;
    for term in self.others.into_iter() {
      match V::eval(& term, offset, model, factory) {
        Ok(v) => vec = insert_in_vec(vec, v, term),
        Err(s) => return Err(s),
      }
    } ;
    Ok(vec)
  }
}

/** Helper function for `split`, inserts a value / term pair in a sorted
value / node pair.

Inserts the term in the node corresponding to the value if any, otherwise
creates a new node with this term as representative. */
fn insert_in_vec<V: Val>(
  vec: Vec<(V, Node<V>)>, val: V, term: Term
) -> Vec<(V, Node<V>)> {
  use std::cmp::Ordering::* ;
  use std::iter::Extend ;
  let mut new = Vec::with_capacity(vec.len() + 1) ;
  let mut old = vec.into_iter() ;
  loop {
    if let Some( (v, mut node) ) = old.next() {
      match v.cmp(& val) {
        Less => new.push( (v, node) ),
        Equal => {
          node.insert(term) ;
          new.push( (v, node) ) ;
          break
        },
        Greater => {
          new.push( (v, node) ) ;
          new.push( (val, Node::of_rep(term)) ) ;
          break
        },
      }
    } else {
      new.push( (val, Node::of_rep(term)) ) ;
      break
    }
  }
  new.extend(old) ;
  new
}

impl<V> Hash for Node<V> {
  fn hash<H: Hasher>(& self, state: & mut H) {
    state.write_u64(self.rep.hkey())
  }
}

impl<V> fmt::Display for Node<V> {
  fn fmt(& self, fmt: & mut fmt::Formatter) -> fmt::Result {
    write!(
      fmt, "{}[{}]({}<{}<{})",
      self.rep.hkey(), self.rep.get(),
      self.above.len(), self.others.len(), self.below.len()
    )
  }
}

/// A graph is some roots and some nodes.
struct Graph<V> {
  /// Roots of the graph.
  roots: HashSet<Key>,
  /// Nodes of the graph.
  nodes: HashMap<Key, Node<V>>,
}
impl<V: Val> Graph<V> {
  /// The node and value associated with a key.
  #[inline(always)]
  pub fn node(& self, index: & Key) -> Option<& Node<V>> {
    self.nodes.get(index)
  }
  /// The node and value associated with a key (mutable).
  #[inline(always)]
  pub fn node_mut(
    & mut self, index: & Key
  ) -> Option<& mut Node<V>> {
    self.nodes.get_mut(index)
  }

  /** Extracts a root. Removes it from the set of nodes and returns the root
  and its kids. */
  #[inline]
  pub fn root(& mut self) -> Option<Node<V>> {
    let root = match self.roots.iter().next() {
      Some(key) => * key,
      None => return None,
    } ;
    let was_there = self.roots.remove(& root) ;
    debug_assert!( was_there ) ;
    match self.nodes.remove(& root) {
      Some( root ) => Some(root),
      None => panic!(
        "node {} is registered as root but unknown to set of nodes",
        root
      )
    }
  }

  /// Splits a graph according to a model.
  pub fn split(
    mut self, model: & Model, offset: & Offset2, factory: & Factory
  ) -> Result<Self, String> {
    // Orphan kids, kids we can process.
    let mut orphans = Vec::with_capacity(13) ;
    // The new graph we're building.
    let mut new = Graph {
      roots: HashSet::with_capacity(self.roots.len()),
      nodes: HashMap::with_capacity(self.nodes.len()),
    } ;

    // Handle all roots first.
    'roots: loop {
      if let Some(root) = self.root() {
        let old_key = root.key() ;

        // Splitting root.
        let mut ordered = match root.split(model, offset, factory) {
          Ok(ordered) => ordered, Err(s) => return Err(s)
        } ;

        // Adding biggest node, i.e. the new root.
        let mut prev = if let Some((_, root)) = ordered.pop() {
          let key = root.key() ;
          new.roots.insert(key) ;
          new.nodes.insert(key, root) ;
          key
        } else {
          return Err(
            format!("split of root {} resulted in nothing", old_key)
          )
        } ;

        // Looping over what's below the new root.
        'nu_kids: loop {
          if let Some((_, mut kid)) = ordered.pop() {
            kid.above.insert(prev) ;
            match new.nodes.get_mut(& prev) {
              Some(prev) => prev.below.insert(kid.key()),
              None => return Err(
                format!("unknown previous node {}", prev)
              ),
            } ;
            prev = kid.key() ;
            let was_there = new.nodes.insert(kid.key(), kid) ;
            debug_assert!(was_there.is_none())
          } else {
            break 'nu_kids
          }
        } ;

        // Removing the root from its kids, adding smallet new node as
        // transient. Remembering orphan kids.
        for kid in new.nodes.get_mut(& old_key).unwrap().above().iter() {
          match self.nodes.get_mut(kid) {
            Some(kid) => {
              let was_there = kid.rm_above(old_key) ;
              debug_assert!(was_there) ;
              let was_there = kid.above_transient.insert(prev) ;
              debug_assert!(! was_there) ;
              if kid.above.is_empty() {
                orphans.push(kid.key()) // Orphan, remember it.
              }
            },
            None => return Err(
              format!("unknown root with key {}", kid)
            ),
          }
        } ;
        ()
      } else { break 'roots }
    } ;

    // 'non_roots: loop {
    //   if let Some(node) = orphans.pop() {
    //     let old_key = node.key() ;

    //     // Split node.
    //     let mut ordered = match node.split(model, offset, factory) {
    //       Ok(ordered) => ordered,
    //       Err(s) => return Err(s),
    //     } ;

    //     // Updating biggest node.
    //     let mut prev = if let Some((_, node)) = ordered.pop() {
    //       let key = node.key() ;
    //       new.nodes.insert
    //     }

    //   } else { break 'non_roots }
    // } ;

    Ok(new)
  }
}

<|endoftext|>


<commit_before>extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new(&hostname, &token);

    let project_id = 142;
    let merge_requests_ids = vec![409, 410];

    let merge_requests = gl.merge_requests(project_id).list();
    println!("merge_requests: {:?}", merge_requests);

    let merge_request = gl.merge_requests(project_id).single(merge_requests_ids[0]).list();
    println!("merge_request: {:?}", merge_request);

    let merge_requests = gl.merge_requests(project_id).iid(vec![merge_requests_ids[0]]).list();
    println!("merge_requests: {:?}", merge_requests);

    let merge_requests = gl.merge_requests(project_id).iid(merge_requests_ids).list();
    println!("merge_requests: {:?}", merge_requests);
}
<commit_msg>List merge requests per iid<commit_after>extern crate gitlab_api as gitlab;

use std::env;
#[macro_use]
extern crate log;
extern crate env_logger;

use gitlab::GitLab;

fn main() {
    env_logger::init().unwrap();
    info!("starting up");

    let hostname = match env::var("GITLAB_HOSTNAME") {
        Ok(val) => val,
        Err(_) => {
            let default = String::from("gitlab.com");
            println!("Please set environment variable 'GITLAB_HOSTNAME'. Using default '{}'.",
                     default);
            default
        }
    };

    let token = match env::var("GITLAB_TOKEN") {
        Ok(val) => val,
        Err(_) => {
            panic!("Please set environment variable 'GITLAB_TOKEN'. Take it from \
                    http://{}/profile/account",
                   hostname);
        }
    };

    let gl = GitLab::new(&hostname, &token);

    let project_id = 142;
    let merge_requests_ids = vec![409, 410];
    let merge_requests_iids = vec![3, 4];

    let merge_requests = gl.merge_requests(project_id).list();
    println!("merge_requests: {:?}", merge_requests);

    let merge_request = gl.merge_requests(project_id).single(merge_requests_ids[0]).list();
    println!("merge_request: {:?}", merge_request);

    let merge_requests = gl.merge_requests(project_id).iid(vec![merge_requests_iids[0]]).list();
    println!("merge_requests: {:?}", merge_requests);

    // let merge_requests = gl.merge_requests(project_id).iid(merge_requests_iids).list();
    // println!("merge_requests: {:?}", merge_requests);
}
<|endoftext|>