<commit_before>use clap::{Arg, ArgMatches, App, SubCommand};

use tag::Tag;

/// Generates a `clap::SubCommand` to be integrated in the commandline-ui builder for building a
/// "tags --add foo --remove bar" subcommand to do tagging action.
pub fn tag_subcommand<'a, 'b>() -> App<'a, 'b> {
    SubCommand::with_name(tag_subcommand_name())
        .author("Matthias Beyer <mail@beyermatthias.de>")
        .version("0.1")
        .about("Add or remove tags")

        .arg(Arg::with_name(tag_subcommand_add_arg_name())
             .short("a")
             .long("add")
             .takes_value(true)
             .multiple(true)
             .help("Add tags, seperated by comma or by specifying multiple times"))

        .arg(Arg::with_name(tag_subcommand_remove_arg_name())
             .short("r")
             .long("remove")
             .takes_value(true)
             .multiple(true)
             .help("Remove tags, seperated by comma or by specifying multiple times"))
}

pub fn tag_subcommand_name() -> &'static str {
    "tags"
}

pub fn tag_subcommand_add_arg_name() -> &'static str {
    "add-tags"
}

pub fn tag_subcommand_remove_arg_name() -> &'static str {
    "remove-tags"
}

pub fn tag_subcommand_names() -> Vec<&'static str> {
    vec![tag_subcommand_add_arg_name(), tag_subcommand_remove_arg_name()]
}

/// Generates a `clap::Arg` which can be integrated into the commandline-ui builder for building a
/// "-t" or "--tags" argument which takes values for tagging actions (add, remove)
pub fn tag_argument<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_argument_name())
        .short("t")
        .long("tags")
        .takes_value(true)
        .multiple(true)
        .help("Add or remove tags, prefixed by '+' (for adding) or '-' (for removing)")
}

pub fn tag_argument_name() -> &'static str {
    "specify-tags"
}

/// Get the tags which should be added from the commandline
///
/// Returns none if the argument was not specified
pub fn get_add_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
    extract_tags(matches, "add-tags", '+')
}

/// Get the tags which should be removed from the commandline
///
/// Returns none if the argument was not specified
pub fn get_remove_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
    extract_tags(matches, "remove-tags", '-')
}

fn extract_tags(matches: &ArgMatches, specifier: &str, specchar: char) -> Option<Vec<Tag>> {
    if let Some(submatch) = matches.subcommand_matches("tags") {
        submatch.values_of(specifier)
            .map(|values| values.map(String::from).collect())
    } else {
        matches.values_of("specify-tags")
            .map(|argmatches| {
                argmatches
                    .map(String::from)
                    .filter(|s| s.starts_with(specchar))
                    .map(|s| {
                        String::from(s.split_at(1).1)
                    })
                    .collect()
            })
    }
}

<commit_msg>Extract args into new helper functions<commit_after>use clap::{Arg, ArgMatches, App, SubCommand};

use tag::Tag;

/// Generates a `clap::SubCommand` to be integrated in the commandline-ui builder for building a
/// "tags --add foo --remove bar" subcommand to do tagging action.
pub fn tag_subcommand<'a, 'b>() -> App<'a, 'b> {
    SubCommand::with_name(tag_subcommand_name())
        .author("Matthias Beyer <mail@beyermatthias.de>")
        .version("0.1")
        .about("Add or remove tags")
        .arg(tag_add_arg())
        .arg(tag_remove_arg())
}

pub fn tag_add_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_subcommand_add_arg_name())
        .short("a")
        .long("add")
        .takes_value(true)
        .multiple(true)
        .help("Add tags, seperated by comma or by specifying multiple times")
}

pub fn tag_remove_arg<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_subcommand_remove_arg_name())
        .short("r")
        .long("remove")
        .takes_value(true)
        .multiple(true)
        .help("Remove tags, seperated by comma or by specifying multiple times")
}

pub fn tag_subcommand_name() -> &'static str {
    "tags"
}

pub fn tag_subcommand_add_arg_name() -> &'static str {
    "add-tags"
}

pub fn tag_subcommand_remove_arg_name() -> &'static str {
    "remove-tags"
}

pub fn tag_subcommand_names() -> Vec<&'static str> {
    vec![tag_subcommand_add_arg_name(), tag_subcommand_remove_arg_name()]
}

/// Generates a `clap::Arg` which can be integrated into the commandline-ui builder for building a
/// "-t" or "--tags" argument which takes values for tagging actions (add, remove)
pub fn tag_argument<'a, 'b>() -> Arg<'a, 'b> {
    Arg::with_name(tag_argument_name())
        .short("t")
        .long("tags")
        .takes_value(true)
        .multiple(true)
        .help("Add or remove tags, prefixed by '+' (for adding) or '-' (for removing)")
}

pub fn tag_argument_name() -> &'static str {
    "specify-tags"
}

/// Get the tags which should be added from the commandline
///
/// Returns none if the argument was not specified
pub fn get_add_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
    extract_tags(matches, "add-tags", '+')
}

/// Get the tags which should be removed from the commandline
///
/// Returns none if the argument was not specified
pub fn get_remove_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
    extract_tags(matches, "remove-tags", '-')
}

fn extract_tags(matches: &ArgMatches, specifier: &str, specchar: char) -> Option<Vec<Tag>> {
    if let Some(submatch) = matches.subcommand_matches("tags") {
        submatch.values_of(specifier)
            .map(|values| values.map(String::from).collect())
    } else {
        matches.values_of("specify-tags")
            .map(|argmatches| {
                argmatches
                    .map(String::from)
                    .filter(|s| s.starts_with(specchar))
                    .map(|s| {
                        String::from(s.split_at(1).1)
                    })
                    .collect()
            })
    }
}

<|endoftext|>


<commit_before>//! OS-specific functionality.

#![stable(feature = "os", since = "1.0.0")]
#![allow(missing_docs, nonstandard_style, missing_debug_implementations)]

cfg_if::cfg_if! {
    if #[cfg(doc)] {

        // When documenting libstd we want to show unix/windows/linux modules as
        // these are the "main modules" that are used across platforms. This
        // should help show platform-specific functionality in a hopefully
        // cross-platform way in the documentation

        #[stable(feature = "rust1", since = "1.0.0")]
        pub use crate::sys::unix_ext as unix;

        #[stable(feature = "rust1", since = "1.0.0")]
        pub use crate::sys::windows_ext as windows;

        #[doc(cfg(target_os = "linux"))]
        pub mod linux;
    } else {

        // If we're not documenting libstd then we just expose the main modules
        // as we otherwise would.

        #[cfg(any(target_os = "redox", unix, target_os = "vxworks", target_os = "hermit"))]
        #[stable(feature = "rust1", since = "1.0.0")]
        pub use crate::sys::ext as unix;

        #[cfg(windows)]
        #[stable(feature = "rust1", since = "1.0.0")]
        pub use crate::sys::ext as windows;

        #[cfg(any(target_os = "linux", target_os = "l4re"))]
        pub mod linux;

    }
}

#[cfg(target_os = "android")]
pub mod android;
#[cfg(target_os = "dragonfly")]
pub mod dragonfly;
#[cfg(target_os = "emscripten")]
pub mod emscripten;
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
pub mod fortanix_sgx;
#[cfg(target_os = "freebsd")]
pub mod freebsd;
#[cfg(target_os = "fuchsia")]
pub mod fuchsia;
#[cfg(target_os = "haiku")]
pub mod haiku;
#[cfg(target_os = "illumos")]
pub mod illumos;
#[cfg(target_os = "ios")]
pub mod ios;
#[cfg(target_os = "macos")]
pub mod macos;
#[cfg(target_os = "netbsd")]
pub mod netbsd;
#[cfg(target_os = "openbsd")]
pub mod openbsd;
#[cfg(target_os = "redox")]
pub mod redox;
#[cfg(target_os = "solaris")]
pub mod solaris;
#[cfg(target_os = "vxworks")]
pub mod vxworks;
#[cfg(target_os = "wasi")]
pub mod wasi;

pub mod raw;
<commit_msg>Rollup merge of #81969 - jonas-schievink:no-cfg-if, r=Mark-Simulacrum<commit_after>//! OS-specific functionality.

#![stable(feature = "os", since = "1.0.0")]
#![allow(missing_docs, nonstandard_style, missing_debug_implementations)]

// When documenting libstd we want to show unix/windows/linux modules as these are the "main
// modules" that are used across platforms, so all modules are enabled when `cfg(doc)` is set.
// This should help show platform-specific functionality in a hopefully cross-platform way in the
// documentation.
// Note that we deliberately avoid `cfg_if!` here to work around a rust-analyzer bug that would make
// `std::os` submodules unusable: https://github.com/rust-analyzer/rust-analyzer/issues/6038

#[cfg(doc)]
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys::unix_ext as unix;

#[cfg(doc)]
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys::windows_ext as windows;

#[cfg(doc)]
#[doc(cfg(target_os = "linux"))]
pub mod linux;

// If we're not documenting libstd then we just expose the main modules as we otherwise would.

#[cfg(not(doc))]
#[cfg(any(target_os = "redox", unix, target_os = "vxworks", target_os = "hermit"))]
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys::ext as unix;

#[cfg(not(doc))]
#[cfg(windows)]
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys::ext as windows;

#[cfg(not(doc))]
#[cfg(any(target_os = "linux", target_os = "l4re"))]
pub mod linux;

#[cfg(target_os = "android")]
pub mod android;
#[cfg(target_os = "dragonfly")]
pub mod dragonfly;
#[cfg(target_os = "emscripten")]
pub mod emscripten;
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
pub mod fortanix_sgx;
#[cfg(target_os = "freebsd")]
pub mod freebsd;
#[cfg(target_os = "fuchsia")]
pub mod fuchsia;
#[cfg(target_os = "haiku")]
pub mod haiku;
#[cfg(target_os = "illumos")]
pub mod illumos;
#[cfg(target_os = "ios")]
pub mod ios;
#[cfg(target_os = "macos")]
pub mod macos;
#[cfg(target_os = "netbsd")]
pub mod netbsd;
#[cfg(target_os = "openbsd")]
pub mod openbsd;
#[cfg(target_os = "redox")]
pub mod redox;
#[cfg(target_os = "solaris")]
pub mod solaris;
#[cfg(target_os = "vxworks")]
pub mod vxworks;
#[cfg(target_os = "wasi")]
pub mod wasi;

pub mod raw;
<|endoftext|>


<commit_before>// From #1174:

use std;
import str;
import libc::*;

#[nolink]
native mod libc {
    fn write(fd: core::libc::c_int, buf: *u8, nbyte: core::libc::size_t);
}

fn main() {
    let s = "hello world\n";
    let b = str::bytes(s);
    let l = str::len(s);
    let b8 = unsafe { vec::unsafe::to_ptr(b) };
    libc::write(0i32, b8, l);
    let a = bind libc::write(0i32, _, _);
    a(b8, l);
}
<commit_msg>Xfail-fast a case on window<commit_after>// From #1174:
// xfail-fast

use std;
import str;
import libc::*;

#[nolink]
native mod libc {
    fn write(fd: core::libc::c_int, buf: *u8, nbyte: core::libc::size_t);
}

fn main() {
    let s = "hello world\n";
    let b = str::bytes(s);
    let l = str::len(s);
    let b8 = unsafe { vec::unsafe::to_ptr(b) };
    libc::write(0i32, b8, l);
    let a = bind libc::write(0i32, _, _);
    a(b8, l);
}
<|endoftext|>


<commit_before>use crate::msg::diagnostic_msgs::{DiagnosticArray, DiagnosticStatus};
use crate::msg::std_msgs::Header;
use crate::{Level, Status, Task};
use rosrust::{error::Result, Publisher};
use std::sync::Mutex;

/// Manages a list of diagnostic tasks, and calls them in a rate-limited manner.
///
/// This class manages a list of diagnostic tasks. Its `update` function
/// should be called frequently. At some predetermined rate, the `update`
/// function will cause all the diagnostic tasks to run, and will collate
/// and publish the resulting diagnostics.
///
/// The publication rate is determined by the `~diagnostic_period` ROS parameter.
///
/// The class also allows an update to be forced when something significant
/// has happened, and allows a single message to be broadcast on all the
/// diagnostics if normal operation of the node is suspended for some
/// reason.
pub struct Updater<'a> {
    publisher: Publisher<DiagnosticArray>,
    tasks: Vec<&'a dyn Task>,
    hardware_id: String,
    verbose: bool,
    check_tracker: Mutex<CheckTracker>,
}

struct CheckTracker {
    last_update: f64,
    last_check_time_seconds: f64,
    diagnostic_period_seconds: f64,
}

impl CheckTracker {
    fn check_diagnostic_period(&mut self) {
        let now = rosrust::now();
        let now_seconds = now.seconds();
        if now_seconds < self.last_check_time_seconds + 0.25 {
            return;
        }
        self.last_check_time_seconds = now_seconds;
        self.diagnostic_period_seconds = get_diagnostic_period().unwrap_or(1.0);
    }
}

impl<'a> Updater<'a> {
    /// Constructs a new updater.
    ///
    /// The call will fail if creating a publisher for diagnostics fails.
    ///
    /// That failure should only happen if `rosrust::init()` was not called already.
    pub fn new() -> Result<Self> {
        let publisher = rosrust::publish("/diagnostics", 10)?;
        Ok(Self {
            publisher,
            tasks: vec![],
            hardware_id: "none".into(),
            verbose: false,
            check_tracker: Mutex::new(CheckTracker {
                last_update: 0.0,
                last_check_time_seconds: 0.0,
                diagnostic_period_seconds: 1.0,
            }),
        })
    }

    /// Sets the hardware ID.
    #[inline]
    pub fn set_hardware_id(&mut self, hardware_id: impl std::string::ToString) {
        self.hardware_id = hardware_id.to_string();
    }

    /// Gets the hardware ID.
    #[inline]
    pub fn get_hardware_id(&self) -> &str {
        &self.hardware_id
    }

    /// Sets the log verbosity.
    ///
    /// Making the log verbose will output any detected warnings or errors to the log.
    #[inline]
    pub fn set_verbose(&mut self, verbose: bool) {
        self.verbose = verbose;
    }

    /// Gets the log verbosity.
    #[inline]
    pub fn is_verbose(&self) -> bool {
        self.verbose
    }

    /// Adds a task to the updater.
    ///
    /// The operation will be advertised to the diagnostics topic.
    ///
    /// This call will only fail if the advertisement fails. Note that the task is still added,
    /// as the advertisement failing isn't catastrophic.
    #[inline]
    pub fn add_task(&mut self, task: &'a dyn Task) -> Result<()> {
        let advertisement_result = self.advertise_added_task(task);
        self.tasks.push(task);
        advertisement_result
    }

    /// Advertise a task being added.
    ///
    /// You only need to call this if you do not want to add a task to the updater, but instead
    /// want to pass the task as an extra every time.
    ///
    /// Call this method on any task that the updater will not own, but will be called as an extra.
    pub fn advertise_added_task(&self, task: &dyn Task) -> Result<()> {
        let status = self.make_broadcast_status_for(task, Level::Ok, "Node starting up");
        self.publish(vec![status])
    }

    /// Remove any task with the given name.
    pub fn remove_task(&mut self, name: &str) {
        self.tasks.retain(|task| task.name() != name);
    }

    /// Causes the diagnostics to update if the inter-update interval has been exceeded.
    #[inline]
    pub fn update(&self) -> Result<()> {
        self.update_with_extra(&[])
    }

    /// Same as update, but with extra tasks provided to be run.
    ///
    /// If you do not want the updater to share ownership of a task, you can provide it
    /// whenever needed this way.
    ///
    /// Make sure you run `advertise_added_task` for any extra task you decide to pass before
    /// doing any updates.
    #[inline]
    pub fn update_with_extra(&self, extra_tasks: &[&dyn Task]) -> Result<()> {
        if !self.should_update() {
            return Ok(());
        }
        self.force_update_with_extra(extra_tasks)
    }

    fn should_update(&self) -> bool {
        let mut tracker = self.check_tracker.lock().expect(FAILED_TO_LOCK);
        tracker.check_diagnostic_period();
        rosrust::now().seconds() > tracker.last_update + tracker.diagnostic_period_seconds
    }

    fn refresh_last_time(&self) {
        let mut check_tracker = self.check_tracker.lock().expect(FAILED_TO_LOCK);
        check_tracker.last_update = rosrust::now().seconds();
    }

    /// Forces the diagnostics to update.
    ///
    /// Useful if the node has undergone a drastic state change that should be published
    /// immediately.
    #[inline]
    pub fn force_update(&self) -> Result<()> {
        self.force_update_with_extra(&[])
    }

    /// Same as force update, but with extra tasks provided to be run.
    ///
    /// If you do not want the updater to share ownership of a task, you can provide it
    /// whenever needed this way.
    ///
    /// Make sure you run `advertise_added_task` for any extra task you decide to pass before
    /// doing any updates.
    #[inline]
    pub fn force_update_with_extra(&self, extra_tasks: &[&dyn Task]) -> Result<()> {
        self.refresh_last_time();
        self.publish(self.make_update_statuses(extra_tasks))
    }

    /// Outputs a message on all the known tasks.
    ///
    /// Useful if something drastic is happening such as shutdown or a self-test.
    #[inline]
    pub fn broadcast(&self, level: Level, message: &str) -> Result<()> {
        self.broadcast_with_extra(&[], level, message)
    }

    /// Same as broadcast, but with extra tasks provided to be run.
    ///
    /// If you do not want the updater to share ownership of a task, you can provide it
    /// whenever needed this way.
    #[inline]
    pub fn broadcast_with_extra(
        &'a self,
        extra_tasks: &[&'a dyn Task],
        level: Level,
        message: &str,
    ) -> Result<()> {
        self.publish(self.make_broadcast_statuses(extra_tasks, level, message))
    }

    /// Publish a vector of diagnostic statuses to the diagnostics topic.
    #[inline]
    pub fn publish(&self, status: Vec<DiagnosticStatus>) -> Result<()> {
        let message = DiagnosticArray {
            header: Header::default(),
            status,
        };
        self.publisher.send(message)
    }

    fn map_over_tasks<F>(&self, extra_tasks: &[&'a dyn Task], handler: F) -> Vec<DiagnosticStatus>
    where
        F: Fn(&dyn Task) -> DiagnosticStatus,
    {
        Iterator::chain(
            self.tasks.iter().map(|v| &(**v)),
            extra_tasks.iter().cloned(),
        )
        .map(handler)
        .collect()
    }
}

fn get_diagnostic_period() -> Option<f64> {
    let diag_per = rosrust::param("~diagnostic_period")?;
    println!("FOO");
    let val = diag_per.get().ok()?;
    println!("BAR {}", val);
    Some(val)
}

/// A set of methods for low level handling of the updater.
///
/// These methods should only be used if you know what you are doing and need a more fine grained
/// control of publishing diagnostics.
pub trait UpdaterLowLevelExt {
    /// Generate diagnostic statuses for tasks without publishing the results.
    fn make_update_statuses(&self, extra_tasks: &[&dyn Task]) -> Vec<DiagnosticStatus>;

    /// Generate the diagnostic status for a single task without publishing the results.
    fn make_update_status(&self, task: &dyn Task) -> DiagnosticStatus;

    /// Generate broadcast statuses for tasks without publishing the results.
    fn make_broadcast_statuses(
        &self,
        extra_tasks: &[&dyn Task],
        level: Level,
        message: &str,
    ) -> Vec<DiagnosticStatus>;

    /// Generate the broadcast status for a single task without publishing the results.
    fn make_broadcast_status_for(
        &self,
        task: &dyn Task,
        level: Level,
        message: &str,
    ) -> DiagnosticStatus;
}

impl<'a> UpdaterLowLevelExt for Updater<'a> {
    #[inline]
    fn make_update_statuses(&self, extra_tasks: &[&dyn Task]) -> Vec<DiagnosticStatus> {
        self.map_over_tasks(extra_tasks, |task| self.make_update_status(task))
    }

    fn make_update_status(&self, task: &dyn Task) -> DiagnosticStatus {
        let mut status = Status {
            name: task.name().into(),
            hardware_id: self.hardware_id.clone(),
            level: Level::Error,
            message: "No message was set".into(),
            values: vec![],
        };
        task.run(&mut status);
        if self.verbose && status.level != Level::Ok {
            rosrust::ros_warn!(
                "Non-zero diagnostic status. Name: '{}', status {}: '{}'",
                status.name,
                status.level as i8,
                status.message,
            );
        }
        status.into()
    }

    #[inline]
    fn make_broadcast_statuses(
        &self,
        extra_tasks: &[&dyn Task],
        level: Level,
        message: &str,
    ) -> Vec<DiagnosticStatus> {
        self.map_over_tasks(extra_tasks, |task| {
            self.make_broadcast_status_for(task, level, message)
        })
    }

    #[inline]
    fn make_broadcast_status_for(
        &self,
        task: &dyn Task,
        level: Level,
        message: &str,
    ) -> DiagnosticStatus {
        Status {
            name: task.name().into(),
            hardware_id: self.hardware_id.clone(),
            level,
            message: message.into(),
            values: vec![],
        }
        .into()
    }
}

static FAILED_TO_LOCK: &'static str = "Failed to acquire lock";
<commit_msg>Drop `println` calls in diagnostics<commit_after>use crate::msg::diagnostic_msgs::{DiagnosticArray, DiagnosticStatus};
use crate::msg::std_msgs::Header;
use crate::{Level, Status, Task};
use rosrust::{error::Result, Publisher};
use std::sync::Mutex;

/// Manages a list of diagnostic tasks, and calls them in a rate-limited manner.
///
/// This class manages a list of diagnostic tasks. Its `update` function
/// should be called frequently. At some predetermined rate, the `update`
/// function will cause all the diagnostic tasks to run, and will collate
/// and publish the resulting diagnostics.
///
/// The publication rate is determined by the `~diagnostic_period` ROS parameter.
///
/// The class also allows an update to be forced when something significant
/// has happened, and allows a single message to be broadcast on all the
/// diagnostics if normal operation of the node is suspended for some
/// reason.
pub struct Updater<'a> {
    publisher: Publisher<DiagnosticArray>,
    tasks: Vec<&'a dyn Task>,
    hardware_id: String,
    verbose: bool,
    check_tracker: Mutex<CheckTracker>,
}

struct CheckTracker {
    last_update: f64,
    last_check_time_seconds: f64,
    diagnostic_period_seconds: f64,
}

impl CheckTracker {
    fn check_diagnostic_period(&mut self) {
        let now = rosrust::now();
        let now_seconds = now.seconds();
        if now_seconds < self.last_check_time_seconds + 0.25 {
            return;
        }
        self.last_check_time_seconds = now_seconds;
        self.diagnostic_period_seconds = get_diagnostic_period().unwrap_or(1.0);
    }
}

impl<'a> Updater<'a> {
    /// Constructs a new updater.
    ///
    /// The call will fail if creating a publisher for diagnostics fails.
    ///
    /// That failure should only happen if `rosrust::init()` was not called already.
    pub fn new() -> Result<Self> {
        let publisher = rosrust::publish("/diagnostics", 10)?;
        Ok(Self {
            publisher,
            tasks: vec![],
            hardware_id: "none".into(),
            verbose: false,
            check_tracker: Mutex::new(CheckTracker {
                last_update: 0.0,
                last_check_time_seconds: 0.0,
                diagnostic_period_seconds: 1.0,
            }),
        })
    }

    /// Sets the hardware ID.
    #[inline]
    pub fn set_hardware_id(&mut self, hardware_id: impl std::string::ToString) {
        self.hardware_id = hardware_id.to_string();
    }

    /// Gets the hardware ID.
    #[inline]
    pub fn get_hardware_id(&self) -> &str {
        &self.hardware_id
    }

    /// Sets the log verbosity.
    ///
    /// Making the log verbose will output any detected warnings or errors to the log.
    #[inline]
    pub fn set_verbose(&mut self, verbose: bool) {
        self.verbose = verbose;
    }

    /// Gets the log verbosity.
    #[inline]
    pub fn is_verbose(&self) -> bool {
        self.verbose
    }

    /// Adds a task to the updater.
    ///
    /// The operation will be advertised to the diagnostics topic.
    ///
    /// This call will only fail if the advertisement fails. Note that the task is still added,
    /// as the advertisement failing isn't catastrophic.
    #[inline]
    pub fn add_task(&mut self, task: &'a dyn Task) -> Result<()> {
        let advertisement_result = self.advertise_added_task(task);
        self.tasks.push(task);
        advertisement_result
    }

    /// Advertise a task being added.
    ///
    /// You only need to call this if you do not want to add a task to the updater, but instead
    /// want to pass the task as an extra every time.
    ///
    /// Call this method on any task that the updater will not own, but will be called as an extra.
    pub fn advertise_added_task(&self, task: &dyn Task) -> Result<()> {
        let status = self.make_broadcast_status_for(task, Level::Ok, "Node starting up");
        self.publish(vec![status])
    }

    /// Remove any task with the given name.
    pub fn remove_task(&mut self, name: &str) {
        self.tasks.retain(|task| task.name() != name);
    }

    /// Causes the diagnostics to update if the inter-update interval has been exceeded.
    #[inline]
    pub fn update(&self) -> Result<()> {
        self.update_with_extra(&[])
    }

    /// Same as update, but with extra tasks provided to be run.
    ///
    /// If you do not want the updater to share ownership of a task, you can provide it
    /// whenever needed this way.
    ///
    /// Make sure you run `advertise_added_task` for any extra task you decide to pass before
    /// doing any updates.
    #[inline]
    pub fn update_with_extra(&self, extra_tasks: &[&dyn Task]) -> Result<()> {
        if !self.should_update() {
            return Ok(());
        }
        self.force_update_with_extra(extra_tasks)
    }

    fn should_update(&self) -> bool {
        let mut tracker = self.check_tracker.lock().expect(FAILED_TO_LOCK);
        tracker.check_diagnostic_period();
        rosrust::now().seconds() > tracker.last_update + tracker.diagnostic_period_seconds
    }

    fn refresh_last_time(&self) {
        let mut check_tracker = self.check_tracker.lock().expect(FAILED_TO_LOCK);
        check_tracker.last_update = rosrust::now().seconds();
    }

    /// Forces the diagnostics to update.
    ///
    /// Useful if the node has undergone a drastic state change that should be published
    /// immediately.
    #[inline]
    pub fn force_update(&self) -> Result<()> {
        self.force_update_with_extra(&[])
    }

    /// Same as force update, but with extra tasks provided to be run.
    ///
    /// If you do not want the updater to share ownership of a task, you can provide it
    /// whenever needed this way.
    ///
    /// Make sure you run `advertise_added_task` for any extra task you decide to pass before
    /// doing any updates.
    #[inline]
    pub fn force_update_with_extra(&self, extra_tasks: &[&dyn Task]) -> Result<()> {
        self.refresh_last_time();
        self.publish(self.make_update_statuses(extra_tasks))
    }

    /// Outputs a message on all the known tasks.
    ///
    /// Useful if something drastic is happening such as shutdown or a self-test.
    #[inline]
    pub fn broadcast(&self, level: Level, message: &str) -> Result<()> {
        self.broadcast_with_extra(&[], level, message)
    }

    /// Same as broadcast, but with extra tasks provided to be run.
    ///
    /// If you do not want the updater to share ownership of a task, you can provide it
    /// whenever needed this way.
    #[inline]
    pub fn broadcast_with_extra(
        &'a self,
        extra_tasks: &[&'a dyn Task],
        level: Level,
        message: &str,
    ) -> Result<()> {
        self.publish(self.make_broadcast_statuses(extra_tasks, level, message))
    }

    /// Publish a vector of diagnostic statuses to the diagnostics topic.
    #[inline]
    pub fn publish(&self, status: Vec<DiagnosticStatus>) -> Result<()> {
        let message = DiagnosticArray {
            header: Header::default(),
            status,
        };
        self.publisher.send(message)
    }

    fn map_over_tasks<F>(&self, extra_tasks: &[&'a dyn Task], handler: F) -> Vec<DiagnosticStatus>
    where
        F: Fn(&dyn Task) -> DiagnosticStatus,
    {
        Iterator::chain(
            self.tasks.iter().map(|v| &(**v)),
            extra_tasks.iter().cloned(),
        )
        .map(handler)
        .collect()
    }
}

fn get_diagnostic_period() -> Option<f64> {
    let diag_per = rosrust::param("~diagnostic_period")?;
    let val = diag_per.get().ok()?;
    Some(val)
}

/// A set of methods for low level handling of the updater.
///
/// These methods should only be used if you know what you are doing and need a more fine grained
/// control of publishing diagnostics.
pub trait UpdaterLowLevelExt {
    /// Generate diagnostic statuses for tasks without publishing the results.
    fn make_update_statuses(&self, extra_tasks: &[&dyn Task]) -> Vec<DiagnosticStatus>;

    /// Generate the diagnostic status for a single task without publishing the results.
    fn make_update_status(&self, task: &dyn Task) -> DiagnosticStatus;

    /// Generate broadcast statuses for tasks without publishing the results.
    fn make_broadcast_statuses(
        &self,
        extra_tasks: &[&dyn Task],
        level: Level,
        message: &str,
    ) -> Vec<DiagnosticStatus>;

    /// Generate the broadcast status for a single task without publishing the results.
    fn make_broadcast_status_for(
        &self,
        task: &dyn Task,
        level: Level,
        message: &str,
    ) -> DiagnosticStatus;
}

impl<'a> UpdaterLowLevelExt for Updater<'a> {
    #[inline]
    fn make_update_statuses(&self, extra_tasks: &[&dyn Task]) -> Vec<DiagnosticStatus> {
        self.map_over_tasks(extra_tasks, |task| self.make_update_status(task))
    }

    fn make_update_status(&self, task: &dyn Task) -> DiagnosticStatus {
        let mut status = Status {
            name: task.name().into(),
            hardware_id: self.hardware_id.clone(),
            level: Level::Error,
            message: "No message was set".into(),
            values: vec![],
        };
        task.run(&mut status);
        if self.verbose && status.level != Level::Ok {
            rosrust::ros_warn!(
                "Non-zero diagnostic status. Name: '{}', status {}: '{}'",
                status.name,
                status.level as i8,
                status.message,
            );
        }
        status.into()
    }

    #[inline]
    fn make_broadcast_statuses(
        &self,
        extra_tasks: &[&dyn Task],
        level: Level,
        message: &str,
    ) -> Vec<DiagnosticStatus> {
        self.map_over_tasks(extra_tasks, |task| {
            self.make_broadcast_status_for(task, level, message)
        })
    }

    #[inline]
    fn make_broadcast_status_for(
        &self,
        task: &dyn Task,
        level: Level,
        message: &str,
    ) -> DiagnosticStatus {
        Status {
            name: task.name().into(),
            hardware_id: self.hardware_id.clone(),
            level,
            message: message.into(),
            values: vec![],
        }
        .into()
    }
}

static FAILED_TO_LOCK: &'static str = "Failed to acquire lock";
<|endoftext|>


<commit_before>/// Internal enum mapping type
///
/// This trait is internally used by `#[derive(EnumMap)]`. Despite it being
/// a public trait, it's not intended to be public. `Internal<T>` is
/// implemented by any enum type where V is a generic type representing a
/// value. The purpose of this generic type is to allow providing a value
/// type for arrays, as Rust currently does not support higher kinded types.
/// Users aren't expected to use this trait directly, but rather to use
/// `EnumMap<K, V>` which uses this internally.
///
/// This trait is also implemented by `bool` and `u8` type. While `u8` is
/// strictly speaking not an actual enum, there are good reasons to consider
/// it like one, as array of `u8` keys is a relatively common pattern.
pub trait Internal<V>: Sized {
    #[doc(hidden)]
    type Array;
    #[doc(hidden)]
    fn slice(&Self::Array) -> &[V];
    #[doc(hidden)]
    fn slice_mut(&mut Self::Array) -> &mut [V];
    #[doc(hidden)]
    fn from_usize(usize) -> Self;
    #[doc(hidden)]
    fn to_usize(self) -> usize;
    #[doc(hidden)]
    fn from_function<F: FnMut(Self) -> V>(F) -> Self::Array;
}

impl<T> Internal<T> for bool {
    type Array = [T; 2];
    fn slice(array: &[T; 2]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 2]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        match value {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 2] {
        [f(false), f(true)]
    }
}

impl<T> Internal<T> for u8 {
    type Array = [T; 256];
    fn slice(array: &[T; 256]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 256]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        value as u8
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 256] {
        array![|i| f(i); 256]
    }
}
<commit_msg>Document Internal::Array<commit_after>/// Internal enum mapping type
///
/// This trait is internally used by `#[derive(EnumMap)]`. Despite it being
/// a public trait, it's not intended to be public. `Internal<T>` is
/// implemented by any enum type where V is a generic type representing a
/// value. The purpose of this generic type is to allow providing a value
/// type for arrays, as Rust currently does not support higher kinded types.
/// Users aren't expected to use this trait directly, but rather to use
/// `EnumMap<K, V>` which uses this internally.
///
/// This trait is also implemented by `bool` and `u8` type. While `u8` is
/// strictly speaking not an actual enum, there are good reasons to consider
/// it like one, as array of `u8` keys is a relatively common pattern.
pub trait Internal<V>: Sized {
    /// Representation of an enum map for type `V`, usually an array.
    type Array;
    #[doc(hidden)]
    fn slice(&Self::Array) -> &[V];
    #[doc(hidden)]
    fn slice_mut(&mut Self::Array) -> &mut [V];
    #[doc(hidden)]
    fn from_usize(usize) -> Self;
    #[doc(hidden)]
    fn to_usize(self) -> usize;
    #[doc(hidden)]
    fn from_function<F: FnMut(Self) -> V>(F) -> Self::Array;
}

impl<T> Internal<T> for bool {
    type Array = [T; 2];
    fn slice(array: &[T; 2]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 2]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        match value {
            0 => false,
            1 => true,
            _ => unreachable!(),
        }
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 2] {
        [f(false), f(true)]
    }
}

impl<T> Internal<T> for u8 {
    type Array = [T; 256];
    fn slice(array: &[T; 256]) -> &[T] {
        array
    }
    fn slice_mut(array: &mut [T; 256]) -> &mut [T] {
        array
    }
    fn from_usize(value: usize) -> Self {
        value as u8
    }
    fn to_usize(self) -> usize {
        self as usize
    }
    fn from_function<F: FnMut(Self) -> T>(mut f: F) -> [T; 256] {
        array![|i| f(i); 256]
    }
}
<|endoftext|>


<commit_before>fn main() {
    loop {
        println!("Hello, world!");
    }
}
<commit_msg>Example of countdown while loop<commit_after>fn main() {
    while_loop(5);
}

fn infinite_loop() {
    loop {
        println!("Hello, world!");
    }
}

fn while_loop(x: i32) {
    let mut number = x;

    while number != 0 {
        println!("{}!", number);

        number = number - 1;
    }

    println!("Looping done!");
}<|endoftext|>


<commit_before>extern crate bit_vec;

use bit_vec::BitVec;

use std::io;
use std::io::prelude::*;

pub fn main() {
    let mut blacklist = BitVec::from_elem(4_294_967_296, false);

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let line = line.split('-').collect::<Vec<_>>();
        let (from, to) = (line[0].parse::<usize>().unwrap(), line[1].parse::<usize>().unwrap());
        for ip in from..to+1 {
            blacklist.set(ip, true);
        }
    }

    for i in 0..4_294_967_295 {
        if blacklist.get(i) == Some(false) {
            println!("part 1: {}", i);
            break;
        }
    }
}<commit_msg>rust day20 part2<commit_after>extern crate bit_vec;

use bit_vec::BitVec;

use std::io;
use std::io::prelude::*;

pub fn main() {
    let mut blacklist = BitVec::from_elem(4_294_967_296, false);

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let line = line.split('-').collect::<Vec<_>>();
        let (from, to) = (line[0].parse::<usize>().unwrap(), line[1].parse::<usize>().unwrap());
        for ip in from..to+1 {
            blacklist.set(ip, true);
        }
    }

    for i in 0..4_294_967_295 {
        if blacklist.get(i) == Some(false) {
            println!("part 1: {}", i);
            break;
        }
    }
    let part2 = blacklist.iter().filter(|&ip| !ip).count();
    println!("part 2: {}", part2);
}<|endoftext|>


<commit_before>use crate::api::error::{self, ErrorKind, Result};
use crate::tcpros::{Subscriber, Topic};
use crate::util::FAILED_TO_LOCK;
use crate::Message;
use log::error;
use std::collections::{BTreeSet, HashMap};
use std::iter::FromIterator;
use std::sync::{Arc, Mutex};

#[derive(Clone, Default)]
pub struct SubscriptionsTracker {
    mapping: Arc<Mutex<HashMap<String, Subscriber>>>,
}

impl SubscriptionsTracker {
    pub fn add_publishers<T>(&self, topic: &str, name: &str, publishers: T) -> Result<()>
    where
        T: Iterator<Item = String>,
    {
        if let Some(mut subscription) = self.mapping.lock().expect(FAILED_TO_LOCK).get_mut(topic) {
            let publisher_set: BTreeSet<String> = publishers.collect();
            subscription.limit_publishers_to(&publisher_set);
            for publisher in publisher_set {
                if let Err(err) = connect_to_publisher(&mut subscription, name, &publisher, topic) {
                    let info = err
                        .iter()
                        .map(|v| format!("{}", v))
                        .collect::<Vec<_>>()
                        .join("\nCaused by:");
                    error!("Failed to connect to publisher '{}': {}", publisher, info);
                    return Err(err);
                }
            }
        }
        Ok(())
    }

    #[inline]
    pub fn get_topics<T: FromIterator<Topic>>(&self) -> T {
        self.mapping
            .lock()
            .expect(FAILED_TO_LOCK)
            .values()
            .map(Subscriber::get_topic)
            .cloned()
            .collect()
    }

    pub fn add<T, F>(&self, name: &str, topic: &str, queue_size: usize, callback: F) -> Result<()>
    where
        T: Message,
        F: Fn(T, &str) + Send + 'static,
    {
        use std::collections::hash_map::Entry;
        match self
            .mapping
            .lock()
            .expect(FAILED_TO_LOCK)
            .entry(String::from(topic))
        {
            Entry::Occupied(..) => {
                error!("Duplicate subscription to topic '{}' attempted", topic);
                Err(ErrorKind::Duplicate("subscription".into()).into())
            }
            Entry::Vacant(entry) => {
                let subscriber = Subscriber::new::<T, F>(name, topic, queue_size, callback);
                entry.insert(subscriber);
                Ok(())
            }
        }
    }

    #[inline]
    pub fn remove(&self, topic: &str) {
        self.mapping.lock().expect(FAILED_TO_LOCK).remove(topic);
    }

    #[inline]
    pub fn publisher_count(&self, topic: &str) -> usize {
        self.mapping
            .lock()
            .expect(FAILED_TO_LOCK)
            .get(topic)
            .map_or(0, Subscriber::publisher_count)
    }

    #[inline]
    pub fn publisher_uris(&self, topic: &str) -> Vec<String> {
        self.mapping
            .lock()
            .expect(FAILED_TO_LOCK)
            .get(topic)
            .map_or_else(Vec::new, Subscriber::publisher_uris)
    }
}

fn connect_to_publisher(
    subscriber: &mut Subscriber,
    caller_id: &str,
    publisher: &str,
    topic: &str,
) -> Result<()> {
    if subscriber.is_connected_to(publisher) {
        return Ok(());
    }
    let (protocol, hostname, port) = request_topic(publisher, caller_id, topic)?;
    if protocol != "TCPROS" {
        bail!(ErrorKind::CommunicationIssue(format!(
            "Publisher responded with a non-TCPROS protocol: {}",
            protocol
        )))
    }
    subscriber
        .connect_to(publisher, (hostname.as_str(), port as u16))
        .map_err(|err| ErrorKind::Io(err).into())
}

fn request_topic(
    publisher_uri: &str,
    caller_id: &str,
    topic: &str,
) -> error::rosxmlrpc::Result<(String, String, i32)> {
    use crate::rosxmlrpc::error::ResultExt;
    let (_code, _message, protocols): (i32, String, (String, String, i32)) = xml_rpc::Client::new()
        .map_err(error::rosxmlrpc::ErrorKind::ForeignXmlRpc)?
        .call(
            &publisher_uri
                .parse()
                .chain_err(|| error::rosxmlrpc::ErrorKind::BadUri(publisher_uri.into()))?,
            "requestTopic",
            &(caller_id, topic, [["TCPROS"]]),
        )
        .chain_err(|| error::rosxmlrpc::ErrorKind::TopicConnectionError(topic.to_owned()))?
        .map_err(|_| "error")?;
    Ok(protocols)
}
<commit_msg>Keep on connecting to publishers in spite of errors<commit_after>use crate::api::error::{self, ErrorKind, Result};
use crate::tcpros::{Subscriber, Topic};
use crate::util::FAILED_TO_LOCK;
use crate::Message;
use log::error;
use std::collections::{BTreeSet, HashMap};
use std::iter::FromIterator;
use std::sync::{Arc, Mutex};

#[derive(Clone, Default)]
pub struct SubscriptionsTracker {
    mapping: Arc<Mutex<HashMap<String, Subscriber>>>,
}

impl SubscriptionsTracker {
    pub fn add_publishers<T>(&self, topic: &str, name: &str, publishers: T) -> Result<()>
    where
        T: Iterator<Item = String>,
    {
        let mut last_error_message = None;
        if let Some(mut subscription) = self.mapping.lock().expect(FAILED_TO_LOCK).get_mut(topic) {
            let publisher_set: BTreeSet<String> = publishers.collect();
            subscription.limit_publishers_to(&publisher_set);
            for publisher in publisher_set {
                if let Err(err) = connect_to_publisher(&mut subscription, name, &publisher, topic) {
                    let info = err
                        .iter()
                        .map(|v| format!("{}", v))
                        .collect::<Vec<_>>()
                        .join("\nCaused by:");
                    error!("Failed to connect to publisher '{}': {}", publisher, info);
                    last_error_message = Some(err);
                }
            }
        }
        match last_error_message {
            None => Ok(()),
            Some(err) => Err(err),
        }
    }

    #[inline]
    pub fn get_topics<T: FromIterator<Topic>>(&self) -> T {
        self.mapping
            .lock()
            .expect(FAILED_TO_LOCK)
            .values()
            .map(Subscriber::get_topic)
            .cloned()
            .collect()
    }

    pub fn add<T, F>(&self, name: &str, topic: &str, queue_size: usize, callback: F) -> Result<()>
    where
        T: Message,
        F: Fn(T, &str) + Send + 'static,
    {
        use std::collections::hash_map::Entry;
        match self
            .mapping
            .lock()
            .expect(FAILED_TO_LOCK)
            .entry(String::from(topic))
        {
            Entry::Occupied(..) => {
                error!("Duplicate subscription to topic '{}' attempted", topic);
                Err(ErrorKind::Duplicate("subscription".into()).into())
            }
            Entry::Vacant(entry) => {
                let subscriber = Subscriber::new::<T, F>(name, topic, queue_size, callback);
                entry.insert(subscriber);
                Ok(())
            }
        }
    }

    #[inline]
    pub fn remove(&self, topic: &str) {
        self.mapping.lock().expect(FAILED_TO_LOCK).remove(topic);
    }

    #[inline]
    pub fn publisher_count(&self, topic: &str) -> usize {
        self.mapping
            .lock()
            .expect(FAILED_TO_LOCK)
            .get(topic)
            .map_or(0, Subscriber::publisher_count)
    }

    #[inline]
    pub fn publisher_uris(&self, topic: &str) -> Vec<String> {
        self.mapping
            .lock()
            .expect(FAILED_TO_LOCK)
            .get(topic)
            .map_or_else(Vec::new, Subscriber::publisher_uris)
    }
}

fn connect_to_publisher(
    subscriber: &mut Subscriber,
    caller_id: &str,
    publisher: &str,
    topic: &str,
) -> Result<()> {
    if subscriber.is_connected_to(publisher) {
        return Ok(());
    }
    let (protocol, hostname, port) = request_topic(publisher, caller_id, topic)?;
    if protocol != "TCPROS" {
        bail!(ErrorKind::CommunicationIssue(format!(
            "Publisher responded with a non-TCPROS protocol: {}",
            protocol
        )))
    }
    subscriber
        .connect_to(publisher, (hostname.as_str(), port as u16))
        .map_err(|err| ErrorKind::Io(err).into())
}

fn request_topic(
    publisher_uri: &str,
    caller_id: &str,
    topic: &str,
) -> error::rosxmlrpc::Result<(String, String, i32)> {
    use crate::rosxmlrpc::error::ResultExt;
    let (_code, _message, protocols): (i32, String, (String, String, i32)) = xml_rpc::Client::new()
        .map_err(error::rosxmlrpc::ErrorKind::ForeignXmlRpc)?
        .call(
            &publisher_uri
                .parse()
                .chain_err(|| error::rosxmlrpc::ErrorKind::BadUri(publisher_uri.into()))?,
            "requestTopic",
            &(caller_id, topic, [["TCPROS"]]),
        )
        .chain_err(|| error::rosxmlrpc::ErrorKind::TopicConnectionError(topic.to_owned()))?
        .map_err(|_| "error")?;
    Ok(protocols)
}
<|endoftext|>


<commit_before>use clap::{App, Arg};

fn main() {
    // Of the three argument types, flags are the most simple. Flags are simple switches which can
    // be either "on" or "off"
    //
    // clap also supports multiple occurrences of flags, the common example is "verbosity" where a
    // user could want a little information with "-v" or tons of information with "-v -v" or "-vv"
    let matches = App::new("MyApp")
        // Regular App configuration goes here...
        // We'll add a flag that represents an awesome meter...
        //
        // I'll explain each possible setting that "flags" accept. Keep in mind
        // that you DO NOT need to set each of these for every flag, only the ones
        // you want for your individual case.
        .arg(
            Arg::new("awesome")
                .about("turns up the awesome") // Displayed when showing help info
                .short('a') // Trigger this arg with "-a"
                .long("awesome") // Trigger this arg with "--awesome"
                .multiple_occurrences(true) // This flag should allow multiple
                // occurrences such as "-aaa" or "-a -a"
                .requires("config") // Says, "If the user uses -a, they MUST
                // also use this other 'config' arg too"
                // Can also specify a list using
                // requires_all(Vec<&str>)
                .conflicts_with("output"), // Opposite of requires(), says "if the
                                           // user uses -a, they CANNOT use 'output'"
                                           // also has a conflicts_with_all(Vec<&str>)
                                           // and an exclusive(true)
        )
        .arg(
            // Sometimes we might want to accept one of the following: `--pseudo-flag`, `--pseudo-flag=true`, `--pseudo-flag=false.`
            // The following is the `pseudo-flag` pattern stated in https://github.com/clap-rs/clap/issues/1649#issuecomment-661274943
            Arg::new("pseudo-flag") // Create a "pesudo-flag" with optional value
                .possible_values(&["true", "false"]) // Limit that value to `true` of `false`
                .long("pseudo-flag")
                .min_values(0)
                .max_values(1),
        )
        .arg("-c, --config=[FILE] 'sets a custom config file'")
        .arg("<output> 'sets an output file'")
        .get_matches();

    // We can find out whether or not awesome was used
    if matches.is_present("awesome") {
        println!("Awesomeness is turned on");
    }

    // Same thing with `pseudo-flag`
    if matches.value_of("pseudo-flag") != Some("false") {
        println!("Pseudo-flag is turned on");
    }

    // If we set the multiple option of a flag we can check how many times the user specified
    //
    // Note: if we did not specify the multiple option, and the user used "awesome" we would get
    // a 1 (no matter how many times they actually used it), or a 0 if they didn't use it at all
    match matches.occurrences_of("awesome") {
        0 => println!("Nothing is awesome"),
        1 => println!("Some things are awesome"),
        2 => println!("Lots of things are awesome"),
        _ => println!("EVERYTHING is awesome!"),
    }

    // Continued program logic goes here...
}
<commit_msg>docs(example): update `pseudo-flag` example<commit_after>use clap::{App, Arg};

fn main() {
    // Of the three argument types, flags are the most simple. Flags are simple switches which can
    // be either "on" or "off"
    //
    // clap also supports multiple occurrences of flags, the common example is "verbosity" where a
    // user could want a little information with "-v" or tons of information with "-v -v" or "-vv"
    let matches = App::new("MyApp")
        // Regular App configuration goes here...
        // We'll add a flag that represents an awesome meter...
        //
        // I'll explain each possible setting that "flags" accept. Keep in mind
        // that you DO NOT need to set each of these for every flag, only the ones
        // you want for your individual case.
        .arg(
            Arg::new("awesome")
                .about("turns up the awesome") // Displayed when showing help info
                .short('a') // Trigger this arg with "-a"
                .long("awesome") // Trigger this arg with "--awesome"
                .multiple_occurrences(true) // This flag should allow multiple
                // occurrences such as "-aaa" or "-a -a"
                .requires("config") // Says, "If the user uses -a, they MUST
                // also use this other 'config' arg too"
                // Can also specify a list using
                // requires_all(Vec<&str>)
                .conflicts_with("output"), // Opposite of requires(), says "if the
                                           // user uses -a, they CANNOT use 'output'"
                                           // also has a conflicts_with_all(Vec<&str>)
                                           // and an exclusive(true)
        )
        .arg(
            // Sometimes we might want to accept one of the following: `--pseudo-flag`, `--pseudo-flag=true`, `--pseudo-flag=false.`
            // The following is the `pseudo-flag` pattern stated in https://github.com/clap-rs/clap/issues/1649#issuecomment-661274943
            Arg::new("pseudo-flag") // Create a "pesudo-flag" with optional value
                .possible_values(&["true", "false"]), // Limit that value to `true` of `false`
        )
        .arg("-c, --config=[FILE] 'sets a custom config file'")
        .arg("<output> 'sets an output file'")
        .get_matches();

    // We can find out whether or not awesome was used
    if matches.is_present("awesome") {
        println!("Awesomeness is turned on");
    }

    // Same thing with `pseudo-flag`
    if matches.value_of("pseudo-flag") != Some("false") {
        println!("Pseudo-flag is turned on");
    }

    // If we set the multiple option of a flag we can check how many times the user specified
    //
    // Note: if we did not specify the multiple option, and the user used "awesome" we would get
    // a 1 (no matter how many times they actually used it), or a 0 if they didn't use it at all
    match matches.occurrences_of("awesome") {
        0 => println!("Nothing is awesome"),
        1 => println!("Some things are awesome"),
        2 => println!("Lots of things are awesome"),
        _ => println!("EVERYTHING is awesome!"),
    }

    // Continued program logic goes here...
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]

#![allow(unused_variable)]

fn takes_an_immutable_reference(a: &i32) {
}

fn takes_a_mutable_reference(a: &mut i32) {
}

struct MyStruct;

impl MyStruct {
    fn takes_an_immutable_reference(&self, a: &i32) {
    }

    fn takes_a_mutable_reference(&self, a: &mut i32) {
    }
}

#[deny(unnecessary_mut_passed)]
fn main() {
    // Functions
    takes_an_immutable_reference(&mut 42); //~ERROR The function/method "takes_an_immutable_reference" doesn't need a mutable reference

    // Methods
    let my_struct = MyStruct;
    my_struct.takes_an_immutable_reference(&mut 42); //~ERROR The function/method "takes_an_immutable_reference" doesn't need a mutable reference

    // No error

    // Functions
    takes_an_immutable_reference(&42);
    takes_a_mutable_reference(&mut 42);
    let a = &mut 42;
    takes_an_immutable_reference(a);

    // Methods
    my_struct.takes_an_immutable_reference(&42);
    my_struct.takes_a_mutable_reference(&mut 42);
    my_struct.takes_an_immutable_reference(a);

}
<commit_msg>Well, fix them again<commit_after>#![feature(plugin)]
#![plugin(clippy)]

#![allow(unused_variables)]

fn takes_an_immutable_reference(a: &i32) {
}

fn takes_a_mutable_reference(a: &mut i32) {
}

struct MyStruct;

impl MyStruct {
    fn takes_an_immutable_reference(&self, a: &i32) {
    }

    fn takes_a_mutable_reference(&self, a: &mut i32) {
    }
}

#[deny(unnecessary_mut_passed)]
fn main() {
    // Functions
    takes_an_immutable_reference(&mut 42); //~ERROR The function/method "takes_an_immutable_reference" doesn't need a mutable reference

    // Methods
    let my_struct = MyStruct;
    my_struct.takes_an_immutable_reference(&mut 42); //~ERROR The function/method "takes_an_immutable_reference" doesn't need a mutable reference

    // No error

    // Functions
    takes_an_immutable_reference(&42);
    takes_a_mutable_reference(&mut 42);
    let a = &mut 42;
    takes_an_immutable_reference(a);

    // Methods
    my_struct.takes_an_immutable_reference(&42);
    my_struct.takes_a_mutable_reference(&mut 42);
    my_struct.takes_an_immutable_reference(a);

}
<|endoftext|>


<commit_before>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{self, Serialize};

use imp_prelude::*;

use super::arraytraits::ARRAY_FORMAT_VERSION;
use super::Elements;

impl<A, D, S> Serialize for ArrayBase<S, D>
    where A: Serialize,
          D: Dimension + Serialize,
          S: DataOwned<Elem = A>

{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: serde::Serializer
    {
        let mut struct_state = try!(serializer.serialize_struct("Array", 3));
        try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION));
        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.dim()));
        try!(serializer.serialize_struct_elt(&mut struct_state, "data", self.iter()));
        serializer.serialize_struct_end(struct_state)
    }
}

impl<'a, A, D> Serialize for Elements<'a, A, D>
    where A: Serialize,
          D: Dimension + Serialize
{
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        let mut seq_state = try!(serializer.serialize_seq(Some(self.len())));
        for elt in self.clone() {
            try!(serializer.serialize_seq_elt(&mut seq_state, elt));
        }
        serializer.serialize_seq_end(seq_state)
    }
}
<commit_msg>serde: Expand ArrayBase Serialize impl to both owned arrays and array views<commit_after>// Copyright 2014-2016 bluss and ndarray developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use serde::{self, Serialize};

use imp_prelude::*;

use super::arraytraits::ARRAY_FORMAT_VERSION;
use super::Elements;

impl<A, D, S> Serialize for ArrayBase<S, D>
    where A: Serialize,
          D: Dimension + Serialize,
          S: Data<Elem = A>

{
    fn serialize<Se>(&self, serializer: &mut Se) -> Result<(), Se::Error>
        where Se: serde::Serializer
    {
        let mut struct_state = try!(serializer.serialize_struct("Array", 3));
        try!(serializer.serialize_struct_elt(&mut struct_state, "v", ARRAY_FORMAT_VERSION));
        try!(serializer.serialize_struct_elt(&mut struct_state, "dim", self.dim()));
        try!(serializer.serialize_struct_elt(&mut struct_state, "data", self.iter()));
        serializer.serialize_struct_end(struct_state)
    }
}

impl<'a, A, D> Serialize for Elements<'a, A, D>
    where A: Serialize,
          D: Dimension + Serialize
{
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        let mut seq_state = try!(serializer.serialize_seq(Some(self.len())));
        for elt in self.clone() {
            try!(serializer.serialize_seq_elt(&mut seq_state, elt));
        }
        serializer.serialize_seq_end(seq_state)
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::io::{self, Write};
use std::iter;
use std::process;

/// A trait that adds the ability for numbers to find their digit count and to convert them to padded strings.
pub trait Digits {
    /// Counts the number of digits in a number. **Example:** {{0 = 0}, {1 = 1}, {10 = 2}, {100 = 3}}
    fn digits(&self) -> usize;

    /// Converts a number into a padded String, using `pad` as the character to pad with and `limit` as the size.
    fn to_padded_string(&self, pad: char, limit: usize) -> String;
}

impl Digits for usize {
    fn digits(&self) -> usize {
        let mut digits = if *self % 10 == 0 {
            1
        } else {
            0
        };
        let mut temp = 1;
        while temp < *self {
            digits += 1;
            temp = (temp << 3) + (temp << 1);
        }
        digits
    }

    fn to_padded_string(&self, pad: char, limit: usize) -> String {
        if self.digits() < limit {
            let mut output = String::with_capacity(limit);
            output.push_str(&iter::repeat(pad).take(limit - self.digits()).collect::<String>());
            output.push_str(&self.to_string());
            output
        } else {
            self.to_string()
        }
    }
}

pub trait Try {
    type Succ;

    /// Unwrap or abort program with an exit status of 1.
    fn try(self, message: &[u8], stderr: &mut io::Stderr) -> Self::Succ;
}

pub trait TryAndIgnore {
    type Succ;

    /// Print an error message and ignore the error.
    fn try_and_ignore(self, message: &[u8], stderr: &mut io::Stderr) -> Self::Succ;
}

impl<T, U: Error> Try for Result<T, U> {
    type Succ = T;

    fn try(self, message: &[u8], stderr: &mut io::Stderr) -> T {
        self.unwrap_or_else(|e| {
            let mut stderr = stderr.lock();
            let _ = stderr.write(b"tv-renamer: ");
            let _ = stderr.write(message);
            let _ = stderr.write(e.description().as_bytes());
            let _ = stderr.write(b"\n");
            let _ = stderr.flush();
            process::exit(1);
        })
    }
}

impl<T, U: Error> TryAndIgnore for Result<T, U> {
    type Succ = T;

    fn try_and_ignore(self, message: &[u8], stderr: &mut io::Stderr) -> T {
        self.unwrap_or_else(|_| {
            let mut stderr = stderr.lock();
            let _ = stderr.write(b"tv-renamer: ");
            let _ = stderr.write(message);
            let _ = stderr.write(b"\n");
            let _ = stderr.flush();
            process::exit(1);
        })
    }
}
impl<T> Try for Option<T> {
    type Succ = T;

    fn try(self, message: &[u8], stderr: &mut io::Stderr) -> T {
        self.unwrap_or_else(|| {
            let mut stderr = stderr.lock();
            let _ = stderr.write(b"tv-renamer: ");
            let _ = stderr.write(message);
            let _ = stderr.write(b"\n");
            let _ = stderr.flush();
            process::exit(1);
        })
    }
}

#[test]
fn test_digits() {
    assert_eq!(  5.to_padded_string('0', 2).as_str(), "05");
    assert_eq!( 10.to_padded_string('0', 2).as_str(), "10");
    assert_eq!(100.to_padded_string('0', 2).as_str(), "100");
    assert_eq!( 10.to_padded_string('0', 3).as_str(), "010");
    assert_eq!(  5.to_padded_string('0', 3).as_str(), "005");
}
<commit_msg>Fix Introduced Bug That Causes 01 to become 001 instead<commit_after>use std::error::Error;
use std::io::{self, Write};
use std::iter;
use std::process;

/// A trait that adds the ability for numbers to find their digit count and to convert them to padded strings.
pub trait Digits {
    /// Counts the number of digits in a number. **Example:** {{0 = 0}, {1 = 1}, {10 = 2}, {100 = 3}}
    fn digits(&self) -> usize;

    /// Converts a number into a padded String, using `pad` as the character to pad with and `limit` as the size.
    fn to_padded_string(&self, pad: char, limit: usize) -> String;
}

impl Digits for usize {
    fn digits(&self) -> usize {
        let mut digits = if *self == 1 || *self % 10 == 0 { 1 } else { 0 };
        let mut temp = 1;
        while temp < *self {
            digits += 1;
            temp = (temp << 3) + (temp << 1);
        }
        digits
    }

    fn to_padded_string(&self, pad: char, limit: usize) -> String {
        if self.digits() < limit {
            let mut output = String::with_capacity(limit);
            output.push_str(&iter::repeat(pad).take(limit - self.digits()).collect::<String>());
            output.push_str(&self.to_string());
            output
        } else {
            self.to_string()
        }
    }
}

pub trait Try {
    type Succ;

    /// Unwrap or abort program with an exit status of 1.
    fn try(self, message: &[u8], stderr: &mut io::Stderr) -> Self::Succ;
}

pub trait TryAndIgnore {
    type Succ;

    /// Print an error message and ignore the error.
    fn try_and_ignore(self, message: &[u8], stderr: &mut io::Stderr) -> Self::Succ;
}

impl<T, U: Error> Try for Result<T, U> {
    type Succ = T;

    fn try(self, message: &[u8], stderr: &mut io::Stderr) -> T {
        self.unwrap_or_else(|e| {
            let mut stderr = stderr.lock();
            let _ = stderr.write(b"tv-renamer: ");
            let _ = stderr.write(message);
            let _ = stderr.write(e.description().as_bytes());
            let _ = stderr.write(b"\n");
            let _ = stderr.flush();
            process::exit(1);
        })
    }
}

impl<T, U: Error> TryAndIgnore for Result<T, U> {
    type Succ = T;

    fn try_and_ignore(self, message: &[u8], stderr: &mut io::Stderr) -> T {
        self.unwrap_or_else(|_| {
            let mut stderr = stderr.lock();
            let _ = stderr.write(b"tv-renamer: ");
            let _ = stderr.write(message);
            let _ = stderr.write(b"\n");
            let _ = stderr.flush();
            process::exit(1);
        })
    }
}
impl<T> Try for Option<T> {
    type Succ = T;

    fn try(self, message: &[u8], stderr: &mut io::Stderr) -> T {
        self.unwrap_or_else(|| {
            let mut stderr = stderr.lock();
            let _ = stderr.write(b"tv-renamer: ");
            let _ = stderr.write(message);
            let _ = stderr.write(b"\n");
            let _ = stderr.flush();
            process::exit(1);
        })
    }
}

#[test]
fn test_digits() {
    assert_eq!(1.digits(), 1);
    assert_eq!(9.digits(), 1);
    assert_eq!(10.digits(), 2);
    assert_eq!(100.digits(), 3);
}
#[test]
fn test_padded_digits() {
    assert_eq!(  5.to_padded_string('0', 2).as_str(), "05");
    assert_eq!( 10.to_padded_string('0', 2).as_str(), "10");
    assert_eq!(100.to_padded_string('0', 2).as_str(), "100");
    assert_eq!( 10.to_padded_string('0', 3).as_str(), "010");
    assert_eq!(  5.to_padded_string('0', 3).as_str(), "005");
}
<|endoftext|>


<commit_before>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate ssz;

use ssz::{DecodeError, Decodable, Encodable};

// Fuzz ssz_decode(u8)
fuzz_target!(|data: &[u8]| {
    let result: Result<(u8, usize), DecodeError> = Decodable::ssz_decode(data, 0);
    if data.len() > 0 {
        // Should have valid result
        let (number_u8, index) = result.unwrap();
        assert_eq!(number_u8, data[0]);
        assert_eq!(index, 2);
    } else {
        // Length of 0 should return error
        assert_eq!(result, Err(DecodeError::TooShort));
    }
});
<commit_msg>Fixing minor bug in assert statement<commit_after>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate ssz;

use ssz::{DecodeError, Decodable, Encodable};

// Fuzz ssz_decode(u8)
fuzz_target!(|data: &[u8]| {
    let result: Result<(u8, usize), DecodeError> = Decodable::ssz_decode(data, 0);
    if data.len() > 0 {
        // Should have valid result
        let (number_u8, index) = result.unwrap();
        assert_eq!(number_u8, data[0]);
        assert_eq!(index, 1);
    } else {
        // Length of 0 should return error
        assert_eq!(result, Err(DecodeError::TooShort));
    }
});
<|endoftext|>


<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::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, ExitStatus};
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<ExitStatus, io::Error>, opts: &getopts::Options) -> i32 {
    match status {
        Err(e) => {
            print_usage_to_stderr(opts, &e.to_string());
            FAILURE
        }
        Ok(status) => {
            if status.success() {
                SUCCESS
            } else {
                status.code().unwrap_or(FAILURE)
            }
        }
    }
}

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

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

    // Currently only bin and lib files get formatted
    let files: Vec<_> = targets
        .into_iter()
        .inspect(|t| {
            if verbosity == Verbosity::Verbose {
                println!("[{}] {:?}", t.kind, t.path)
            }
        }).map(|t| t.path)
        .collect();

    run_rustfmt(&files, &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,
}

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(),
        }
    }
}

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(
    files: &[PathBuf],
    fmt_args: &[String],
    verbosity: Verbosity,
) -> Result<ExitStatus, io::Error> {
    let stdout = if verbosity == Verbosity::Quiet {
        std::process::Stdio::null()
    } else {
        std::process::Stdio::inherit()
    };

    if verbosity == Verbosity::Verbose {
        print!("rustfmt");
        for a in fmt_args {
            print!(" {}", a);
        }
        for f in files {
            print!(" {}", f.display());
        }
        println!();
    }

    let mut command = Command::new("rustfmt")
        .stdout(stdout)
        .args(files)
        .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,
        })?;

    command.wait()
}

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(..) => Err(io::Error::new(
            io::ErrorKind::Other,
            "`cargo manifest` failed.",
        )),
    }
}
<commit_msg>cargo fmt: fix typo in format_crate(): (verison -> version)<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::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, ExitStatus};
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<ExitStatus, io::Error>, opts: &getopts::Options) -> i32 {
    match status {
        Err(e) => {
            print_usage_to_stderr(opts, &e.to_string());
            FAILURE
        }
        Ok(status) => {
            if status.success() {
                SUCCESS
            } else {
                status.code().unwrap_or(FAILURE)
            }
        }
    }
}

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

fn format_crate(
    verbosity: Verbosity,
    strategy: &CargoFmtStrategy,
) -> Result<ExitStatus, 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
    let files: Vec<_> = targets
        .into_iter()
        .inspect(|t| {
            if verbosity == Verbosity::Verbose {
                println!("[{}] {:?}", t.kind, t.path)
            }
        }).map(|t| t.path)
        .collect();

    run_rustfmt(&files, &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,
}

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(),
        }
    }
}

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(
    files: &[PathBuf],
    fmt_args: &[String],
    verbosity: Verbosity,
) -> Result<ExitStatus, io::Error> {
    let stdout = if verbosity == Verbosity::Quiet {
        std::process::Stdio::null()
    } else {
        std::process::Stdio::inherit()
    };

    if verbosity == Verbosity::Verbose {
        print!("rustfmt");
        for a in fmt_args {
            print!(" {}", a);
        }
        for f in files {
            print!(" {}", f.display());
        }
        println!();
    }

    let mut command = Command::new("rustfmt")
        .stdout(stdout)
        .args(files)
        .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,
        })?;

    command.wait()
}

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(..) => Err(io::Error::new(
            io::ErrorKind::Other,
            "`cargo manifest` failed.",
        )),
    }
}
<|endoftext|>