<commit_before>/// Irradiance d'un point, en Watts par mètre carré, en fonction de la masse d'air
/// devant être traversée par les rayons du Soleil.
pub fn irradiance(air_mass: f64) -> f64 {
    1.353 * 0.7f64.powf(air_mass.powf(0.678)) * 1000.0
}

/// Masse d'air devant être traversée par les rayons du Soleil en fonction de l'angle
/// zénithal.
pub fn air_mass(zenith_angle: f64) -> f64 {
    assert!(0.0 <= zenith_angle && zenith_angle <= 90.0);
    1.0 / zenith_angle.to_radians().cos()
}

/// Angle zénithal en fonction de l'angle d'élévation.
pub fn zenith_angle(elevation_angle: f64) -> f64 {
    assert!(0.0 <= elevation_angle && elevation_angle <= 90.0);
    90.0 - elevation_angle
}

/// Angle d'élévation en fonction de l'angle de déclinaison, de la latitude et de l'angle horaire.
pub fn elevation_angle(declination_angle: f64,
                       latitude: f64,
                       hour_angle: f64)
                       -> f64 {
    assert!(-23.45 <= declination_angle && declination_angle <= 23.45);
    assert!(-90.0 <= latitude && latitude <= 90.0);
    assert!(-180.0 <= hour_angle && hour_angle <= 180.0);
    (declination_angle.to_radians().sin() * latitude.to_radians().sin() +
     declination_angle.to_radians().cos() * latitude.to_radians().cos() *
     hour_angle.to_radians().cos())
        .asin()
        .to_degrees()
}

/// Angle de déclinaison en fonction du jour de l'année.
pub fn declination_angle(day_of_year: u32) -> f64 {
    assert!(1 <= day_of_year && day_of_year <= 366); // leap years

    (23.45f64.to_radians().sin() *
     ((360.0 / 365.0) * (day_of_year - 81) as f64).to_radians().sin())
        .asin()
        .to_degrees()
}

/// Angle horaire, en degrés, en fonction de l'heure solaire.
pub fn hour_angle(solar_time: f64) -> f64 {
    assert!(0.0 <= solar_time && solar_time <= 24.0);
    15.0 * (solar_time - 12.0)
}

/// Heure solaire en fonction de l'heure locale et du facteur de correction de l'heure.
pub fn solar_time(local_time: f64, time_correction_factor: f64) -> f64 {
    local_time + time_correction_factor / 60.0
}

/// Facteur de correction de l'heure, en minutes, en fonction de la longitude du point étudié,
/// de la longitude du méridien standard local et de l'équation du temps.
pub fn time_correction_factor(longitude: f64,
                              local_standard_meridian_longitude: f64,
                              equation_of_time: f64)
                              -> f64 {
    assert!(-15.0 <= equation_of_time && equation_of_time <= 20.0);
    4.0 * (longitude - local_standard_meridian_longitude) + equation_of_time
}

/// Longitude du méridien standard local en fonction du décalage horaire par rapport
/// au fuseau horaire GMT.
pub fn local_standard_meridian_longitude(gmt_offset: f64) -> f64 {
    15.0 * gmt_offset
}

/// Équation du temps en fonction du jour de l'année, en minutes.
pub fn equation_of_time(day_of_year: u32) -> f64 {
    let b = (360.0 / 365.0) * (day_of_year - 81) as f64;
    9.87 * (2.0 * b).to_radians().sin() - 7.53 * b.to_radians().cos() -
    1.5 * b.to_radians().sin()
}
<commit_msg>shorten line length to 80 chars max<commit_after>/// Éclairement énergétique solaire d'un point, en Watts par mètre carré,
/// en fonction de la masse d'air devant être traversée par les rayons du
/// Soleil.
pub fn irradiance(air_mass: f64) -> f64 {
    1.353 * 0.7f64.powf(air_mass.powf(0.678)) * 1000.0
}

/// Masse d'air devant être traversée par les rayons du Soleil en fonction de
/// l'angle zénithal.
pub fn air_mass(zenith_angle: f64) -> f64 {
    assert!(0.0 <= zenith_angle && zenith_angle <= 90.0);
    1.0 / zenith_angle.to_radians().cos()
}

/// Angle zénithal en fonction de l'angle d'élévation.
pub fn zenith_angle(elevation_angle: f64) -> f64 {
    assert!(0.0 <= elevation_angle && elevation_angle <= 90.0);
    90.0 - elevation_angle
}

/// Angle d'élévation en fonction de l'angle de déclinaison, de la latitude et
/// de l'angle horaire.
pub fn elevation_angle(declination_angle: f64,
                       latitude: f64,
                       hour_angle: f64)
                       -> f64 {
    assert!(-23.45 <= declination_angle && declination_angle <= 23.45);
    assert!(-90.0 <= latitude && latitude <= 90.0);
    assert!(-180.0 <= hour_angle && hour_angle <= 180.0);
    (declination_angle.to_radians().sin() * latitude.to_radians().sin() +
     declination_angle.to_radians().cos() * latitude.to_radians().cos() *
     hour_angle.to_radians().cos())
        .asin()
        .to_degrees()
}

/// Angle de déclinaison en fonction du jour de l'année.
pub fn declination_angle(day_of_year: u32) -> f64 {
    assert!(1 <= day_of_year && day_of_year <= 366); // leap years

    (23.45f64.to_radians().sin() *
     ((360.0 / 365.0) * (day_of_year - 81) as f64).to_radians().sin())
        .asin()
        .to_degrees()
}

/// Angle horaire, en degrés, en fonction de l'heure solaire.
pub fn hour_angle(solar_time: f64) -> f64 {
    assert!(0.0 <= solar_time && solar_time <= 24.0);
    15.0 * (solar_time - 12.0)
}

/// Heure solaire en fonction de l'heure locale et du facteur de correction de
/// l'heure.
pub fn solar_time(local_time: f64, time_correction_factor: f64) -> f64 {
    local_time + time_correction_factor / 60.0
}

/// Facteur de correction de l'heure, en minutes, en fonction de la longitude
/// du point étudié, de la longitude du méridien standard local et de
/// l'équation du temps.
pub fn time_correction_factor(longitude: f64,
                              local_standard_meridian_longitude: f64,
                              equation_of_time: f64)
                              -> f64 {
    assert!(-15.0 <= equation_of_time && equation_of_time <= 20.0);
    4.0 * (longitude - local_standard_meridian_longitude) + equation_of_time
}

/// Longitude du méridien standard local en fonction du décalage horaire par
/// rapport au fuseau horaire GMT.
pub fn local_standard_meridian_longitude(gmt_offset: f64) -> f64 {
    15.0 * gmt_offset
}

/// Équation du temps en fonction du jour de l'année, en minutes.
pub fn equation_of_time(day_of_year: u32) -> f64 {
    let b = (360.0 / 365.0) * (day_of_year - 81) as f64;
    9.87 * (2.0 * b).to_radians().sin() - 7.53 * b.to_radians().cos() -
    1.5 * b.to_radians().sin()
}
<|endoftext|>


<commit_before><commit_msg>Add further BeaconBlock v0.5.0 updates<commit_after><|endoftext|>


<commit_before>use std::collections::BTreeMap;

use comfy_table::*;

use pueue_lib::network::message::TaskLogMessage;
use pueue_lib::settings::Settings;
use pueue_lib::task::{Task, TaskResult, TaskStatus};

use super::OutputStyle;
use crate::cli::SubCommand;

mod json;
mod local;
mod remote;

use json::*;
use local::*;
use remote::*;

/// Determine how many lines of output should be printed/returned.
/// `None` implicates that all lines are printed.
///
/// By default, everything is returned for single tasks and only some lines for multiple.
/// `json` is an exception to this, in json mode we always only return some lines
/// (unless otherwise explicitely requested).
///
/// `full` always forces the full log output
/// `lines` force a specific amount of lines
pub fn determine_log_line_amount(full: bool, lines: &Option<usize>) -> Option<usize> {
    if full {
        None
    } else if let Some(lines) = lines {
        Some(*lines)
    } else {
        // By default, only some lines are shown per task
        Some(15)
    }
}

/// Print the log ouput of finished tasks.
/// Either print the logs of every task
/// or only print the logs of the specified tasks.
pub fn print_logs(
    mut task_logs: BTreeMap<usize, TaskLogMessage>,
    cli_command: &SubCommand,
    style: &OutputStyle,
    settings: &Settings,
) {
    // Get actual commandline options.
    // This is necessary to know how we should display/return the log information.
    let (json, task_ids, lines, full) = match cli_command {
        SubCommand::Log {
            json,
            task_ids,
            lines,
            full,
        } => (*json, task_ids.clone(), *lines, *full),
        _ => panic!("Got wrong Subcommand {cli_command:?} in print_log. This shouldn't happen"),
    };

    let lines = determine_log_line_amount(full, &lines);

    // Return the server response in json representation.
    if json {
        print_log_json(task_logs, settings, lines);
        return;
    }

    // Check some early return conditions
    if task_ids.is_empty() && task_logs.is_empty() {
        println!("There are no finished tasks");
        return;
    }

    if !task_ids.is_empty() && task_logs.is_empty() {
        println!("There are no finished tasks for your specified ids");
        return;
    }

    // Iterate over each task and print the respective log.
    let mut task_iter = task_logs.iter_mut().peekable();
    while let Some((_, task_log)) = task_iter.next() {
        print_log(task_log, style, settings, lines);

        // Add a newline if there is another task that's going to be printed.
        if let Some((_, task_log)) = task_iter.peek() {
            if matches!(
                &task_log.task.status,
                TaskStatus::Done(_) | TaskStatus::Running | TaskStatus::Paused,
            ) {
                println!();
            }
        }
    }
}

/// Print the log of a single task.
///
/// message: The message returned by the daemon. This message includes all
///          requested tasks and the tasks' logs, if we don't read local logs.
/// lines: Whether we should reduce the log output of each task to a specific number of lines.
///         `None` implicates that everything should be printed.
///         This is only important, if we read local lines.
fn print_log(
    message: &mut TaskLogMessage,
    style: &OutputStyle,
    settings: &Settings,
    lines: Option<usize>,
) {
    let task = &message.task;
    // We only show logs of finished or running tasks.
    if !matches!(
        task.status,
        TaskStatus::Done(_) | TaskStatus::Running | TaskStatus::Paused
    ) {
        return;
    }

    print_task_info(task, style);

    if settings.client.read_local_logs {
        print_local_log(message.task.id, style, settings, lines);
    } else if message.output.is_some() {
        print_remote_log(message, style);
    } else {
        println!("Logs requested from pueue daemon, but none received. Please report this bug.");
    }
}

/// Print some information about a task, which is displayed on top of the task's log output.
fn print_task_info(task: &Task, style: &OutputStyle) {
    // Print task id and exit code.
    let task_cell = style.styled_cell(format!("Task {}: ", task.id), None, Some(Attribute::Bold));

    let (exit_status, color) = match &task.status {
        TaskStatus::Paused => ("paused".into(), Color::White),
        TaskStatus::Running => ("running".into(), Color::Yellow),
        TaskStatus::Done(result) => match result {
            TaskResult::Success => ("completed successfully".into(), Color::Green),
            TaskResult::Failed(exit_code) => {
                (format!("failed with exit code {}", exit_code), Color::Red)
            }
            TaskResult::FailedToSpawn(err) => (format!("failed to spawn: {}", err), Color::Red),
            TaskResult::Killed => ("killed by system or user".into(), Color::Red),
            TaskResult::Errored => ("some IO error.\n Check daemon log.".into(), Color::Red),
            TaskResult::DependencyFailed => ("dependency failed".into(), Color::Red),
        },
        _ => (task.status.to_string(), Color::White),
    };
    let status_cell = style.styled_cell(exit_status, Some(color), None);

    // The styling of the task number and status is done by a single-row table.
    let mut table = Table::new();
    table.load_preset("││─ └──┘     ─ ┌┐  ");
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
    table.set_header(vec![task_cell, status_cell]);
    println!("{}", table);

    // All other information is alligned and styled by using a separat table.
    let mut table = Table::new();
    table.load_preset(comfy_table::presets::NOTHING);
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);

    // Command and path
    table.add_row(vec![
        style.styled_cell("Command:", None, Some(Attribute::Bold)),
        Cell::new(&task.command),
    ]);
    table.add_row(vec![
        style.styled_cell("Path:", None, Some(Attribute::Bold)),
        Cell::new(&task.path.to_string_lossy()),
    ]);

    // Start and end time
    if let Some(start) = task.start {
        table.add_row(vec![
            style.styled_cell("Start:", None, Some(Attribute::Bold)),
            Cell::new(start.to_rfc2822()),
        ]);
    }
    if let Some(end) = task.end {
        table.add_row(vec![
            style.styled_cell("End:", None, Some(Attribute::Bold)),
            Cell::new(end.to_rfc2822()),
        ]);
    }

    // Set the padding of the left column to 0 align the keys to the right
    let first_column = table.column_mut(0).unwrap();
    first_column.set_cell_alignment(CellAlignment::Right);
    first_column.set_padding((0, 0));

    println!("{table}");
}
<commit_msg>fix: Force comfy-table styling with --color=always in logs<commit_after>use std::collections::BTreeMap;

use comfy_table::*;

use pueue_lib::network::message::TaskLogMessage;
use pueue_lib::settings::Settings;
use pueue_lib::task::{Task, TaskResult, TaskStatus};

use super::OutputStyle;
use crate::cli::SubCommand;

mod json;
mod local;
mod remote;

use json::*;
use local::*;
use remote::*;

/// Determine how many lines of output should be printed/returned.
/// `None` implicates that all lines are printed.
///
/// By default, everything is returned for single tasks and only some lines for multiple.
/// `json` is an exception to this, in json mode we always only return some lines
/// (unless otherwise explicitely requested).
///
/// `full` always forces the full log output
/// `lines` force a specific amount of lines
pub fn determine_log_line_amount(full: bool, lines: &Option<usize>) -> Option<usize> {
    if full {
        None
    } else if let Some(lines) = lines {
        Some(*lines)
    } else {
        // By default, only some lines are shown per task
        Some(15)
    }
}

/// Print the log ouput of finished tasks.
/// Either print the logs of every task
/// or only print the logs of the specified tasks.
pub fn print_logs(
    mut task_logs: BTreeMap<usize, TaskLogMessage>,
    cli_command: &SubCommand,
    style: &OutputStyle,
    settings: &Settings,
) {
    // Get actual commandline options.
    // This is necessary to know how we should display/return the log information.
    let (json, task_ids, lines, full) = match cli_command {
        SubCommand::Log {
            json,
            task_ids,
            lines,
            full,
        } => (*json, task_ids.clone(), *lines, *full),
        _ => panic!("Got wrong Subcommand {cli_command:?} in print_log. This shouldn't happen"),
    };

    let lines = determine_log_line_amount(full, &lines);

    // Return the server response in json representation.
    if json {
        print_log_json(task_logs, settings, lines);
        return;
    }

    // Check some early return conditions
    if task_ids.is_empty() && task_logs.is_empty() {
        println!("There are no finished tasks");
        return;
    }

    if !task_ids.is_empty() && task_logs.is_empty() {
        println!("There are no finished tasks for your specified ids");
        return;
    }

    // Iterate over each task and print the respective log.
    let mut task_iter = task_logs.iter_mut().peekable();
    while let Some((_, task_log)) = task_iter.next() {
        print_log(task_log, style, settings, lines);

        // Add a newline if there is another task that's going to be printed.
        if let Some((_, task_log)) = task_iter.peek() {
            if matches!(
                &task_log.task.status,
                TaskStatus::Done(_) | TaskStatus::Running | TaskStatus::Paused,
            ) {
                println!();
            }
        }
    }
}

/// Print the log of a single task.
///
/// message: The message returned by the daemon. This message includes all
///          requested tasks and the tasks' logs, if we don't read local logs.
/// lines: Whether we should reduce the log output of each task to a specific number of lines.
///         `None` implicates that everything should be printed.
///         This is only important, if we read local lines.
fn print_log(
    message: &mut TaskLogMessage,
    style: &OutputStyle,
    settings: &Settings,
    lines: Option<usize>,
) {
    let task = &message.task;
    // We only show logs of finished or running tasks.
    if !matches!(
        task.status,
        TaskStatus::Done(_) | TaskStatus::Running | TaskStatus::Paused
    ) {
        return;
    }

    print_task_info(task, style);

    if settings.client.read_local_logs {
        print_local_log(message.task.id, style, settings, lines);
    } else if message.output.is_some() {
        print_remote_log(message, style);
    } else {
        println!("Logs requested from pueue daemon, but none received. Please report this bug.");
    }
}

/// Print some information about a task, which is displayed on top of the task's log output.
fn print_task_info(task: &Task, style: &OutputStyle) {
    // Print task id and exit code.
    let task_cell = style.styled_cell(format!("Task {}: ", task.id), None, Some(Attribute::Bold));

    let (exit_status, color) = match &task.status {
        TaskStatus::Paused => ("paused".into(), Color::White),
        TaskStatus::Running => ("running".into(), Color::Yellow),
        TaskStatus::Done(result) => match result {
            TaskResult::Success => ("completed successfully".into(), Color::Green),
            TaskResult::Failed(exit_code) => {
                (format!("failed with exit code {}", exit_code), Color::Red)
            }
            TaskResult::FailedToSpawn(err) => (format!("failed to spawn: {}", err), Color::Red),
            TaskResult::Killed => ("killed by system or user".into(), Color::Red),
            TaskResult::Errored => ("some IO error.\n Check daemon log.".into(), Color::Red),
            TaskResult::DependencyFailed => ("dependency failed".into(), Color::Red),
        },
        _ => (task.status.to_string(), Color::White),
    };
    let status_cell = style.styled_cell(exit_status, Some(color), None);

    // The styling of the task number and status is done by a single-row table.
    let mut table = Table::new();
    table.load_preset("││─ └──┘     ─ ┌┐  ");
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
    table.set_header(vec![task_cell, status_cell]);

    // Explicitly force styling, in case we aren't on a tty, but `--color=always` is set.
    if style.enabled {
        table.enforce_styling();
    }
    println!("{}", table);

    // All other information is alligned and styled by using a separat table.
    let mut table = Table::new();
    table.load_preset(comfy_table::presets::NOTHING);
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);

    // Command and path
    table.add_row(vec![
        style.styled_cell("Command:", None, Some(Attribute::Bold)),
        Cell::new(&task.command),
    ]);
    table.add_row(vec![
        style.styled_cell("Path:", None, Some(Attribute::Bold)),
        Cell::new(&task.path.to_string_lossy()),
    ]);

    // Start and end time
    if let Some(start) = task.start {
        table.add_row(vec![
            style.styled_cell("Start:", None, Some(Attribute::Bold)),
            Cell::new(start.to_rfc2822()),
        ]);
    }
    if let Some(end) = task.end {
        table.add_row(vec![
            style.styled_cell("End:", None, Some(Attribute::Bold)),
            Cell::new(end.to_rfc2822()),
        ]);
    }

    // Set the padding of the left column to 0 align the keys to the right
    let first_column = table.column_mut(0).unwrap();
    first_column.set_cell_alignment(CellAlignment::Right);
    first_column.set_padding((0, 0));

    println!("{table}");
}
<|endoftext|>


<commit_before>use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then};
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use std::borrow::Cow;
use syntax::ast::*;
use syntax::parse::{parser, token};
use syntax::tokenstream::TokenStream;
use syntax_pos::{BytePos, Span};

declare_clippy_lint! {
    /// **What it does:** This lint warns when you use `println!("")` to
    /// print a newline.
    ///
    /// **Why is this bad?** You should use `println!()`, which is simpler.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// println!("");
    /// ```
    pub PRINTLN_EMPTY_STRING,
    style,
    "using `println!(\"\")` with an empty string"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns when you use `print!()` with a format
    /// string that
    /// ends in a newline.
    ///
    /// **Why is this bad?** You should use `println!()` instead, which appends the
    /// newline.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # let name = "World";
    /// print!("Hello {}!\n", name);
    /// ```
    /// use println!() instead
    /// ```rust
    /// # let name = "World";
    /// println!("Hello {}!", name);
    /// ```
    pub PRINT_WITH_NEWLINE,
    style,
    "using `print!()` with a format string that ends in a single newline"
}

declare_clippy_lint! {
    /// **What it does:** Checks for printing on *stdout*. The purpose of this lint
    /// is to catch debugging remnants.
    ///
    /// **Why is this bad?** People often print on *stdout* while debugging an
    /// application and might forget to remove those prints afterward.
    ///
    /// **Known problems:** Only catches `print!` and `println!` calls.
    ///
    /// **Example:**
    /// ```rust
    /// println!("Hello world!");
    /// ```
    pub PRINT_STDOUT,
    restriction,
    "printing on stdout"
}

declare_clippy_lint! {
    /// **What it does:** Checks for use of `Debug` formatting. The purpose of this
    /// lint is to catch debugging remnants.
    ///
    /// **Why is this bad?** The purpose of the `Debug` trait is to facilitate
    /// debugging Rust code. It should not be used in in user-facing output.
    ///
    /// **Example:**
    /// ```rust
    /// # let foo = "bar";
    /// println!("{:?}", foo);
    /// ```
    pub USE_DEBUG,
    restriction,
    "use of `Debug`-based formatting"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns about the use of literals as `print!`/`println!` args.
    ///
    /// **Why is this bad?** Using literals as `println!` args is inefficient
    /// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
    /// (i.e., just put the literal in the format string)
    ///
    /// **Known problems:** Will also warn with macro calls as arguments that expand to literals
    /// -- e.g., `println!("{}", env!("FOO"))`.
    ///
    /// **Example:**
    /// ```rust
    /// println!("{}", "foo");
    /// ```
    /// use the literal without formatting:
    /// ```rust
    /// println!("foo");
    /// ```
    pub PRINT_LITERAL,
    style,
    "printing a literal with a format string"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns when you use `writeln!(buf, "")` to
    /// print a newline.
    ///
    /// **Why is this bad?** You should use `writeln!(buf)`, which is simpler.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # use std::fmt::Write;
    /// # let mut buf = String::new();
    /// writeln!(buf, "");
    /// ```
    pub WRITELN_EMPTY_STRING,
    style,
    "using `writeln!(buf, \"\")` with an empty string"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns when you use `write!()` with a format
    /// string that
    /// ends in a newline.
    ///
    /// **Why is this bad?** You should use `writeln!()` instead, which appends the
    /// newline.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # use std::fmt::Write;
    /// # let mut buf = String::new();
    /// # let name = "World";
    /// write!(buf, "Hello {}!\n", name);
    /// ```
    pub WRITE_WITH_NEWLINE,
    style,
    "using `write!()` with a format string that ends in a single newline"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns about the use of literals as `write!`/`writeln!` args.
    ///
    /// **Why is this bad?** Using literals as `writeln!` args is inefficient
    /// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
    /// (i.e., just put the literal in the format string)
    ///
    /// **Known problems:** Will also warn with macro calls as arguments that expand to literals
    /// -- e.g., `writeln!(buf, "{}", env!("FOO"))`.
    ///
    /// **Example:**
    /// ```rust
    /// # use std::fmt::Write;
    /// # let mut buf = String::new();
    /// writeln!(buf, "{}", "foo");
    /// ```
    pub WRITE_LITERAL,
    style,
    "writing a literal with a format string"
}

declare_lint_pass!(Write => [
    PRINT_WITH_NEWLINE,
    PRINTLN_EMPTY_STRING,
    PRINT_STDOUT,
    USE_DEBUG,
    PRINT_LITERAL,
    WRITE_WITH_NEWLINE,
    WRITELN_EMPTY_STRING,
    WRITE_LITERAL
]);

impl EarlyLintPass for Write {
    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) {
        if mac.node.path == sym!(println) {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
            if let (Some(fmt_str), _) = check_tts(cx, &mac.node.tts, false) {
                if fmt_str.contents.is_empty() {
                    span_lint_and_sugg(
                        cx,
                        PRINTLN_EMPTY_STRING,
                        mac.span,
                        "using `println!(\"\")`",
                        "replace it with",
                        "println!()".to_string(),
                        Applicability::MachineApplicable,
                    );
                }
            }
        } else if mac.node.path == sym!(print) {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
            if let (Some(fmt_str), _) = check_tts(cx, &mac.node.tts, false) {
                if check_newlines(&fmt_str) {
                    span_lint_and_then(
                        cx,
                        PRINT_WITH_NEWLINE,
                        mac.span,
                        "using `print!()` with a format string that ends in a single newline",
                        |err| {
                            err.multipart_suggestion(
                                "use `println!` instead",
                                vec![
                                    (mac.node.path.span, String::from("println")),
                                    (fmt_str.newline_span(), String::new()),
                                ],
                                Applicability::MachineApplicable,
                            );
                        },
                    );
                }
            }
        } else if mac.node.path == sym!(write) {
            if let (Some(fmt_str), _) = check_tts(cx, &mac.node.tts, true) {
                if check_newlines(&fmt_str) {
                    span_lint_and_then(
                        cx,
                        WRITE_WITH_NEWLINE,
                        mac.span,
                        "using `write!()` with a format string that ends in a single newline",
                        |err| {
                            err.multipart_suggestion(
                                "use `writeln!()` instead",
                                vec![
                                    (mac.node.path.span, String::from("writeln")),
                                    (fmt_str.newline_span(), String::new()),
                                ],
                                Applicability::MachineApplicable,
                            );
                        },
                    )
                }
            }
        } else if mac.node.path == sym!(writeln) {
            if let (Some(fmt_str), expr) = check_tts(cx, &mac.node.tts, true) {
                if fmt_str.contents.is_empty() {
                    let mut applicability = Applicability::MachineApplicable;
                    let suggestion = expr.map_or_else(
                        move || {
                            applicability = Applicability::HasPlaceholders;
                            Cow::Borrowed("v")
                        },
                        move |expr| snippet_with_applicability(cx, expr.span, "v", &mut applicability),
                    );

                    span_lint_and_sugg(
                        cx,
                        WRITELN_EMPTY_STRING,
                        mac.span,
                        format!("using `writeln!({}, \"\")`", suggestion).as_str(),
                        "replace it with",
                        format!("writeln!({})", suggestion),
                        applicability,
                    );
                }
            }
        }
    }
}

/// The arguments of a `print[ln]!` or `write[ln]!` invocation.
struct FmtStr {
    /// The contents of the format string (inside the quotes).
    contents: String,
    style: StrStyle,
    /// The span of the format string, including quotes, the raw marker, and any raw hashes.
    span: Span,
}

impl FmtStr {
    /// Given a format string that ends in a newline and its span, calculates the span of the
    /// newline.
    fn newline_span(&self) -> Span {
        let sp = self.span;

        let newline_sp_hi = sp.hi()
            - match self.style {
                StrStyle::Cooked => BytePos(1),
                StrStyle::Raw(hashes) => BytePos((1 + hashes).into()),
            };

        let newline_sp_len = if self.contents.ends_with('\n') {
            BytePos(1)
        } else if self.contents.ends_with(r"\n") {
            BytePos(2)
        } else {
            panic!("expected format string to contain a newline");
        };

        sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi)
    }
}

/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
/// `Option`s. The first `Option` of the tuple is the macro's format string. It includes
/// the contents of the string, whether it's a raw string, and the span of the literal in the
/// source. The second `Option` in the tuple is, in the `write[ln]!` case, the expression the
/// `format_str` should be written to.
///
/// Example:
///
/// Calling this function on
/// ```rust
/// # use std::fmt::Write;
/// # let mut buf = String::new();
/// # let something = "something";
/// writeln!(buf, "string to write: {}", something);
/// ```
/// will return
/// ```rust,ignore
/// (Some("string to write: {}"), Some(buf))
/// ```
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option<FmtStr>, Option<Expr>) {
    use fmt_macros::*;
    let tts = tts.clone();

    let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false, None);
    let mut expr: Option<Expr> = None;
    if is_write {
        expr = match parser.parse_expr().map_err(|mut err| err.cancel()) {
            Ok(p) => Some(p.into_inner()),
            Err(_) => return (None, None),
        };
        // might be `writeln!(foo)`
        if parser.expect(&token::Comma).map_err(|mut err| err.cancel()).is_err() {
            return (None, expr);
        }
    }

    let (fmtstr, fmtstyle) = match parser.parse_str().map_err(|mut err| err.cancel()) {
        Ok((fmtstr, fmtstyle)) => (fmtstr.to_string(), fmtstyle),
        Err(_) => return (None, expr),
    };
    let fmtspan = parser.prev_span;
    let tmp = fmtstr.clone();
    let mut args = vec![];
    let mut fmt_parser = Parser::new(&tmp, None, Vec::new(), false);
    while let Some(piece) = fmt_parser.next() {
        if !fmt_parser.errors.is_empty() {
            return (None, expr);
        }
        if let Piece::NextArgument(arg) = piece {
            if arg.format.ty == "?" {
                // FIXME: modify rustc's fmt string parser to give us the current span
                span_lint(cx, USE_DEBUG, parser.prev_span, "use of `Debug`-based formatting");
            }
            args.push(arg);
        }
    }
    let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL };
    let mut idx = 0;
    loop {
        const SIMPLE: FormatSpec<'_> = FormatSpec {
            fill: None,
            align: AlignUnknown,
            flags: 0,
            precision: CountImplied,
            precision_span: None,
            width: CountImplied,
            width_span: None,
            ty: "",
        };
        if !parser.eat(&token::Comma) {
            return (
                Some(FmtStr {
                    contents: fmtstr,
                    style: fmtstyle,
                    span: fmtspan,
                }),
                expr,
            );
        }
        let token_expr = if let Ok(expr) = parser.parse_expr().map_err(|mut err| err.cancel()) {
            expr
        } else {
            return (
                Some(FmtStr {
                    contents: fmtstr,
                    style: fmtstyle,
                    span: fmtspan,
                }),
                None,
            );
        };
        match &token_expr.node {
            ExprKind::Lit(_) => {
                let mut all_simple = true;
                let mut seen = false;
                for arg in &args {
                    match arg.position {
                        ArgumentImplicitlyIs(n) | ArgumentIs(n) => {
                            if n == idx {
                                all_simple &= arg.format == SIMPLE;
                                seen = true;
                            }
                        },
                        ArgumentNamed(_) => {},
                    }
                }
                if all_simple && seen {
                    span_lint(cx, lint, token_expr.span, "literal with an empty format string");
                }
                idx += 1;
            },
            ExprKind::Assign(lhs, rhs) => {
                if let ExprKind::Lit(_) = rhs.node {
                    if let ExprKind::Path(_, p) = &lhs.node {
                        let mut all_simple = true;
                        let mut seen = false;
                        for arg in &args {
                            match arg.position {
                                ArgumentImplicitlyIs(_) | ArgumentIs(_) => {},
                                ArgumentNamed(name) => {
                                    if *p == name {
                                        seen = true;
                                        all_simple &= arg.format == SIMPLE;
                                    }
                                },
                            }
                        }
                        if all_simple && seen {
                            span_lint(cx, lint, rhs.span, "literal with an empty format string");
                        }
                    }
                }
            },
            _ => idx += 1,
        }
    }
}

/// Checks if the format string constains a single newline that terminates it.
///
/// Literal and escaped newlines are both checked (only literal for raw strings).
fn check_newlines(fmt_str: &FmtStr) -> bool {
    let s = &fmt_str.contents;

    if s.ends_with('\n') {
        return true;
    } else if let StrStyle::Raw(_) = fmt_str.style {
        return false;
    }

    if s.len() < 2 {
        return false;
    }

    let bytes = s.as_bytes();
    if bytes[bytes.len() - 2] != b'\\' || bytes[bytes.len() - 1] != b'n' {
        return false;
    }

    let mut escaping = false;
    for (index, &byte) in bytes.iter().enumerate() {
        if escaping {
            if byte == b'n' {
                return index == bytes.len() - 1;
            }
            escaping = false;
        } else if byte == b'\\' {
            escaping = true;
        }
    }

    false
}
<commit_msg>Fixed repeated word<commit_after>use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then};
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use rustc_errors::Applicability;
use std::borrow::Cow;
use syntax::ast::*;
use syntax::parse::{parser, token};
use syntax::tokenstream::TokenStream;
use syntax_pos::{BytePos, Span};

declare_clippy_lint! {
    /// **What it does:** This lint warns when you use `println!("")` to
    /// print a newline.
    ///
    /// **Why is this bad?** You should use `println!()`, which is simpler.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// println!("");
    /// ```
    pub PRINTLN_EMPTY_STRING,
    style,
    "using `println!(\"\")` with an empty string"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns when you use `print!()` with a format
    /// string that
    /// ends in a newline.
    ///
    /// **Why is this bad?** You should use `println!()` instead, which appends the
    /// newline.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # let name = "World";
    /// print!("Hello {}!\n", name);
    /// ```
    /// use println!() instead
    /// ```rust
    /// # let name = "World";
    /// println!("Hello {}!", name);
    /// ```
    pub PRINT_WITH_NEWLINE,
    style,
    "using `print!()` with a format string that ends in a single newline"
}

declare_clippy_lint! {
    /// **What it does:** Checks for printing on *stdout*. The purpose of this lint
    /// is to catch debugging remnants.
    ///
    /// **Why is this bad?** People often print on *stdout* while debugging an
    /// application and might forget to remove those prints afterward.
    ///
    /// **Known problems:** Only catches `print!` and `println!` calls.
    ///
    /// **Example:**
    /// ```rust
    /// println!("Hello world!");
    /// ```
    pub PRINT_STDOUT,
    restriction,
    "printing on stdout"
}

declare_clippy_lint! {
    /// **What it does:** Checks for use of `Debug` formatting. The purpose of this
    /// lint is to catch debugging remnants.
    ///
    /// **Why is this bad?** The purpose of the `Debug` trait is to facilitate
    /// debugging Rust code. It should not be used in user-facing output.
    ///
    /// **Example:**
    /// ```rust
    /// # let foo = "bar";
    /// println!("{:?}", foo);
    /// ```
    pub USE_DEBUG,
    restriction,
    "use of `Debug`-based formatting"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns about the use of literals as `print!`/`println!` args.
    ///
    /// **Why is this bad?** Using literals as `println!` args is inefficient
    /// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
    /// (i.e., just put the literal in the format string)
    ///
    /// **Known problems:** Will also warn with macro calls as arguments that expand to literals
    /// -- e.g., `println!("{}", env!("FOO"))`.
    ///
    /// **Example:**
    /// ```rust
    /// println!("{}", "foo");
    /// ```
    /// use the literal without formatting:
    /// ```rust
    /// println!("foo");
    /// ```
    pub PRINT_LITERAL,
    style,
    "printing a literal with a format string"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns when you use `writeln!(buf, "")` to
    /// print a newline.
    ///
    /// **Why is this bad?** You should use `writeln!(buf)`, which is simpler.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # use std::fmt::Write;
    /// # let mut buf = String::new();
    /// writeln!(buf, "");
    /// ```
    pub WRITELN_EMPTY_STRING,
    style,
    "using `writeln!(buf, \"\")` with an empty string"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns when you use `write!()` with a format
    /// string that
    /// ends in a newline.
    ///
    /// **Why is this bad?** You should use `writeln!()` instead, which appends the
    /// newline.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// # use std::fmt::Write;
    /// # let mut buf = String::new();
    /// # let name = "World";
    /// write!(buf, "Hello {}!\n", name);
    /// ```
    pub WRITE_WITH_NEWLINE,
    style,
    "using `write!()` with a format string that ends in a single newline"
}

declare_clippy_lint! {
    /// **What it does:** This lint warns about the use of literals as `write!`/`writeln!` args.
    ///
    /// **Why is this bad?** Using literals as `writeln!` args is inefficient
    /// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
    /// (i.e., just put the literal in the format string)
    ///
    /// **Known problems:** Will also warn with macro calls as arguments that expand to literals
    /// -- e.g., `writeln!(buf, "{}", env!("FOO"))`.
    ///
    /// **Example:**
    /// ```rust
    /// # use std::fmt::Write;
    /// # let mut buf = String::new();
    /// writeln!(buf, "{}", "foo");
    /// ```
    pub WRITE_LITERAL,
    style,
    "writing a literal with a format string"
}

declare_lint_pass!(Write => [
    PRINT_WITH_NEWLINE,
    PRINTLN_EMPTY_STRING,
    PRINT_STDOUT,
    USE_DEBUG,
    PRINT_LITERAL,
    WRITE_WITH_NEWLINE,
    WRITELN_EMPTY_STRING,
    WRITE_LITERAL
]);

impl EarlyLintPass for Write {
    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) {
        if mac.node.path == sym!(println) {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
            if let (Some(fmt_str), _) = check_tts(cx, &mac.node.tts, false) {
                if fmt_str.contents.is_empty() {
                    span_lint_and_sugg(
                        cx,
                        PRINTLN_EMPTY_STRING,
                        mac.span,
                        "using `println!(\"\")`",
                        "replace it with",
                        "println!()".to_string(),
                        Applicability::MachineApplicable,
                    );
                }
            }
        } else if mac.node.path == sym!(print) {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
            if let (Some(fmt_str), _) = check_tts(cx, &mac.node.tts, false) {
                if check_newlines(&fmt_str) {
                    span_lint_and_then(
                        cx,
                        PRINT_WITH_NEWLINE,
                        mac.span,
                        "using `print!()` with a format string that ends in a single newline",
                        |err| {
                            err.multipart_suggestion(
                                "use `println!` instead",
                                vec![
                                    (mac.node.path.span, String::from("println")),
                                    (fmt_str.newline_span(), String::new()),
                                ],
                                Applicability::MachineApplicable,
                            );
                        },
                    );
                }
            }
        } else if mac.node.path == sym!(write) {
            if let (Some(fmt_str), _) = check_tts(cx, &mac.node.tts, true) {
                if check_newlines(&fmt_str) {
                    span_lint_and_then(
                        cx,
                        WRITE_WITH_NEWLINE,
                        mac.span,
                        "using `write!()` with a format string that ends in a single newline",
                        |err| {
                            err.multipart_suggestion(
                                "use `writeln!()` instead",
                                vec![
                                    (mac.node.path.span, String::from("writeln")),
                                    (fmt_str.newline_span(), String::new()),
                                ],
                                Applicability::MachineApplicable,
                            );
                        },
                    )
                }
            }
        } else if mac.node.path == sym!(writeln) {
            if let (Some(fmt_str), expr) = check_tts(cx, &mac.node.tts, true) {
                if fmt_str.contents.is_empty() {
                    let mut applicability = Applicability::MachineApplicable;
                    let suggestion = expr.map_or_else(
                        move || {
                            applicability = Applicability::HasPlaceholders;
                            Cow::Borrowed("v")
                        },
                        move |expr| snippet_with_applicability(cx, expr.span, "v", &mut applicability),
                    );

                    span_lint_and_sugg(
                        cx,
                        WRITELN_EMPTY_STRING,
                        mac.span,
                        format!("using `writeln!({}, \"\")`", suggestion).as_str(),
                        "replace it with",
                        format!("writeln!({})", suggestion),
                        applicability,
                    );
                }
            }
        }
    }
}

/// The arguments of a `print[ln]!` or `write[ln]!` invocation.
struct FmtStr {
    /// The contents of the format string (inside the quotes).
    contents: String,
    style: StrStyle,
    /// The span of the format string, including quotes, the raw marker, and any raw hashes.
    span: Span,
}

impl FmtStr {
    /// Given a format string that ends in a newline and its span, calculates the span of the
    /// newline.
    fn newline_span(&self) -> Span {
        let sp = self.span;

        let newline_sp_hi = sp.hi()
            - match self.style {
                StrStyle::Cooked => BytePos(1),
                StrStyle::Raw(hashes) => BytePos((1 + hashes).into()),
            };

        let newline_sp_len = if self.contents.ends_with('\n') {
            BytePos(1)
        } else if self.contents.ends_with(r"\n") {
            BytePos(2)
        } else {
            panic!("expected format string to contain a newline");
        };

        sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi)
    }
}

/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
/// `Option`s. The first `Option` of the tuple is the macro's format string. It includes
/// the contents of the string, whether it's a raw string, and the span of the literal in the
/// source. The second `Option` in the tuple is, in the `write[ln]!` case, the expression the
/// `format_str` should be written to.
///
/// Example:
///
/// Calling this function on
/// ```rust
/// # use std::fmt::Write;
/// # let mut buf = String::new();
/// # let something = "something";
/// writeln!(buf, "string to write: {}", something);
/// ```
/// will return
/// ```rust,ignore
/// (Some("string to write: {}"), Some(buf))
/// ```
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option<FmtStr>, Option<Expr>) {
    use fmt_macros::*;
    let tts = tts.clone();

    let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false, None);
    let mut expr: Option<Expr> = None;
    if is_write {
        expr = match parser.parse_expr().map_err(|mut err| err.cancel()) {
            Ok(p) => Some(p.into_inner()),
            Err(_) => return (None, None),
        };
        // might be `writeln!(foo)`
        if parser.expect(&token::Comma).map_err(|mut err| err.cancel()).is_err() {
            return (None, expr);
        }
    }

    let (fmtstr, fmtstyle) = match parser.parse_str().map_err(|mut err| err.cancel()) {
        Ok((fmtstr, fmtstyle)) => (fmtstr.to_string(), fmtstyle),
        Err(_) => return (None, expr),
    };
    let fmtspan = parser.prev_span;
    let tmp = fmtstr.clone();
    let mut args = vec![];
    let mut fmt_parser = Parser::new(&tmp, None, Vec::new(), false);
    while let Some(piece) = fmt_parser.next() {
        if !fmt_parser.errors.is_empty() {
            return (None, expr);
        }
        if let Piece::NextArgument(arg) = piece {
            if arg.format.ty == "?" {
                // FIXME: modify rustc's fmt string parser to give us the current span
                span_lint(cx, USE_DEBUG, parser.prev_span, "use of `Debug`-based formatting");
            }
            args.push(arg);
        }
    }
    let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL };
    let mut idx = 0;
    loop {
        const SIMPLE: FormatSpec<'_> = FormatSpec {
            fill: None,
            align: AlignUnknown,
            flags: 0,
            precision: CountImplied,
            precision_span: None,
            width: CountImplied,
            width_span: None,
            ty: "",
        };
        if !parser.eat(&token::Comma) {
            return (
                Some(FmtStr {
                    contents: fmtstr,
                    style: fmtstyle,
                    span: fmtspan,
                }),
                expr,
            );
        }
        let token_expr = if let Ok(expr) = parser.parse_expr().map_err(|mut err| err.cancel()) {
            expr
        } else {
            return (
                Some(FmtStr {
                    contents: fmtstr,
                    style: fmtstyle,
                    span: fmtspan,
                }),
                None,
            );
        };
        match &token_expr.node {
            ExprKind::Lit(_) => {
                let mut all_simple = true;
                let mut seen = false;
                for arg in &args {
                    match arg.position {
                        ArgumentImplicitlyIs(n) | ArgumentIs(n) => {
                            if n == idx {
                                all_simple &= arg.format == SIMPLE;
                                seen = true;
                            }
                        },
                        ArgumentNamed(_) => {},
                    }
                }
                if all_simple && seen {
                    span_lint(cx, lint, token_expr.span, "literal with an empty format string");
                }
                idx += 1;
            },
            ExprKind::Assign(lhs, rhs) => {
                if let ExprKind::Lit(_) = rhs.node {
                    if let ExprKind::Path(_, p) = &lhs.node {
                        let mut all_simple = true;
                        let mut seen = false;
                        for arg in &args {
                            match arg.position {
                                ArgumentImplicitlyIs(_) | ArgumentIs(_) => {},
                                ArgumentNamed(name) => {
                                    if *p == name {
                                        seen = true;
                                        all_simple &= arg.format == SIMPLE;
                                    }
                                },
                            }
                        }
                        if all_simple && seen {
                            span_lint(cx, lint, rhs.span, "literal with an empty format string");
                        }
                    }
                }
            },
            _ => idx += 1,
        }
    }
}

/// Checks if the format string constains a single newline that terminates it.
///
/// Literal and escaped newlines are both checked (only literal for raw strings).
fn check_newlines(fmt_str: &FmtStr) -> bool {
    let s = &fmt_str.contents;

    if s.ends_with('\n') {
        return true;
    } else if let StrStyle::Raw(_) = fmt_str.style {
        return false;
    }

    if s.len() < 2 {
        return false;
    }

    let bytes = s.as_bytes();
    if bytes[bytes.len() - 2] != b'\\' || bytes[bytes.len() - 1] != b'n' {
        return false;
    }

    let mut escaping = false;
    for (index, &byte) in bytes.iter().enumerate() {
        if escaping {
            if byte == b'n' {
                return index == bytes.len() - 1;
            }
            escaping = false;
        } else if byte == b'\\' {
            escaping = true;
        }
    }

    false
}
<|endoftext|>


<commit_before>//! This file was generated by asn1tools version 0.145.2 Sun Jan 20 10:31:38 2019.

struct Encoder<'a> {
    buf: &'a mut [u8],
    size: isize,
    pos: isize
}

struct Decoder<'a> {
    buf: &'a[u8],
    size: isize,
    pos: isize
}

impl<'a> Encoder<'a> {

    fn new(dst: &'a mut [u8]) -> Encoder {
        Encoder {
            size: 8 * dst.len() as isize,
            buf: dst,
            pos: 0
        }
    }

    fn get_result(&self) -> Result<usize, &'static str>
    {
        if self.size >= 0 {
            return Ok((self.pos as usize + 7) / 8);
        } else {
            return Err("error");
        }
    }

    fn abort(&mut self, error: isize)
    {
        if self.size >= 0 {
            self.size = -error;
            self.pos = -error;
        }
    }

    fn alloc(&mut self, size: usize) -> isize
    {
        let pos: isize;

        if self.pos + size as isize <= self.size {
            pos = self.pos;
            self.pos += size as isize;
        } else {
            pos = -1;
            self.abort(3);
        }

        return pos;
    }

    fn append_bit(&mut self, value: u8)
    {
        let pos: isize;

        pos = self.alloc(1);

        if pos < 0 {
            return;
        }

        if pos % 8 == 0 {
            self.buf[pos as usize / 8] = 0;
        }

        self.buf[pos as usize / 8] |= value << (7 - (pos % 8));
    }

    fn append_bytes(&mut self, buf: &[u8], size: usize)
    {
        let pos: isize;
        let byte_pos: usize;
        let pos_in_byte: usize;

        pos = self.alloc(8 * size);

        if pos < 0 {
            return;
        }

        byte_pos = pos as usize / 8;
        pos_in_byte = pos as usize % 8;

        if pos_in_byte == 0 {
            self.buf.get_mut(byte_pos..byte_pos + size)
                .unwrap()
                .copy_from_slice(buf.get(0..size).unwrap());
        } else {
            for i in 0..size {
                self.buf[byte_pos + i] |= buf[i] >> pos_in_byte;
                self.buf[byte_pos + i + 1] = buf[i] << (8 - pos_in_byte);
            }
        }
    }

    fn append_u8(&mut self, value: u8)
    {
        self.append_bytes(&[value], 1);
    }

    fn append_u16(&mut self, value: u16)
    {
        self.append_bytes(&[(value >> 8) as u8,
                            value as u8],
                          2);
    }

    fn append_u32(&mut self, value: u32)
    {
        self.append_bytes(&[(value >> 24) as u8,
                            (value >> 16) as u8,
                            (value >> 8) as u8,
                            value as u8],
                          4);
    }

    fn append_u64(&mut self, value: u64)
    {
        self.append_bytes(&[(value >> 56) as u8,
                            (value >> 48) as u8,
                            (value >> 40) as u8,
                            (value >> 32) as u8,
                            (value >> 24) as u8,
                            (value >> 16) as u8,
                            (value >> 8) as u8,
                            value as u8],
                          8);
    }

    fn append_i8(&mut self, value: i8)
    {
        self.append_u8((value as u8).wrapping_add(128));
    }

    fn append_i16(&mut self, value: i16)
    {
        self.append_u16((value as u16).wrapping_add(32768));
    }

    fn append_i32(&mut self, value: i32)
    {
        self.append_u32((value as u32).wrapping_add(2147483648));
    }

    fn append_i64(&mut self, value: i64)
    {
        self.append_u64((value as u64).wrapping_add(9223372036854775808));
    }

    fn append_bool(&mut self, value: bool)
    {
        self.append_bit(value as u8);
    }
}

impl<'a> Decoder<'a> {

    fn new(src: &'a[u8]) -> Decoder {
        Decoder {
            buf: src,
            size: 8 * src.len() as isize,
            pos: 0
        }
    }

    fn get_result(&self) -> Result<usize, &'static str>
    {
        if self.size >= 0 {
            return Ok((self.pos as usize + 7) / 8);
        } else {
            return Err("error");
        }
    }

    fn abort(&mut self, error: isize)
    {
        if self.size >= 0 {
            self.size = -error;
            self.pos = -error;
        }
    }

    fn free(&mut self, size: usize) -> isize
    {
        let pos: isize;

        if self.pos + size as isize <= self.size {
            pos = self.pos;
            self.pos += size as isize;
        } else {
            pos = -1;
            self.abort(2);
        }

        return pos;
    }

    fn read_bit(&mut self) -> u8
    {
        let pos: isize;
        let value: u8;

        pos = self.free(1);

        if pos >= 0 {
            value = (self.buf[pos as usize / 8] >> (7 - (pos % 8))) & 1;
        } else {
            value = 0;
        }

        return value;
    }

    fn read_bytes(&mut self, buf: &mut [u8], size: usize)
    {
        let pos: isize;
        let byte_pos: usize;
        let pos_in_byte: usize;

        pos = self.free(8 * size);

        if pos < 0 {
            return;
        }

        byte_pos = pos as usize / 8;
        pos_in_byte = pos as usize % 8;

        if pos_in_byte == 0 {
            buf.get_mut(..size)
                .unwrap()
                .copy_from_slice(self.buf.get(byte_pos..byte_pos + size).unwrap());
        } else {
            for i in 0..size {
                buf[i] = self.buf[byte_pos + i] << pos_in_byte;
                buf[i] |= self.buf[byte_pos + i + 1] >> (8 - pos_in_byte);
            }
        }
    }

    fn read_u8(&mut self) -> u8
    {
        let mut value = [0; 1];

        self.read_bytes(&mut value, 1);

        return value[0];
    }

    fn read_u16(&mut self) -> u16
    {
        let mut buf = [0; 2];

        self.read_bytes(&mut buf, 2);

        return ((buf[0] as u16) << 8) | (buf[1] as u16);
    }

    fn read_u32(&mut self) -> u32
    {
        let mut buf = [0; 4];

        self.read_bytes(&mut buf, 4);

        return ((buf[0] as u32) << 24)
               | ((buf[1] as u32) << 16)
               | ((buf[2] as u32) << 8)
               | (buf[3] as u32);
    }

    fn read_u64(&mut self) -> u64
    {
        let mut buf = [0; 8];

        self.read_bytes(&mut buf, 8);

        return ((buf[0] as u64) << 56)
               | ((buf[1] as u64) << 48)
               | ((buf[2] as u64) << 40)
               | ((buf[3] as u64) << 32)
               | ((buf[4] as u64) << 24)
               | ((buf[5] as u64) << 16)
               | ((buf[6] as u64) << 8)
               | buf[7] as u64;
    }

    fn read_i8(&mut self) -> i8
    {
        return self.read_u8().wrapping_sub(128) as i8;
    }

    fn read_i16(&mut self) -> i16
    {
        return self.read_u16().wrapping_sub(32768) as i16;
    }

    fn read_i32(&mut self) -> i32
    {
        return self.read_u32().wrapping_sub(2147483648) as i32;
    }

    fn read_i64(&mut self) -> i64
    {
        return self.read_u64().wrapping_sub(9223372036854775808) as i64;
    }

    fn read_bool(&mut self) -> bool
    {
        return self.read_bit() != 0;
    }
}

/// Type A in module RustSource.
#[derive(Debug, Default, PartialEq)]
pub struct RustSourceAJ {
    pub buf: [u8; 11]
}

#[derive(Debug, Default, PartialEq)]
pub struct RustSourceA {
    pub a: i8,
    pub b: i16,
    pub c: i32,
    pub d: i64,
    pub e: u8,
    pub f: u16,
    pub g: u32,
    pub h: u64,
    pub i: bool,
    pub j: RustSourceAJ
}

impl RustSourceA {

    pub fn to_bytes(&mut self, mut dst: &mut [u8]) -> Result<usize, &'static str>
    {
        let mut encoder = Encoder::new(&mut dst);

        self.to_bytes_inner(&mut encoder);

        return encoder.get_result();
    }

    pub fn from_bytes(&mut self, src: &[u8]) -> Result<usize, &'static str>
    {
        let mut decoder = Decoder::new(&src);

        self.from_bytes_inner(&mut decoder);

        return decoder.get_result();
    }

    fn to_bytes_inner(&mut self, encoder: &mut Encoder)
    {
        encoder.append_i8(self.a);
        encoder.append_i16(self.b);
        encoder.append_i32(self.c);
        encoder.append_i64(self.d);
        encoder.append_u8(self.e);
        encoder.append_u16(self.f);
        encoder.append_u32(self.g);
        encoder.append_u64(self.h);
        encoder.append_bool(self.i);
        encoder.append_bytes(&self.j.buf,
                             11);
    }

    fn from_bytes_inner(&mut self, decoder: &mut Decoder)
    {
        self.a = decoder.read_i8();
        self.b = decoder.read_i16();
        self.c = decoder.read_i32();
        self.d = decoder.read_i64();
        self.e = decoder.read_u8();
        self.f = decoder.read_u16();
        self.g = decoder.read_u32();
        self.h = decoder.read_u64();
        self.i = decoder.read_bool();
        decoder.read_bytes(&mut self.j.buf,
                           11);
    }
}
<commit_msg>Removed size argument to Rust bytes functions.<commit_after>//! This file was generated by asn1tools version 0.145.2 Sun Jan 20 10:31:38 2019.

struct Encoder<'a> {
    buf: &'a mut [u8],
    size: isize,
    pos: isize
}

struct Decoder<'a> {
    buf: &'a[u8],
    size: isize,
    pos: isize
}

impl<'a> Encoder<'a> {

    fn new(dst: &'a mut [u8]) -> Encoder {
        Encoder {
            size: 8 * dst.len() as isize,
            buf: dst,
            pos: 0
        }
    }

    fn get_result(&self) -> Result<usize, &'static str>
    {
        if self.size >= 0 {
            return Ok((self.pos as usize + 7) / 8);
        } else {
            return Err("error");
        }
    }

    fn abort(&mut self, error: isize)
    {
        if self.size >= 0 {
            self.size = -error;
            self.pos = -error;
        }
    }

    fn alloc(&mut self, size: usize) -> isize
    {
        let pos: isize;

        if self.pos + size as isize <= self.size {
            pos = self.pos;
            self.pos += size as isize;
        } else {
            pos = -1;
            self.abort(3);
        }

        return pos;
    }

    fn append_bit(&mut self, value: u8)
    {
        let pos: isize;

        pos = self.alloc(1);

        if pos < 0 {
            return;
        }

        if pos % 8 == 0 {
            self.buf[pos as usize / 8] = 0;
        }

        self.buf[pos as usize / 8] |= value << (7 - (pos % 8));
    }

    fn append_bytes(&mut self, buf: &[u8])
    {
        let pos: isize;
        let byte_pos: usize;
        let pos_in_byte: usize;

        pos = self.alloc(8 * buf.len());

        if pos < 0 {
            return;
        }

        byte_pos = pos as usize / 8;
        pos_in_byte = pos as usize % 8;

        if pos_in_byte == 0 {
            self.buf.get_mut(byte_pos..byte_pos + buf.len())
                .unwrap()
                .copy_from_slice(buf.get(0..buf.len()).unwrap());
        } else {
            for i in 0..buf.len() {
                self.buf[byte_pos + i] |= buf[i] >> pos_in_byte;
                self.buf[byte_pos + i + 1] = buf[i] << (8 - pos_in_byte);
            }
        }
    }

    fn append_u8(&mut self, value: u8)
    {
        self.append_bytes(&[value]);
    }

    fn append_u16(&mut self, value: u16)
    {
        self.append_bytes(&[(value >> 8) as u8,
                            value as u8]);
    }

    fn append_u32(&mut self, value: u32)
    {
        self.append_bytes(&[(value >> 24) as u8,
                            (value >> 16) as u8,
                            (value >> 8) as u8,
                            value as u8]);
    }

    fn append_u64(&mut self, value: u64)
    {
        self.append_bytes(&[(value >> 56) as u8,
                            (value >> 48) as u8,
                            (value >> 40) as u8,
                            (value >> 32) as u8,
                            (value >> 24) as u8,
                            (value >> 16) as u8,
                            (value >> 8) as u8,
                            value as u8]);
    }

    fn append_i8(&mut self, value: i8)
    {
        self.append_u8((value as u8).wrapping_add(128));
    }

    fn append_i16(&mut self, value: i16)
    {
        self.append_u16((value as u16).wrapping_add(32768));
    }

    fn append_i32(&mut self, value: i32)
    {
        self.append_u32((value as u32).wrapping_add(2147483648));
    }

    fn append_i64(&mut self, value: i64)
    {
        self.append_u64((value as u64).wrapping_add(9223372036854775808));
    }

    fn append_bool(&mut self, value: bool)
    {
        self.append_bit(value as u8);
    }
}

impl<'a> Decoder<'a> {

    fn new(src: &'a[u8]) -> Decoder {
        Decoder {
            buf: src,
            size: 8 * src.len() as isize,
            pos: 0
        }
    }

    fn get_result(&self) -> Result<usize, &'static str>
    {
        if self.size >= 0 {
            return Ok((self.pos as usize + 7) / 8);
        } else {
            return Err("error");
        }
    }

    fn abort(&mut self, error: isize)
    {
        if self.size >= 0 {
            self.size = -error;
            self.pos = -error;
        }
    }

    fn free(&mut self, size: usize) -> isize
    {
        let pos: isize;

        if self.pos + size as isize <= self.size {
            pos = self.pos;
            self.pos += size as isize;
        } else {
            pos = -1;
            self.abort(2);
        }

        return pos;
    }

    fn read_bit(&mut self) -> u8
    {
        let pos: isize;
        let value: u8;

        pos = self.free(1);

        if pos >= 0 {
            value = (self.buf[pos as usize / 8] >> (7 - (pos % 8))) & 1;
        } else {
            value = 0;
        }

        return value;
    }

    fn read_bytes(&mut self, buf: &mut [u8])
    {
        let pos: isize;
        let byte_pos: usize;
        let pos_in_byte: usize;

        pos = self.free(8 * buf.len());

        if pos < 0 {
            return;
        }

        byte_pos = pos as usize / 8;
        pos_in_byte = pos as usize % 8;

        if pos_in_byte == 0 {
            buf.copy_from_slice(self.buf.get(byte_pos..byte_pos + buf.len()).unwrap());
        } else {
            for i in 0..buf.len() {
                buf[i] = self.buf[byte_pos + i] << pos_in_byte;
                buf[i] |= self.buf[byte_pos + i + 1] >> (8 - pos_in_byte);
            }
        }
    }

    fn read_u8(&mut self) -> u8
    {
        let mut value = [0; 1];

        self.read_bytes(&mut value);

        return value[0];
    }

    fn read_u16(&mut self) -> u16
    {
        let mut buf = [0; 2];

        self.read_bytes(&mut buf);

        return ((buf[0] as u16) << 8) | (buf[1] as u16);
    }

    fn read_u32(&mut self) -> u32
    {
        let mut buf = [0; 4];

        self.read_bytes(&mut buf);

        return ((buf[0] as u32) << 24)
               | ((buf[1] as u32) << 16)
               | ((buf[2] as u32) << 8)
               | (buf[3] as u32);
    }

    fn read_u64(&mut self) -> u64
    {
        let mut buf = [0; 8];

        self.read_bytes(&mut buf);

        return ((buf[0] as u64) << 56)
               | ((buf[1] as u64) << 48)
               | ((buf[2] as u64) << 40)
               | ((buf[3] as u64) << 32)
               | ((buf[4] as u64) << 24)
               | ((buf[5] as u64) << 16)
               | ((buf[6] as u64) << 8)
               | buf[7] as u64;
    }

    fn read_i8(&mut self) -> i8
    {
        return self.read_u8().wrapping_sub(128) as i8;
    }

    fn read_i16(&mut self) -> i16
    {
        return self.read_u16().wrapping_sub(32768) as i16;
    }

    fn read_i32(&mut self) -> i32
    {
        return self.read_u32().wrapping_sub(2147483648) as i32;
    }

    fn read_i64(&mut self) -> i64
    {
        return self.read_u64().wrapping_sub(9223372036854775808) as i64;
    }

    fn read_bool(&mut self) -> bool
    {
        return self.read_bit() != 0;
    }
}

/// Type A in module RustSource.
#[derive(Debug, Default, PartialEq)]
pub struct RustSourceAJ {
    pub buf: [u8; 11]
}

#[derive(Debug, Default, PartialEq)]
pub struct RustSourceA {
    pub a: i8,
    pub b: i16,
    pub c: i32,
    pub d: i64,
    pub e: u8,
    pub f: u16,
    pub g: u32,
    pub h: u64,
    pub i: bool,
    pub j: RustSourceAJ
}

impl RustSourceA {

    pub fn to_bytes(&mut self, mut dst: &mut [u8]) -> Result<usize, &'static str>
    {
        let mut encoder = Encoder::new(&mut dst);

        self.to_bytes_inner(&mut encoder);

        return encoder.get_result();
    }

    pub fn from_bytes(&mut self, src: &[u8]) -> Result<usize, &'static str>
    {
        let mut decoder = Decoder::new(&src);

        self.from_bytes_inner(&mut decoder);

        return decoder.get_result();
    }

    fn to_bytes_inner(&mut self, encoder: &mut Encoder)
    {
        encoder.append_i8(self.a);
        encoder.append_i16(self.b);
        encoder.append_i32(self.c);
        encoder.append_i64(self.d);
        encoder.append_u8(self.e);
        encoder.append_u16(self.f);
        encoder.append_u32(self.g);
        encoder.append_u64(self.h);
        encoder.append_bool(self.i);
        encoder.append_bytes(&self.j.buf);
    }

    fn from_bytes_inner(&mut self, decoder: &mut Decoder)
    {
        self.a = decoder.read_i8();
        self.b = decoder.read_i16();
        self.c = decoder.read_i32();
        self.d = decoder.read_i64();
        self.e = decoder.read_u8();
        self.f = decoder.read_u16();
        self.g = decoder.read_u32();
        self.h = decoder.read_u64();
        self.i = decoder.read_bool();
        decoder.read_bytes(&mut self.j.buf);
    }
}
<|endoftext|>


<commit_before>
extern crate mprovision;
#[macro_use(version)]
extern crate version;
extern crate chrono;
#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;
extern crate clap;

use mprovision as mp;
use cli::Command;
use std::env;
use std::path::PathBuf;
use chrono::*;

mod cli;

fn main() {
    let result = cli::parse(env::args()).and_then(|command| {
        match command {
            Command::List(cli::ListParams { filter, expire_in_days, directory }) => {
                list(filter, expire_in_days, directory)
            }
            Command::ShowUuid(uuid, directory) => show_uuid(uuid, directory),
            Command::ShowFile(path) => show_file(path),
            Command::Remove(uuid, directory) => remove(uuid, directory),
            Command::Clean(directory) => clean(directory),
        }
    });
    if let Err(e) = result {
        e.exit();
    }
}

fn list(filter: Option<String>,
        expires_in_days: Option<i64>,
        directory: Option<PathBuf>)
        -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| {
            let total = entries.len();
            let date = expires_in_days.map(|days| UTC::now() + Duration::days(days));
            let filter_string = filter.as_ref();
            let profiles = mp::filter(entries, |profile| {
                match (date, filter_string) {
                    (Some(date), Some(string)) => {
                        profile.expiration_date <= date && profile.contains(&string)
                    }
                    (Some(date), _) => profile.expiration_date <= date,
                    (_, Some(string)) => profile.contains(&string),
                    (_, _) => false,
                }
            });
            (total, profiles)
        })
        .and_then(|(total, profiles)| {
            if profiles.is_empty() {
                Ok(println!("Nothing found"))
            } else {
                for profile in &profiles {
                    println!("\n{}", profile.description());
                }
                Ok(println!("\nFound {} of {}", profiles.len(), total))
            }
        })
}

fn show_uuid(uuid: String, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::show(&profile.path).map(|xml| println!("{}", xml)))
        })
        .map_err(|err| err.into())
}

fn show_file(path: PathBuf) -> Result<(), cli::Error> {
    mp::show(&path)
        .map(|xml| println!("{}", xml))
        .map_err(|err| err.into())
}

fn remove(uuid: String, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::remove(&profile.path))
                .map(|_| println!("'{}' was removed", uuid))
        })
        .map_err(|err| err.into())
}

fn clean(directory: Option<PathBuf>) -> Result<(), cli::Error> {

    fn concat(mut s1: String, s2: String) -> String {
        s1.push_str(&s2);
        s1
    }

    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| {
            let date = UTC::now();
            mp::filter(entries, |profile| profile.expiration_date <= date)
        })
        .and_then(|profiles| {
            if profiles.is_empty() {
                Ok(println!("All provisioning profiles are valid"))
            } else {
                profiles.iter()
                    .map(|profile| {
                        std::fs::remove_file(&profile.path)
                            .map(|_| format!("'{}' was removed\n", profile.uuid))
                            .map_err(|err| format!("'{}' {}\n", profile.uuid, err))
                    })
                    .fold(Ok(String::new()), |acc, s| {
                        match (acc, s) {
                            (Ok(acc), Ok(s)) => Ok(concat(acc, s)),
                            (Err(acc), Ok(s)) => Err(concat(acc, s)),
                            (Err(acc), Err(s)) => Err(concat(acc, s)),
                            (Ok(acc), Err(s)) => Err(concat(acc, s)),
                        }
                    })
                    .map(|s| println!("{}", s))
                    .map_err(|err| cli::Error::Custom(err))
            }
        })
}
<commit_msg>List all profiles if runs without args<commit_after>
extern crate mprovision;
#[macro_use(version)]
extern crate version;
extern crate chrono;
#[cfg(test)]
#[macro_use(expect)]
extern crate expectest;
extern crate clap;

use mprovision as mp;
use cli::Command;
use std::env;
use std::path::PathBuf;
use chrono::*;

mod cli;

fn main() {
    let result = cli::parse(env::args()).and_then(|command| {
        match command {
            Command::List(cli::ListParams { filter, expire_in_days, directory }) => {
                list(filter, expire_in_days, directory)
            }
            Command::ShowUuid(uuid, directory) => show_uuid(uuid, directory),
            Command::ShowFile(path) => show_file(path),
            Command::Remove(uuid, directory) => remove(uuid, directory),
            Command::Clean(directory) => clean(directory),
        }
    });
    if let Err(e) = result {
        e.exit();
    }
}

fn list(filter: Option<String>,
        expires_in_days: Option<i64>,
        directory: Option<PathBuf>)
        -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| {
            let total = entries.len();
            let date = expires_in_days.map(|days| UTC::now() + Duration::days(days));
            let filter_string = filter.as_ref();
            let profiles = mp::filter(entries, |profile| {
                match (date, filter_string) {
                    (Some(date), Some(string)) => {
                        profile.expiration_date <= date && profile.contains(&string)
                    }
                    (Some(date), _) => profile.expiration_date <= date,
                    (_, Some(string)) => profile.contains(&string),
                    (_, _) => true,
                }
            });
            (total, profiles)
        })
        .and_then(|(total, profiles)| {
            if profiles.is_empty() {
                Ok(println!("Nothing found"))
            } else {
                for profile in &profiles {
                    println!("\n{}", profile.description());
                }
                Ok(println!("\nFound {} of {}", profiles.len(), total))
            }
        })
}

fn show_uuid(uuid: String, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::show(&profile.path).map(|xml| println!("{}", xml)))
        })
        .map_err(|err| err.into())
}

fn show_file(path: PathBuf) -> Result<(), cli::Error> {
    mp::show(&path)
        .map(|xml| println!("{}", xml))
        .map_err(|err| err.into())
}

fn remove(uuid: String, directory: Option<PathBuf>) -> Result<(), cli::Error> {
    mp::with_directory(directory)
        .and_then(|directory| {
            mp::find_by_uuid(&directory, &uuid)
                .and_then(|profile| mp::remove(&profile.path))
                .map(|_| println!("'{}' was removed", uuid))
        })
        .map_err(|err| err.into())
}

fn clean(directory: Option<PathBuf>) -> Result<(), cli::Error> {

    fn concat(mut s1: String, s2: String) -> String {
        s1.push_str(&s2);
        s1
    }

    mp::with_directory(directory)
        .and_then(|dir| mp::entries(&dir).map(|entries| entries.collect::<Vec<_>>()))
        .map_err(|err| err.into())
        .map(|entries| {
            let date = UTC::now();
            mp::filter(entries, |profile| profile.expiration_date <= date)
        })
        .and_then(|profiles| {
            if profiles.is_empty() {
                Ok(println!("All provisioning profiles are valid"))
            } else {
                profiles.iter()
                    .map(|profile| {
                        std::fs::remove_file(&profile.path)
                            .map(|_| format!("'{}' was removed\n", profile.uuid))
                            .map_err(|err| format!("'{}' {}\n", profile.uuid, err))
                    })
                    .fold(Ok(String::new()), |acc, s| {
                        match (acc, s) {
                            (Ok(acc), Ok(s)) => Ok(concat(acc, s)),
                            (Err(acc), Ok(s)) => Err(concat(acc, s)),
                            (Err(acc), Err(s)) => Err(concat(acc, s)),
                            (Ok(acc), Err(s)) => Err(concat(acc, s)),
                        }
                    })
                    .map(|s| println!("{}", s))
                    .map_err(|err| cli::Error::Custom(err))
            }
        })
}
<|endoftext|>


<commit_before>#![cfg_attr(test, allow(dead_code))]

#![feature(collections)]
#![feature(env)]
#![feature(fs)]
#![feature(io)]
#![feature(old_io)]

extern crate document;

use std::env;
use std::cmp::min;
use std::fs::File;
use std::io::{Read,Cursor};
use std::old_io::stdio;

use document::parser::Parser;

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn process_input<R>(input: R)
    where R: Read
{
    let mut input = input;
    let mut data = String::new();
    match input.read_to_string(&mut data) {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    let p = Parser::new();

    let package = match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    };

    // TODO: Remove buffering when std::io gets stdout
    let mut out = Vec::new();
    let d = package.as_document();
    document::writer::format_document(&d, &mut out).ok().expect("I can't output");

    stdio::stdout_raw().write_all(&out).unwrap();
}

fn main() {
    let mut args: Vec<_> = env::args().collect();

    let filename = args.remove(1);

    if filename == "-" {
        let data = stdio::stdin_raw().read_to_end().unwrap();
        process_input(Cursor::new(data));
    } else {
        let file = File::open(&filename).unwrap();
        process_input(file);
    }
}
<commit_msg>env feature is no longer gated<commit_after>#![cfg_attr(test, allow(dead_code))]

#![feature(collections)]
#![feature(fs)]
#![feature(io)]
#![feature(old_io)]

extern crate document;

use std::env;
use std::cmp::min;
use std::fs::File;
use std::io::{Read,Cursor};
use std::old_io::stdio;

use document::parser::Parser;

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn process_input<R>(input: R)
    where R: Read
{
    let mut input = input;
    let mut data = String::new();
    match input.read_to_string(&mut data) {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    let p = Parser::new();

    let package = match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    };

    // TODO: Remove buffering when std::io gets stdout
    let mut out = Vec::new();
    let d = package.as_document();
    document::writer::format_document(&d, &mut out).ok().expect("I can't output");

    stdio::stdout_raw().write_all(&out).unwrap();
}

fn main() {
    let mut args: Vec<_> = env::args().collect();

    let filename = args.remove(1);

    if filename == "-" {
        let data = stdio::stdin_raw().read_to_end().unwrap();
        process_input(Cursor::new(data));
    } else {
        let file = File::open(&filename).unwrap();
        process_input(file);
    }
}
<|endoftext|>