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

// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/)

#![cfg(not(test))]
#![deny(warnings)]

extern crate cargo_metadata;
extern crate getopts;
extern crate serde_json as json;

use std::collections::{HashMap, HashSet};
use std::env;
use std::fs;
use std::hash::{Hash, Hasher};
use std::io::{self, Write};
use std::iter::FromIterator;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;

use getopts::{Matches, Options};

fn main() {
    let exit_status = execute();
    std::io::stdout().flush().unwrap();
    std::process::exit(exit_status);
}

const SUCCESS: i32 = 0;
const FAILURE: i32 = 1;

fn execute() -> i32 {
    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("q", "quiet", "no output printed to stdout");
    opts.optflag("v", "verbose", "use verbose output");
    opts.optmulti(
        "p",
        "package",
        "specify package to format (only usable in workspaces)",
        "<package>",
    );
    opts.optflag("", "version", "print rustfmt version and exit");
    opts.optflag("", "all", "format all packages (only usable in workspaces)");

    // If there is any invalid argument passed to `cargo fmt`, return without formatting.
    let mut is_package_arg = false;
    for arg in env::args().skip(2).take_while(|a| a != "--") {
        if arg.starts_with('-') {
            is_package_arg = arg.starts_with("--package");
        } else if !is_package_arg {
            print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg));
            return FAILURE;
        } else {
            is_package_arg = false;
        }
    }

    let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) {
        Ok(m) => m,
        Err(e) => {
            print_usage_to_stderr(&opts, &e.to_string());
            return FAILURE;
        }
    };

    let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) {
        (false, false) => Verbosity::Normal,
        (false, true) => Verbosity::Quiet,
        (true, false) => Verbosity::Verbose,
        (true, true) => {
            print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible");
            return FAILURE;
        }
    };

    if matches.opt_present("h") {
        print_usage_to_stdout(&opts, "");
        return SUCCESS;
    }

    if matches.opt_present("version") {
        return handle_command_status(get_version(verbosity), &opts);
    }

    let strategy = CargoFmtStrategy::from_matches(&matches);
    handle_command_status(format_crate(verbosity, &strategy), &opts)
}

macro_rules! print_usage {
    ($print:ident, $opts:ident, $reason:expr) => {{
        let msg = format!("{}\nusage: cargo fmt [options]", $reason);
        $print!(
            "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \
             Arguments after `--` are passed to rustfmt.",
            $opts.usage(&msg)
        );
    }};
}

fn print_usage_to_stdout(opts: &Options, reason: &str) {
    print_usage!(println, opts, reason);
}

fn print_usage_to_stderr(opts: &Options, reason: &str) {
    print_usage!(eprintln, opts, reason);
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Verbosity {
    Verbose,
    Normal,
    Quiet,
}

fn handle_command_status(status: Result<i32, io::Error>, opts: &getopts::Options) -> i32 {
    match status {
        Err(e) => {
            print_usage_to_stderr(opts, &e.to_string());
            FAILURE
        }
        Ok(status) => status,
    }
}

fn get_version(verbosity: Verbosity) -> Result<i32, io::Error> {
    run_rustfmt(&HashSet::new(), &[String::from("--version")], verbosity)
}

fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result<i32, io::Error> {
    let rustfmt_args = get_fmt_args();
    let targets = if rustfmt_args
        .iter()
        .any(|s| ["--print-config", "-h", "--help", "-V", "--version"].contains(&s.as_str()))
    {
        HashSet::new()
    } else {
        get_targets(strategy)?
    };

    // Currently only bin and lib files get formatted
    run_rustfmt(&targets, &rustfmt_args, verbosity)
}

fn get_fmt_args() -> Vec<String> {
    // All arguments after -- are passed to rustfmt
    env::args().skip_while(|a| a != "--").skip(1).collect()
}

/// Target uses a `path` field for equality and hashing.
#[derive(Debug)]
pub struct Target {
    /// A path to the main source file of the target.
    path: PathBuf,
    /// A kind of target (e.g. lib, bin, example, ...).
    kind: String,
    /// Rust edition for this target.
    edition: String,
}

impl Target {
    pub fn from_target(target: &cargo_metadata::Target) -> Self {
        let path = PathBuf::from(&target.src_path);
        let canonicalized = fs::canonicalize(&path).unwrap_or(path);

        Target {
            path: canonicalized,
            kind: target.kind[0].clone(),
            edition: target.edition.clone(),
        }
    }
}

impl PartialEq for Target {
    fn eq(&self, other: &Target) -> bool {
        self.path == other.path
    }
}

impl Eq for Target {}

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

#[derive(Debug, PartialEq, Eq)]
pub enum CargoFmtStrategy {
    /// Format every packages and dependencies.
    All,
    /// Format packages that are specified by the command line argument.
    Some(Vec<String>),
    /// Format the root packages only.
    Root,
}

impl CargoFmtStrategy {
    pub fn from_matches(matches: &Matches) -> CargoFmtStrategy {
        match (matches.opt_present("all"), matches.opt_present("p")) {
            (false, false) => CargoFmtStrategy::Root,
            (true, _) => CargoFmtStrategy::All,
            (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")),
        }
    }
}

/// Based on the specified `CargoFmtStrategy`, returns a set of main source files.
fn get_targets(strategy: &CargoFmtStrategy) -> Result<HashSet<Target>, io::Error> {
    let mut targets = HashSet::new();

    match *strategy {
        CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?,
        CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?,
        CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?,
    }

    if targets.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "Failed to find targets".to_owned(),
        ))
    } else {
        Ok(targets)
    }
}

fn get_targets_root_only(targets: &mut HashSet<Target>) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;
    let current_dir = env::current_dir()?.canonicalize()?;
    let current_dir_manifest = current_dir.join("Cargo.toml");
    let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?;
    let in_workspace_root = workspace_root_path == current_dir;

    for package in metadata.packages {
        if in_workspace_root || PathBuf::from(&package.manifest_path) == current_dir_manifest {
            for target in package.targets {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    Ok(())
}

fn get_targets_recursive(
    manifest_path: Option<&Path>,
    mut targets: &mut HashSet<Target>,
    visited: &mut HashSet<String>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(manifest_path)?;

    for package in metadata.packages {
        add_targets(&package.targets, &mut targets);

        // Look for local dependencies.
        for dependency in package.dependencies {
            if dependency.source.is_some() || visited.contains(&dependency.name) {
                continue;
            }

            let mut manifest_path = PathBuf::from(&package.manifest_path);

            manifest_path.pop();
            manifest_path.push(&dependency.name);
            manifest_path.push("Cargo.toml");

            if manifest_path.exists() {
                visited.insert(dependency.name);
                get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
            }
        }
    }

    Ok(())
}

fn get_targets_with_hitlist(
    hitlist: &[String],
    targets: &mut HashSet<Target>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist);

    for package in metadata.packages {
        if workspace_hitlist.remove(&package.name) {
            for target in package.targets {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    if workspace_hitlist.is_empty() {
        Ok(())
    } else {
        let package = workspace_hitlist.iter().next().unwrap();
        Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("package `{}` is not a member of the workspace", package),
        ))
    }
}

fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet<Target>) {
    for target in target_paths {
        targets.insert(Target::from_target(target));
    }
}

fn run_rustfmt(
    targets: &HashSet<Target>,
    fmt_args: &[String],
    verbosity: Verbosity,
) -> Result<i32, io::Error> {
    let by_edition: HashMap<_, _> = targets
        .iter()
        .inspect(|t| {
            if verbosity == Verbosity::Verbose {
                println!("[{} ({})] {:?}", t.kind, t.edition, t.path)
            }
        })
        .map(|t| (&t.edition, vec![&t.path]))
        .collect();

    for (edition, files) in by_edition {
        let stdout = if verbosity == Verbosity::Quiet {
            std::process::Stdio::null()
        } else {
            std::process::Stdio::inherit()
        };

        if verbosity == Verbosity::Verbose {
            print!("rustfmt");
            fmt_args.iter().for_each(|f| print!(" {}", f));
            files.iter().for_each(|f| print!(" {}", f.display()));
            println!();
        }

        let mut command = Command::new("rustfmt")
            .stdout(stdout)
            .args(files)
            .args(&["--edition", edition])
            .args(fmt_args)
            .spawn()
            .map_err(|e| match e.kind() {
                io::ErrorKind::NotFound => io::Error::new(
                    io::ErrorKind::Other,
                    "Could not run rustfmt, please make sure it is in your PATH.",
                ),
                _ => e,
            })?;

        let status = command.wait()?;
        if !status.success() {
            return Ok(status.code().unwrap_or(FAILURE));
        }
    }

    Ok(SUCCESS)
}

fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> {
    match cargo_metadata::metadata(manifest_path) {
        Ok(metadata) => Ok(metadata),
        Err(error) => Err(io::Error::new(io::ErrorKind::Other, error.to_string())),
    }
}
<commit_msg>cargo-fmt: Add --edition when printing the command<commit_after>// Copyright 2015-2016 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.

// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/)

#![cfg(not(test))]
#![deny(warnings)]

extern crate cargo_metadata;
extern crate getopts;
extern crate serde_json as json;

use std::collections::{HashMap, HashSet};
use std::env;
use std::fs;
use std::hash::{Hash, Hasher};
use std::io::{self, Write};
use std::iter::FromIterator;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;

use getopts::{Matches, Options};

fn main() {
    let exit_status = execute();
    std::io::stdout().flush().unwrap();
    std::process::exit(exit_status);
}

const SUCCESS: i32 = 0;
const FAILURE: i32 = 1;

fn execute() -> i32 {
    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("q", "quiet", "no output printed to stdout");
    opts.optflag("v", "verbose", "use verbose output");
    opts.optmulti(
        "p",
        "package",
        "specify package to format (only usable in workspaces)",
        "<package>",
    );
    opts.optflag("", "version", "print rustfmt version and exit");
    opts.optflag("", "all", "format all packages (only usable in workspaces)");

    // If there is any invalid argument passed to `cargo fmt`, return without formatting.
    let mut is_package_arg = false;
    for arg in env::args().skip(2).take_while(|a| a != "--") {
        if arg.starts_with('-') {
            is_package_arg = arg.starts_with("--package");
        } else if !is_package_arg {
            print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg));
            return FAILURE;
        } else {
            is_package_arg = false;
        }
    }

    let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) {
        Ok(m) => m,
        Err(e) => {
            print_usage_to_stderr(&opts, &e.to_string());
            return FAILURE;
        }
    };

    let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) {
        (false, false) => Verbosity::Normal,
        (false, true) => Verbosity::Quiet,
        (true, false) => Verbosity::Verbose,
        (true, true) => {
            print_usage_to_stderr(&opts, "quiet mode and verbose mode are not compatible");
            return FAILURE;
        }
    };

    if matches.opt_present("h") {
        print_usage_to_stdout(&opts, "");
        return SUCCESS;
    }

    if matches.opt_present("version") {
        return handle_command_status(get_version(verbosity), &opts);
    }

    let strategy = CargoFmtStrategy::from_matches(&matches);
    handle_command_status(format_crate(verbosity, &strategy), &opts)
}

macro_rules! print_usage {
    ($print:ident, $opts:ident, $reason:expr) => {{
        let msg = format!("{}\nusage: cargo fmt [options]", $reason);
        $print!(
            "{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \
             Arguments after `--` are passed to rustfmt.",
            $opts.usage(&msg)
        );
    }};
}

fn print_usage_to_stdout(opts: &Options, reason: &str) {
    print_usage!(println, opts, reason);
}

fn print_usage_to_stderr(opts: &Options, reason: &str) {
    print_usage!(eprintln, opts, reason);
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Verbosity {
    Verbose,
    Normal,
    Quiet,
}

fn handle_command_status(status: Result<i32, io::Error>, opts: &getopts::Options) -> i32 {
    match status {
        Err(e) => {
            print_usage_to_stderr(opts, &e.to_string());
            FAILURE
        }
        Ok(status) => status,
    }
}

fn get_version(verbosity: Verbosity) -> Result<i32, io::Error> {
    run_rustfmt(&HashSet::new(), &[String::from("--version")], verbosity)
}

fn format_crate(verbosity: Verbosity, strategy: &CargoFmtStrategy) -> Result<i32, io::Error> {
    let rustfmt_args = get_fmt_args();
    let targets = if rustfmt_args
        .iter()
        .any(|s| ["--print-config", "-h", "--help", "-V", "--version"].contains(&s.as_str()))
    {
        HashSet::new()
    } else {
        get_targets(strategy)?
    };

    // Currently only bin and lib files get formatted
    run_rustfmt(&targets, &rustfmt_args, verbosity)
}

fn get_fmt_args() -> Vec<String> {
    // All arguments after -- are passed to rustfmt
    env::args().skip_while(|a| a != "--").skip(1).collect()
}

/// Target uses a `path` field for equality and hashing.
#[derive(Debug)]
pub struct Target {
    /// A path to the main source file of the target.
    path: PathBuf,
    /// A kind of target (e.g. lib, bin, example, ...).
    kind: String,
    /// Rust edition for this target.
    edition: String,
}

impl Target {
    pub fn from_target(target: &cargo_metadata::Target) -> Self {
        let path = PathBuf::from(&target.src_path);
        let canonicalized = fs::canonicalize(&path).unwrap_or(path);

        Target {
            path: canonicalized,
            kind: target.kind[0].clone(),
            edition: target.edition.clone(),
        }
    }
}

impl PartialEq for Target {
    fn eq(&self, other: &Target) -> bool {
        self.path == other.path
    }
}

impl Eq for Target {}

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

#[derive(Debug, PartialEq, Eq)]
pub enum CargoFmtStrategy {
    /// Format every packages and dependencies.
    All,
    /// Format packages that are specified by the command line argument.
    Some(Vec<String>),
    /// Format the root packages only.
    Root,
}

impl CargoFmtStrategy {
    pub fn from_matches(matches: &Matches) -> CargoFmtStrategy {
        match (matches.opt_present("all"), matches.opt_present("p")) {
            (false, false) => CargoFmtStrategy::Root,
            (true, _) => CargoFmtStrategy::All,
            (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")),
        }
    }
}

/// Based on the specified `CargoFmtStrategy`, returns a set of main source files.
fn get_targets(strategy: &CargoFmtStrategy) -> Result<HashSet<Target>, io::Error> {
    let mut targets = HashSet::new();

    match *strategy {
        CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?,
        CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?,
        CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?,
    }

    if targets.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "Failed to find targets".to_owned(),
        ))
    } else {
        Ok(targets)
    }
}

fn get_targets_root_only(targets: &mut HashSet<Target>) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;
    let current_dir = env::current_dir()?.canonicalize()?;
    let current_dir_manifest = current_dir.join("Cargo.toml");
    let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?;
    let in_workspace_root = workspace_root_path == current_dir;

    for package in metadata.packages {
        if in_workspace_root || PathBuf::from(&package.manifest_path) == current_dir_manifest {
            for target in package.targets {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    Ok(())
}

fn get_targets_recursive(
    manifest_path: Option<&Path>,
    mut targets: &mut HashSet<Target>,
    visited: &mut HashSet<String>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(manifest_path)?;

    for package in metadata.packages {
        add_targets(&package.targets, &mut targets);

        // Look for local dependencies.
        for dependency in package.dependencies {
            if dependency.source.is_some() || visited.contains(&dependency.name) {
                continue;
            }

            let mut manifest_path = PathBuf::from(&package.manifest_path);

            manifest_path.pop();
            manifest_path.push(&dependency.name);
            manifest_path.push("Cargo.toml");

            if manifest_path.exists() {
                visited.insert(dependency.name);
                get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
            }
        }
    }

    Ok(())
}

fn get_targets_with_hitlist(
    hitlist: &[String],
    targets: &mut HashSet<Target>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist);

    for package in metadata.packages {
        if workspace_hitlist.remove(&package.name) {
            for target in package.targets {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    if workspace_hitlist.is_empty() {
        Ok(())
    } else {
        let package = workspace_hitlist.iter().next().unwrap();
        Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("package `{}` is not a member of the workspace", package),
        ))
    }
}

fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet<Target>) {
    for target in target_paths {
        targets.insert(Target::from_target(target));
    }
}

fn run_rustfmt(
    targets: &HashSet<Target>,
    fmt_args: &[String],
    verbosity: Verbosity,
) -> Result<i32, io::Error> {
    let by_edition: HashMap<_, _> = targets
        .iter()
        .inspect(|t| {
            if verbosity == Verbosity::Verbose {
                println!("[{} ({})] {:?}", t.kind, t.edition, t.path)
            }
        })
        .map(|t| (&t.edition, vec![&t.path]))
        .collect();

    for (edition, files) in by_edition {
        let stdout = if verbosity == Verbosity::Quiet {
            std::process::Stdio::null()
        } else {
            std::process::Stdio::inherit()
        };

        if verbosity == Verbosity::Verbose {
            print!("rustfmt");
            print!(" --edition {}", edition);
            fmt_args.iter().for_each(|f| print!(" {}", f));
            files.iter().for_each(|f| print!(" {}", f.display()));
            println!();
        }

        let mut command = Command::new("rustfmt")
            .stdout(stdout)
            .args(files)
            .args(&["--edition", edition])
            .args(fmt_args)
            .spawn()
            .map_err(|e| match e.kind() {
                io::ErrorKind::NotFound => io::Error::new(
                    io::ErrorKind::Other,
                    "Could not run rustfmt, please make sure it is in your PATH.",
                ),
                _ => e,
            })?;

        let status = command.wait()?;
        if !status.success() {
            return Ok(status.code().unwrap_or(FAILURE));
        }
    }

    Ok(SUCCESS)
}

fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> {
    match cargo_metadata::metadata(manifest_path) {
        Ok(metadata) => Ok(metadata),
        Err(error) => Err(io::Error::new(io::ErrorKind::Other, error.to_string())),
    }
}
<|endoftext|>


<commit_before>//! A system for creating and managing IRC client connections.
//!
//! This API provides the ability to create and manage multiple IRC clients that can run on the same
//! thread through the use of a shared event loop. It can also be used to encapsulate the dependency
//! on `tokio` and `futures` in the use of `IrcClient::new_future`. This means that knowledge of
//! those libraries should be unnecessary for the average user. Nevertheless, this API also provides
//! some escape hatches that let advanced users take further advantage of these dependencies.
//!
//! # Example
//! ```no_run
//! # extern crate irc;
//! # use std::default::Default;
//! use irc::client::prelude::*;
//! use irc::error;
//!
//! fn main() {
//!   let config = Config::default();
//!   let mut reactor = IrcReactor::new().unwrap();
//!   let client = reactor.prepare_client_and_connect(&config).unwrap();
//!   reactor.register_client_with_handler(client, process_msg);
//!   reactor.run().unwrap();
//! }
//! # fn process_msg(client: &IrcClient, message: Message) -> error::Result<()> { Ok(()) }
//! ```

use futures::{Future, IntoFuture, Stream};
use futures::future;
use tokio_core::reactor::{Core, Handle};

use client::data::Config;
use client::{IrcClient, IrcClientFuture, PackedIrcClient, Client};
use error;
use proto::Message;

/// A thin wrapper over an event loop.
///
/// An IRC reactor is used to create new IRC clients and to drive the management of all connected
/// clients as the application runs. It can be used to run multiple clients on the same thread, as
/// well as to get better control over error management in an IRC client.
///
/// For a full example usage, see [`irc::client::reactor`](./index.html).
pub struct IrcReactor {
    inner: Core,
    handlers: Vec<Box<Future<Item = (), Error = error::IrcError>>>,
}

impl IrcReactor {
    /// Creates a new reactor.
    pub fn new() -> error::Result<IrcReactor> {
        Ok(IrcReactor {
            inner: Core::new()?,
            handlers: Vec::new(),
        })
    }

    /// Creates a representation of an IRC client that has not yet attempted to connect. In
    /// particular, this representation is as a `Future` that when run will produce a connected
    /// [`IrcClient`](../struct.IrcClient.html).
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let future_client = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_client(&config)
    /// });
    /// # }
    /// ```
    pub fn prepare_client<'a>(&mut self, config: &'a Config) -> error::Result<IrcClientFuture<'a>> {
        IrcClient::new_future(self.inner_handle(), config)
    }

    /// Runs an [`IrcClientFuture`](../struct.IrcClientFuture.html), such as one from
    /// `prepare_client` to completion, yielding an [`IrcClient`](../struct.IrcClient.html).
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let client = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_client(&config).and_then(|future| {
    ///         reactor.connect_client(future)
    ///     })
    /// });
    /// # }
    /// ```
    pub fn connect_client(&mut self, future: IrcClientFuture) -> error::Result<IrcClient> {
        self.inner.run(future).map(|PackedIrcClient(client, future)| {
            self.register_future(future);
            client
        })
    }

    /// Creates a new [`IrcClient`](../struct.IrcClient.html) from the specified configuration,
    /// connecting immediately. This is guaranteed to be the composition of `prepare_client` and
    /// `connect_client`.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let client = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_client_and_connect(&config)
    /// });
    /// # }
    /// ```
    pub fn prepare_client_and_connect(&mut self, config: &Config) -> error::Result<IrcClient> {
        self.prepare_client(config).and_then(|future| self.connect_client(future))
    }

    /// Registers the given client with the specified message handler. The reactor will store this
    /// setup until the next call to run, where it will be used to process new messages over the
    /// connection indefinitely (or until failure). As registration is consumed by `run`, subsequent
    /// calls to run will require new registration.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let mut reactor = IrcReactor::new().unwrap();
    /// let client = reactor.prepare_client_and_connect(&config).unwrap();
    /// reactor.register_client_with_handler(client, |client, msg| {
    ///   // Message processing happens here.
    ///   Ok(())
    /// })
    /// # }
    /// ```
    pub fn register_client_with_handler<F, U>(
        &mut self, client: IrcClient, mut handler: F
    ) where F: FnMut(&IrcClient, Message) -> U + 'static,
            U: IntoFuture<Item = (), Error = error::IrcError> + 'static {
        self.handlers.push(Box::new(client.stream().for_each(move |message| {
            handler(&client, message)
        })));
    }

    /// Registers an arbitrary future with this reactor. This is a sort of escape hatch that allows
    /// you to take more control over what runs on the reactor without requiring you to bring in
    /// additional knowledge about `tokio`. It is suspected that `register_client_with_handler` will
    /// be sufficient for most use cases.
    pub fn register_future<F>(
        &mut self, future: F
    ) where F: IntoFuture<Item = (), Error = error::IrcError> + 'static {
        self.handlers.push(Box::new(future.into_future()))
    }

    /// Returns a handle to the internal event loop. This is a sort of escape hatch that allows you
    /// to take more control over what runs on the reactor using `tokio`. This can be used for
    /// sharing this reactor with some elements of other libraries.
    pub fn inner_handle(&self) -> Handle {
        self.inner.handle()
    }

    /// Consumes all registered handlers and futures, and runs them. When using
    /// `register_client_with_handler`, this will block indefinitely (until failure occurs) as it
    /// will simply continue to process new, incoming messages for each client that was registered.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # use irc::error;
    /// # fn main() {
    /// # let config = Config::default();
    /// let mut reactor = IrcReactor::new().unwrap();
    /// let client = reactor.prepare_client_and_connect(&config).unwrap();
    /// reactor.register_client_with_handler(client, process_msg);
    /// reactor.run().unwrap();
    /// # }
    /// # fn process_msg(client: &IrcClient, message: Message) -> error::Result<()> { Ok(()) }
    /// ```
    pub fn run(&mut self) -> error::Result<()> {
        let mut handlers = Vec::new();
        while let Some(handler) = self.handlers.pop() {
            handlers.push(handler);
        }
        self.inner.run(future::join_all(handlers).map(|_| ()))
    }
}
<commit_msg>Documented panic condition for client registration with a reactor.<commit_after>//! A system for creating and managing IRC client connections.
//!
//! This API provides the ability to create and manage multiple IRC clients that can run on the same
//! thread through the use of a shared event loop. It can also be used to encapsulate the dependency
//! on `tokio` and `futures` in the use of `IrcClient::new_future`. This means that knowledge of
//! those libraries should be unnecessary for the average user. Nevertheless, this API also provides
//! some escape hatches that let advanced users take further advantage of these dependencies.
//!
//! # Example
//! ```no_run
//! # extern crate irc;
//! # use std::default::Default;
//! use irc::client::prelude::*;
//! use irc::error;
//!
//! fn main() {
//!   let config = Config::default();
//!   let mut reactor = IrcReactor::new().unwrap();
//!   let client = reactor.prepare_client_and_connect(&config).unwrap();
//!   reactor.register_client_with_handler(client, process_msg);
//!   reactor.run().unwrap();
//! }
//! # fn process_msg(client: &IrcClient, message: Message) -> error::Result<()> { Ok(()) }
//! ```

use futures::{Future, IntoFuture, Stream};
use futures::future;
use tokio_core::reactor::{Core, Handle};

use client::data::Config;
use client::{IrcClient, IrcClientFuture, PackedIrcClient, Client};
use error;
use proto::Message;

/// A thin wrapper over an event loop.
///
/// An IRC reactor is used to create new IRC clients and to drive the management of all connected
/// clients as the application runs. It can be used to run multiple clients on the same thread, as
/// well as to get better control over error management in an IRC client.
///
/// For a full example usage, see [`irc::client::reactor`](./index.html).
pub struct IrcReactor {
    inner: Core,
    handlers: Vec<Box<Future<Item = (), Error = error::IrcError>>>,
}

impl IrcReactor {
    /// Creates a new reactor.
    pub fn new() -> error::Result<IrcReactor> {
        Ok(IrcReactor {
            inner: Core::new()?,
            handlers: Vec::new(),
        })
    }

    /// Creates a representation of an IRC client that has not yet attempted to connect. In
    /// particular, this representation is as a `Future` that when run will produce a connected
    /// [`IrcClient`](../struct.IrcClient.html).
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let future_client = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_client(&config)
    /// });
    /// # }
    /// ```
    pub fn prepare_client<'a>(&mut self, config: &'a Config) -> error::Result<IrcClientFuture<'a>> {
        IrcClient::new_future(self.inner_handle(), config)
    }

    /// Runs an [`IrcClientFuture`](../struct.IrcClientFuture.html), such as one from
    /// `prepare_client` to completion, yielding an [`IrcClient`](../struct.IrcClient.html).
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let client = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_client(&config).and_then(|future| {
    ///         reactor.connect_client(future)
    ///     })
    /// });
    /// # }
    /// ```
    pub fn connect_client(&mut self, future: IrcClientFuture) -> error::Result<IrcClient> {
        self.inner.run(future).map(|PackedIrcClient(client, future)| {
            self.register_future(future);
            client
        })
    }

    /// Creates a new [`IrcClient`](../struct.IrcClient.html) from the specified configuration,
    /// connecting immediately. This is guaranteed to be the composition of `prepare_client` and
    /// `connect_client`.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let client = IrcReactor::new().and_then(|mut reactor| {
    ///     reactor.prepare_client_and_connect(&config)
    /// });
    /// # }
    /// ```
    pub fn prepare_client_and_connect(&mut self, config: &Config) -> error::Result<IrcClient> {
        self.prepare_client(config).and_then(|future| self.connect_client(future))
    }

    /// Registers the given client with the specified message handler. The reactor will store this
    /// setup until the next call to run, where it will be used to process new messages over the
    /// connection indefinitely (or until failure). As registration is consumed by `run`, subsequent
    /// calls to run will require new registration.
    ///
    /// **Note**: A client can only be registered once. Subsequent attempts will cause a panic.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # fn main() {
    /// # let config = Config::default();
    /// let mut reactor = IrcReactor::new().unwrap();
    /// let client = reactor.prepare_client_and_connect(&config).unwrap();
    /// reactor.register_client_with_handler(client, |client, msg| {
    ///   // Message processing happens here.
    ///   Ok(())
    /// })
    /// # }
    /// ```
    pub fn register_client_with_handler<F, U>(
        &mut self, client: IrcClient, mut handler: F
    ) where F: FnMut(&IrcClient, Message) -> U + 'static,
            U: IntoFuture<Item = (), Error = error::IrcError> + 'static {
        self.handlers.push(Box::new(client.stream().for_each(move |message| {
            handler(&client, message)
        })));
    }

    /// Registers an arbitrary future with this reactor. This is a sort of escape hatch that allows
    /// you to take more control over what runs on the reactor without requiring you to bring in
    /// additional knowledge about `tokio`. It is suspected that `register_client_with_handler` will
    /// be sufficient for most use cases.
    pub fn register_future<F>(
        &mut self, future: F
    ) where F: IntoFuture<Item = (), Error = error::IrcError> + 'static {
        self.handlers.push(Box::new(future.into_future()))
    }

    /// Returns a handle to the internal event loop. This is a sort of escape hatch that allows you
    /// to take more control over what runs on the reactor using `tokio`. This can be used for
    /// sharing this reactor with some elements of other libraries.
    pub fn inner_handle(&self) -> Handle {
        self.inner.handle()
    }

    /// Consumes all registered handlers and futures, and runs them. When using
    /// `register_client_with_handler`, this will block indefinitely (until failure occurs) as it
    /// will simply continue to process new, incoming messages for each client that was registered.
    ///
    /// # Example
    /// ```no_run
    /// # extern crate irc;
    /// # use std::default::Default;
    /// # use irc::client::prelude::*;
    /// # use irc::error;
    /// # fn main() {
    /// # let config = Config::default();
    /// let mut reactor = IrcReactor::new().unwrap();
    /// let client = reactor.prepare_client_and_connect(&config).unwrap();
    /// reactor.register_client_with_handler(client, process_msg);
    /// reactor.run().unwrap();
    /// # }
    /// # fn process_msg(client: &IrcClient, message: Message) -> error::Result<()> { Ok(()) }
    /// ```
    pub fn run(&mut self) -> error::Result<()> {
        let mut handlers = Vec::new();
        while let Some(handler) = self.handlers.pop() {
            handlers.push(handler);
        }
        self.inner.run(future::join_all(handlers).map(|_| ()))
    }
}
<|endoftext|>


<commit_before>use std::error;
use hyper;
use rusoto_core::{default_tls_client, DefaultCredentialsProvider, Region};
use rusoto_ssm;
use rusoto_ssm::{Ssm, SsmClient};
use config;

use super::error::CommandError;

pub trait ParamsExecuter {
    fn client(&self) -> SsmClient<DefaultCredentialsProvider, hyper::client::Client> {
        let credentials = DefaultCredentialsProvider::new().unwrap();
        return SsmClient::new(
            default_tls_client().unwrap(),
            credentials,
            Region::ApNortheast1,
        );
    }

    fn config(&self) -> &config::command::ParamsConfig;

    fn name_with_path(&self, name: &str) -> String {
        let mut path = self.path();
        path.push_str(name);
        path
    }

    fn path(&self) -> String {
        let mut path = self.config().path.to_owned();
        if !path.ends_with("/") {
            path.push_str("/");
        }
        if !path.starts_with("/") {
            path = format!("/{}", path);
        }
        path
    }

    fn strip_path<'a>(&self, name: &'a str) -> Result<&'a str, Box<error::Error>> {
        let path = self.path();
        if name.starts_with(&path) {
            return Ok(name.trim_left_matches(&path));
        } else {
            Err(Box::new(CommandError::Unknown))
        }
    }

    fn params(&self) -> Result<Option<Vec<rusoto_ssm::Parameter>>, Box<error::Error>> {
        let path = self.path();
        let with_decription = self.config().secure.is_some();

        let req = rusoto_ssm::GetParametersByPathRequest {
            path: path,
            with_decryption: Some(with_decription),
            ..Default::default()
        };

        let client = self.client();
        let res = try!(client.get_parameters_by_path(&req));
        info!("get parameters-by-path successfully");

        Ok(res.parameters)
    }
}
<commit_msg>remove unnecessary trailing slash of parameter store path<commit_after>use std::error;
use hyper;
use rusoto_core::{default_tls_client, DefaultCredentialsProvider, Region};
use rusoto_ssm;
use rusoto_ssm::{Ssm, SsmClient};
use config;

use super::error::CommandError;

pub trait ParamsExecuter {
    fn client(&self) -> SsmClient<DefaultCredentialsProvider, hyper::client::Client> {
        let credentials = DefaultCredentialsProvider::new().unwrap();
        return SsmClient::new(
            default_tls_client().unwrap(),
            credentials,
            Region::ApNortheast1,
        );
    }

    fn config(&self) -> &config::command::ParamsConfig;

    fn name_with_path(&self, name: &str) -> String {
        let mut path = self.path(true);
        path.push_str(name);
        path
    }

    fn path(&self, with_trailing_slash: bool) -> String {
        let mut path = self.config().path.to_owned();

        if with_trailing_slash && !path.ends_with("/") {
            path.push_str("/");
        }
        if !with_trailing_slash && path.ends_with("/") {
            path.trim_right_matches('/');
        }

        if !path.starts_with("/") {
            path = format!("/{}", path);
        }
        path
    }

    fn strip_path<'a>(&self, name: &'a str) -> Result<&'a str, Box<error::Error>> {
        let path = self.path(true);
        if name.starts_with(&path) {
            return Ok(name.trim_left_matches(&path));
        } else {
            Err(Box::new(CommandError::Unknown))
        }
    }

    fn params(&self) -> Result<Option<Vec<rusoto_ssm::Parameter>>, Box<error::Error>> {
        let path = self.path(false);
        let with_decription = self.config().secure.is_some();

        let req = rusoto_ssm::GetParametersByPathRequest {
            path: path,
            with_decryption: Some(with_decription),
            ..Default::default()
        };

        let client = self.client();
        let res = try!(client.get_parameters_by_path(&req));
        info!("get parameters-by-path successfully");

        Ok(res.parameters)
    }
}
<|endoftext|>


<commit_before>//! This module contains the code representing Mastodon nodes and API Clients
//!
use api::APIMethodRequest;
use errors::*;
use hyper::Uri;
use hyper::header::Bearer;
use mastodon::ApiHandler;
use std::str::FromStr;
use super::entities;
use super::methods;
use super::methods::{
    AccountID,
    HomeTimelineQuery,
    NotificationID,
    SearchAccountsQuery,
    SearchContentsQuery,
    StatusID,
    TagID,
    TimelineQuery,
    UserFormData
};
use url::Url;

/// The API Client, currently works for version 1 of the Mastodon API.
pub struct Client {
    pub url_base: Url,
    pub token: Bearer
}

impl ApiHandler for Client {
    fn endpoint_url(&self, path: &str) -> Result<Url> {
        self.url_base.clone().join(path).chain_err(|| "could not join path with URL")
    }
    fn endpoint_url_string(&self, path: &str) -> String {
        self.endpoint_url(path).unwrap().into_string()
    }
}

impl methods::Accounts for Client {
    fn fetch_account(&self, account_id: AccountID) -> Result<entities::Account> {
        let api_method = APIMethodRequest {
            uri: Uri::from_str(&format!("/api/v1/accounts/{}", account_id.id)).unwrap(),
            ..APIMethodRequest::default()
        };
        println!("FETCH ACCOUNT: {:?}", api_method);
        Ok(entities::Account::default())
    }
    fn get_current_user(&self) -> Result<entities::Account> {
        unimplemented!();
    }
    fn update_current_user(&self, form_data: UserFormData) -> Result<entities::Account> {
        unimplemented!()
    }
    fn get_account_followers(&self, account_id: AccountID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn get_account_following(&self, account_id: AccountID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn get_account_statutes(&self, account_id: AccountID) -> Result<Vec<entities::Status>> {
        unimplemented!()
    }
    fn follow_account(&self, account_id: AccountID) -> Result<entities::Relationship> {
        unimplemented!()
    }
    fn unfollow_account(&self, account_id: AccountID) -> Result<entities::Relationship> {
        unimplemented!()
    }
    fn block_account(&self, account_id: AccountID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn unblock_account(&self, account_id: AccountID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn mute_account(&self, account_id: AccountID) -> Result<entities::Relationship> {
        unimplemented!()
    }
    fn unmute_account(&self, account_id: AccountID) -> Result<entities::Relationship> {
        unimplemented!()
    }
    fn get_account_relationships(&self, account_id: AccountID) -> Result<Vec<entities::Relationship>> {
        unimplemented!()
    }
    fn search_accounts(&self, query: SearchAccountsQuery) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
}
impl methods::Blocks for Client {
    fn fetch_blocks(&self, query: String) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
}
impl methods::Favourites for Client {
    fn fetch_favourites(&self, query: String) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
}
impl methods::FollowRequests for Client {
    fn fetch_follow_requests(&self, query: String) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn authorize_follow_request(&self, form_data: String) -> Result<()> {
        unimplemented!()
    }
    fn reject_follow_request(&self, form_data: String) -> Result<()> {
        unimplemented!()
    }
}

impl methods::Follows for Client {
    fn follow_remote_user(&self, form_data: String) -> Result<entities::Account> {
        unimplemented!()
    }
}

impl methods::Instances for Client {
    fn get_instance(&self) -> Result<entities::Instance> {
        unimplemented!()
    }
}

impl methods::Media for Client {
    fn upload_media(&self, form_data: String) -> Result<entities::Attachment> {
        unimplemented!()
    }
}

impl methods::Mutes for Client {
    fn fetch_mutes(&self, query: String) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
}

impl methods::Notifications for Client {
    fn fetch_notifications(&self, query: String) -> Result<Vec<entities::Notification>> {
        unimplemented!()
    }
    fn get_notification(&self, notification_id: NotificationID) -> Result<entities::Notification> {
        unimplemented!()
    }
    fn clear_notifications(&self) -> Result<()> {
        unimplemented!()
    }
}

impl methods::Reports for Client {
    fn fetching_reports(&self) -> Result<Vec<entities::Report>> {
        unimplemented!()
    }
    fn reporting_user(&self, form_data: String) -> Result<entities::Report> {
        unimplemented!()
    }
}

impl methods::Search for Client {
    fn search_content(&self, query: SearchContentsQuery) -> Result<entities::Results> {
        unimplemented!()
    }
}

impl methods::Statuses for Client {
    fn fetch_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn get_status_context(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn get_status_card(&self, status_id: StatusID) -> Result<entities::Card> {
        unimplemented!()
    }
    fn reblogged_by(&self, status_id: StatusID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn favourited_by(&self, status_id: StatusID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn post_status(&self, form_data: String) -> Result<entities::Status> {
        unimplemented!()
    }
    fn delete_status(&self, status_id: StatusID) -> Result<()> {
        unimplemented!()
    }
    fn reblog_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn unreblog_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn favourite_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn unfavourite_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
}

impl methods::Timelines for Client {
    fn home_timeline(&self, query: HomeTimelineQuery) -> Result<Vec<entities::Status>> {
        unimplemented!()
    }
    fn public_timeline(&self, query: TimelineQuery) -> Result<Vec<entities::Status>> {
        unimplemented!()
    }
    fn tag_timeline(&self, hashtag: TagID, query: TimelineQuery) -> Result<Vec<entities::Status>> {
        unimplemented!()
    }
}
<commit_msg>basic implementation of API Methods: Accounts<commit_after>//! This module contains the code representing Mastodon nodes and API Clients
//!
use api::APIMethodRequest;
use errors::*;
use hyper::Uri;
use hyper::header::Bearer;
use hyper::Client as WebClient;
use hyper::{Body, Uri};
use hyper::Method::{Get, Patch, Post};
use hyper::client::Request;
use mastodon::ApiHandler;
use std::str::FromStr;
use super::entities;
use super::methods;
use super::methods::{
    AccountID,
    APIEndpoint,
    APIEndpointRequest,
    HomeTimelineQuery,
    NotificationID,
    SearchAccountsQuery,
    SearchContentsQuery,
    StatusID,
    TagID,
    TimelineQuery,
    UserFormData
};
use url::Url;

/// The API Client, currently works for version 1 of the Mastodon API.
pub struct Client {
    pub url_base: Url,
    pub token: Bearer
}

impl ApiHandler for Client {
    fn endpoint_url(&self, path: &str) -> Result<Url> {
        self.url_base.clone().join(path).chain_err(|| "could not join path with URL")
    }
    fn endpoint_url_string(&self, path: &str) -> String {
        self.endpoint_url(path).unwrap().into_string()
    }
}

impl APIEndpointRequest for Client {
    fn build_request(&self, endpoint: APIEndpoint) -> Result<Request<Body>> {
        match endpoint {
            APIEndpoint::FetchAccount(account) => {
                let url = self.endpoint_url_string(&format!("/api/v1/accounts/{}", account.id));
                let uri = Uri::from_str(&url).unwrap();
                let mut req = Request::new(Get, uri);
                Ok(req)
            },
            APIEndpoint::GetCurrentUser => {
                let url = self.endpoint_url_string("/api/v1/accounts/verify_credentials");
                let uri = Uri::from_str(&url).unwrap();
                let mut req = Request::new(Get, uri);
                Ok(req)
            },
            APIEndpoint::UpdateCurrentUser(d) => {
                let url = self.endpoint_url_string("/api/v1/accounts/update_credentials");
                let uri = Uri::from_str(&url).unwrap();
                let mut req = Request::new(Patch, uri);
                Ok(req)
            },
            APIEndpoint::GetAccountFollowers(a) => {
                let uri = Uri::from_str(&format!("/api/v1/accounts/{}/followers", a.id)).unwrap();
                let mut req = Request::new(Get, uri);
                Ok(req)
            },
            APIEndpoint::GetFollowing(a) => {
                let uri = Uri::from_str(&format!("/api/v1/accounts/{}/following", a.id)).unwrap();
                Ok(Request::new(Get, uri))
            },
            APIEndpoint::GetAccountStatuses(a) => {
                let uri = Uri::from_str(&format!("/api/v1/accounts/{}/statuses", a.id)).unwrap();
                Ok(Request::new(Get, uri))
            },
            APIEndpoint::FollowAccount(account) => {
                let url = self.endpoint_url_string(&format!("/api/v1/accounts/{}/follow", account.id));
                let uri = Uri::from_str(&url).unwrap();
                Ok(Request::new(Post, uri))
            },
            APIEndpoint::UnfollowAccount(account) => {
                let url = self.endpoint_url_string(&format!("/api/v1/accounts/{}/unfollow", account.id));
                let uri = Uri::from_str(&url).unwrap();
                Ok(Request::new(Post, uri))
            },
            APIEndpoint::BlockAccount(account) => {
                let url = self.endpoint_url_string(&format!("/api/v1/accounts/{}/block", account.id));
                let uri = Uri::from_str(&url).unwrap();
                Ok(Request::new(Post, uri))
            },
            APIEndpoint::UnblockAccount(account) => {
                let url = self.endpoint_url_string(&format!("/api/v1/accounts/{}/unblock", account.id));
                let uri = Uri::from_str(&url).unwrap();
                Ok(Request::new(Post, uri))
            },
            APIEndpoint::MuteAccount(account) => {
                let url = self.endpoint_url_string(&format!("/api/v1/accounts/{}/mute", account.id));
                let uri = Uri::from_str(&url).unwrap();
                Ok(Request::new(Post, uri))
            },
            APIEndpoint::UnmuteAccount(account) => {
                let url = self.endpoint_url_string(&format!("/api/v1/accounts/{}/unmute", account.id));
                let uri = Uri::from_str(&url).unwrap();
                Ok(Request::new(Post, uri))
            },
            APIEndpoint::GetAccountRelationships(query) => {
                let mut url = self.endpoint_url("/api/v1/accounts/relationships").unwrap();
                match query {
                    RelationshipsQuery::SingleAccount(account) => {
                        url.query_pairs_mut().append_pair("id", &format!("{}", account.id));
                    },
                    RelationshipsQuery::MultipleAccounts(accounts) => {
                        for account in &accounts {
                            url.query_pairs_mut().append_pair("id[]", &format!("{}", account.id));
                        }
                    }
                };
                let req = Request::new(Get, Uri::from_str(url.as_str()).unwrap());
                Ok(req)
            },
            APIEndpoint::SearchAccounts(q) => {
                let mut url = self.endpoint_url("/api/v1/accounts/search").unwrap();
                url.query_pairs_mut().append_pair("q", &q.q);
                if let Some(limit) = q.limit {
                    url.query_pairs_mut().append_pair("limit", &format!("{}", limit));
                };
                let uri = Uri::from_str(url.as_str()).unwrap();
                Ok(Request::new(Get, uri))
            }
        }
    }
}

impl methods::Accounts for Client {
    fn fetch_account(&self, account_id: AccountID) -> Result<entities::Account> {
        let api_method = APIMethodRequest {
            uri: Uri::from_str(&format!("/api/v1/accounts/{}", account_id.id)).unwrap(),
            ..APIMethodRequest::default()
        };
        println!("FETCH ACCOUNT: {:?}", api_method);
        Ok(entities::Account::default())
    }
    fn get_current_user(&self) -> Result<entities::Account> {
        unimplemented!();
    }
    fn update_current_user(&self, form_data: UserFormData) -> Result<entities::Account> {
        unimplemented!()
    }
    fn get_account_followers(&self, account_id: AccountID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn get_account_following(&self, account_id: AccountID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn get_account_statutes(&self, account_id: AccountID) -> Result<Vec<entities::Status>> {
        unimplemented!()
    }
    fn follow_account(&self, account_id: AccountID) -> Result<entities::Relationship> {
        unimplemented!()
    }
    fn unfollow_account(&self, account_id: AccountID) -> Result<entities::Relationship> {
        unimplemented!()
    }
    fn block_account(&self, account_id: AccountID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn unblock_account(&self, account_id: AccountID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn mute_account(&self, account_id: AccountID) -> Result<entities::Relationship> {
        unimplemented!()
    }
    fn unmute_account(&self, account_id: AccountID) -> Result<entities::Relationship> {
        unimplemented!()
    }
    fn get_account_relationships(&self, account_id: AccountID) -> Result<Vec<entities::Relationship>> {
        unimplemented!()
    }
    fn search_accounts(&self, query: SearchAccountsQuery) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
}
impl methods::Blocks for Client {
    fn fetch_blocks(&self, query: String) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
}
impl methods::Favourites for Client {
    fn fetch_favourites(&self, query: String) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
}
impl methods::FollowRequests for Client {
    fn fetch_follow_requests(&self, query: String) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn authorize_follow_request(&self, form_data: String) -> Result<()> {
        unimplemented!()
    }
    fn reject_follow_request(&self, form_data: String) -> Result<()> {
        unimplemented!()
    }
}

impl methods::Follows for Client {
    fn follow_remote_user(&self, form_data: String) -> Result<entities::Account> {
        unimplemented!()
    }
}

impl methods::Instances for Client {
    fn get_instance(&self) -> Result<entities::Instance> {
        unimplemented!()
    }
}

impl methods::Media for Client {
    fn upload_media(&self, form_data: String) -> Result<entities::Attachment> {
        unimplemented!()
    }
}

impl methods::Mutes for Client {
    fn fetch_mutes(&self, query: String) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
}

impl methods::Notifications for Client {
    fn fetch_notifications(&self, query: String) -> Result<Vec<entities::Notification>> {
        unimplemented!()
    }
    fn get_notification(&self, notification_id: NotificationID) -> Result<entities::Notification> {
        unimplemented!()
    }
    fn clear_notifications(&self) -> Result<()> {
        unimplemented!()
    }
}

impl methods::Reports for Client {
    fn fetching_reports(&self) -> Result<Vec<entities::Report>> {
        unimplemented!()
    }
    fn reporting_user(&self, form_data: String) -> Result<entities::Report> {
        unimplemented!()
    }
}

impl methods::Search for Client {
    fn search_content(&self, query: SearchContentsQuery) -> Result<entities::Results> {
        unimplemented!()
    }
}

impl methods::Statuses for Client {
    fn fetch_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn get_status_context(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn get_status_card(&self, status_id: StatusID) -> Result<entities::Card> {
        unimplemented!()
    }
    fn reblogged_by(&self, status_id: StatusID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn favourited_by(&self, status_id: StatusID) -> Result<Vec<entities::Account>> {
        unimplemented!()
    }
    fn post_status(&self, form_data: String) -> Result<entities::Status> {
        unimplemented!()
    }
    fn delete_status(&self, status_id: StatusID) -> Result<()> {
        unimplemented!()
    }
    fn reblog_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn unreblog_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn favourite_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
    fn unfavourite_status(&self, status_id: StatusID) -> Result<entities::Status> {
        unimplemented!()
    }
}

impl methods::Timelines for Client {
    fn home_timeline(&self, query: HomeTimelineQuery) -> Result<Vec<entities::Status>> {
        unimplemented!()
    }
    fn public_timeline(&self, query: TimelineQuery) -> Result<Vec<entities::Status>> {
        unimplemented!()
    }
    fn tag_timeline(&self, hashtag: TagID, query: TimelineQuery) -> Result<Vec<entities::Status>> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix deserializing KeyedContextVec<commit_after><|endoftext|>


<commit_before>//! `cargo add`

#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

#![deny(missing_docs)]

extern crate docopt;
extern crate rustc_serialize;
extern crate pad;
extern crate toml;

use std::error::Error;
use std::process;
use std::io::{self, Write};

extern crate cargo_edit;
use cargo_edit::Manifest;

mod list;
mod list_error;
mod tree;

use list::list_section;
use tree::parse_lock_file as list_tree;

static USAGE: &'static str = r"
Usage:
    cargo list [<section>] [options]
    cargo list (-h|--help)
    cargo list --version

Options:
    --manifest-path=<path>  Path to the manifest to add a dependency to.
    --tree                  List dependencies recursively as tree.
    -h --help               Show this help page.

Display a crate's dependencies using its Cargo.toml file.
";

#[derive(Debug, RustcDecodable)]
/// Docopts input args.
struct Args {
    arg_section: Option<String>,
    flag_manifest_path: Option<String>,
    flag_tree: bool,
    flag_version: bool,
}

impl Args {
    pub fn get_section(&self) -> String {
        let section = self.arg_section.clone().unwrap_or("dependencies".to_owned());

        let toml_field = match &(section[..]) {
            // Handle shortcuts
            "deps" => "dependencies",
            "dev-deps" => "dev-dependencies",
            "build-deps" => "build-dependencies",
            // No shortcut
            field => field,
        };

        String::from(toml_field)
    }
}

fn handle_list(args: &Args) -> Result<(), Box<Error>> {
    let listing = if args.flag_tree {
        let manifest = try!(Manifest::open_lock_file(&args.flag_manifest_path
                                                          .as_ref()
                                                          .map(|s| &s[..])));
        list_tree(&manifest)
    } else {
        let manifest = try!(Manifest::open(&args.flag_manifest_path.as_ref().map(|s| &s[..])));
        list_section(&manifest, args.get_section())
    };

    listing.map(|listing| println!("{}", listing)).or_else(|err| {
        println!("Could not list your stuff.\n\nERROR: {}", err);
        Err(err)
    })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
                   .and_then(|d| d.decode::<Args>())
                   .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-list version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    if let Err(err) = handle_list(&args) {
        write!(io::stderr(), "{}", err).unwrap();
        process::exit(1);
    }
}
<commit_msg>Fix help text of cargo-list<commit_after>//! `cargo add`

#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

#![deny(missing_docs)]

extern crate docopt;
extern crate rustc_serialize;
extern crate pad;
extern crate toml;

use std::error::Error;
use std::process;
use std::io::{self, Write};

extern crate cargo_edit;
use cargo_edit::Manifest;

mod list;
mod list_error;
mod tree;

use list::list_section;
use tree::parse_lock_file as list_tree;

static USAGE: &'static str = r"
Usage:
    cargo list [<section>] [options]
    cargo list (-h|--help)
    cargo list --version

Options:
    --manifest-path=<path>  Path to the manifest to list dependencies of.
    --tree                  List dependencies recursively as tree.
    -h --help               Show this help page.

Display a crate's dependencies using its Cargo.toml file.
";

#[derive(Debug, RustcDecodable)]
/// Docopts input args.
struct Args {
    arg_section: Option<String>,
    flag_manifest_path: Option<String>,
    flag_tree: bool,
    flag_version: bool,
}

impl Args {
    pub fn get_section(&self) -> String {
        let section = self.arg_section.clone().unwrap_or("dependencies".to_owned());

        let toml_field = match &(section[..]) {
            // Handle shortcuts
            "deps" => "dependencies",
            "dev-deps" => "dev-dependencies",
            "build-deps" => "build-dependencies",
            // No shortcut
            field => field,
        };

        String::from(toml_field)
    }
}

fn handle_list(args: &Args) -> Result<(), Box<Error>> {
    let listing = if args.flag_tree {
        let manifest = try!(Manifest::open_lock_file(&args.flag_manifest_path
                                                          .as_ref()
                                                          .map(|s| &s[..])));
        list_tree(&manifest)
    } else {
        let manifest = try!(Manifest::open(&args.flag_manifest_path.as_ref().map(|s| &s[..])));
        list_section(&manifest, args.get_section())
    };

    listing.map(|listing| println!("{}", listing)).or_else(|err| {
        println!("Could not list your stuff.\n\nERROR: {}", err);
        Err(err)
    })
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
                   .and_then(|d| d.decode::<Args>())
                   .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-list version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    if let Err(err) = handle_list(&args) {
        write!(io::stderr(), "{}", err).unwrap();
        process::exit(1);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::string::ToString;
use std::default::Default;
use std::ops::Deref;
use rustc_serialize::json::{Json,ToJson};
use chrono::{DateTime,UTC,NaiveDate,NaiveDateTime};

use parse::*;
use parse::Presence::*;
use record;
use record::{Record, PartialRecord};
use types::File;

#[derive(Clone, PartialEq, Debug)]
pub struct Date(pub DateTime<UTC>);

impl Deref for Date  {
    type Target = DateTime<UTC>;
    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

impl Default for Date {
    fn default() -> Date {
        Date(DateTime::<UTC>::from_utc(NaiveDateTime::from_timestamp(0, 0), UTC))
    }
}

impl ToJson for Date {
    fn to_json(&self) -> Json {
        Json::String(self.format("%Y-%m-%dT%H:%M:%SZ").to_string())
    }
}

impl FromJson for Date {
    fn from_json(json: &Json) -> Result<Date,ParseError> {
        match *json {
            Json::String(ref v) => {
                match v.parse::<DateTime<UTC>>() {
                    Ok(dt) => Ok(Date(dt)),
                    _      => Err(ParseError::InvalidStructure("Date".to_string())),
                }
            },
            _ => Err(ParseError::InvalidJsonType("Date".to_string())),
        }
    }
}

#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
pub struct LocalDate(pub NaiveDate);

impl Deref for LocalDate  {
    type Target = NaiveDate;
    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

impl Default for LocalDate {
    fn default() -> LocalDate {
        LocalDate(NaiveDate::from_yo(0,0))
    }
}

impl ToString for LocalDate {
    fn to_string(&self) -> String {
        self.format("%Y-%m-%d").to_string()
    }
}

impl ToJson for LocalDate {
    fn to_json(&self) -> Json {
        Json::String(self.to_string())
    }
}

impl FromJson for LocalDate {
    fn from_json(json: &Json) -> Result<LocalDate,ParseError> {
        match *json {
            Json::String(ref v) => {
                match v.parse::<NaiveDate>() {
                    Ok(dt) => Ok(LocalDate(dt)),
                    _      => Err(ParseError::InvalidStructure("LocalDate".to_string())),
                }
            },
            _ => Err(ParseError::InvalidJsonType("LocalDate".to_string())),
        }
    }
}

make_prop_enum_type!(Frequency, "Frequency", Secondly, // XXX don't really want a default
    Yearly   => "yearly",
    Monthly  => "monthly",
    Weekly   => "weekly",
    Daily    => "daily",
    Hourly   => "hourly",
    Minutely => "minutely",
    Secondly => "secondly"
);

make_prop_type!(Recurrence, "Recurrence",
    frequency:         Frequency        => "frequency",
    interval:          Option<i32>      => "interval",
    first_day_of_week: Option<i32>      => "firstDayOfWeek", // XXX how to represent value rules?
    by_day:            Option<Vec<i32>> => "byDay",
    by_date:           Option<Vec<i32>> => "byDate",
    by_month:          Option<Vec<i32>> => "byMonth",
    by_year_day:       Option<Vec<i32>> => "byYearDay",
    by_week_no:        Option<Vec<i32>> => "byWeekNo",
    by_hour:           Option<Vec<i32>> => "byHour",
    by_minute:         Option<Vec<i32>> => "byMinute",
    by_second:         Option<Vec<i32>> => "bySecond",
    by_set_position:   Option<Vec<i32>> => "bySetPosition",
    count:             Option<usize>    => "count",
    until:             LocalDate        => "until"
);

make_prop_enum_type!(AlertType, "AlertType", Alert,
    Email => "email",
    Alert => "alert"
);

make_prop_type!(Alert, "Alert",
    minutes_before: i32       => "minutesBefore",
    typ:            AlertType => "type"
);

make_prop_enum_type!(Rsvp, "Rsvp", None,
    None  => "",
    Yes   => "yes",
    Maybe => "maybe",
    No    => "no"
);

make_prop_type!(Participant, "Participant",
    name:   String => "name",
    email:  String => "email",
    is_you: bool   => "isYou",
    rsvp:   Rsvp   => "rsvp"
);

#[derive(Clone, PartialEq, Debug)]
pub struct ExceptionMap(pub BTreeMap<LocalDate,Option<PartialCalendarEvent>>);

impl Deref for ExceptionMap  {
    type Target = BTreeMap<LocalDate,Option<PartialCalendarEvent>>;
    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

impl ToJson for ExceptionMap {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        for (k,v) in self.iter() {
            d.insert(k.to_string(), v.to_json());
        }
        Json::Object(d)
    }
}

impl FromJson for ExceptionMap {
    fn from_json(json: &Json) -> Result<ExceptionMap,ParseError> {
        match *json {
            Json::Object(ref v) => {
                let mut d = BTreeMap::<LocalDate,Option<PartialCalendarEvent>>::new();
                for (k,v) in v.iter() {
                    let date = try!(LocalDate::from_json(&Json::String(k.clone()))); // XXX awkward
                    let obj = match *v { // XXX prefer FromJson for Option<T> but meh, compiler
                        Json::Null => None,
                        _ => {
                            let p = try!(PartialCalendarEvent::from_json(v));
                            Some(p)
                        },
                    };
                    d.insert(date, obj);

                }
                Ok(ExceptionMap(d))
            },
            _ => Err(ParseError::InvalidJsonType("ExceptionMap".to_string()))
        }
    }
}

make_record_type!(CalendarEvent, PartialCalendarEvent, "CalendarEvent",
    calendar_id:     String                   => "calendarId",
    summary:         String                   => "summary",
    description:     String                   => "description",
    location:        String                   => "location",
    show_as_free:    bool                     => "showAsFree",
    is_all_day:      bool                     => "isAllDay",
    utc_start:       Date                     => "utcStart",
    utc_end:         Date                     => "utcEnd",
    start_time_zone: Option<String>           => "startTimeZone",
    end_time_zone:   Option<String>           => "endTimeZone",
    recurrence:      Option<Recurrence>       => "recurrence",
    inclusions:      Option<Vec<LocalDate>>   => "inclusions",
    exceptions:      Option<ExceptionMap>     => "exceptions",
    alerts:          Option<Vec<Alert>>       => "alerts",
    organizer:       Option<Participant>      => "organizer",
    attendees:       Option<Vec<Participant>> => "attendees",
    attachments:     Option<Vec<File>>        => "attachments"
);
<commit_msg>LocalDate includes a time component<commit_after>use std::collections::BTreeMap;
use std::string::ToString;
use std::default::Default;
use std::ops::Deref;
use rustc_serialize::json::{Json,ToJson};
use chrono::{DateTime,UTC,NaiveDateTime};

use parse::*;
use parse::Presence::*;
use record;
use record::{Record, PartialRecord};
use types::File;

#[derive(Clone, PartialEq, Debug)]
pub struct Date(pub DateTime<UTC>);

impl Deref for Date  {
    type Target = DateTime<UTC>;
    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

impl Default for Date {
    fn default() -> Date {
        Date(DateTime::<UTC>::from_utc(NaiveDateTime::from_timestamp(0, 0), UTC))
    }
}

impl ToJson for Date {
    fn to_json(&self) -> Json {
        Json::String(self.format("%Y-%m-%dT%H:%M:%SZ").to_string())
    }
}

impl FromJson for Date {
    fn from_json(json: &Json) -> Result<Date,ParseError> {
        match *json {
            Json::String(ref v) => {
                match v.parse::<DateTime<UTC>>() {
                    Ok(dt) => Ok(Date(dt)),
                    _      => Err(ParseError::InvalidStructure("Date".to_string())),
                }
            },
            _ => Err(ParseError::InvalidJsonType("Date".to_string())),
        }
    }
}

#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
pub struct LocalDate(pub NaiveDateTime);

impl Deref for LocalDate  {
    type Target = NaiveDateTime;
    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

impl Default for LocalDate {
    fn default() -> LocalDate {
        LocalDate(NaiveDateTime::from_timestamp(0, 0))
    }
}

impl ToString for LocalDate {
    fn to_string(&self) -> String {
        self.format("%Y-%m-%d").to_string()
    }
}

impl ToJson for LocalDate {
    fn to_json(&self) -> Json {
        Json::String(self.to_string())
    }
}

impl FromJson for LocalDate {
    fn from_json(json: &Json) -> Result<LocalDate,ParseError> {
        match *json {
            Json::String(ref v) => {
                match v.parse::<NaiveDateTime>() {
                    Ok(dt) => Ok(LocalDate(dt)),
                    _      => Err(ParseError::InvalidStructure("LocalDate".to_string())),
                }
            },
            _ => Err(ParseError::InvalidJsonType("LocalDate".to_string())),
        }
    }
}

make_prop_enum_type!(Frequency, "Frequency", Secondly, // XXX don't really want a default
    Yearly   => "yearly",
    Monthly  => "monthly",
    Weekly   => "weekly",
    Daily    => "daily",
    Hourly   => "hourly",
    Minutely => "minutely",
    Secondly => "secondly"
);

make_prop_type!(Recurrence, "Recurrence",
    frequency:         Frequency        => "frequency",
    interval:          Option<i32>      => "interval",
    first_day_of_week: Option<i32>      => "firstDayOfWeek", // XXX how to represent value rules?
    by_day:            Option<Vec<i32>> => "byDay",
    by_date:           Option<Vec<i32>> => "byDate",
    by_month:          Option<Vec<i32>> => "byMonth",
    by_year_day:       Option<Vec<i32>> => "byYearDay",
    by_week_no:        Option<Vec<i32>> => "byWeekNo",
    by_hour:           Option<Vec<i32>> => "byHour",
    by_minute:         Option<Vec<i32>> => "byMinute",
    by_second:         Option<Vec<i32>> => "bySecond",
    by_set_position:   Option<Vec<i32>> => "bySetPosition",
    count:             Option<usize>    => "count",
    until:             LocalDate        => "until"
);

make_prop_enum_type!(AlertType, "AlertType", Alert,
    Email => "email",
    Alert => "alert"
);

make_prop_type!(Alert, "Alert",
    minutes_before: i32       => "minutesBefore",
    typ:            AlertType => "type"
);

make_prop_enum_type!(Rsvp, "Rsvp", None,
    None  => "",
    Yes   => "yes",
    Maybe => "maybe",
    No    => "no"
);

make_prop_type!(Participant, "Participant",
    name:   String => "name",
    email:  String => "email",
    is_you: bool   => "isYou",
    rsvp:   Rsvp   => "rsvp"
);

#[derive(Clone, PartialEq, Debug)]
pub struct ExceptionMap(pub BTreeMap<LocalDate,Option<PartialCalendarEvent>>);

impl Deref for ExceptionMap  {
    type Target = BTreeMap<LocalDate,Option<PartialCalendarEvent>>;
    fn deref<'a>(&'a self) -> &'a Self::Target {
        &self.0
    }
}

impl ToJson for ExceptionMap {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::<String,Json>::new();
        for (k,v) in self.iter() {
            d.insert(k.to_string(), v.to_json());
        }
        Json::Object(d)
    }
}

impl FromJson for ExceptionMap {
    fn from_json(json: &Json) -> Result<ExceptionMap,ParseError> {
        match *json {
            Json::Object(ref v) => {
                let mut d = BTreeMap::<LocalDate,Option<PartialCalendarEvent>>::new();
                for (k,v) in v.iter() {
                    let date = try!(LocalDate::from_json(&Json::String(k.clone()))); // XXX awkward
                    let obj = match *v { // XXX prefer FromJson for Option<T> but meh, compiler
                        Json::Null => None,
                        _ => {
                            let p = try!(PartialCalendarEvent::from_json(v));
                            Some(p)
                        },
                    };
                    d.insert(date, obj);

                }
                Ok(ExceptionMap(d))
            },
            _ => Err(ParseError::InvalidJsonType("ExceptionMap".to_string()))
        }
    }
}

make_record_type!(CalendarEvent, PartialCalendarEvent, "CalendarEvent",
    calendar_id:     String                   => "calendarId",
    summary:         String                   => "summary",
    description:     String                   => "description",
    location:        String                   => "location",
    show_as_free:    bool                     => "showAsFree",
    is_all_day:      bool                     => "isAllDay",
    utc_start:       Date                     => "utcStart",
    utc_end:         Date                     => "utcEnd",
    start_time_zone: Option<String>           => "startTimeZone",
    end_time_zone:   Option<String>           => "endTimeZone",
    recurrence:      Option<Recurrence>       => "recurrence",
    inclusions:      Option<Vec<LocalDate>>   => "inclusions",
    exceptions:      Option<ExceptionMap>     => "exceptions",
    alerts:          Option<Vec<Alert>>       => "alerts",
    organizer:       Option<Participant>      => "organizer",
    attendees:       Option<Vec<Participant>> => "attendees",
    attachments:     Option<Vec<File>>        => "attachments"
);
<|endoftext|>


<commit_before>use cocoa::base::{id, nil};
use cocoa::foundation::{NSString, NSUInteger};
use device::_make_device;
use std::borrow::Cow;
use std::error::Error;
use std::ffi::CStr;
use std::fmt::{self, Display, Formatter};
use sys::{MTLCommandQueue, MTLDevice};
use {Device};

pub struct CommandQueue(id);

impl CommandQueue {
    pub fn new(device: &Device) -> Result<Self, CommandQueueError> {
        let command_queue = unsafe { device.get_raw().newCommandQueue() };
        if command_queue != nil {
            Ok(CommandQueue(command_queue))
        } else {
            Err(CommandQueueError::CouldNotCreate)
        }
    }

    pub fn with_max_command_buffer_count(device: &Device,
                                         max_command_buffer_count: usize) -> Result<Self, CommandQueueError> {
        let command_queue = unsafe {
            device.get_raw().newCommandQueueWithMaxCommandBufferCount(max_command_buffer_count as NSUInteger)
        };
        if command_queue != nil {
            Ok(CommandQueue(command_queue))
        } else {
            Err(CommandQueueError::CouldNotCreate)
        }
    }

    pub fn insert_debug_capture_boundary(&self) {
        unsafe { self.0.insertDebugCaptureBoundary(); }
    }

    pub fn set_label(&self, label: &str) {
        unsafe { self.0.setLabel(NSString::alloc(nil).init_str(label)) }
    }

    pub fn get_label(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.label().UTF8String()).to_string_lossy() }
    }

    pub fn get_device(&self) -> Device {
        unsafe { _make_device(self.0.device()) };
    }
}

/// Internal utility function to create a CommandQueue without exposing internals.
/// Not exported publicly from this crate.
#[doc(hidden)]
pub fn _make_command_queue(command_queue: id) -> CommandQueue {
    CommandQueue(command_queue)
}

#[derive(Clone, Debug)]
pub enum CommandQueueError {
    CouldNotCreate
}

impl Display for CommandQueueError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let descr = match *self {
            CommandQueueError::CouldNotCreate => "DeviceError::CouldNotCreate"
        };
        write!(f, "{}", descr)
    }
}

impl Error for CommandQueueError {
    fn description(&self) -> &str {
        match *self {
            CommandQueueError::CouldNotCreate => "Could not create command queue."
        }
    }
}
<commit_msg>Remove errant semicolon<commit_after>use cocoa::base::{id, nil};
use cocoa::foundation::{NSString, NSUInteger};
use device::_make_device;
use std::borrow::Cow;
use std::error::Error;
use std::ffi::CStr;
use std::fmt::{self, Display, Formatter};
use sys::{MTLCommandQueue, MTLDevice};
use {Device};

pub struct CommandQueue(id);

impl CommandQueue {
    pub fn new(device: &Device) -> Result<Self, CommandQueueError> {
        let command_queue = unsafe { device.get_raw().newCommandQueue() };
        if command_queue != nil {
            Ok(CommandQueue(command_queue))
        } else {
            Err(CommandQueueError::CouldNotCreate)
        }
    }

    pub fn with_max_command_buffer_count(device: &Device,
                                         max_command_buffer_count: usize) -> Result<Self, CommandQueueError> {
        let command_queue = unsafe {
            device.get_raw().newCommandQueueWithMaxCommandBufferCount(max_command_buffer_count as NSUInteger)
        };
        if command_queue != nil {
            Ok(CommandQueue(command_queue))
        } else {
            Err(CommandQueueError::CouldNotCreate)
        }
    }

    pub fn insert_debug_capture_boundary(&self) {
        unsafe { self.0.insertDebugCaptureBoundary(); }
    }

    pub fn set_label(&self, label: &str) {
        unsafe { self.0.setLabel(NSString::alloc(nil).init_str(label)) }
    }

    pub fn get_label(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.label().UTF8String()).to_string_lossy() }
    }

    pub fn get_device(&self) -> Device {
        unsafe { _make_device(self.0.device()) }
    }
}

/// Internal utility function to create a CommandQueue without exposing internals.
/// Not exported publicly from this crate.
#[doc(hidden)]
pub fn _make_command_queue(command_queue: id) -> CommandQueue {
    CommandQueue(command_queue)
}

#[derive(Clone, Debug)]
pub enum CommandQueueError {
    CouldNotCreate
}

impl Display for CommandQueueError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let descr = match *self {
            CommandQueueError::CouldNotCreate => "DeviceError::CouldNotCreate"
        };
        write!(f, "{}", descr)
    }
}

impl Error for CommandQueueError {
    fn description(&self) -> &str {
        match *self {
            CommandQueueError::CouldNotCreate => "Could not create command queue."
        }
    }
}
<|endoftext|>


<commit_before>extern crate yaml_rust;
use self::yaml_rust::{YamlLoader, Yaml};
use command;
use file;

pub struct Configuration {
    pub commands: Vec<command::Command>,
    pub packages: Vec<String>,
    pub files: Vec<file::FileResource>,
    pub install_command: Option<String>
}

fn convert_yaml_string(yaml_str: &yaml_rust::yaml::Yaml) -> String {
    match yaml_str.as_str() {
        Some(s) => {
            return s.to_string()
        },
        None => {
            return String::new();
        }
    }
}

fn extract_file_resources(file_list: &yaml_rust::yaml::Yaml) -> Vec<file::FileResource> {
    let mut file_resources = Vec::new();
    match file_list.as_vec() {
        Some(lst) => {
            file_resources = lst.iter()
                .map(|e| file::FileResource{
                    content: convert_yaml_string(e.as_hash().unwrap().get(&Yaml::from_str("content")).unwrap()),
                    path: convert_yaml_string(e.as_hash().unwrap().get(&Yaml::from_str("path")).unwrap())
                })
                .collect::<Vec<_>>()
        }
        None => {}
    }
    return file_resources;
}

pub fn from_yaml(yaml_file: String) -> Configuration {
    let docs = YamlLoader::load_from_str(&yaml_file).unwrap();
    let doc = &docs[0];

    let default_node = doc.as_hash().unwrap().get(&Yaml::from_str("default")).unwrap();
    let empty_list = Yaml::Array(Vec::new());
    let command_list = default_node.as_hash().unwrap().get(&Yaml::from_str("commands")).unwrap_or(&empty_list);
    let package_list = default_node.as_hash().unwrap().get(&Yaml::from_str("packages")).unwrap_or(&empty_list);
    let yaml_install_command = default_node.as_hash().unwrap().get(&Yaml::from_str("package_install_cmd"));
    let file_list = default_node.as_hash().unwrap().get(&Yaml::from_str("files")).unwrap_or(&empty_list);
    let mut yaml_commands = Vec::new();
    let mut yaml_packages = Vec::new();

    match command_list.as_vec() {
        Some(lst) => {
            yaml_commands = lst.iter()
                 .map(|e| command::parse(e.as_str().expect("expected string").to_string()))
                 .collect::<Vec<_>>()
        },
        None => {}
    }

    match package_list.as_vec() {
        Some(lst) => {
            yaml_packages = lst.iter()
                .map(|e| e.as_str().expect("expected string").to_string())
                .collect::<Vec<_>>()
        },
        None => { }
    }

    let file_resources = extract_file_resources(file_list);

    let mut install_cmd = None;

    match yaml_install_command {
        Some(cmd) => {
            let s = cmd.as_str().unwrap();
            install_cmd = Some(s.to_string())
        },
        None => {}
    }

    Configuration {
        commands: yaml_commands,
        packages: yaml_packages,
        files: file_resources,
        install_command: install_cmd
    }
}
<commit_msg>Use deconstructuring let instead of match<commit_after>extern crate yaml_rust;
use self::yaml_rust::{YamlLoader, Yaml};
use command;
use file;

pub struct Configuration {
    pub commands: Vec<command::Command>,
    pub packages: Vec<String>,
    pub files: Vec<file::FileResource>,
    pub install_command: Option<String>
}

fn convert_yaml_string(yaml_str: &yaml_rust::yaml::Yaml) -> String {
    if let Some(s) = yaml_str.as_str() {
        s.into()
    } else {
        String::new()
    }
}

fn extract_file_resources(file_list: &yaml_rust::yaml::Yaml) -> Vec<file::FileResource> {
    let mut file_resources = Vec::new();
    match file_list.as_vec() {
        Some(lst) => {
            file_resources = lst.iter()
                .map(|e| file::FileResource{
                    content: convert_yaml_string(e.as_hash().unwrap().get(&Yaml::from_str("content")).unwrap()),
                    path: convert_yaml_string(e.as_hash().unwrap().get(&Yaml::from_str("path")).unwrap())
                })
                .collect::<Vec<_>>()
        }
        None => {}
    }
    return file_resources;
}

pub fn from_yaml(yaml_file: String) -> Configuration {
    let docs = YamlLoader::load_from_str(&yaml_file).unwrap();
    let doc = &docs[0];

    let default_node = doc.as_hash().unwrap().get(&Yaml::from_str("default")).unwrap();
    let empty_list = Yaml::Array(Vec::new());
    let command_list = default_node.as_hash().unwrap().get(&Yaml::from_str("commands")).unwrap_or(&empty_list);
    let package_list = default_node.as_hash().unwrap().get(&Yaml::from_str("packages")).unwrap_or(&empty_list);
    let yaml_install_command = default_node.as_hash().unwrap().get(&Yaml::from_str("package_install_cmd"));
    let file_list = default_node.as_hash().unwrap().get(&Yaml::from_str("files")).unwrap_or(&empty_list);
    let mut yaml_commands = Vec::new();
    let mut yaml_packages = Vec::new();

    match command_list.as_vec() {
        Some(lst) => {
            yaml_commands = lst.iter()
                 .map(|e| command::parse(e.as_str().expect("expected string").to_string()))
                 .collect::<Vec<_>>()
        },
        None => {}
    }

    match package_list.as_vec() {
        Some(lst) => {
            yaml_packages = lst.iter()
                .map(|e| e.as_str().expect("expected string").to_string())
                .collect::<Vec<_>>()
        },
        None => { }
    }

    let file_resources = extract_file_resources(file_list);

    let mut install_cmd = None;

    match yaml_install_command {
        Some(cmd) => {
            let s = cmd.as_str().unwrap();
            install_cmd = Some(s.to_string())
        },
        None => {}
    }

    Configuration {
        commands: yaml_commands,
        packages: yaml_packages,
        files: file_resources,
        install_command: install_cmd
    }
}
<|endoftext|>