<commit_before>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Copyright 2017 - Dario Ostuni <dario.ostuni@gmail.com>
 *
 */

#[macro_use]
extern crate log;
extern crate mowl;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate twox_hash;
extern crate tungstenite;
extern crate serde;
extern crate rand;
extern crate url;

mod common;

use common::*;
use serde::Serialize;
use std::env;
use std::io::{BufRead, BufReader, Read, Write};
use std::io::ErrorKind;
use std::process::{Command, Stdio};
use tungstenite::{Error, Message, WebSocket};
use tungstenite::client::connect;
use url::Url;

fn send_data<T: ?Sized + Serialize, U: Read + Write>(ws: &mut WebSocket<U>, value: &T)
{
    match serde_json::to_string(value)
    {
        Ok(s) =>
        {
            match ws.write_message(Message::text(s))
            {
                Ok(_) =>
                {}
                Err(Error::Io(x)) =>
                {
                    match x.kind()
                    {
                        ErrorKind::WouldBlock =>
                        {
                            match ws.write_pending()
                            {
                                Ok(_) =>
                                {}
                                Err(why) => error!("Unable to flush WebSocket {}", why),
                            }
                        }
                        _ => error!("I/O error"),
                    }
                }
                Err(_) => panic!("Connection closed!"),
            }
        }
        Err(_) => unreachable!(),
    };
}

#[cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
fn main()
{
    mowl::init_with_level(log::LogLevel::Info).unwrap();
    info!("Starting dazzle...");
    let args: Vec<String> = env::args().skip(1).collect();
    if args.len() < 2
    {
        error!("Usage: dazzle ws://ip:port/ <program> [arguments]");
        return;
    }
    info!("dazzle started successfully!");
    let mut websocket = match connect(Url::parse(args[0].as_str()).unwrap())
    {
        Ok(ws) => ws,
        Err(why) => panic!("Cannot connect to {} -> {}", args[0], why),
    };
    info!("Connected to {}", args[0]);
    let child = Command::new(&args[1])
        .args(args.iter().skip(2))
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("Cannot fork");
    info!("Started guest program");
    let mut stdout = BufReader::new(child.stdout.unwrap());
    let mut stdin = child.stdin.unwrap();
    let mut name_string = String::new();
    stdout.read_line(&mut name_string).unwrap();
    let connect_message = ClientMessage::HandShake(ClientRole::Player(PlayerInfo { name: name_string }));
    send_data(&mut websocket, &connect_message);
    let response: ServerResponse = serde_json::from_str(websocket.read_message().unwrap().to_text().unwrap()).unwrap();
    if let ServerResponse::Error(s) = response
    {
        panic!("Error from server: {}", s);
    }
    loop
    {
        let overview: Overview = serde_json::from_str(websocket.read_message().unwrap().to_text().unwrap()).unwrap();
        let n = overview.players.len();
        let r = overview.grid.len();
        let c = overview.grid[0].len();
        let t = overview.tokens.len();
        let e = overview.turns_left;
        let m = overview.ms_for_turn;
        writeln!(&mut stdin, "{} {} {} {} {} {}", n, r, c, t, e, m).unwrap();
        for p in &overview.players
        {
            writeln!(&mut stdin, "{} {} {} {} {}", p.id, p.name, p.points, p.position.x, p.position.y).unwrap();
        }
        for rows in &overview.grid
        {
            for pos in 0..rows.len()
            {
                if let Some(value) = rows[pos]
                {
                    write!(&mut stdin, "{}", value).unwrap();
                }
                else
                {
                    write!(&mut stdin, "{}", -1).unwrap();
                }
                if pos != rows.len() - 1
                {
                    write!(&mut stdin, " ").unwrap();
                }
            }
            writeln!(&mut stdin, "").unwrap();
        }
        for token in &overview.tokens
        {
            writeln!(&mut stdin, "{} {}", token.x, token.y).unwrap();
        }
        stdin.flush().unwrap();
        let mut cli = String::new();
        stdout.read_line(&mut cli).unwrap();
        let command = match cli.trim()
        {
            "NOTHING" => ClientCommand::Nothing,
            "UP" => ClientCommand::Move(Direction::Up),
            "DOWN" => ClientCommand::Move(Direction::Down),
            "LEFT" => ClientCommand::Move(Direction::Left),
            "RIGHT" => ClientCommand::Move(Direction::Right),
            "QUIT" => break,
            cmd => panic!("Invalid command: {}", cmd),
        };
        let command = ClientMessage::Command(command);
        send_data(&mut websocket, &command);
        let _: ServerResponse = serde_json::from_str(websocket.read_message().unwrap().to_text().unwrap()).unwrap();
    }
    websocket.close(None).unwrap();
}

/* INPUT FORMAT
N: number of players
R, C: rows and columns of the grid
T: number of tokens
E: turns left
M: milliseconds to make the move
positionals arguments
ID: player id
S: player name (string)
P: points
X, Y: position

INPUT:
N R C T E M
N lines containing: ID S P X Y
R lines, each containing C numbers: -1 for nothing, the player id otherwise
T lines: X Y
*/
<commit_msg>Resolved some clippy issues<commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Copyright 2017 - Dario Ostuni <dario.ostuni@gmail.com>
 *
 */

#[macro_use]
extern crate log;
extern crate mowl;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate twox_hash;
extern crate tungstenite;
extern crate serde;
extern crate rand;
extern crate url;

mod common;

use common::*;
use serde::Serialize;
use std::env;
use std::io::{BufRead, BufReader, Read, Write};
use std::io::ErrorKind;
use std::process::{Command, Stdio};
use tungstenite::{Error, Message, WebSocket};
use tungstenite::client::connect;
use url::Url;

fn send_data<T: ?Sized + Serialize, U: Read + Write>(ws: &mut WebSocket<U>, value: &T)
{
    match serde_json::to_string(value)
    {
        Ok(s) =>
        {
            match ws.write_message(Message::text(s))
            {
                Ok(_) =>
                {}
                Err(Error::Io(x)) =>
                {
                    match x.kind()
                    {
                        ErrorKind::WouldBlock =>
                        {
                            match ws.write_pending()
                            {
                                Ok(_) =>
                                {}
                                Err(why) => error!("Unable to flush WebSocket {}", why),
                            }
                        }
                        _ => error!("I/O error"),
                    }
                }
                _ => panic!("Connection closed!"),
            }
        }
        Err(_) => unreachable!(),
    };
}

#[cfg_attr(feature = "cargo-clippy", allow(many_single_char_names, needless_range_loop))]
fn main()
{
    mowl::init_with_level(log::LogLevel::Info).unwrap();
    info!("Starting dazzle...");
    let args: Vec<String> = env::args().skip(1).collect();
    if args.len() < 2
    {
        error!("Usage: dazzle ws://ip:port/ <program> [arguments]");
        return;
    }
    info!("dazzle started successfully!");
    let mut websocket = match connect(Url::parse(args[0].as_str()).unwrap())
    {
        Ok(ws) => ws,
        Err(why) => panic!("Cannot connect to {} -> {}", args[0], why),
    };
    info!("Connected to {}", args[0]);
    let child = Command::new(&args[1])
        .args(args.iter().skip(2))
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .expect("Cannot fork");
    info!("Started guest program");
    let mut stdout = BufReader::new(child.stdout.unwrap());
    let mut stdin = child.stdin.unwrap();
    let mut name_string = String::new();
    stdout.read_line(&mut name_string).unwrap();
    let connect_message = ClientMessage::HandShake(ClientRole::Player(PlayerInfo { name: name_string }));
    send_data(&mut websocket, &connect_message);
    let response: ServerResponse = serde_json::from_str(websocket.read_message().unwrap().to_text().unwrap()).unwrap();
    if let ServerResponse::Error(s) = response
    {
        panic!("Error from server: {}", s);
    }
    loop
    {
        let overview: Overview = serde_json::from_str(websocket.read_message().unwrap().to_text().unwrap()).unwrap();
        let n = overview.players.len();
        let r = overview.grid.len();
        let c = overview.grid[0].len();
        let t = overview.tokens.len();
        let e = overview.turns_left;
        let m = overview.ms_for_turn;
        writeln!(&mut stdin, "{} {} {} {} {} {}", n, r, c, t, e, m).unwrap();
        for p in &overview.players
        {
            writeln!(&mut stdin, "{} {} {} {} {}", p.id, p.name, p.points, p.position.x, p.position.y).unwrap();
        }
        for rows in &overview.grid
        {
            for pos in 0..rows.len()
            {
                if let Some(value) = rows[pos]
                {
                    write!(&mut stdin, "{}", value).unwrap();
                }
                else
                {
                    write!(&mut stdin, "{}", -1).unwrap();
                }
                if pos != rows.len() - 1
                {
                    write!(&mut stdin, " ").unwrap();
                }
            }
            writeln!(&mut stdin, "").unwrap();
        }
        for token in &overview.tokens
        {
            writeln!(&mut stdin, "{} {}", token.x, token.y).unwrap();
        }
        stdin.flush().unwrap();
        let mut cli = String::new();
        stdout.read_line(&mut cli).unwrap();
        let command = match cli.trim()
        {
            "NOTHING" => ClientCommand::Nothing,
            "UP" => ClientCommand::Move(Direction::Up),
            "DOWN" => ClientCommand::Move(Direction::Down),
            "LEFT" => ClientCommand::Move(Direction::Left),
            "RIGHT" => ClientCommand::Move(Direction::Right),
            "QUIT" => break,
            cmd => panic!("Invalid command: {}", cmd),
        };
        let command = ClientMessage::Command(command);
        send_data(&mut websocket, &command);
        let _: ServerResponse = serde_json::from_str(websocket.read_message().unwrap().to_text().unwrap()).unwrap();
    }
    websocket.close(None).unwrap();
}

/* INPUT FORMAT
N: number of players
R, C: rows and columns of the grid
T: number of tokens
E: turns left
M: milliseconds to make the move
positionals arguments
ID: player id
S: player name (string)
P: points
X, Y: position

INPUT:
N R C T E M
N lines containing: ID S P X Y
R lines, each containing C numbers: -1 for nothing, the player id otherwise
T lines: X Y
*/
<|endoftext|>


<commit_before>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

mod copy;
mod flash;
mod imxkobs;
mod mender;
mod raw;
mod tarball;
mod test;
mod ubifs;
mod uboot_env;
mod zephyr;

mod update_package;

/// Internal structures in the Objects for some type validation
pub mod definitions;
/// Objects representing each possible install mode
pub mod objects {
    pub use crate::{
        copy::Copy, flash::Flash, imxkobs::Imxkobs, raw::Raw, tarball::Tarball, test::Test,
        ubifs::Ubifs, uboot_env::UbootEnv,
    };
}
pub use update_package::{SupportedHardware, UpdatePackage};

use serde::Deserialize;

/// Represents the install mode for the object data
#[derive(Deserialize, PartialEq, Debug)]
#[serde(tag = "mode")]
#[serde(rename_all = "lowercase")]
pub enum Object {
    Copy(Box<objects::Copy>),
    Flash(Box<objects::Flash>),
    Imxkobs(Box<objects::Imxkobs>),
    Raw(Box<objects::Raw>),
    Tarball(Box<objects::Tarball>),
    Test(Box<objects::Test>),
    Ubifs(Box<objects::Ubifs>),
    #[serde(rename = "uboot-env")]
    UbootEnv(Box<objects::UbootEnv>),
    // FIXME: Add support for the missing modes: Mende Zephyr
}
<commit_msg>package_schema: Add Mender and Zephyr objects<commit_after>// Copyright (C) 2019 O.S. Systems Sofware LTDA
//
// SPDX-License-Identifier: Apache-2.0

mod copy;
mod flash;
mod imxkobs;
mod mender;
mod raw;
mod tarball;
mod test;
mod ubifs;
mod uboot_env;
mod zephyr;

mod update_package;

/// Internal structures in the Objects for some type validation
pub mod definitions;
/// Objects representing each possible install mode
pub mod objects {
    pub use crate::{
        copy::Copy, flash::Flash, imxkobs::Imxkobs, mender::Mender, raw::Raw, tarball::Tarball,
        test::Test, ubifs::Ubifs, uboot_env::UbootEnv, zephyr::Zephyr,
    };
}
pub use update_package::{SupportedHardware, UpdatePackage};

use serde::Deserialize;

/// Represents the install mode for the object data
#[derive(Deserialize, PartialEq, Debug)]
#[serde(tag = "mode")]
#[serde(rename_all = "lowercase")]
pub enum Object {
    Copy(Box<objects::Copy>),
    Flash(Box<objects::Flash>),
    Imxkobs(Box<objects::Imxkobs>),
    Mender(Box<objects::Mender>),
    Raw(Box<objects::Raw>),
    Tarball(Box<objects::Tarball>),
    Test(Box<objects::Test>),
    Ubifs(Box<objects::Ubifs>),
    #[serde(rename = "uboot-env")]
    UbootEnv(Box<objects::UbootEnv>),
    Zephyr(Box<objects::Zephyr>),
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]
#![feature(once_cell)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
// warn on rustc internal lints
#![deny(rustc::internal)]

// FIXME: switch to something more ergonomic here, once available.
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_interface;
extern crate rustc_middle;

use rustc_interface::interface;
use rustc_middle::ty::TyCtxt;
use rustc_tools_util::VersionInfo;

use std::borrow::Cow;
use std::env;
use std::lazy::SyncLazy;
use std::ops::Deref;
use std::panic;
use std::path::{Path, PathBuf};
use std::process::{exit, Command};

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a, T: Deref<Target = str>>(
    args: &'a [T],
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.iter().map(Deref::deref);
    while let Some(arg) = args.next() {
        let mut arg = arg.splitn(2, '=');
        if arg.next() != Some(find_arg) {
            continue;
        }

        match arg.next().or_else(|| args.next()) {
            Some(v) if pred(v) => return Some(v),
            _ => {},
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args = &["--bar=bar", "--foobar", "123", "--foo"];

    assert_eq!(arg_value(&[] as &[&str], "--foobar", |_| true), None);
    assert_eq!(arg_value(args, "--bar", |_| false), None);
    assert_eq!(arg_value(args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(args, "--foo", |_| true), None);
}

struct DefaultCallbacks;
impl rustc_driver::Callbacks for DefaultCallbacks {}

struct ClippyCallbacks;
impl rustc_driver::Callbacks for ClippyCallbacks {
    fn config(&mut self, config: &mut interface::Config) {
        let previous = config.register_lints.take();
        config.register_lints = Some(Box::new(move |sess, mut lint_store| {
            // technically we're ~guaranteed that this is none but might as well call anything that
            // is there already. Certainly it can't hurt.
            if let Some(previous) = &previous {
                (previous)(sess, lint_store);
            }

            let conf = clippy_lints::read_conf(&[], &sess);
            clippy_lints::register_plugins(&mut lint_store, &sess, &conf);
            clippy_lints::register_pre_expansion_lints(&mut lint_store);
            clippy_lints::register_renamed(&mut lint_store);
        }));

        // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be
        // run on the unoptimized MIR. On the other hand this results in some false negatives. If
        // MIR passes can be enabled / disabled separately, we should figure out, what passes to
        // use for Clippy.
        config.opts.debugging_opts.mir_opt_level = 0;
    }
}

fn display_help() {
    println!(
        "\
Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
        --rustc              Pass all args to rustc
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"
    );
}

const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new";

static ICE_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> = SyncLazy::new(|| {
    let hook = panic::take_hook();
    panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL)));
    hook
});

fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
    // Invoke our ICE handler, which prints the actual panic message and optionally a backtrace
    (*ICE_HOOK)(info);

    // Separate the output with an empty line
    eprintln!();

    let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
        rustc_errors::ColorConfig::Auto,
        None,
        false,
        false,
        None,
        false,
    ));
    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);

    // a .span_bug or .bug call has already printed what
    // it wants to print.
    if !info.payload().is::<rustc_errors::ExplicitBug>() {
        let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
        handler.emit_diagnostic(&d);
    }

    let version_info = rustc_tools_util::get_version_info!();

    let xs: Vec<Cow<'static, str>> = vec![
        "the compiler unexpectedly panicked. this is a bug.".into(),
        format!("we would appreciate a bug report: {}", bug_report_url).into(),
        format!("Clippy version: {}", version_info).into(),
    ];

    for note in &xs {
        handler.note_without_error(&note);
    }

    // If backtraces are enabled, also print the query stack
    let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");

    let num_frames = if backtrace { None } else { Some(2) };

    TyCtxt::try_print_query_stack(&handler, num_frames);
}

fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<PathBuf> {
    home.and_then(|home| {
        toolchain.map(|toolchain| {
            let mut path = PathBuf::from(home);
            path.push("toolchains");
            path.push(toolchain);
            path
        })
    })
}

#[allow(clippy::too_many_lines)]
pub fn main() {
    rustc_driver::init_rustc_env_logger();
    SyncLazy::force(&ICE_HOOK);
    exit(rustc_driver::catch_with_exit_code(move || {
        let mut orig_args: Vec<String> = env::args().collect();

        // Get the sysroot, looking from most specific to this invocation to the least:
        // - command line
        // - runtime environment
        //    - SYSROOT
        //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
        // - sysroot from rustc in the path
        // - compile-time environment
        //    - SYSROOT
        //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
        let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
        let have_sys_root_arg = sys_root_arg.is_some();
        let sys_root = sys_root_arg
            .map(PathBuf::from)
            .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from))
            .or_else(|| {
                let home = std::env::var("RUSTUP_HOME")
                    .or_else(|_| std::env::var("MULTIRUST_HOME"))
                    .ok();
                let toolchain = std::env::var("RUSTUP_TOOLCHAIN")
                    .or_else(|_| std::env::var("MULTIRUST_TOOLCHAIN"))
                    .ok();
                toolchain_path(home, toolchain)
            })
            .or_else(|| {
                Command::new("rustc")
                    .arg("--print")
                    .arg("sysroot")
                    .output()
                    .ok()
                    .and_then(|out| String::from_utf8(out.stdout).ok())
                    .map(|s| PathBuf::from(s.trim()))
            })
            .or_else(|| option_env!("SYSROOT").map(PathBuf::from))
            .or_else(|| {
                let home = option_env!("RUSTUP_HOME")
                    .or(option_env!("MULTIRUST_HOME"))
                    .map(ToString::to_string);
                let toolchain = option_env!("RUSTUP_TOOLCHAIN")
                    .or(option_env!("MULTIRUST_TOOLCHAIN"))
                    .map(ToString::to_string);
                toolchain_path(home, toolchain)
            })
            .map(|pb| pb.to_string_lossy().to_string())
            .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

        // make "clippy-driver --rustc" work like a subcommand that passes further args to "rustc"
        // for example `clippy-driver --rustc --version` will print the rustc version that clippy-driver
        // uses
        if let Some(pos) = orig_args.iter().position(|arg| arg == "--rustc") {
            orig_args.remove(pos);
            orig_args[0] = "rustc".to_string();

            // if we call "rustc", we need to pass --sysroot here as well
            let mut args: Vec<String> = orig_args.clone();
            if !have_sys_root_arg {
                args.extend(vec!["--sysroot".into(), sys_root]);
            };

            return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
        }

        if orig_args.iter().any(|a| a == "--version" || a == "-V") {
            let version_info = rustc_tools_util::get_version_info!();
            println!("{}", version_info);
            exit(0);
        }

        // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
        // We're invoking the compiler programmatically, so we ignore this/
        let wrapper_mode = orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref());

        if wrapper_mode {
            // we still want to be able to invoke it normally though
            orig_args.remove(1);
        }

        if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) {
            display_help();
            exit(0);
        }

        // this conditional check for the --sysroot flag is there so users can call
        // `clippy_driver` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = orig_args.clone();
        if !have_sys_root_arg {
            args.extend(vec!["--sysroot".into(), sys_root]);
        };

        let mut no_deps = false;
        let clippy_args = env::var("CLIPPY_ARGS")
            .unwrap_or_default()
            .split("__CLIPPY_HACKERY__")
            .filter_map(|s| match s {
                "" => None,
                "--no-deps" => {
                    no_deps = true;
                    None
                },
                _ => Some(s.to_string()),
            })
            .chain(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()])
            .collect::<Vec<String>>();

        // this check ensures that dependencies are built but not linted and the final
        // crate is linted but not built
        let clippy_tests_set = env::var("CLIPPY_TESTS").map_or(false, |val| val == "true");
        let cap_lints_allow = arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_some();
        let in_primary_package = env::var("CARGO_PRIMARY_PACKAGE").is_ok();

        let clippy_enabled = clippy_tests_set || (!cap_lints_allow && (!no_deps || in_primary_package));
        if clippy_enabled {
            args.extend(clippy_args);
        }

        let mut clippy = ClippyCallbacks;
        let mut default = DefaultCallbacks;
        let callbacks: &mut (dyn rustc_driver::Callbacks + Send) =
            if clippy_enabled { &mut clippy } else { &mut default };

        rustc_driver::RunCompiler::new(&args, callbacks).run()
    }))
}
<commit_msg>Reword bitrotten comment<commit_after>#![feature(rustc_private)]
#![feature(once_cell)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
// warn on rustc internal lints
#![deny(rustc::internal)]

// FIXME: switch to something more ergonomic here, once available.
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_interface;
extern crate rustc_middle;

use rustc_interface::interface;
use rustc_middle::ty::TyCtxt;
use rustc_tools_util::VersionInfo;

use std::borrow::Cow;
use std::env;
use std::lazy::SyncLazy;
use std::ops::Deref;
use std::panic;
use std::path::{Path, PathBuf};
use std::process::{exit, Command};

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a, T: Deref<Target = str>>(
    args: &'a [T],
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.iter().map(Deref::deref);
    while let Some(arg) = args.next() {
        let mut arg = arg.splitn(2, '=');
        if arg.next() != Some(find_arg) {
            continue;
        }

        match arg.next().or_else(|| args.next()) {
            Some(v) if pred(v) => return Some(v),
            _ => {},
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args = &["--bar=bar", "--foobar", "123", "--foo"];

    assert_eq!(arg_value(&[] as &[&str], "--foobar", |_| true), None);
    assert_eq!(arg_value(args, "--bar", |_| false), None);
    assert_eq!(arg_value(args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(args, "--foo", |_| true), None);
}

struct DefaultCallbacks;
impl rustc_driver::Callbacks for DefaultCallbacks {}

struct ClippyCallbacks;
impl rustc_driver::Callbacks for ClippyCallbacks {
    fn config(&mut self, config: &mut interface::Config) {
        let previous = config.register_lints.take();
        config.register_lints = Some(Box::new(move |sess, mut lint_store| {
            // technically we're ~guaranteed that this is none but might as well call anything that
            // is there already. Certainly it can't hurt.
            if let Some(previous) = &previous {
                (previous)(sess, lint_store);
            }

            let conf = clippy_lints::read_conf(&[], &sess);
            clippy_lints::register_plugins(&mut lint_store, &sess, &conf);
            clippy_lints::register_pre_expansion_lints(&mut lint_store);
            clippy_lints::register_renamed(&mut lint_store);
        }));

        // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be
        // run on the unoptimized MIR. On the other hand this results in some false negatives. If
        // MIR passes can be enabled / disabled separately, we should figure out, what passes to
        // use for Clippy.
        config.opts.debugging_opts.mir_opt_level = 0;
    }
}

fn display_help() {
    println!(
        "\
Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
        --rustc              Pass all args to rustc
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"
    );
}

const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new";

static ICE_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> = SyncLazy::new(|| {
    let hook = panic::take_hook();
    panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL)));
    hook
});

fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
    // Invoke our ICE handler, which prints the actual panic message and optionally a backtrace
    (*ICE_HOOK)(info);

    // Separate the output with an empty line
    eprintln!();

    let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
        rustc_errors::ColorConfig::Auto,
        None,
        false,
        false,
        None,
        false,
    ));
    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);

    // a .span_bug or .bug call has already printed what
    // it wants to print.
    if !info.payload().is::<rustc_errors::ExplicitBug>() {
        let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
        handler.emit_diagnostic(&d);
    }

    let version_info = rustc_tools_util::get_version_info!();

    let xs: Vec<Cow<'static, str>> = vec![
        "the compiler unexpectedly panicked. this is a bug.".into(),
        format!("we would appreciate a bug report: {}", bug_report_url).into(),
        format!("Clippy version: {}", version_info).into(),
    ];

    for note in &xs {
        handler.note_without_error(&note);
    }

    // If backtraces are enabled, also print the query stack
    let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");

    let num_frames = if backtrace { None } else { Some(2) };

    TyCtxt::try_print_query_stack(&handler, num_frames);
}

fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<PathBuf> {
    home.and_then(|home| {
        toolchain.map(|toolchain| {
            let mut path = PathBuf::from(home);
            path.push("toolchains");
            path.push(toolchain);
            path
        })
    })
}

#[allow(clippy::too_many_lines)]
pub fn main() {
    rustc_driver::init_rustc_env_logger();
    SyncLazy::force(&ICE_HOOK);
    exit(rustc_driver::catch_with_exit_code(move || {
        let mut orig_args: Vec<String> = env::args().collect();

        // Get the sysroot, looking from most specific to this invocation to the least:
        // - command line
        // - runtime environment
        //    - SYSROOT
        //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
        // - sysroot from rustc in the path
        // - compile-time environment
        //    - SYSROOT
        //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
        let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
        let have_sys_root_arg = sys_root_arg.is_some();
        let sys_root = sys_root_arg
            .map(PathBuf::from)
            .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from))
            .or_else(|| {
                let home = std::env::var("RUSTUP_HOME")
                    .or_else(|_| std::env::var("MULTIRUST_HOME"))
                    .ok();
                let toolchain = std::env::var("RUSTUP_TOOLCHAIN")
                    .or_else(|_| std::env::var("MULTIRUST_TOOLCHAIN"))
                    .ok();
                toolchain_path(home, toolchain)
            })
            .or_else(|| {
                Command::new("rustc")
                    .arg("--print")
                    .arg("sysroot")
                    .output()
                    .ok()
                    .and_then(|out| String::from_utf8(out.stdout).ok())
                    .map(|s| PathBuf::from(s.trim()))
            })
            .or_else(|| option_env!("SYSROOT").map(PathBuf::from))
            .or_else(|| {
                let home = option_env!("RUSTUP_HOME")
                    .or(option_env!("MULTIRUST_HOME"))
                    .map(ToString::to_string);
                let toolchain = option_env!("RUSTUP_TOOLCHAIN")
                    .or(option_env!("MULTIRUST_TOOLCHAIN"))
                    .map(ToString::to_string);
                toolchain_path(home, toolchain)
            })
            .map(|pb| pb.to_string_lossy().to_string())
            .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

        // make "clippy-driver --rustc" work like a subcommand that passes further args to "rustc"
        // for example `clippy-driver --rustc --version` will print the rustc version that clippy-driver
        // uses
        if let Some(pos) = orig_args.iter().position(|arg| arg == "--rustc") {
            orig_args.remove(pos);
            orig_args[0] = "rustc".to_string();

            // if we call "rustc", we need to pass --sysroot here as well
            let mut args: Vec<String> = orig_args.clone();
            if !have_sys_root_arg {
                args.extend(vec!["--sysroot".into(), sys_root]);
            };

            return rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run();
        }

        if orig_args.iter().any(|a| a == "--version" || a == "-V") {
            let version_info = rustc_tools_util::get_version_info!();
            println!("{}", version_info);
            exit(0);
        }

        // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
        // We're invoking the compiler programmatically, so we ignore this/
        let wrapper_mode = orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref());

        if wrapper_mode {
            // we still want to be able to invoke it normally though
            orig_args.remove(1);
        }

        if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) {
            display_help();
            exit(0);
        }

        // this conditional check for the --sysroot flag is there so users can call
        // `clippy_driver` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = orig_args.clone();
        if !have_sys_root_arg {
            args.extend(vec!["--sysroot".into(), sys_root]);
        };

        let mut no_deps = false;
        let clippy_args = env::var("CLIPPY_ARGS")
            .unwrap_or_default()
            .split("__CLIPPY_HACKERY__")
            .filter_map(|s| match s {
                "" => None,
                "--no-deps" => {
                    no_deps = true;
                    None
                },
                _ => Some(s.to_string()),
            })
            .chain(vec!["--cfg".into(), r#"feature="cargo-clippy""#.into()])
            .collect::<Vec<String>>();

        // We enable Clippy if one of the following conditions is met
        // - IF Clippy is run on its test suite OR
        // - IF Clippy is run on the main crate, not on deps (`!cap_lints_allow`) THEN
        //    - IF `--no-deps` is not set (`!no_deps`) OR
        //    - IF `--no-deps` is set and Clippy is run on the specified primary package
        let clippy_tests_set = env::var("CLIPPY_TESTS").map_or(false, |val| val == "true");
        let cap_lints_allow = arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_some();
        let in_primary_package = env::var("CARGO_PRIMARY_PACKAGE").is_ok();

        let clippy_enabled = clippy_tests_set || (!cap_lints_allow && (!no_deps || in_primary_package));
        if clippy_enabled {
            args.extend(clippy_args);
        }

        let mut clippy = ClippyCallbacks;
        let mut default = DefaultCallbacks;
        let callbacks: &mut (dyn rustc_driver::Callbacks + Send) =
            if clippy_enabled { &mut clippy } else { &mut default };

        rustc_driver::RunCompiler::new(&args, callbacks).run()
    }))
}
<|endoftext|>


<commit_before>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use url;
use hyper;
use serde;
use serde_json;

// use Groups;

use ::errors::*;

pub const API_VERSION: u16 = 3;

#[derive(Default, Clone, Copy, Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Default)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    url: Option<url::Url>,
    private_token: String,
    pagination: Option<Pagination>,
    client: hyper::Client,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
               self.pagination)
    }
}

impl GitLab {
    pub fn _new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        let mut url = url::Url::parse(&format!("{}://{}/api/v{}/", scheme, domain, API_VERSION))
                                .unwrap();
        url.set_port(Some(port)).unwrap();
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            url: Some(url),
            private_token: private_token.to_string(),
            pagination: None,
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                }
                Err(_) => hyper::Client::new(),
            },
        }
    }

    pub fn new_insecure(domain: &str, private_token: &str) -> GitLab {
        warn!("Using insecure http:// protocol: Token will be sent in clear!");
        GitLab::_new("http", domain, 80, private_token)
    }

    pub fn new(domain: &str, private_token: &str) -> GitLab {
        GitLab::_new("https", domain, 443, private_token)
    }

    pub fn port(mut self, port: u16) -> Self {
        self.port = port;
        self.url.as_mut().map(|url| url.set_port(Some(port)));
        self
    }

    pub fn scheme(mut self, scheme: &str) -> Self {
        self.scheme = scheme.to_string();
        self.url.as_mut().map(|url| url.set_scheme(scheme));
        self
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com\
    ///                     /api/v3/groups?order_by=path&private_token=XXXXXXXXXXXXX";
    ///
    /// let gl = GitLab::new("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> String {
        let mut new_url = self.url.clone().unwrap().join(query).unwrap();
        new_url.query_pairs_mut().append_pair("private_token", &self.private_token);
        self.pagination.as_ref().map(|pagination| {
            new_url.query_pairs_mut().append_pair("page", &pagination.page.to_string());
            new_url.query_pairs_mut().append_pair("per_page", &pagination.per_page.to_string());
        });

        new_url.into_string()
    }

    // pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
    //     let url = self.build_url("version");
    //     // Close connections after each GET.
    //     self.client.get(&url).header(hyper::header::Connection::close()).send()
    // }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = Some(pagination);
    }

    pub fn get<T>(&self, query: &str) -> Result<T>
        where T: serde::Deserialize
    {
        let url = self.build_url(query);
        info!("url: {:?}", url);

        // Close connections after each GET.
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .chain_err(|| format!("cannot send request '{}' to {:?}", query, self))?;
        info!("res.status: {:?}", res.status);
        debug!("res.headers: {:?}", res.headers);
        debug!("res.url: {:?}", res.url);

        let mut body = String::new();
        res.read_to_string(&mut body).chain_err(|| "cannot read response body")?;
        debug!("body:\n{:?}", body);

        // assert_eq!(res.status, hyper::status::StatusCode::Ok);
        if res.status != hyper::status::StatusCode::Ok {
            bail!(format!("status code ({}) not Ok()", res.status));
        }

        serde_json::from_str(body.as_str()).chain_err(|| format!("cannot build Rust struct from JSON data: {}", body))
    }

    pub fn version(&self) -> Result<::Version> {
        self.get("version").chain_err(|| "cannot query 'version'")
    }

    pub fn groups(&self) -> ::groups::GroupsLister {
        ::groups::GroupsLister::new(self)
    }

    pub fn projects(&self) -> ::projects::ProjectsLister {
        ::projects::ProjectsLister::new(self)
    }

    pub fn issues(&self) -> ::issues::IssuesLister {
        ::issues::IssuesLister::new(self)
    }

    pub fn merge_requests(&self, project_id: i64) -> ::merge_requests::MergeRequestsLister {
        ::merge_requests::MergeRequestsLister::new(self, project_id)
    }

    // pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
    //     let query = listing.build_query();
    //     // self.get(&query)
    //     unimplemented!();
    // }

    // pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
    //     let query = ::groups::owned_groups::Listing::new().build_query();
    //     info!("query: {:?}", query);
    //     self.get(&query)
    // }
}

// #[cfg(test)]
// mod tests {
//
// #[test]
// fn it_works() {
// }
// }
//
<commit_msg>Use error-chain for `GitLab::build_url()`<commit_after>
use std::fmt;
use std::io::Read;  // Trait providing read_to_string()
use std::env;

use url;
use hyper;
use serde;
use serde_json;

// use Groups;

use ::errors::*;

pub const API_VERSION: u16 = 3;

#[derive(Default, Clone, Copy, Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Default)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    url: Option<url::Url>,
    private_token: String,
    pagination: Option<Pagination>,
    client: hyper::Client,
}

// Explicitly implement Debug trait for GitLab so we can hide the token.
impl fmt::Debug for GitLab {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "GitLab {{ scheme: {}, domain: {}, port: {}, private_token: XXXXXXXXXXXXXXXXXXXX, \
                pagination: {:?} }}",
               self.scheme,
               self.domain,
               self.port,
               self.pagination)
    }
}

impl GitLab {
    pub fn _new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        let mut url = url::Url::parse(&format!("{}://{}/api/v{}/", scheme, domain, API_VERSION))
                                .unwrap();
        url.set_port(Some(port)).unwrap();
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port: port,
            url: Some(url),
            private_token: private_token.to_string(),
            pagination: None,
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                }
                Err(_) => hyper::Client::new(),
            },
        }
    }

    pub fn new_insecure(domain: &str, private_token: &str) -> GitLab {
        warn!("Using insecure http:// protocol: Token will be sent in clear!");
        GitLab::_new("http", domain, 80, private_token)
    }

    pub fn new(domain: &str, private_token: &str) -> GitLab {
        GitLab::_new("https", domain, 443, private_token)
    }

    pub fn port(mut self, port: u16) -> Self {
        self.port = port;
        self.url.as_mut().map(|url| url.set_port(Some(port)));
        self
    }

    pub fn scheme(mut self, scheme: &str) -> Self {
        self.scheme = scheme.to_string();
        self.url.as_mut().map(|url| url.set_scheme(scheme));
        self
    }

    /// Build a URL used to access GitLab instance, including some parameters.
    ///
    /// # Examples
    ///
    /// Example from GitLab: https://docs.gitlab.com/ce/api/#basic-usage
    ///
    /// ```
    /// use gitlab_api::GitLab;
    ///
    /// let expected_url = "https://gitlab.example.com\
    ///                     /api/v3/groups?order_by=path&private_token=XXXXXXXXXXXXX";
    ///
    /// let gl = GitLab::new("gitlab.example.com", "XXXXXXXXXXXXX");
    ///
    /// assert_eq!(gl.build_url("groups?order_by=path"), expected_url);
    /// ```
    pub fn build_url(&self, query: &str) -> Result<String> {
        let mut new_url =
            self.url.clone().chain_err(|| "failure to clone URL").join(query).chain_err(|| {
                format!("Failure to join query '{}' to url {}",
                        query,
                        self.url.as_str())
            });
        new_url.query_pairs_mut().append_pair("private_token", &self.private_token);
        self.pagination.as_ref().map(|pagination| {
            new_url.query_pairs_mut().append_pair("page", &pagination.page.to_string());
            new_url.query_pairs_mut().append_pair("per_page", &pagination.per_page.to_string());
        });

        Ok(new_url.into_string())
    }

    // pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
    //     let url = self.build_url("version");
    //     // Close connections after each GET.
    //     self.client.get(&url).header(hyper::header::Connection::close()).send()
    // }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = Some(pagination);
    }

    pub fn get<T>(&self, query: &str) -> Result<T>
        where T: serde::Deserialize
    {
        let url = self.build_url(query);
        info!("url: {:?}", url);

        // Close connections after each GET.
        let mut res: hyper::client::Response = self.client
            .get(&url)
            .header(hyper::header::Connection::close())
            .send()
            .chain_err(|| format!("cannot send request '{}' to {:?}", query, self))?;
        info!("res.status: {:?}", res.status);
        debug!("res.headers: {:?}", res.headers);
        debug!("res.url: {:?}", res.url);

        let mut body = String::new();
        res.read_to_string(&mut body).chain_err(|| "cannot read response body")?;
        debug!("body:\n{:?}", body);

        // assert_eq!(res.status, hyper::status::StatusCode::Ok);
        if res.status != hyper::status::StatusCode::Ok {
            bail!(format!("status code ({}) not Ok()", res.status));
        }

        serde_json::from_str(body.as_str()).chain_err(|| format!("cannot build Rust struct from JSON data: {}", body))
    }

    pub fn version(&self) -> Result<::Version> {
        self.get("version").chain_err(|| "cannot query 'version'")
    }

    pub fn groups(&self) -> ::groups::GroupsLister {
        ::groups::GroupsLister::new(self)
    }

    pub fn projects(&self) -> ::projects::ProjectsLister {
        ::projects::ProjectsLister::new(self)
    }

    pub fn issues(&self) -> ::issues::IssuesLister {
        ::issues::IssuesLister::new(self)
    }

    pub fn merge_requests(&self, project_id: i64) -> ::merge_requests::MergeRequestsLister {
        ::merge_requests::MergeRequestsLister::new(self, project_id)
    }

    // pub fn groups(&mut self, listing: ::groups::Listing) -> Result<Groups, serde_json::Error> {
    //     let query = listing.build_query();
    //     // self.get(&query)
    //     unimplemented!();
    // }

    // pub fn owned_groups(&mut self) -> Result<Groups, serde_json::Error> {
    //     let query = ::groups::owned_groups::Listing::new().build_query();
    //     info!("query: {:?}", query);
    //     self.get(&query)
    // }
}

// #[cfg(test)]
// mod tests {
//
// #[test]
// fn it_works() {
// }
// }
//
<|endoftext|>


<commit_before>// http://erlang.org/doc/apps/erts/erl_dist_protocol.html
extern crate erl_dist;
extern crate fibers;
extern crate futures;
extern crate handy_async;
extern crate clap;

use clap::{App, Arg, SubCommand};
use fibers::Executor;

fn main() {
    let matches = App::new("epmd_cli")
        .arg(Arg::with_name("EPMD_HOST").short("h").takes_value(true).default_value("127.0.0.1"))
        .arg(Arg::with_name("EPMD_PORT").short("p").takes_value(true).default_value("4369"))
        .subcommand(SubCommand::with_name("names"))
        .subcommand(SubCommand::with_name("dump"))
        .subcommand(SubCommand::with_name("port_please")
            .arg(Arg::with_name("NODE").index(1).required(true)))
        .subcommand(SubCommand::with_name("kill"))
        .subcommand(SubCommand::with_name("register")
            .arg(Arg::with_name("NAME").index(1).required(true))
            .arg(Arg::with_name("PORT").index(2).required(true))
            .arg(Arg::with_name("HIDDEN").long("hidden")))
        .get_matches();
    let epmd_host = matches.value_of("EPMD_HOST").unwrap();
    let epmd_port = matches.value_of("EPMD_PORT").unwrap();
    let epmd_addr = format!("{}:{}", epmd_host, epmd_port).parse().expect("Invalid epmd address");

    let client = erl_dist::epmd::EpmdClient::new(epmd_addr);
    let mut executor = fibers::InPlaceExecutor::new().unwrap();

    if let Some(_matches) = matches.subcommand_matches("names") {
        let monitor = executor.spawn_monitor(client.get_names());
        let names = executor.run_fiber(monitor).unwrap().expect("'names' request failed");
        println!("Registered Names");
        println!("================\n");
        println!("{:?}", names);
    } else if let Some(_matches) = matches.subcommand_matches("dump") {
        let monitor = executor.spawn_monitor(client.dump());
        let dump = executor.run_fiber(monitor).unwrap().expect("'dump' request failed");
        println!("Dump");
        println!("=====\n");
        println!("{:?}", dump);
    } else if let Some(matches) = matches.subcommand_matches("port_please") {
        let node = matches.value_of("NODE").unwrap();
        let monitor = executor.spawn_monitor(client.get_node_info(node));
        let info = executor.run_fiber(monitor).unwrap().expect("'port_please' request failed");
        println!("Node Info");
        println!("=========\n");
        println!("{:?}", info);
    } else if let Some(_matches) = matches.subcommand_matches("kill") {
        let monitor = executor.spawn_monitor(client.kill());
        let result = executor.run_fiber(monitor).unwrap().expect("'kill' request failed");
        println!("KILLED: {:?}", result);
    } else if let Some(matches) = matches.subcommand_matches("register") {
        let name = matches.value_of("NAME").unwrap();
        let port = matches.value_of("PORT").unwrap().parse().expect("Invalid port number");
        let hidden = matches.is_present("HIDDEN");
        let mut node = erl_dist::epmd::NodeInfo::new(name, port);
        if hidden {
            node.set_hidden();
        }
        let monitor = executor.spawn_monitor(client.register(node));
        let connection = executor.run_fiber(monitor).unwrap().expect("'register' request failed");
        println!("CREATION: {}", connection.creation());
    } else {
        println!("{}", matches.usage());
    }
}
<commit_msg>Rewrite epmd_cli command<commit_after>//! EPMD client example.
//!
//! # Usage Examples
//!
//! ```bash
//! $ cargo run --example epmd_cli -- --help
//! $ cargo run --example epmd_cli names
//! $ cargo run --example epmd_cli node_info foo
//! ```
extern crate erl_dist;
extern crate fibers;
extern crate futures;
extern crate clap;

use clap::{App, Arg, SubCommand};
use fibers::{Executor, InPlaceExecutor};
use fibers::net::TcpStream;
use futures::Future;
use erl_dist::EpmdClient;
use erl_dist::epmd::NodeInfo;

fn main() {
    let matches = App::new("epmd_cli")
        .arg(Arg::with_name("EPMD_HOST").short("h").takes_value(true).default_value("127.0.0.1"))
        .arg(Arg::with_name("EPMD_PORT").short("p").takes_value(true).default_value("4369"))
        .subcommand(SubCommand::with_name("names"))
        .subcommand(SubCommand::with_name("dump"))
        .subcommand(SubCommand::with_name("node_info")
            .arg(Arg::with_name("NODE").index(1).required(true)))
        .subcommand(SubCommand::with_name("kill"))
        .subcommand(SubCommand::with_name("register")
            .arg(Arg::with_name("NAME").index(1).required(true))
            .arg(Arg::with_name("PORT").index(2).required(true))
            .arg(Arg::with_name("HIDDEN").long("hidden")))
        .get_matches();
    let epmd_host = matches.value_of("EPMD_HOST").unwrap();
    let epmd_port = matches.value_of("EPMD_PORT").unwrap();
    let epmd_addr = format!("{}:{}", epmd_host, epmd_port).parse().expect("Invalid epmd address");

    let client = EpmdClient::new();
    let mut executor = InPlaceExecutor::new().unwrap();

    let connect = TcpStream::connect(epmd_addr);
    if let Some(_matches) = matches.subcommand_matches("names") {
        // 'NAMES_REQ'
        //
        let monitor =
            executor.spawn_monitor(connect.and_then(move |socket| client.get_names(socket)));
        let names = executor.run_fiber(monitor).unwrap().expect("'names' request failed");
        println!("Registered Names");
        println!("================\n");
        println!("{:?}", names);
    } else if let Some(_matches) = matches.subcommand_matches("dump") {
        // 'DUMP_REQ'
        //
        let monitor = executor.spawn_monitor(connect.and_then(move |socket| client.dump(socket)));
        let dump = executor.run_fiber(monitor).unwrap().expect("'dump' request failed");
        println!("Dump");
        println!("=====\n");
        println!("{:?}", dump);
    } else if let Some(matches) = matches.subcommand_matches("node_info") {
        // 'PORT_PLEASE2_REQ'
        //
        let node = matches.value_of("NODE").unwrap().to_string();
        let monitor =
            executor.spawn_monitor(connect.and_then(move |socket| {
                    client.get_node_info(socket, &node)
                }));
        let info = executor.run_fiber(monitor).unwrap().expect("'node_info' request failed");
        println!("Node Info");
        println!("=========\n");
        println!("{:?}", info);
    } else if let Some(_matches) = matches.subcommand_matches("kill") {
        // 'KILL_REQ'
        //
        let monitor = executor.spawn_monitor(connect.and_then(move |socket| client.kill(socket)));
        let result = executor.run_fiber(monitor).unwrap().expect("'kill' request failed");
        println!("KILLED: {:?}", result);
    } else if let Some(matches) = matches.subcommand_matches("register") {
        // 'ALIVE2_REQ'
        //
        let name = matches.value_of("NAME").unwrap();
        let port = matches.value_of("PORT").unwrap().parse().expect("Invalid port number");
        let hidden = matches.is_present("HIDDEN");
        let mut node = NodeInfo::new(name, port);
        if hidden {
            node.set_hidden();
        }
        let monitor =
            executor.spawn_monitor(connect.and_then(move |socket| client.register(socket, node)));
        let (_, creation) =
            executor.run_fiber(monitor).unwrap().expect("'register' request failed");
        println!("CREATION: {:?}", creation);
    } else {
        println!("{}", matches.usage());
    }
}
<|endoftext|>


<commit_before>
use BuildQuery;
use Groups;

// https://docs.gitlab.com/ce/api/groups.html
// List groups:                 GET /groups
// List owned groups:           GET /groups/owned
// List a group's projects:     GET /groups/:id/projects
// Details of a group:          GET /groups/:id
// New group:                   POST /groups
// Transfer project to group:   POST  /groups/:id/projects/:project_id
// Update group:                PUT /groups/:id
// Remove group:                DELETE /groups/:id
// Search for group:            GET /groups?search=foobar

// https://docs.gitlab.com/ce/api/groups.html#list-groups

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsOrderBy {
    Name,
    Path,
}

// impl Default for GroupListerOptionsOrderBy {
//     fn default() -> GroupListerOptionsOrderBy { GroupListerOptionsOrderBy::Name }
// }

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsSort {
    Asc,
    Desc,
}

// impl Default for GroupListerOptionsSort {
//     fn default() -> GroupListerOptionsSort { GroupListerOptionsSort::Asc }
// }

fn append_group_lister_options_order_by(order_by: GroupListerOptionsOrderBy, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsOrderBy::Name => "name",
        GroupListerOptionsOrderBy::Path => "path",
    });
}

fn append_group_lister_options_sort(order_by: GroupListerOptionsSort, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsSort::Asc => "asc",
        GroupListerOptionsSort::Desc => "desc",
    });
}

/// https://docs.gitlab.com/ce/api/groups.html#list-groups
#[derive(Default, Debug)]
struct GroupListerOptions {
    /// Skip the group IDs passes
    pub skip_groups: Option<Vec<i64>>,
    /// Show all the groups you have access to
    pub all_available: Option<bool>,
    /// Return list of authorized groups matching the search criteria
    pub search: Option<String>,
    /// Order groups by `name` or `path`. Default is `name`
    pub order_by: Option<GroupListerOptionsOrderBy>,
    /// Order groups in `asc` or `desc` order. Default is `asc`
    pub sort: Option<GroupListerOptionsSort>,
}

#[derive(Default, Debug)]
pub struct GroupListing {
    options: GroupListerOptions,
}

impl BuildQuery for GroupListing {
    fn build_query(&self) -> String {
        let options = &self.options;

        let mut query = String::from("groups");

        // Append a "?", only if one of the `Option` is `Some(_)`
        query.push_str(match (&options.skip_groups,
                              &options.all_available,
                              &options.search,
                              &options.order_by,
                              &options.sort) {
            (&None, &None, &None, &None, &None) => "",
            _ => "?",
        });

        options.all_available.map(|all_available| {
            if all_available {
                query.push_str("all_available=true")
            } else {
                query.push_str("all_available=false")
            }
        });

        options.order_by.map(|order_by| {
            query.push_str("order_by=");
            append_group_lister_options_order_by(order_by, &mut query);
        });

        query
    }
}

impl GroupListing {
    fn list(&self) -> Groups {
        let groups: Groups = vec![];

        groups
    }
}

#[test]
fn test_append_group_lister_options_order_by() {
    let expected_string = "Initialnamepathpathname";

    let mut s = String::from("Initial");

    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn test_append_group_lister_options_sort() {
    let expected_string = "Initialascdescascdesc";

    let mut s = String::from("Initial");

    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn groups_build_query() {

    let expected_string = "groups";
    let listing: GroupListing = Default::default();
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups";
    let listing = GroupListing { options: Default::default() };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?order_by=name";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Name),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}
<commit_msg>Include all options in `build_query()` except `skip_groups`<commit_after>
use BuildQuery;
use Groups;

// https://docs.gitlab.com/ce/api/groups.html
// List groups:                 GET /groups
// List owned groups:           GET /groups/owned
// List a group's projects:     GET /groups/:id/projects
// Details of a group:          GET /groups/:id
// New group:                   POST /groups
// Transfer project to group:   POST  /groups/:id/projects/:project_id
// Update group:                PUT /groups/:id
// Remove group:                DELETE /groups/:id
// Search for group:            GET /groups?search=foobar

// https://docs.gitlab.com/ce/api/groups.html#list-groups

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsOrderBy {
    Name,
    Path,
}

// impl Default for GroupListerOptionsOrderBy {
//     fn default() -> GroupListerOptionsOrderBy { GroupListerOptionsOrderBy::Name }
// }

#[derive(Debug, Copy, Clone)]
enum GroupListerOptionsSort {
    Asc,
    Desc,
}

// impl Default for GroupListerOptionsSort {
//     fn default() -> GroupListerOptionsSort { GroupListerOptionsSort::Asc }
// }

fn append_group_lister_options_order_by(order_by: GroupListerOptionsOrderBy, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsOrderBy::Name => "name",
        GroupListerOptionsOrderBy::Path => "path",
    });
}

fn append_group_lister_options_sort(order_by: GroupListerOptionsSort, s: &mut String) {
    s.push_str(match order_by {
        GroupListerOptionsSort::Asc => "asc",
        GroupListerOptionsSort::Desc => "desc",
    });
}

/// https://docs.gitlab.com/ce/api/groups.html#list-groups
#[derive(Default, Debug)]
struct GroupListerOptions {
    /// Skip the group IDs passes
    pub skip_groups: Option<Vec<i64>>,
    /// Show all the groups you have access to
    pub all_available: Option<bool>,
    /// Return list of authorized groups matching the search criteria
    pub search: Option<String>,
    /// Order groups by `name` or `path`. Default is `name`
    pub order_by: Option<GroupListerOptionsOrderBy>,
    /// Order groups in `asc` or `desc` order. Default is `asc`
    pub sort: Option<GroupListerOptionsSort>,
}

#[derive(Default, Debug)]
pub struct GroupListing {
    options: GroupListerOptions,
}

impl BuildQuery for GroupListing {
    fn build_query(&self) -> String {

        let mut query = String::from("groups");

        let options = &self.options;

        // FIXME: Add skip_groups

        // Append a "?", only if one of the `Option` is `Some(_)`
        query.push_str(match (&options.skip_groups,
                              &options.all_available,
                              &options.search,
                              &options.order_by,
                              &options.sort) {
            (&None, &None, &None, &None, &None) => "",
            _ => "?",
        });

        options.all_available.map(|all_available| {
            if all_available {
                query.push_str("all_available=true")
            } else {
                query.push_str("all_available=false")
            }
        });

        options.search.as_ref().map(|search| {
            query.push_str("search=");
            query.push_str(search);
        });

        options.order_by.map(|order_by| {
            query.push_str("order_by=");
            append_group_lister_options_order_by(order_by, &mut query);
        });

        options.sort.map(|sort| {
            query.push_str("sort=");
            append_group_lister_options_sort(sort, &mut query);
        });

        query
    }
}

impl GroupListing {
    fn list(&self) -> Groups {
        let groups: Groups = vec![];

        groups
    }
}

#[test]
fn test_append_group_lister_options_order_by() {
    let expected_string = "Initialnamepathpathname";

    let mut s = String::from("Initial");

    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Path, &mut s);
    append_group_lister_options_order_by(GroupListerOptionsOrderBy::Name, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn test_append_group_lister_options_sort() {
    let expected_string = "Initialascdescascdesc";

    let mut s = String::from("Initial");

    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Asc, &mut s);
    append_group_lister_options_sort(GroupListerOptionsSort::Desc, &mut s);

    assert_eq!(s, expected_string);
}

#[test]
fn groups_build_query_default() {
    let expected_string = "groups";
    let listing: GroupListing = Default::default();
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups";
    let listing = GroupListing { options: Default::default() };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

// FIXME: Add for 'skip_groups'

#[test]
fn groups_build_query_all_available() {
    let expected_string = "groups?all_available=true";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(true),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?all_available=false";
    let listing = GroupListing {
        options: GroupListerOptions {
            all_available: Some(false),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_search() {
    let expected_string = "groups?search=SearchPattern";
    let listing = GroupListing {
        options: GroupListerOptions {
            search: Some(String::from("SearchPattern")),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_name() {
    let expected_string = "groups?order_by=name";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Name),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_order_by_path() {
    let expected_string = "groups?order_by=path";
    let listing = GroupListing {
        options: GroupListerOptions {
            order_by: Some(GroupListerOptionsOrderBy::Path),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}

#[test]
fn groups_build_query_sort() {
    let expected_string = "groups?sort=asc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Asc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);

    let expected_string = "groups?sort=desc";
    let listing = GroupListing {
        options: GroupListerOptions {
            sort: Some(GroupListerOptionsSort::Desc),
            ..Default::default()
        },
    };
    let query = listing.build_query();
    assert_eq!(query, expected_string);
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::cmp::Ordering;

struct PhantomVertex;
pub struct PhantomFace;
pub struct PhantomEdge;
pub struct PhantomHalfedge;
pub type Vertex = BaseHandle<PhantomVertex>;
pub type Face = BaseHandle<PhantomFace>;
pub type Edge = BaseHandle<PhantomEdge>;
pub type Halfedge = BaseHandle<PhantomHalfedge>;

pub struct BaseHandle<A> {
    type_ : PhantomData<A>,
    index_ : Option<u32>,
}

impl<A> BaseHandle<A> {
    pub fn invalid() -> BaseHandle<A> {
        BaseHandle {
            type_ : PhantomData,
            index_ : None,
        }
    }

    pub fn new(idx : u32) -> BaseHandle<A> {
        BaseHandle {
            type_ : PhantomData,
            index_ : Some(idx),
        }
    }

    pub fn idx(&self) -> Option<u32> {
        self.index_
    }

    pub fn reset(&mut self) {
        self.index_ = None;
    }

    pub fn is_valid(&self) -> bool {
        self.index_.is_some()
    }
}

impl<A> Ord for BaseHandle<A> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.index_.cmp(&other.index_)
    }
}

impl<A> PartialOrd for BaseHandle<A> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.index_.cmp(&other.index_))
    }
}

impl<A> PartialEq for BaseHandle<A> {
    fn eq(&self, other: &Self) -> bool {
        self.index_ == other.index_
    }
}
impl<A> Eq for BaseHandle<A> { }

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

    #[test]
    fn base_handle_invalid() {
        let handle : BaseHandle<Vertex> = BaseHandle::invalid();
        assert!(!handle.is_valid());
        assert!(handle.idx().is_none());
    }

    #[test]
    fn base_handle_idx() {
        let idx = 42;
        let handle : BaseHandle<Vertex> = BaseHandle::new(idx);
        assert!(handle.is_valid());

        assert!(handle.idx().is_some());
        assert!(handle.idx().unwrap() == idx);
    }

    #[test]
    fn base_handle_reset() {
        let idx = 42;
        let mut handle : BaseHandle<Vertex> = BaseHandle::new(idx);
        assert!(handle.is_valid());

        handle.reset();
        assert!(!handle.is_valid());
    }

    #[test]
    fn base_handle_cmp() {
        let idx1 = 42;
        let idx2 = 13;
        let h1 : BaseHandle<Vertex> = BaseHandle::new(idx1);
        let h2 : BaseHandle<Vertex> = BaseHandle::new(idx2);
        let h3 : BaseHandle<Vertex> = BaseHandle::new(idx1);

        assert!(h1!=h2);
        assert!(h1>h2);
        assert!(h2<h1);
        assert!(h1==h3);
        assert!(h1<=h3);
        assert_eq!(h2.cmp(&h1), Ordering::Less);
        assert_eq!(h1.cmp(&h2), Ordering::Greater);
        assert_eq!(h1.cmp(&h3), Ordering::Equal);
    }
}
<commit_msg>Set BaseHandle to private<commit_after>use std::marker::PhantomData;
use std::cmp::Ordering;

struct PhantomVertex;
struct PhantomFace;
struct PhantomEdge;
struct PhantomHalfedge;
pub type Vertex = BaseHandle<PhantomVertex>;
pub type Face = BaseHandle<PhantomFace>;
pub type Edge = BaseHandle<PhantomEdge>;
pub type Halfedge = BaseHandle<PhantomHalfedge>;

struct BaseHandle<A> {
    type_ : PhantomData<A>,
    index_ : Option<u32>,
}

impl<A> BaseHandle<A> {
    pub fn invalid() -> BaseHandle<A> {
        BaseHandle {
            type_ : PhantomData,
            index_ : None,
        }
    }

    pub fn new(idx : u32) -> BaseHandle<A> {
        BaseHandle {
            type_ : PhantomData,
            index_ : Some(idx),
        }
    }

    pub fn idx(&self) -> Option<u32> {
        self.index_
    }

    pub fn reset(&mut self) {
        self.index_ = None;
    }

    pub fn is_valid(&self) -> bool {
        self.index_.is_some()
    }
}

impl<A> Ord for BaseHandle<A> {
    fn cmp(&self, other: &Self) -> Ordering {
        self.index_.cmp(&other.index_)
    }
}

impl<A> PartialOrd for BaseHandle<A> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.index_.cmp(&other.index_))
    }
}

impl<A> PartialEq for BaseHandle<A> {
    fn eq(&self, other: &Self) -> bool {
        self.index_ == other.index_
    }
}
impl<A> Eq for BaseHandle<A> { }

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

    #[test]
    fn base_handle_invalid() {
        let handle : Vertex = Vertex::invalid();
        assert!(!handle.is_valid());
        assert!(handle.idx().is_none());
    }

    #[test]
    fn base_handle_idx() {
        let idx = 42;
        let handle : Vertex = Vertex::new(idx);
        assert!(handle.is_valid());

        assert!(handle.idx().is_some());
        assert!(handle.idx().unwrap() == idx);
    }

    #[test]
    fn base_handle_reset() {
        let idx = 42;
        let mut handle : Vertex = Vertex::new(idx);
        assert!(handle.is_valid());

        handle.reset();
        assert!(!handle.is_valid());
    }

    #[test]
    fn base_handle_cmp() {
        let idx1 = 42;
        let idx2 = 13;
        let h1 : Vertex = Vertex::new(idx1);
        let h2 : Vertex = Vertex::new(idx2);
        let h3 : Vertex = Vertex::new(idx1);

        assert!(h1!=h2);
        assert!(h1>h2);
        assert!(h2<h1);
        assert!(h1==h3);
        assert!(h1<=h3);
        assert_eq!(h2.cmp(&h1), Ordering::Less);
        assert_eq!(h1.cmp(&h2), Ordering::Greater);
        assert_eq!(h1.cmp(&h3), Ordering::Equal);
    }
}
<|endoftext|>


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

//! Implementations of serialization for structures found in libcollections

use std::hash::Hash;

use {Decodable, Encodable, Decoder, Encoder};
use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet};

impl<
    T: Encodable
> Encodable for LinkedList<T> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_seq(self.len(), |s| {
            for (i, e) in self.iter().enumerate() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
            }
            Ok(())
        })
    }
}

impl<T:Decodable> Decodable for LinkedList<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<LinkedList<T>, D::Error> {
        d.read_seq(|d, len| {
            let mut list = LinkedList::new();
            for i in 0..len {
                list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(list)
        })
    }
}

impl<T: Encodable> Encodable for VecDeque<T> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_seq(self.len(), |s| {
            for (i, e) in self.iter().enumerate() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
            }
            Ok(())
        })
    }
}

impl<T:Decodable> Decodable for VecDeque<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<VecDeque<T>, D::Error> {
        d.read_seq(|d, len| {
            let mut deque: VecDeque<T> = VecDeque::new();
            for i in 0..len {
                deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(deque)
        })
    }
}

impl<
    K: Encodable + PartialEq + Ord,
    V: Encodable + PartialEq
> Encodable for BTreeMap<K, V> {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    K: Decodable + PartialEq + Ord,
    V: Decodable + PartialEq
> Decodable for BTreeMap<K, V> {
    fn decode<D: Decoder>(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
        d.read_map(|d, len| {
            let mut map = BTreeMap::new();
            for i in 0..len {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<
    T: Encodable + PartialEq + Ord
> Encodable for BTreeSet<T> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    T: Decodable + PartialEq + Ord
> Decodable for BTreeSet<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
        d.read_seq(|d, len| {
            let mut set = BTreeSet::new();
            for i in 0..len {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}

impl<K, V> Encodable for HashMap<K, V>
    where K: Encodable + Hash + Eq,
          V: Encodable,
{
    fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<K, V> Decodable for HashMap<K, V>
    where K: Decodable + Hash + Eq,
          V: Decodable,
{
    fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V>, D::Error> {
        d.read_map(|d, len| {
            let mut map = HashMap::with_capacity(len);
            for i in 0..len {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<T> Encodable for HashSet<T> where T: Encodable + Hash + Eq {
    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<T> Decodable for HashSet<T> where T: Decodable + Hash + Eq, {
    fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T>, D::Error> {
        d.read_seq(|d, len| {
            let mut set = HashSet::with_capacity(len);
            for i in 0..len {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}
<commit_msg>BTree{Map,Set}s do not require PartialEq, only Ord<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations of serialization for structures found in libcollections

use std::hash::Hash;

use {Decodable, Encodable, Decoder, Encoder};
use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet};

impl<
    T: Encodable
> Encodable for LinkedList<T> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_seq(self.len(), |s| {
            for (i, e) in self.iter().enumerate() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
            }
            Ok(())
        })
    }
}

impl<T:Decodable> Decodable for LinkedList<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<LinkedList<T>, D::Error> {
        d.read_seq(|d, len| {
            let mut list = LinkedList::new();
            for i in 0..len {
                list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(list)
        })
    }
}

impl<T: Encodable> Encodable for VecDeque<T> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_seq(self.len(), |s| {
            for (i, e) in self.iter().enumerate() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
            }
            Ok(())
        })
    }
}

impl<T:Decodable> Decodable for VecDeque<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<VecDeque<T>, D::Error> {
        d.read_seq(|d, len| {
            let mut deque: VecDeque<T> = VecDeque::new();
            for i in 0..len {
                deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(deque)
        })
    }
}

impl<
    K: Encodable + Ord,
    V: Encodable
> Encodable for BTreeMap<K, V> {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    K: Decodable + Ord,
    V: Decodable
> Decodable for BTreeMap<K, V> {
    fn decode<D: Decoder>(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
        d.read_map(|d, len| {
            let mut map = BTreeMap::new();
            for i in 0..len {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<
    T: Encodable + Ord
> Encodable for BTreeSet<T> {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    T: Decodable + Ord
> Decodable for BTreeSet<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
        d.read_seq(|d, len| {
            let mut set = BTreeSet::new();
            for i in 0..len {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}

impl<K, V> Encodable for HashMap<K, V>
    where K: Encodable + Hash + Eq,
          V: Encodable,
{
    fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<K, V> Decodable for HashMap<K, V>
    where K: Decodable + Hash + Eq,
          V: Decodable,
{
    fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V>, D::Error> {
        d.read_map(|d, len| {
            let mut map = HashMap::with_capacity(len);
            for i in 0..len {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<T> Encodable for HashSet<T> where T: Encodable + Hash + Eq {
    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<T> Decodable for HashSet<T> where T: Decodable + Hash + Eq, {
    fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T>, D::Error> {
        d.read_seq(|d, len| {
            let mut set = HashSet::with_capacity(len);
            for i in 0..len {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}
<|endoftext|>


<commit_before>//! System tests for compiling Rust code with cargo.
//!
//! Any copyright is dedicated to the Public Domain.
//! http://creativecommons.org/publicdomain/zero/1.0/

extern crate assert_cli;
extern crate chrono;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate tempdir;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

use assert_cli::{Assert, Environment};
use env_logger::LogBuilder;
use chrono::Local;
use tempdir::TempDir;

fn find_sccache_binary() -> PathBuf {
    // Older versions of cargo put the test binary next to the sccache binary.
    // Newer versions put it in the deps/ subdirectory.
    let exe = env::current_exe().unwrap();
    let this_dir = exe.parent().unwrap();
    let dirs = &[&this_dir, &this_dir.parent().unwrap()];
    dirs
        .iter()
        .map(|d| d.join("sccache").with_extension(env::consts::EXE_EXTENSION))
        .filter_map(|d| fs::metadata(&d).ok().map(|_| d))
        .next()
        .expect(&format!("Error: sccache binary not found, looked in `{:?}`. Do you need to run `cargo build`?", dirs))
}

fn stop(sccache: &Path) {
    //TODO: should be able to use Assert::ignore_status when that is released.
    let output = Command::new(&sccache)
        .arg("--stop-server")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .output()
        .unwrap();
    trace!("stop-server returned {}", output.status);
}

/// Test that building a simple Rust crate with cargo using sccache results in a cache hit
/// when built a second time.
#[test]
fn test_rust_cargo() {
    drop(LogBuilder::new()
         .format(|record| {
             format!("{} [{}] - {}",
                     Local::now().format("%Y-%m-%dT%H:%M:%S%.3f"),
                     record.level(),
                     record.args())
         })
        .parse(&env::var("RUST_LOG").unwrap_or_default())
        .init());
    let cargo = env!("CARGO");
    debug!("cargo: {}", cargo);
    let sccache = find_sccache_binary();
    debug!("sccache: {:?}", sccache);
    let crate_dir = Path::new(file!()).parent().unwrap().join("test-crate");
    // Ensure there's no existing sccache server running.
    trace!("sccache --stop-server");
    stop(&sccache);
    // Create a temp directory to use for the disk cache.
    let tempdir = TempDir::new("sccache_test_rust_cargo").unwrap();
    let cache_dir = tempdir.path().join("cache");
    fs::create_dir(&cache_dir).unwrap();
    let cargo_dir = tempdir.path().join("cargo");
    fs::create_dir(&cargo_dir).unwrap();
    let env = Environment::inherit().insert("SCCACHE_DIR", &cache_dir);
    // Start a new sccache server.
    trace!("sccache --start-server");
    Assert::command(&[&sccache.to_string_lossy()])
        .with_args(&["--start-server"]).with_env(env).succeeds().unwrap();
    // `cargo clean` first, just to be sure there's no leftover build objects.
    let env = Environment::inherit()
        .insert("RUSTC_WRAPPER", &sccache)
        .insert("CARGO_TARGET_DIR", &cargo_dir);
    let a = Assert::command(&[&cargo])
        .with_args(&["clean"]).with_env(&env).current_dir(&crate_dir).succeeds();
    trace!("cargo clean: {:?}", a);
    a.unwrap();
    // Now build the crate with cargo.
    let a = Assert::command(&[&cargo])
        .with_args(&["build"]).with_env(&env).current_dir(&crate_dir).succeeds();
    trace!("cargo build: {:?}", a);
    a.unwrap();
    // Clean it so we can build it again.
    let a = Assert::command(&[&cargo])
        .with_args(&["clean"]).with_env(&env).current_dir(&crate_dir).succeeds();
    trace!("cargo clean: {:?}", a);
    a.unwrap();
    let a = Assert::command(&[&cargo])
        .with_args(&["build"]).with_env(&env).current_dir(&crate_dir).succeeds();
    trace!("cargo build: {:?}", a);
    a.unwrap();
    // Now get the stats and ensure that we had a cache hit for the second build.
    trace!("sccache --show-stats");
    Assert::command(&[&sccache.to_string_lossy()])
        .with_args(&["--show-stats", "--stats-format=json"])
        .stdout().contains(r#""cache_hits":1"#).succeeds().execute()
        .expect("Should have had 1 cache hit");
    trace!("sccache --stop-server");
    stop(&sccache);
}
<commit_msg>Skip failing cargo integration test on macos for now<commit_after>//! System tests for compiling Rust code with cargo.
//!
//! Any copyright is dedicated to the Public Domain.
//! http://creativecommons.org/publicdomain/zero/1.0/

extern crate assert_cli;
extern crate chrono;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate tempdir;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

use assert_cli::{Assert, Environment};
use env_logger::LogBuilder;
use chrono::Local;
use tempdir::TempDir;

fn find_sccache_binary() -> PathBuf {
    // Older versions of cargo put the test binary next to the sccache binary.
    // Newer versions put it in the deps/ subdirectory.
    let exe = env::current_exe().unwrap();
    let this_dir = exe.parent().unwrap();
    let dirs = &[&this_dir, &this_dir.parent().unwrap()];
    dirs
        .iter()
        .map(|d| d.join("sccache").with_extension(env::consts::EXE_EXTENSION))
        .filter_map(|d| fs::metadata(&d).ok().map(|_| d))
        .next()
        .expect(&format!("Error: sccache binary not found, looked in `{:?}`. Do you need to run `cargo build`?", dirs))
}

fn stop(sccache: &Path) {
    //TODO: should be able to use Assert::ignore_status when that is released.
    let output = Command::new(&sccache)
        .arg("--stop-server")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .output()
        .unwrap();
    trace!("stop-server returned {}", output.status);
}

/// Test that building a simple Rust crate with cargo using sccache results in a cache hit
/// when built a second time.
#[test]
#[cfg(not(target_os="macos"))] // test currently fails on macos
fn test_rust_cargo() {
    drop(LogBuilder::new()
         .format(|record| {
             format!("{} [{}] - {}",
                     Local::now().format("%Y-%m-%dT%H:%M:%S%.3f"),
                     record.level(),
                     record.args())
         })
        .parse(&env::var("RUST_LOG").unwrap_or_default())
        .init());
    let cargo = env!("CARGO");
    debug!("cargo: {}", cargo);
    let sccache = find_sccache_binary();
    debug!("sccache: {:?}", sccache);
    let crate_dir = Path::new(file!()).parent().unwrap().join("test-crate");
    // Ensure there's no existing sccache server running.
    trace!("sccache --stop-server");
    stop(&sccache);
    // Create a temp directory to use for the disk cache.
    let tempdir = TempDir::new("sccache_test_rust_cargo").unwrap();
    let cache_dir = tempdir.path().join("cache");
    fs::create_dir(&cache_dir).unwrap();
    let cargo_dir = tempdir.path().join("cargo");
    fs::create_dir(&cargo_dir).unwrap();
    let env = Environment::inherit().insert("SCCACHE_DIR", &cache_dir);
    // Start a new sccache server.
    trace!("sccache --start-server");
    Assert::command(&[&sccache.to_string_lossy()])
        .with_args(&["--start-server"]).with_env(env).succeeds().unwrap();
    // `cargo clean` first, just to be sure there's no leftover build objects.
    let env = Environment::inherit()
        .insert("RUSTC_WRAPPER", &sccache)
        .insert("CARGO_TARGET_DIR", &cargo_dir);
    let a = Assert::command(&[&cargo])
        .with_args(&["clean"]).with_env(&env).current_dir(&crate_dir).succeeds();
    trace!("cargo clean: {:?}", a);
    a.unwrap();
    // Now build the crate with cargo.
    let a = Assert::command(&[&cargo])
        .with_args(&["build"]).with_env(&env).current_dir(&crate_dir).succeeds();
    trace!("cargo build: {:?}", a);
    a.unwrap();
    // Clean it so we can build it again.
    let a = Assert::command(&[&cargo])
        .with_args(&["clean"]).with_env(&env).current_dir(&crate_dir).succeeds();
    trace!("cargo clean: {:?}", a);
    a.unwrap();
    let a = Assert::command(&[&cargo])
        .with_args(&["build"]).with_env(&env).current_dir(&crate_dir).succeeds();
    trace!("cargo build: {:?}", a);
    a.unwrap();
    // Now get the stats and ensure that we had a cache hit for the second build.
    trace!("sccache --show-stats");
    Assert::command(&[&sccache.to_string_lossy()])
        .with_args(&["--show-stats", "--stats-format=json"])
        .stdout().contains(r#""cache_hits":1"#).succeeds().execute()
        .expect("Should have had 1 cache hit");
    trace!("sccache --stop-server");
    stop(&sccache);
}
<|endoftext|>