<commit_before>use cairo::{self, MatrixTrait};
use std::cell::Cell;

use crate::attributes::Attribute;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::drawing_ctx::DrawingCtx;
use crate::error::RenderingError;
use crate::length::{LengthHorizontal, LengthVertical};
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
use crate::properties::Opacity;
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
use crate::surface_utils::{
    iterators::Pixels,
    shared_surface::SharedImageSurface,
    shared_surface::SurfaceType,
    ImageSurfaceDataExt,
};
use crate::unit_interval::UnitInterval;

coord_units!(MaskUnits, CoordUnits::ObjectBoundingBox);
coord_units!(MaskContentUnits, CoordUnits::UserSpaceOnUse);

pub struct NodeMask {
    x: Cell<LengthHorizontal>,
    y: Cell<LengthVertical>,
    width: Cell<LengthHorizontal>,
    height: Cell<LengthVertical>,

    units: Cell<MaskUnits>,
    content_units: Cell<MaskContentUnits>,
}

impl NodeMask {
    pub fn new() -> NodeMask {
        NodeMask {
            // these values are per the spec
            x: Cell::new(LengthHorizontal::parse_str("-10%").unwrap()),
            y: Cell::new(LengthVertical::parse_str("-10%").unwrap()),

            width: Cell::new(LengthHorizontal::parse_str("120%").unwrap()),
            height: Cell::new(LengthVertical::parse_str("120%").unwrap()),

            units: Cell::new(MaskUnits::default()),
            content_units: Cell::new(MaskContentUnits::default()),
        }
    }

    pub fn generate_cairo_mask(
        &self,
        node: &RsvgNode,
        affine_before_mask: &cairo::Matrix,
        draw_ctx: &mut DrawingCtx,
        bbox: &BoundingBox,
    ) -> Result<(), RenderingError> {
        let cascaded = node.get_cascaded_values();
        let values = cascaded.get();

        let surface = draw_ctx.create_surface_for_toplevel_viewport()?;

        let mask_units = CoordUnits::from(self.units.get());
        let content_units = CoordUnits::from(self.content_units.get());

        let (x, y, w, h) = {
            let params = if mask_units == CoordUnits::ObjectBoundingBox {
                draw_ctx.push_view_box(1.0, 1.0)
            } else {
                draw_ctx.get_view_params()
            };

            let x = self.x.get().normalize(&values, &params);
            let y = self.y.get().normalize(&values, &params);
            let w = self.width.get().normalize(&values, &params);
            let h = self.height.get().normalize(&values, &params);

            (x, y, w, h)
        };

        // Use a scope because mask_cr needs to release the
        // reference to the surface before we access the pixels
        {
            let bbox_rect = {
                if let Some(ref rect) = bbox.rect {
                    *rect
                } else {
                    // The node being masked is empty / doesn't have a
                    // bounding box, so there's nothing to mask!
                    return Ok(());
                }
            };

            let save_cr = draw_ctx.get_cairo_context();

            let mask_cr = cairo::Context::new(&surface);
            mask_cr.set_matrix(*affine_before_mask);
            mask_cr.transform(node.get_transform());

            draw_ctx.set_cairo_context(&mask_cr);

            if mask_units == CoordUnits::ObjectBoundingBox {
                draw_ctx.clip(
                    x * bbox_rect.width + bbox_rect.x,
                    y * bbox_rect.height + bbox_rect.y,
                    w * bbox_rect.width,
                    h * bbox_rect.height,
                );
            } else {
                draw_ctx.clip(x, y, w, h);
            }

            {
                let _params = if content_units == CoordUnits::ObjectBoundingBox {
                    let bbtransform = cairo::Matrix::new(
                        bbox_rect.width,
                        0.0,
                        0.0,
                        bbox_rect.height,
                        bbox_rect.x,
                        bbox_rect.y,
                    );

                    mask_cr.transform(bbtransform);

                    draw_ctx.push_view_box(1.0, 1.0)
                } else {
                    draw_ctx.get_view_params()
                };

                let res = draw_ctx.with_discrete_layer(node, values, false, &mut |dc| {
                    node.draw_children(&cascaded, dc, false)
                });

                draw_ctx.set_cairo_context(&save_cr);

                res
            }
        }?;

        let Opacity(opacity) = values.opacity;
        let mask_surface = compute_luminance_to_alpha(surface, opacity)?;

        let cr = draw_ctx.get_cairo_context();

        cr.identity_matrix();

        cr.mask_surface(&mask_surface, 0.0, 0.0);

        Ok(())
    }
}

// Returns a surface whose alpha channel for each pixel is equal to the
// luminance of that pixel's unpremultiplied RGB values.  The resulting
// surface's RGB values are not meanignful; only the alpha channel has
// useful luminance data.
//
// This is to get a mask suitable for use with cairo_mask_surface().
fn compute_luminance_to_alpha(
    surface: cairo::ImageSurface,
    opacity: UnitInterval,
) -> Result<cairo::ImageSurface, cairo::Status> {
    let surface = SharedImageSurface::new(surface, SurfaceType::SRgb)?;

    let width = surface.width();
    let height = surface.height();

    let bounds = IRect {
        x0: 0,
        y0: 0,
        x1: width,
        y1: height,
    };

    let opacity = u8::from(opacity);
    let mut output = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?;
    let output_stride = output.get_stride() as usize;

    {
        let mut output_data = output.get_data().unwrap();

        for (x, y, pixel) in Pixels::new(&surface, bounds) {
            output_data.set_pixel(output_stride, pixel.to_mask(opacity), x, y);
        }
    }

    Ok(output)
}

impl NodeTrait for NodeMask {
    fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
        for (attr, value) in pbag.iter() {
            match attr {
                Attribute::X => self.x.set(attr.parse(value)?),
                Attribute::Y => self.y.set(attr.parse(value)?),
                Attribute::Width => self
                    .width
                    .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
                Attribute::Height => self
                    .height
                    .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
                Attribute::MaskUnits => self.units.set(attr.parse(value)?),
                Attribute::MaskContentUnits => self.content_units.set(attr.parse(value)?),
                _ => (),
            }
        }

        Ok(())
    }
}
<commit_msg>NodeMask::generate_cairo_mask(): Move the short-circuit if there's no bounding box to the beginning<commit_after>use cairo::{self, MatrixTrait};
use std::cell::Cell;

use crate::attributes::Attribute;
use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::drawing_ctx::DrawingCtx;
use crate::error::RenderingError;
use crate::length::{LengthHorizontal, LengthVertical};
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::parsers::{Parse, ParseValue};
use crate::properties::Opacity;
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
use crate::surface_utils::{
    iterators::Pixels,
    shared_surface::SharedImageSurface,
    shared_surface::SurfaceType,
    ImageSurfaceDataExt,
};
use crate::unit_interval::UnitInterval;

coord_units!(MaskUnits, CoordUnits::ObjectBoundingBox);
coord_units!(MaskContentUnits, CoordUnits::UserSpaceOnUse);

pub struct NodeMask {
    x: Cell<LengthHorizontal>,
    y: Cell<LengthVertical>,
    width: Cell<LengthHorizontal>,
    height: Cell<LengthVertical>,

    units: Cell<MaskUnits>,
    content_units: Cell<MaskContentUnits>,
}

impl NodeMask {
    pub fn new() -> NodeMask {
        NodeMask {
            // these values are per the spec
            x: Cell::new(LengthHorizontal::parse_str("-10%").unwrap()),
            y: Cell::new(LengthVertical::parse_str("-10%").unwrap()),

            width: Cell::new(LengthHorizontal::parse_str("120%").unwrap()),
            height: Cell::new(LengthVertical::parse_str("120%").unwrap()),

            units: Cell::new(MaskUnits::default()),
            content_units: Cell::new(MaskContentUnits::default()),
        }
    }

    pub fn generate_cairo_mask(
        &self,
        node: &RsvgNode,
        affine_before_mask: &cairo::Matrix,
        draw_ctx: &mut DrawingCtx,
        bbox: &BoundingBox,
    ) -> Result<(), RenderingError> {
        if bbox.rect.is_none() {
            // The node being masked is empty / doesn't have a
            // bounding box, so there's nothing to mask!
            return Ok(());
        }

        let bbox_rect = bbox.rect.as_ref().unwrap();

        let cascaded = node.get_cascaded_values();
        let values = cascaded.get();

        let surface = draw_ctx.create_surface_for_toplevel_viewport()?;

        let mask_units = CoordUnits::from(self.units.get());
        let content_units = CoordUnits::from(self.content_units.get());

        let (x, y, w, h) = {
            let params = if mask_units == CoordUnits::ObjectBoundingBox {
                draw_ctx.push_view_box(1.0, 1.0)
            } else {
                draw_ctx.get_view_params()
            };

            let x = self.x.get().normalize(&values, &params);
            let y = self.y.get().normalize(&values, &params);
            let w = self.width.get().normalize(&values, &params);
            let h = self.height.get().normalize(&values, &params);

            (x, y, w, h)
        };

        // Use a scope because mask_cr needs to release the
        // reference to the surface before we access the pixels
        {
            let save_cr = draw_ctx.get_cairo_context();

            let mask_cr = cairo::Context::new(&surface);
            mask_cr.set_matrix(*affine_before_mask);
            mask_cr.transform(node.get_transform());

            draw_ctx.set_cairo_context(&mask_cr);

            if mask_units == CoordUnits::ObjectBoundingBox {
                draw_ctx.clip(
                    x * bbox_rect.width + bbox_rect.x,
                    y * bbox_rect.height + bbox_rect.y,
                    w * bbox_rect.width,
                    h * bbox_rect.height,
                );
            } else {
                draw_ctx.clip(x, y, w, h);
            }

            {
                let _params = if content_units == CoordUnits::ObjectBoundingBox {
                    let bbtransform = cairo::Matrix::new(
                        bbox_rect.width,
                        0.0,
                        0.0,
                        bbox_rect.height,
                        bbox_rect.x,
                        bbox_rect.y,
                    );

                    mask_cr.transform(bbtransform);

                    draw_ctx.push_view_box(1.0, 1.0)
                } else {
                    draw_ctx.get_view_params()
                };

                let res = draw_ctx.with_discrete_layer(node, values, false, &mut |dc| {
                    node.draw_children(&cascaded, dc, false)
                });

                draw_ctx.set_cairo_context(&save_cr);

                res
            }
        }?;

        let Opacity(opacity) = values.opacity;
        let mask_surface = compute_luminance_to_alpha(surface, opacity)?;

        let cr = draw_ctx.get_cairo_context();

        cr.identity_matrix();

        cr.mask_surface(&mask_surface, 0.0, 0.0);

        Ok(())
    }
}

// Returns a surface whose alpha channel for each pixel is equal to the
// luminance of that pixel's unpremultiplied RGB values.  The resulting
// surface's RGB values are not meanignful; only the alpha channel has
// useful luminance data.
//
// This is to get a mask suitable for use with cairo_mask_surface().
fn compute_luminance_to_alpha(
    surface: cairo::ImageSurface,
    opacity: UnitInterval,
) -> Result<cairo::ImageSurface, cairo::Status> {
    let surface = SharedImageSurface::new(surface, SurfaceType::SRgb)?;

    let width = surface.width();
    let height = surface.height();

    let bounds = IRect {
        x0: 0,
        y0: 0,
        x1: width,
        y1: height,
    };

    let opacity = u8::from(opacity);
    let mut output = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?;
    let output_stride = output.get_stride() as usize;

    {
        let mut output_data = output.get_data().unwrap();

        for (x, y, pixel) in Pixels::new(&surface, bounds) {
            output_data.set_pixel(output_stride, pixel.to_mask(opacity), x, y);
        }
    }

    Ok(output)
}

impl NodeTrait for NodeMask {
    fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
        for (attr, value) in pbag.iter() {
            match attr {
                Attribute::X => self.x.set(attr.parse(value)?),
                Attribute::Y => self.y.set(attr.parse(value)?),
                Attribute::Width => self
                    .width
                    .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
                Attribute::Height => self
                    .height
                    .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
                Attribute::MaskUnits => self.units.set(attr.parse(value)?),
                Attribute::MaskContentUnits => self.content_units.set(attr.parse(value)?),
                _ => (),
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::io::Error as IoError;
use std::mem;
use std::path::{Path, PathBuf};

#[cfg(any(target_os = "linux", target_os = "macos"))]
use std::os::unix::ffi::OsStrExt;

use chrono::prelude::*;
use libc;

use errors::*;
use marshal::ObjectHash;

#[cfg(any(target_os = "linux", target_os = "macos"))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct IndexMetadata {
    mtime: DateTime<Utc>,
    ctime: DateTime<Utc>,

    uid: u32,
    gid: u32,
    ino: u64,
    mode: u32,
    size: i64,
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
impl IndexMetadata {
    pub fn load<P: AsRef<Path>>(path: P) -> Result<IndexMetadata> {
        let stat = unsafe {
            let path_ptr = path.as_ref().as_os_str().as_bytes().as_ptr() as *const i8;
            let mut stat = mem::zeroed();
            if libc::lstat(path_ptr, &mut stat) != 0 {
                bail!(IoError::last_os_error());
            }
            stat
        };

        let mtime = Utc.timestamp(stat.st_mtime, 0);
        let ctime = Utc.timestamp(stat.st_ctime, 0);

        let uid = stat.st_uid;
        let gid = stat.st_gid;
        let ino = stat.st_ino;
        let mode = stat.st_mode;
        let size = stat.st_size;

        Ok(IndexMetadata {
            mtime,
            ctime,
            uid,
            gid,
            ino,
            mode,
            size,
        })
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Hygiene {
    Clean,
    Dodgy,
    Dirty,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct IndexEntry {
    hygiene: Hygiene,
    cached: IndexMetadata,

    object_hash: ObjectHash,
}

impl IndexEntry {
    fn update(&mut self, fresh: &IndexMetadata, timestamp: &DateTime<Utc>) {
        if self.hygiene == Hygiene::Clean {
            self.hygiene = {
                if &self.cached == fresh {
                    if timestamp > &self.cached.mtime {
                        Hygiene::Dodgy
                    } else {
                        Hygiene::Clean
                    }
                } else {
                    Hygiene::Dirty
                }
            };
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Index {
    timestamp: DateTime<Utc>,
    entries: HashMap<PathBuf, IndexEntry>,
}

impl Index {
    pub fn update(&mut self, base: &Path) -> Result<()> {
        // Create a new timestamp for when we *begin* indexing.
        let fresh_timestamp = Utc::now();

        for (path, entry) in &mut self.entries {
            entry.update(&IndexMetadata::load(base.join(path))?, &self.timestamp);
        }

        // Timestamps refer to the instant at which indexing starts, rather than the instant at
        // which it ends (the mtime of the index itself.)
        self.timestamp = fresh_timestamp;

        Ok(())
    }
}
<commit_msg>index: load from file and write to file on drop<commit_after>use std::collections::HashMap;
use std::fs::File;
use std::io::Error as IoError;
use std::mem;
use std::path::{Path, PathBuf};

#[cfg(any(target_os = "linux", target_os = "macos"))]
use std::os::unix::ffi::OsStrExt;

use bincode;
use chrono::prelude::*;
use libc;

use errors::*;
use marshal::ObjectHash;

#[cfg(any(target_os = "linux", target_os = "macos"))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct IndexMetadata {
    mtime: DateTime<Utc>,
    ctime: DateTime<Utc>,

    uid: u32,
    gid: u32,
    ino: u64,
    mode: u32,
    size: i64,
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
impl IndexMetadata {
    pub fn load<P: AsRef<Path>>(path: P) -> Result<IndexMetadata> {
        let stat = unsafe {
            let path_ptr = path.as_ref().as_os_str().as_bytes().as_ptr() as *const i8;
            let mut stat = mem::zeroed();
            if libc::lstat(path_ptr, &mut stat) != 0 {
                bail!(IoError::last_os_error());
            }
            stat
        };

        let mtime = Utc.timestamp(stat.st_mtime, 0);
        let ctime = Utc.timestamp(stat.st_ctime, 0);

        let uid = stat.st_uid;
        let gid = stat.st_gid;
        let ino = stat.st_ino;
        let mode = stat.st_mode;
        let size = stat.st_size;

        Ok(IndexMetadata {
            mtime,
            ctime,
            uid,
            gid,
            ino,
            mode,
            size,
        })
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum Hygiene {
    Clean,
    Dodgy,
    Dirty,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct IndexEntry {
    hygiene: Hygiene,
    cached: IndexMetadata,

    object_hash: ObjectHash,
}

impl IndexEntry {
    fn update(&mut self, fresh: &IndexMetadata, timestamp: &DateTime<Utc>) {
        if self.hygiene == Hygiene::Clean {
            self.hygiene = {
                if &self.cached == fresh {
                    if timestamp > &self.cached.mtime {
                        Hygiene::Dodgy
                    } else {
                        Hygiene::Clean
                    }
                } else {
                    Hygiene::Dirty
                }
            };
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct IndexData {
    timestamp: DateTime<Utc>,
    entries: HashMap<PathBuf, IndexEntry>,
}

impl IndexData {
    pub fn new() -> Self {
        IndexData {
            timestamp: Utc::now(),
            entries: HashMap::new(),
        }
    }
}

#[derive(Debug)]
pub struct Index {
    path: PathBuf,
    data: IndexData,
}

impl Index {
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Index> {
        let path_ref = path.as_ref();

        let data = if path_ref.is_file() {
            let mut index_file = File::open(path_ref)?;
            bincode::deserialize_from(&mut index_file, bincode::Infinite)?
        } else {
            IndexData::new()
        };

        Ok(Index {
            path: path_ref.to_owned(),
            data,
        })
    }

    pub fn update<P: AsRef<Path>>(&mut self, base: P) -> Result<()> {
        // Create a new timestamp for when we *begin* indexing.
        let fresh_timestamp = Utc::now();

        for (path, entry) in &mut self.data.entries {
            entry.update(
                &IndexMetadata::load(base.as_ref().join(path))?,
                &self.data.timestamp,
            );
        }

        // Timestamps refer to the instant at which indexing starts, rather than the instant at
        // which it ends (the mtime of the index itself.)
        self.data.timestamp = fresh_timestamp;

        Ok(())
    }
}

impl Drop for Index {
    fn drop(&mut self) {
        let mut file = File::create(&self.path).unwrap();
        bincode::serialize_into(&mut file, &self.data, bincode::Infinite).unwrap();
    }
}
<|endoftext|>


<commit_before>#![crate_name = "uu_nl"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Tobias Bohumir Schottdorf <tobias.schottdorf@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 */

extern crate aho_corasick;
extern crate getopts;
extern crate memchr;
extern crate regex;
extern crate regex_syntax;

#[macro_use]
extern crate uucore;

use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read};
use std::iter::repeat;
use std::path::Path;

mod helper;

static NAME: &str = "nl";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static USAGE: &str = "nl [OPTION]... [FILE]...";
// A regular expression matching everything.

// Settings store options used by nl to produce its output.
pub struct Settings {
    // The variables corresponding to the options -h, -b, and -f.
    header_numbering: NumberingStyle,
    body_numbering: NumberingStyle,
    footer_numbering: NumberingStyle,
    // The variable corresponding to -d
    section_delimiter: [char; 2],
    // The variables corresponding to the options -v, -i, -l, -w.
    starting_line_number: u64,
    line_increment: u64,
    join_blank_lines: u64,
    number_width: usize, // Used with String::from_char, hence usize.
    // The format of the number and the (default value for)
    // renumbering each page.
    number_format: NumberFormat,
    renumber: bool,
    // The string appended to each line number output.
    number_separator: String,
}

// NumberingStyle stores which lines are to be numbered.
// The possible options are:
// 1. Number all lines
// 2. Number only nonempty lines
// 3. Don't number any lines at all
// 4. Number all lines that match a basic regular expression.
enum NumberingStyle {
    NumberForAll,
    NumberForNonEmpty,
    NumberForNone,
    NumberForRegularExpression(regex::Regex),
}

// NumberFormat specifies how line numbers are output within their allocated
// space. They are justified to the left or right, in the latter case with
// the option of having all unused space to its left turned into leading zeroes.
enum NumberFormat {
    Left,
    Right,
    RightZero,
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optopt(
        "b",
        "body-numbering",
        "use STYLE for numbering body lines",
        "STYLE",
    );
    opts.optopt(
        "d",
        "section-delimiter",
        "use CC for separating logical pages",
        "CC",
    );
    opts.optopt(
        "f",
        "footer-numbering",
        "use STYLE for numbering footer lines",
        "STYLE",
    );
    opts.optopt(
        "h",
        "header-numbering",
        "use STYLE for numbering header lines",
        "STYLE",
    );
    opts.optopt(
        "i",
        "line-increment",
        "line number increment at each line",
        "",
    );
    opts.optopt(
        "l",
        "join-blank-lines",
        "group of NUMBER empty lines counted as one",
        "NUMBER",
    );
    opts.optopt(
        "n",
        "number-format",
        "insert line numbers according to FORMAT",
        "FORMAT",
    );
    opts.optflag(
        "p",
        "no-renumber",
        "do not reset line numbers at logical pages",
    );
    opts.optopt(
        "s",
        "number-separator",
        "add STRING after (possible) line number",
        "STRING",
    );
    opts.optopt(
        "v",
        "starting-line-number",
        "first line number on each logical page",
        "NUMBER",
    );
    opts.optopt(
        "w",
        "number-width",
        "use NUMBER columns for line numbers",
        "NUMBER",
    );
    opts.optflag("", "help", "display this help and exit");
    opts.optflag("V", "version", "version");

    // A mutable settings object, initialized with the defaults.
    let mut settings = Settings {
        header_numbering: NumberingStyle::NumberForNone,
        body_numbering: NumberingStyle::NumberForAll,
        footer_numbering: NumberingStyle::NumberForNone,
        section_delimiter: ['\\', ':'],
        starting_line_number: 1,
        line_increment: 1,
        join_blank_lines: 1,
        number_width: 6,
        number_format: NumberFormat::Right,
        renumber: true,
        number_separator: String::from("\t"),
    };

    let given_options = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            show_error!("{}", f);
            print_usage(&opts);
            return 1;
        }
    };

    if given_options.opt_present("help") {
        print_usage(&opts);
        return 0;
    }
    if given_options.opt_present("version") {
        version();
        return 0;
    }

    // Update the settings from the command line options, and terminate the
    // program if some options could not successfully be parsed.
    let parse_errors = helper::parse_options(&mut settings, &given_options);
    if !parse_errors.is_empty() {
        show_error!("Invalid arguments supplied.");
        for message in &parse_errors {
            println!("{}", message);
        }
        return 1;
    }

    let files = given_options.free;
    let mut read_stdin = files.is_empty();

    for file in &files {
        if file == "-" {
            // If both file names and '-' are specified, we choose to treat first all
            // regular files, and then read from stdin last.
            read_stdin = true;
            continue;
        }
        let path = Path::new(file);
        let reader = File::open(path).unwrap();
        let mut buffer = BufReader::new(reader);
        nl(&mut buffer, &settings);
    }

    if read_stdin {
        let mut buffer = BufReader::new(stdin());
        nl(&mut buffer, &settings);
    }
    0
}

// nl implements the main functionality for an individual buffer.
fn nl<T: Read>(reader: &mut BufReader<T>, settings: &Settings) {
    let regexp: regex::Regex = regex::Regex::new(r".?").unwrap();
    let mut line_no = settings.starting_line_number;
    // The current line number's width as a string. Using to_string is inefficient
    // but since we only do it once, it should not hurt.
    let mut line_no_width = line_no.to_string().len();
    let line_no_width_initial = line_no_width;
    // Stores the smallest integer with one more digit than line_no, so that
    // when line_no >= line_no_threshold, we need to use one more digit.
    let mut line_no_threshold = 10u64.pow(line_no_width as u32);
    let mut empty_line_count: u64 = 0;
    let fill_char = match settings.number_format {
        NumberFormat::RightZero => '0',
        _ => ' ',
    };
    // Initially, we use the body's line counting settings
    let mut regex_filter = match settings.body_numbering {
        NumberingStyle::NumberForRegularExpression(ref re) => re,
        _ => &regexp,
    };
    let mut line_filter: fn(&str, &regex::Regex) -> bool = pass_regex;
    for mut l in reader.lines().map(|r| r.unwrap()) {
        // Sanitize the string. We want to print the newline ourselves.
        if !l.is_empty() && l.chars().rev().next().unwrap() == '\n' {
            l.pop();
        }
        // Next we iterate through the individual chars to see if this
        // is one of the special lines starting a new "section" in the
        // document.
        let line = l;
        let mut odd = false;
        // matched_group counts how many copies of section_delimiter
        // this string consists of (0 if there's anything else)
        let mut matched_groups = 0u8;
        for c in line.chars() {
            // If this is a newline character, the loop should end.
            if c == '\n' {
                break;
            }
            // If we have already seen three groups (corresponding to
            // a header) or the current char does not form part of
            // a new group, then this line is not a segment indicator.
            if matched_groups >= 3 || settings.section_delimiter[if odd { 1 } else { 0 }] != c {
                matched_groups = 0;
                break;
            }
            if odd {
                // We have seen a new group and count it.
                matched_groups += 1;
            }
            odd = !odd;
        }

        // See how many groups we matched. That will tell us if this is
        // a line starting a new segment, and the number of groups
        // indicates what type of segment.
        if matched_groups > 0 {
            // The current line is a section delimiter, so we output
            // a blank line.
            println!();
            // However the line does not count as a blank line, so we
            // reset the counter used for --join-blank-lines.
            empty_line_count = 0;
            match *match matched_groups {
                3 => {
                    // This is a header, so we may need to reset the
                    // line number and the line width
                    if settings.renumber {
                        line_no = settings.starting_line_number;
                        line_no_width = line_no_width_initial;
                        line_no_threshold = 10u64.pow(line_no_width as u32);
                    }
                    &settings.header_numbering
                }
                1 => &settings.footer_numbering,
                // The only option left is 2, but rust wants
                // a catch-all here.
                _ => &settings.body_numbering,
            } {
                NumberingStyle::NumberForAll => {
                    line_filter = pass_all;
                }
                NumberingStyle::NumberForNonEmpty => {
                    line_filter = pass_nonempty;
                }
                NumberingStyle::NumberForNone => {
                    line_filter = pass_none;
                }
                NumberingStyle::NumberForRegularExpression(ref re) => {
                    line_filter = pass_regex;
                    regex_filter = re;
                }
            }
            continue;
        }
        // From this point on we format and print a "regular" line.
        if line == "" {
            // The line is empty, which means that we have to care
            // about the --join-blank-lines parameter.
            empty_line_count += 1;
        } else {
            // This saves us from having to check for an empty string
            // in the next selector.
            empty_line_count = 0;
        }
        if !line_filter(&line, regex_filter)
            || (empty_line_count > 0 && empty_line_count < settings.join_blank_lines)
        {
            // No number is printed for this line. Either we did not
            // want to print one in the first place, or it is a blank
            // line but we are still collecting more blank lines via
            // the option --join-blank-lines.
            println!("{}", line);
            continue;
        }
        // If we make it here, then either we are printing a non-empty
        // line or assigning a line number to an empty line. Either
        // way, start counting empties from zero once more.
        empty_line_count = 0;
        // A line number is to be printed.
        let w = if settings.number_width > line_no_width {
            settings.number_width - line_no_width
        } else { 0 };
        let fill: String = repeat(fill_char).take(w).collect();
        match settings.number_format {
            NumberFormat::Left => println!(
                "{1}{0}{2}{3}",
                fill, line_no, settings.number_separator, line
            ),
            _ => println!(
                "{0}{1}{2}{3}",
                fill, line_no, settings.number_separator, line
            ),
        }
        // Now update the variables for the (potential) next
        // line.
        line_no += settings.line_increment;
        while line_no >= line_no_threshold {
            // The line number just got longer.
            line_no_threshold *= 10;
            line_no_width += 1;
        }
    }
}

fn pass_regex(line: &str, re: &regex::Regex) -> bool {
    re.is_match(line)
}

fn pass_nonempty(line: &str, _: &regex::Regex) -> bool {
    !line.is_empty()
}

fn pass_none(_: &str, _: &regex::Regex) -> bool {
    false
}

fn pass_all(_: &str, _: &regex::Regex) -> bool {
    true
}

fn print_usage(opts: &getopts::Options) {
    println!("{}", opts.usage(USAGE));
}

fn version() {
    println!("{} {}", NAME, VERSION);
}
<commit_msg>refactor/polish ~ fix `cargo clippy` complaints (allow enum_variant_names)<commit_after>#![crate_name = "uu_nl"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Tobias Bohumir Schottdorf <tobias.schottdorf@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 */

extern crate aho_corasick;
extern crate getopts;
extern crate memchr;
extern crate regex;
extern crate regex_syntax;

#[macro_use]
extern crate uucore;

use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read};
use std::iter::repeat;
use std::path::Path;

mod helper;

static NAME: &str = "nl";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static USAGE: &str = "nl [OPTION]... [FILE]...";
// A regular expression matching everything.

// Settings store options used by nl to produce its output.
pub struct Settings {
    // The variables corresponding to the options -h, -b, and -f.
    header_numbering: NumberingStyle,
    body_numbering: NumberingStyle,
    footer_numbering: NumberingStyle,
    // The variable corresponding to -d
    section_delimiter: [char; 2],
    // The variables corresponding to the options -v, -i, -l, -w.
    starting_line_number: u64,
    line_increment: u64,
    join_blank_lines: u64,
    number_width: usize, // Used with String::from_char, hence usize.
    // The format of the number and the (default value for)
    // renumbering each page.
    number_format: NumberFormat,
    renumber: bool,
    // The string appended to each line number output.
    number_separator: String,
}

// NumberingStyle stores which lines are to be numbered.
// The possible options are:
// 1. Number all lines
// 2. Number only nonempty lines
// 3. Don't number any lines at all
// 4. Number all lines that match a basic regular expression.
#[allow(clippy::enum_variant_names)]
enum NumberingStyle {
    NumberForAll,
    NumberForNonEmpty,
    NumberForNone,
    NumberForRegularExpression(regex::Regex),
}

// NumberFormat specifies how line numbers are output within their allocated
// space. They are justified to the left or right, in the latter case with
// the option of having all unused space to its left turned into leading zeroes.
enum NumberFormat {
    Left,
    Right,
    RightZero,
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = getopts::Options::new();

    opts.optopt(
        "b",
        "body-numbering",
        "use STYLE for numbering body lines",
        "STYLE",
    );
    opts.optopt(
        "d",
        "section-delimiter",
        "use CC for separating logical pages",
        "CC",
    );
    opts.optopt(
        "f",
        "footer-numbering",
        "use STYLE for numbering footer lines",
        "STYLE",
    );
    opts.optopt(
        "h",
        "header-numbering",
        "use STYLE for numbering header lines",
        "STYLE",
    );
    opts.optopt(
        "i",
        "line-increment",
        "line number increment at each line",
        "",
    );
    opts.optopt(
        "l",
        "join-blank-lines",
        "group of NUMBER empty lines counted as one",
        "NUMBER",
    );
    opts.optopt(
        "n",
        "number-format",
        "insert line numbers according to FORMAT",
        "FORMAT",
    );
    opts.optflag(
        "p",
        "no-renumber",
        "do not reset line numbers at logical pages",
    );
    opts.optopt(
        "s",
        "number-separator",
        "add STRING after (possible) line number",
        "STRING",
    );
    opts.optopt(
        "v",
        "starting-line-number",
        "first line number on each logical page",
        "NUMBER",
    );
    opts.optopt(
        "w",
        "number-width",
        "use NUMBER columns for line numbers",
        "NUMBER",
    );
    opts.optflag("", "help", "display this help and exit");
    opts.optflag("V", "version", "version");

    // A mutable settings object, initialized with the defaults.
    let mut settings = Settings {
        header_numbering: NumberingStyle::NumberForNone,
        body_numbering: NumberingStyle::NumberForAll,
        footer_numbering: NumberingStyle::NumberForNone,
        section_delimiter: ['\\', ':'],
        starting_line_number: 1,
        line_increment: 1,
        join_blank_lines: 1,
        number_width: 6,
        number_format: NumberFormat::Right,
        renumber: true,
        number_separator: String::from("\t"),
    };

    let given_options = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            show_error!("{}", f);
            print_usage(&opts);
            return 1;
        }
    };

    if given_options.opt_present("help") {
        print_usage(&opts);
        return 0;
    }
    if given_options.opt_present("version") {
        version();
        return 0;
    }

    // Update the settings from the command line options, and terminate the
    // program if some options could not successfully be parsed.
    let parse_errors = helper::parse_options(&mut settings, &given_options);
    if !parse_errors.is_empty() {
        show_error!("Invalid arguments supplied.");
        for message in &parse_errors {
            println!("{}", message);
        }
        return 1;
    }

    let files = given_options.free;
    let mut read_stdin = files.is_empty();

    for file in &files {
        if file == "-" {
            // If both file names and '-' are specified, we choose to treat first all
            // regular files, and then read from stdin last.
            read_stdin = true;
            continue;
        }
        let path = Path::new(file);
        let reader = File::open(path).unwrap();
        let mut buffer = BufReader::new(reader);
        nl(&mut buffer, &settings);
    }

    if read_stdin {
        let mut buffer = BufReader::new(stdin());
        nl(&mut buffer, &settings);
    }
    0
}

// nl implements the main functionality for an individual buffer.
fn nl<T: Read>(reader: &mut BufReader<T>, settings: &Settings) {
    let regexp: regex::Regex = regex::Regex::new(r".?").unwrap();
    let mut line_no = settings.starting_line_number;
    // The current line number's width as a string. Using to_string is inefficient
    // but since we only do it once, it should not hurt.
    let mut line_no_width = line_no.to_string().len();
    let line_no_width_initial = line_no_width;
    // Stores the smallest integer with one more digit than line_no, so that
    // when line_no >= line_no_threshold, we need to use one more digit.
    let mut line_no_threshold = 10u64.pow(line_no_width as u32);
    let mut empty_line_count: u64 = 0;
    let fill_char = match settings.number_format {
        NumberFormat::RightZero => '0',
        _ => ' ',
    };
    // Initially, we use the body's line counting settings
    let mut regex_filter = match settings.body_numbering {
        NumberingStyle::NumberForRegularExpression(ref re) => re,
        _ => &regexp,
    };
    let mut line_filter: fn(&str, &regex::Regex) -> bool = pass_regex;
    for mut l in reader.lines().map(|r| r.unwrap()) {
        // Sanitize the string. We want to print the newline ourselves.
        if !l.is_empty() && l.chars().rev().next().unwrap() == '\n' {
            l.pop();
        }
        // Next we iterate through the individual chars to see if this
        // is one of the special lines starting a new "section" in the
        // document.
        let line = l;
        let mut odd = false;
        // matched_group counts how many copies of section_delimiter
        // this string consists of (0 if there's anything else)
        let mut matched_groups = 0u8;
        for c in line.chars() {
            // If this is a newline character, the loop should end.
            if c == '\n' {
                break;
            }
            // If we have already seen three groups (corresponding to
            // a header) or the current char does not form part of
            // a new group, then this line is not a segment indicator.
            if matched_groups >= 3 || settings.section_delimiter[if odd { 1 } else { 0 }] != c {
                matched_groups = 0;
                break;
            }
            if odd {
                // We have seen a new group and count it.
                matched_groups += 1;
            }
            odd = !odd;
        }

        // See how many groups we matched. That will tell us if this is
        // a line starting a new segment, and the number of groups
        // indicates what type of segment.
        if matched_groups > 0 {
            // The current line is a section delimiter, so we output
            // a blank line.
            println!();
            // However the line does not count as a blank line, so we
            // reset the counter used for --join-blank-lines.
            empty_line_count = 0;
            match *match matched_groups {
                3 => {
                    // This is a header, so we may need to reset the
                    // line number and the line width
                    if settings.renumber {
                        line_no = settings.starting_line_number;
                        line_no_width = line_no_width_initial;
                        line_no_threshold = 10u64.pow(line_no_width as u32);
                    }
                    &settings.header_numbering
                }
                1 => &settings.footer_numbering,
                // The only option left is 2, but rust wants
                // a catch-all here.
                _ => &settings.body_numbering,
            } {
                NumberingStyle::NumberForAll => {
                    line_filter = pass_all;
                }
                NumberingStyle::NumberForNonEmpty => {
                    line_filter = pass_nonempty;
                }
                NumberingStyle::NumberForNone => {
                    line_filter = pass_none;
                }
                NumberingStyle::NumberForRegularExpression(ref re) => {
                    line_filter = pass_regex;
                    regex_filter = re;
                }
            }
            continue;
        }
        // From this point on we format and print a "regular" line.
        if line == "" {
            // The line is empty, which means that we have to care
            // about the --join-blank-lines parameter.
            empty_line_count += 1;
        } else {
            // This saves us from having to check for an empty string
            // in the next selector.
            empty_line_count = 0;
        }
        if !line_filter(&line, regex_filter)
            || (empty_line_count > 0 && empty_line_count < settings.join_blank_lines)
        {
            // No number is printed for this line. Either we did not
            // want to print one in the first place, or it is a blank
            // line but we are still collecting more blank lines via
            // the option --join-blank-lines.
            println!("{}", line);
            continue;
        }
        // If we make it here, then either we are printing a non-empty
        // line or assigning a line number to an empty line. Either
        // way, start counting empties from zero once more.
        empty_line_count = 0;
        // A line number is to be printed.
        let w = if settings.number_width > line_no_width {
            settings.number_width - line_no_width
        } else { 0 };
        let fill: String = repeat(fill_char).take(w).collect();
        match settings.number_format {
            NumberFormat::Left => println!(
                "{1}{0}{2}{3}",
                fill, line_no, settings.number_separator, line
            ),
            _ => println!(
                "{0}{1}{2}{3}",
                fill, line_no, settings.number_separator, line
            ),
        }
        // Now update the variables for the (potential) next
        // line.
        line_no += settings.line_increment;
        while line_no >= line_no_threshold {
            // The line number just got longer.
            line_no_threshold *= 10;
            line_no_width += 1;
        }
    }
}

fn pass_regex(line: &str, re: &regex::Regex) -> bool {
    re.is_match(line)
}

fn pass_nonempty(line: &str, _: &regex::Regex) -> bool {
    !line.is_empty()
}

fn pass_none(_: &str, _: &regex::Regex) -> bool {
    false
}

fn pass_all(_: &str, _: &regex::Regex) -> bool {
    true
}

fn print_usage(opts: &getopts::Options) {
    println!("{}", opts.usage(USAGE));
}

fn version() {
    println!("{} {}", NAME, VERSION);
}
<|endoftext|>


<commit_before>use std::io;
use {hyper, serde_json};

#[derive(Debug)]
pub enum Error {
    HttpError(hyper::error::Error),
    IoError(io::Error),
    DecodeError(serde_json::Error),
    ServerError(String),
    NotFound,
}

impl From<hyper::error::Error> for Error {
    fn from(e: hyper::error::Error) -> Self {
        Error::HttpError(e)
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::IoError(e)
    }
}

impl From<serde_json::Error> for Error {
    fn from(e: serde_json::Error) -> Self {
        Error::DecodeError(e)
    }
}
<commit_msg>Simplify errors<commit_after>use std::io;
use std::error::Error as StdError;
use {hyper, serde_json};

#[derive(Debug)]
pub enum Error {
    IoError(io::Error),
    ServerError(String),
    NotFound,
}

impl From<hyper::error::Error> for Error {
    fn from(e: hyper::error::Error) -> Self {
        Error::ServerError(e.description().to_string())
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::IoError(e)
    }
}

impl From<serde_json::Error> for Error {
    fn from(e: serde_json::Error) -> Self {
        Error::ServerError(e.description().to_string())
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::Error as FmtError;
use std::clone::Clone;
use std::fmt::{Display, Formatter};

/**
 * Kind of store error
 */
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TaskErrorKind {
    ParserError,
    NoStatus,
}

fn store_error_type_as_str(e: &TaskErrorKind) -> &'static str {
    match e {
        &TaskErrorKind::ParserError => "Parser Error",
        &TaskErrorKind::NoStatus    => "Task status is missing",
    }
}

impl Display for TaskErrorKind {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "{}", store_error_type_as_str(self)));
        Ok(())
    }

}

/**
 * Store error type
 */
#[derive(Debug)]
pub struct TaskError {
    err_type: TaskErrorKind,
    cause: Option<Box<Error>>,
}

impl TaskError {

    /**
     * Build a new TaskError from an TaskErrorKind, optionally with cause
     */
    pub fn new(errtype: TaskErrorKind, cause: Option<Box<Error>>)
        -> TaskError
        {
            TaskError {
                err_type: errtype,
                cause: cause,
            }
        }

    /**
     * Get the error type of this TaskError
     */
    pub fn err_type(&self) -> TaskErrorKind {
        self.err_type.clone()
    }

}

impl Display for TaskError {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "[{}]", store_error_type_as_str(&self.err_type.clone())));
        Ok(())
    }

}

impl Error for TaskError {

    fn description(&self) -> &str {
        store_error_type_as_str(&self.err_type.clone())
    }

    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|e| &**e)
    }

}

<commit_msg>Document error module<commit_after>use std::error::Error;
use std::fmt::Error as FmtError;
use std::clone::Clone;
use std::fmt::{Display, Formatter};

///
/// Kind of task error
///
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TaskErrorKind {
    ParserError,
    NoStatus,
}

fn store_error_type_as_str(e: &TaskErrorKind) -> &'static str {
    match e {
        &TaskErrorKind::ParserError => "Parser Error",
        &TaskErrorKind::NoStatus    => "Task status is missing",
    }
}

impl Display for TaskErrorKind {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "{}", store_error_type_as_str(self)));
        Ok(())
    }

}

///
/// Task error type
///
#[derive(Debug)]
pub struct TaskError {
    err_type: TaskErrorKind,
    cause: Option<Box<Error>>,
}

impl TaskError {

    ///
    /// Build a new TaskError from an TaskErrorKind, optionally with cause
    ///
    pub fn new(errtype: TaskErrorKind, cause: Option<Box<Error>>)
        -> TaskError
        {
            TaskError {
                err_type: errtype,
                cause: cause,
            }
        }

    ///
    /// Get the error type of this TaskError
    ///
    pub fn err_type(&self) -> TaskErrorKind {
        self.err_type.clone()
    }

}

impl Display for TaskError {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "[{}]", store_error_type_as_str(&self.err_type.clone())));
        Ok(())
    }

}

impl Error for TaskError {

    fn description(&self) -> &str {
        store_error_type_as_str(&self.err_type.clone())
    }

    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|e| &**e)
    }

}

<|endoftext|>


<commit_before>use clap;
use globset;
use notify;
use std::{error::Error as StdError, fmt, io, sync::PoisonError};

pub type Result<T> = ::std::result::Result<T, Error>;

pub enum Error {
    Canonicalization(String, io::Error),
    Clap(clap::Error),
    Glob(globset::Error),
    Io(io::Error),
    Notify(notify::Error),
    PoisonedLock,
}

impl StdError for Error {
    fn description(&self) -> &str {
        // This method is soft-deprecated and shouldn't be used,
        // see Display for the actual description.
        "a watchexec error"
    }
}

impl From<clap::Error> for Error {
    fn from(err: clap::Error) -> Self {
        Error::Clap(err)
    }
}

impl From<globset::Error> for Error {
    fn from(err: globset::Error) -> Self {
        Error::Glob(err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::Io(err)
    }
}

impl From<notify::Error> for Error {
    fn from(err: notify::Error) -> Self {
        match err {
            notify::Error::Io(err) => Error::Io(err),
            other => Error::Notify(other),
        }
    }
}

impl<'a, T> From<PoisonError<T>> for Error {
    fn from(_err: PoisonError<T>) -> Self {
        Error::PoisonedLock
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{} error: {}",
            match self {
                Error::Canonicalization(_, _) => "Path",
                Error::Clap(_) => "Argument",
                Error::Glob(_) => "Globset",
                Error::Io(_) => "I/O",
                Error::Notify(_) => "Notify",
                Error::PoisonedLock => "Internal",
            },
            match self {
                Error::Canonicalization(path, err) => {
                    format!("couldn't canonicalize '{}':\n{}", path, err)
                }
                err => format!("{}", err),
            }
        )
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}
<commit_msg>[errors] Fix infinite recursion in fmt::Display for Error (#111)<commit_after>use clap;
use globset;
use notify;
use std::{error::Error as StdError, fmt, io, sync::PoisonError};

pub type Result<T> = ::std::result::Result<T, Error>;

pub enum Error {
    Canonicalization(String, io::Error),
    Clap(clap::Error),
    Glob(globset::Error),
    Io(io::Error),
    Notify(notify::Error),
    PoisonedLock,
}

impl StdError for Error {
    fn description(&self) -> &str {
        // This method is soft-deprecated and shouldn't be used,
        // see Display for the actual description.
        "a watchexec error"
    }
}

impl From<clap::Error> for Error {
    fn from(err: clap::Error) -> Self {
        Error::Clap(err)
    }
}

impl From<globset::Error> for Error {
    fn from(err: globset::Error) -> Self {
        Error::Glob(err)
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::Io(err)
    }
}

impl From<notify::Error> for Error {
    fn from(err: notify::Error) -> Self {
        match err {
            notify::Error::Io(err) => Error::Io(err),
            other => Error::Notify(other),
        }
    }
}

impl<'a, T> From<PoisonError<T>> for Error {
    fn from(_err: PoisonError<T>) -> Self {
        Error::PoisonedLock
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (error_type, error) = match self {
            Error::Canonicalization(path, err) => {
                ("Path", format!("couldn't canonicalize '{}':\n{}", path, err))
            }
            Error::Clap(err) => ("Argument", err.to_string()),
            Error::Glob(err) => ("Globset", err.to_string()),
            Error::Io(err) => ("I/O", err.to_string()),
            Error::Notify(err) => ("Notify", err.to_string()),
            Error::PoisonedLock => ("Internal", "poisoned lock".to_string()),
        };

        write!(f, "{} error: {}", error_type, error)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::io;
use std::fmt;
use ffi;
use ffi::YamlErrorType;
use ffi::YamlErrorType::*;

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct YamlMark {
    pub index: usize,
    pub line: usize,
    pub column: usize
}

impl YamlMark {
    pub fn conv(mark: &ffi::yaml_mark_t) -> YamlMark {
        YamlMark {
            index: mark.index as usize,
            line: mark.line as usize,
            column: mark.column as usize
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct YamlErrorContext {
    pub byte_offset: usize,
    pub problem_mark: YamlMark,
    pub context: Option<String>,
    pub context_mark: YamlMark
}

#[derive(Debug, PartialEq)]
pub struct YamlError {
    pub kind: ffi::YamlErrorType,
    pub problem: Option<String>,
    pub io_error: Option<io::Error>,
    pub context: Option<YamlErrorContext>
}

impl Error for YamlError {
    fn description(&self) -> &str {
        match self.kind {
            YAML_NO_ERROR => "No error is produced",
            YAML_MEMORY_ERROR => "Cannot allocate or reallocate a block of memory",
            YAML_READER_ERROR => "Cannot read or decode the input stream",
            YAML_SCANNER_ERROR => "Cannot scan the input stream",
            YAML_PARSER_ERROR => "Cannot parse the input stream",
            YAML_COMPOSER_ERROR => "Cannot compose a YAML document",
            YAML_WRITER_ERROR => "Cannot write to the output stream",
            YAML_EMITTER_ERROR => "Cannot emit a YAML stream",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self.io_error {
            None => None,
            Some(ref e) => Some(e as &Error)
        }
    }
}

impl YamlError {
    pub fn new(kind: ffi::YamlErrorType, problem: Option<String>) -> YamlError {
        YamlError {
            kind: kind,
            problem: problem,
            io_error: None,
            context: None
        }
    }
}

impl fmt::Display for YamlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.problem {
            None => return Ok(()),
            Some(ref s) => s.fmt(f)
        }
    }
}
<commit_msg>Rust changes: io::Error is no longer PartialEq<commit_after>use std::error::Error;
use std::io;
use std::fmt;
use ffi;
use ffi::YamlErrorType;
use ffi::YamlErrorType::*;

#[derive(Debug, PartialEq, Clone, Copy)]
pub struct YamlMark {
    pub index: usize,
    pub line: usize,
    pub column: usize
}

impl YamlMark {
    pub fn conv(mark: &ffi::yaml_mark_t) -> YamlMark {
        YamlMark {
            index: mark.index as usize,
            line: mark.line as usize,
            column: mark.column as usize
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct YamlErrorContext {
    pub byte_offset: usize,
    pub problem_mark: YamlMark,
    pub context: Option<String>,
    pub context_mark: YamlMark
}

#[derive(Debug)]
pub struct YamlError {
    pub kind: ffi::YamlErrorType,
    pub problem: Option<String>,
    pub io_error: Option<io::Error>,
    pub context: Option<YamlErrorContext>
}

impl PartialEq for YamlError {
    fn eq(&self, rhs: &YamlError) -> bool {
        self.kind == rhs.kind
            && self.problem == rhs.problem
            && self.io_error.is_none()
            && rhs.io_error.is_none()
            && self.context == rhs.context
    }
}

impl Error for YamlError {
    fn description(&self) -> &str {
        match self.kind {
            YAML_NO_ERROR => "No error is produced",
            YAML_MEMORY_ERROR => "Cannot allocate or reallocate a block of memory",
            YAML_READER_ERROR => "Cannot read or decode the input stream",
            YAML_SCANNER_ERROR => "Cannot scan the input stream",
            YAML_PARSER_ERROR => "Cannot parse the input stream",
            YAML_COMPOSER_ERROR => "Cannot compose a YAML document",
            YAML_WRITER_ERROR => "Cannot write to the output stream",
            YAML_EMITTER_ERROR => "Cannot emit a YAML stream",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match self.io_error {
            None => None,
            Some(ref e) => Some(e as &Error)
        }
    }
}

impl YamlError {
    pub fn new(kind: ffi::YamlErrorType, problem: Option<String>) -> YamlError {
        YamlError {
            kind: kind,
            problem: problem,
            io_error: None,
            context: None
        }
    }
}

impl fmt::Display for YamlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.problem {
            None => return Ok(()),
            Some(ref s) => s.fmt(f)
        }
    }
}
<|endoftext|>


<commit_before>//! Error types and conversion functions.

use std;
use std::error::Error;
use std::fmt;
use std::sync::Arc;

use gfx;
use glutin;
use winit;

use gilrs;
use image;
use lyon;
use rodio::decoder::DecoderError;
use toml;
use zip;

/// An enum containing all kinds of game framework errors.
#[derive(Debug, Clone)]
pub enum GameError {
    /// An error in the filesystem layout
    FilesystemError(String),
    /// An error in the config file
    ConfigError(String),
    /// Happens when an `winit::event_loop::EventLoopProxy` attempts to
    /// wake up an `winit::event_loop::EventLoop` that no longer exists.
    EventLoopError(String),
    /// An error trying to load a resource, such as getting an invalid image file.
    ResourceLoadError(String),
    /// Unable to find a resource; the `Vec` is the paths it searched for and associated errors
    ResourceNotFound(String, Vec<(std::path::PathBuf, GameError)>),
    /// Something went wrong in the renderer
    RenderError(String),
    /// Something went wrong in the audio playback
    AudioError(String),
    /// Something went wrong trying to set or get window properties.
    WindowError(String),
    /// Something went wrong trying to create a window
    WindowCreationError(Arc<glutin::CreationError>),
    /// Something went wrong trying to read from a file
    IOError(Arc<std::io::Error>),
    /// Something went wrong trying to load/render a font
    FontError(String),
    /// Something went wrong applying video settings.
    VideoError(String),
    /// Something went wrong compiling shaders
    ShaderProgramError(gfx::shade::ProgramError),
    /// Something went wrong with the `gilrs` gamepad-input library.
    GamepadError(String),
    /// Something went wrong with the `lyon` shape-tesselation library.
    LyonError(String),
}

impl fmt::Display for GameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GameError::ConfigError(ref s) => write!(f, "Config error: {}", s),
            GameError::ResourceLoadError(ref s) => write!(f, "Error loading resource: {}", s),
            GameError::ResourceNotFound(ref s, ref paths) => write!(
                f,
                "Resource not found: {}, searched in paths {:?}",
                s, paths
            ),
            GameError::WindowError(ref e) => write!(f, "Window creation error: {}", e),
            _ => write!(f, "GameError {:?}", self),
        }
    }
}

impl Error for GameError {
    fn cause(&self) -> Option<&dyn Error> {
        match *self {
            GameError::WindowCreationError(ref e) => Some(&**e),
            GameError::IOError(ref e) => Some(&**e),
            GameError::ShaderProgramError(ref e) => Some(e),
            _ => None,
        }
    }
}

/// A convenient result type consisting of a return type and a `GameError`
pub type GameResult<T = ()> = Result<T, GameError>;

impl From<std::io::Error> for GameError {
    fn from(e: std::io::Error) -> GameError {
        GameError::IOError(Arc::new(e))
    }
}

impl From<toml::de::Error> for GameError {
    fn from(e: toml::de::Error) -> GameError {
        let errstr = format!("TOML decode error: {}", e.to_string());

        GameError::ConfigError(errstr)
    }
}

impl From<toml::ser::Error> for GameError {
    fn from(e: toml::ser::Error) -> GameError {
        let errstr = format!("TOML error (possibly encoding?): {}", e.to_string());
        GameError::ConfigError(errstr)
    }
}

impl From<zip::result::ZipError> for GameError {
    fn from(e: zip::result::ZipError) -> GameError {
        let errstr = format!("Zip error: {}", e.to_string());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<DecoderError> for GameError {
    fn from(e: DecoderError) -> GameError {
        let errstr = format!("Audio decoder error: {:?}", e);
        GameError::AudioError(errstr)
    }
}

impl From<image::ImageError> for GameError {
    fn from(e: image::ImageError) -> GameError {
        let errstr = format!("Image load error: {}", e.to_string());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<gfx::PipelineStateError<std::string::String>> for GameError {
    fn from(e: gfx::PipelineStateError<std::string::String>) -> GameError {
        let errstr = format!(
            "Error constructing pipeline!\nThis should probably not be \
             happening; it probably means an error in a shader or \
             something.\nError was: {:?}",
            e
        );
        GameError::VideoError(errstr)
    }
}

impl From<gfx::mapping::Error> for GameError {
    fn from(e: gfx::mapping::Error) -> GameError {
        let errstr = format!("Buffer mapping error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl<S, D> From<gfx::CopyError<S, D>> for GameError
where
    S: fmt::Debug,
    D: fmt::Debug,
{
    fn from(e: gfx::CopyError<S, D>) -> GameError {
        let errstr = format!("Memory copy error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::CombinedError> for GameError {
    fn from(e: gfx::CombinedError) -> GameError {
        let errstr = format!("Texture+view load error: {}", e.to_string());
        GameError::VideoError(errstr)
    }
}

impl From<gfx::texture::CreationError> for GameError {
    fn from(e: gfx::texture::CreationError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::ResourceViewError> for GameError {
    fn from(e: gfx::ResourceViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::TargetViewError> for GameError {
    fn from(e: gfx::TargetViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl<T> From<gfx::UpdateError<T>> for GameError
where
    T: fmt::Debug + fmt::Display + 'static,
{
    fn from(e: gfx::UpdateError<T>) -> GameError {
        let errstr = format!("Buffer update error: {}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::shade::ProgramError> for GameError {
    fn from(e: gfx::shade::ProgramError) -> GameError {
        GameError::ShaderProgramError(e)
    }
}

impl<T> From<winit::event_loop::EventLoopClosed<T>> for GameError {
    fn from(_: glutin::event_loop::EventLoopClosed<T>) -> GameError {
        let e = "An event loop proxy attempted to wake up an event loop that no longer exists."
            .to_owned();
        GameError::EventLoopError(e)
    }
}

impl From<glutin::CreationError> for GameError {
    fn from(s: glutin::CreationError) -> GameError {
        GameError::WindowCreationError(Arc::new(s))
    }
}

impl From<glutin::ContextError> for GameError {
    fn from(s: glutin::ContextError) -> GameError {
        GameError::RenderError(format!("OpenGL context error: {}", s))
    }
}

impl From<gilrs::Error> for GameError {
    fn from(s: gilrs::Error) -> GameError {
        let errstr = format!("Gamepad error: {}", s);
        GameError::GamepadError(errstr)
    }
}

impl From<lyon::lyon_tessellation::TessellationError> for GameError {
    fn from(s: lyon::lyon_tessellation::TessellationError) -> GameError {
        let errstr = format!(
            "Error while tesselating shape (did you give it an infinity or NaN?): {:?}",
            s
        );
        GameError::LyonError(errstr)
    }
}

impl From<lyon::lyon_tessellation::geometry_builder::GeometryBuilderError> for GameError {
    fn from(s: lyon::lyon_tessellation::geometry_builder::GeometryBuilderError) -> GameError {
        let errstr = format!(
            "Error while building geometry (did you give it too many vertices?): {:?}",
            s
        );
        GameError::LyonError(errstr)
    }
}
<commit_msg>Add CustomError variant to GameError<commit_after>//! Error types and conversion functions.

use std;
use std::error::Error;
use std::fmt;
use std::sync::Arc;

use gfx;
use glutin;
use winit;

use gilrs;
use image;
use lyon;
use rodio::decoder::DecoderError;
use toml;
use zip;

/// An enum containing all kinds of game framework errors.
#[derive(Debug, Clone)]
pub enum GameError {
    /// An error in the filesystem layout
    FilesystemError(String),
    /// An error in the config file
    ConfigError(String),
    /// Happens when an `winit::event_loop::EventLoopProxy` attempts to
    /// wake up an `winit::event_loop::EventLoop` that no longer exists.
    EventLoopError(String),
    /// An error trying to load a resource, such as getting an invalid image file.
    ResourceLoadError(String),
    /// Unable to find a resource; the `Vec` is the paths it searched for and associated errors
    ResourceNotFound(String, Vec<(std::path::PathBuf, GameError)>),
    /// Something went wrong in the renderer
    RenderError(String),
    /// Something went wrong in the audio playback
    AudioError(String),
    /// Something went wrong trying to set or get window properties.
    WindowError(String),
    /// Something went wrong trying to create a window
    WindowCreationError(Arc<glutin::CreationError>),
    /// Something went wrong trying to read from a file
    IOError(Arc<std::io::Error>),
    /// Something went wrong trying to load/render a font
    FontError(String),
    /// Something went wrong applying video settings.
    VideoError(String),
    /// Something went wrong compiling shaders
    ShaderProgramError(gfx::shade::ProgramError),
    /// Something went wrong with the `gilrs` gamepad-input library.
    GamepadError(String),
    /// Something went wrong with the `lyon` shape-tesselation library.
    LyonError(String),
    /// A custom error type for use by users of ggez.
    /// This lets you handle custom errors that may happen during your game (such as, trying to load a malformed file for a level)
    /// using the same mechanism you handle ggez's other errors.
    ///
    /// Please include an informative message with the error.
    CustomError(String),
}

impl fmt::Display for GameError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GameError::ConfigError(ref s) => write!(f, "Config error: {}", s),
            GameError::ResourceLoadError(ref s) => write!(f, "Error loading resource: {}", s),
            GameError::ResourceNotFound(ref s, ref paths) => write!(
                f,
                "Resource not found: {}, searched in paths {:?}",
                s, paths
            ),
            GameError::WindowError(ref e) => write!(f, "Window creation error: {}", e),
            GameError::CustomError(ref s) => write!(f, "Custom error: {}", s),
            _ => write!(f, "GameError {:?}", self),
        }
    }
}

impl Error for GameError {
    fn cause(&self) -> Option<&dyn Error> {
        match *self {
            GameError::WindowCreationError(ref e) => Some(&**e),
            GameError::IOError(ref e) => Some(&**e),
            GameError::ShaderProgramError(ref e) => Some(e),
            _ => None,
        }
    }
}

/// A convenient result type consisting of a return type and a `GameError`
pub type GameResult<T = ()> = Result<T, GameError>;

impl From<std::io::Error> for GameError {
    fn from(e: std::io::Error) -> GameError {
        GameError::IOError(Arc::new(e))
    }
}

impl From<toml::de::Error> for GameError {
    fn from(e: toml::de::Error) -> GameError {
        let errstr = format!("TOML decode error: {}", e.to_string());

        GameError::ConfigError(errstr)
    }
}

impl From<toml::ser::Error> for GameError {
    fn from(e: toml::ser::Error) -> GameError {
        let errstr = format!("TOML error (possibly encoding?): {}", e.to_string());
        GameError::ConfigError(errstr)
    }
}

impl From<zip::result::ZipError> for GameError {
    fn from(e: zip::result::ZipError) -> GameError {
        let errstr = format!("Zip error: {}", e.to_string());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<DecoderError> for GameError {
    fn from(e: DecoderError) -> GameError {
        let errstr = format!("Audio decoder error: {:?}", e);
        GameError::AudioError(errstr)
    }
}

impl From<image::ImageError> for GameError {
    fn from(e: image::ImageError) -> GameError {
        let errstr = format!("Image load error: {}", e.to_string());
        GameError::ResourceLoadError(errstr)
    }
}

impl From<gfx::PipelineStateError<std::string::String>> for GameError {
    fn from(e: gfx::PipelineStateError<std::string::String>) -> GameError {
        let errstr = format!(
            "Error constructing pipeline!\nThis should probably not be \
             happening; it probably means an error in a shader or \
             something.\nError was: {:?}",
            e
        );
        GameError::VideoError(errstr)
    }
}

impl From<gfx::mapping::Error> for GameError {
    fn from(e: gfx::mapping::Error) -> GameError {
        let errstr = format!("Buffer mapping error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl<S, D> From<gfx::CopyError<S, D>> for GameError
where
    S: fmt::Debug,
    D: fmt::Debug,
{
    fn from(e: gfx::CopyError<S, D>) -> GameError {
        let errstr = format!("Memory copy error: {:?}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::CombinedError> for GameError {
    fn from(e: gfx::CombinedError) -> GameError {
        let errstr = format!("Texture+view load error: {}", e.to_string());
        GameError::VideoError(errstr)
    }
}

impl From<gfx::texture::CreationError> for GameError {
    fn from(e: gfx::texture::CreationError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::ResourceViewError> for GameError {
    fn from(e: gfx::ResourceViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl From<gfx::TargetViewError> for GameError {
    fn from(e: gfx::TargetViewError) -> GameError {
        gfx::CombinedError::from(e).into()
    }
}

impl<T> From<gfx::UpdateError<T>> for GameError
where
    T: fmt::Debug + fmt::Display + 'static,
{
    fn from(e: gfx::UpdateError<T>) -> GameError {
        let errstr = format!("Buffer update error: {}", e);
        GameError::VideoError(errstr)
    }
}

impl From<gfx::shade::ProgramError> for GameError {
    fn from(e: gfx::shade::ProgramError) -> GameError {
        GameError::ShaderProgramError(e)
    }
}

impl<T> From<winit::event_loop::EventLoopClosed<T>> for GameError {
    fn from(_: glutin::event_loop::EventLoopClosed<T>) -> GameError {
        let e = "An event loop proxy attempted to wake up an event loop that no longer exists."
            .to_owned();
        GameError::EventLoopError(e)
    }
}

impl From<glutin::CreationError> for GameError {
    fn from(s: glutin::CreationError) -> GameError {
        GameError::WindowCreationError(Arc::new(s))
    }
}

impl From<glutin::ContextError> for GameError {
    fn from(s: glutin::ContextError) -> GameError {
        GameError::RenderError(format!("OpenGL context error: {}", s))
    }
}

impl From<gilrs::Error> for GameError {
    fn from(s: gilrs::Error) -> GameError {
        let errstr = format!("Gamepad error: {}", s);
        GameError::GamepadError(errstr)
    }
}

impl From<lyon::lyon_tessellation::TessellationError> for GameError {
    fn from(s: lyon::lyon_tessellation::TessellationError) -> GameError {
        let errstr = format!(
            "Error while tesselating shape (did you give it an infinity or NaN?): {:?}",
            s
        );
        GameError::LyonError(errstr)
    }
}

impl From<lyon::lyon_tessellation::geometry_builder::GeometryBuilderError> for GameError {
    fn from(s: lyon::lyon_tessellation::geometry_builder::GeometryBuilderError) -> GameError {
        let errstr = format!(
            "Error while building geometry (did you give it too many vertices?): {:?}",
            s
        );
        GameError::LyonError(errstr)
    }
}
<|endoftext|>


<commit_before>extern crate xdg_basedir;
use self::xdg_basedir::error::Error as XdgError;

extern crate config;
use self::config::error::ConfigError as ParseError;

use std::fmt;
use std::error::Error;
use std::io;

use self::FsError::{XdgFsError, IoFsError};
use self::ConfigError::{FsConfigError, ParseConfigError};

#[derive(Debug)]
pub enum FsError {
    XdgFsError(XdgError),
    IoFsError(io::Error),
}

impl fmt::Display for FsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }
}

impl Error for FsError {
    fn description(&self) -> &str {
        match *self {
            XdgFsError(ref xdg) => (*xdg).description(),
            IoFsError(ref io) => (*io).description(),
        }
    }
}

impl From<XdgError> for FsError {
    fn from(xdg: XdgError) -> FsError {
        XdgFsError(xdg)
    }
}

impl From<io::Error> for FsError {
    fn from(io: io::Error) -> FsError {
        IoFsError(io)
    }
}

#[derive(Debug)]
pub enum ConfigError {
    FsConfigError(FsError),
    ParseConfigError(String),
}

impl fmt::Display for ConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }
}

impl Error for ConfigError {
    fn description(&self) -> &str {
        match *self {
            FsConfigError(ref fs) => (*fs).description(),
            ParseConfigError(ref desc) => (*desc).as_str(),
        }
    }
}

impl From<FsError> for ConfigError {
    fn from(fs: FsError) -> ConfigError {
        FsConfigError(fs)
    }
}

impl From<ParseError> for ConfigError {
    fn from(config: ParseError) -> ConfigError {
        let desc: String = config.detail.unwrap_or(String::from_str("unknown parse error"));
        ParseConfigError(String::from_str(config.desc) + ": " + desc.as_str())
    }
}
<commit_msg>error: remove use of unstable APIs<commit_after>extern crate xdg_basedir;
use self::xdg_basedir::error::Error as XdgError;

extern crate config;
use self::config::error::ConfigError as ParseError;

use std::fmt;
use std::error::Error;
use std::io;

use self::FsError::{XdgFsError, IoFsError};
use self::ConfigError::{FsConfigError, ParseConfigError};

#[derive(Debug)]
pub enum FsError {
    XdgFsError(XdgError),
    IoFsError(io::Error),
}

impl fmt::Display for FsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }
}

impl Error for FsError {
    fn description(&self) -> &str {
        match *self {
            XdgFsError(ref xdg) => (*xdg).description(),
            IoFsError(ref io) => (*io).description(),
        }
    }
}

impl From<XdgError> for FsError {
    fn from(xdg: XdgError) -> FsError {
        XdgFsError(xdg)
    }
}

impl From<io::Error> for FsError {
    fn from(io: io::Error) -> FsError {
        IoFsError(io)
    }
}

#[derive(Debug)]
pub enum ConfigError {
    FsConfigError(FsError),
    ParseConfigError(String),
}

impl fmt::Display for ConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }
}

impl Error for ConfigError {
    fn description(&self) -> &str {
        match *self {
            FsConfigError(ref fs) => (*fs).description(),
            // XXX: trim -> as_str
            ParseConfigError(ref desc) => (*desc).trim(),
        }
    }
}

impl From<FsError> for ConfigError {
    fn from(fs: FsError) -> ConfigError {
        FsConfigError(fs)
    }
}

impl From<ParseError> for ConfigError {
    fn from(config: ParseError) -> ConfigError {
        // FIXME: Wow, the unstable APIs...
        let mut default_desc = String::new();
        default_desc.push_str("unknown parse error");
        let desc = config.detail.unwrap_or(default_desc);
        let mut err_string = String::new();
        err_string.push_str(config.desc);
        err_string.push_str(": ");
        // XXX: trim -> as_str
        err_string.push_str(desc.trim());
        ParseConfigError(err_string)
    }
}
<|endoftext|>


<commit_before>use std::error::Error as StdError;
use std::fmt;

use std::io::Error as IoError;
use serde_json::error::Error as SerdeJsonError;
use hyper::error::Error as HyperError;

pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    Game(String),
    Http(HyperError),
    Io(IoError),
    Json(SerdeJsonError),
    Parsing(String),
    #[doc(hidden)]
    __Nonexhaustive(Void)
}

#[doc(hidden)]
pub enum Void {}

impl fmt::Debug for Void {
    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
        match *self {}
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Game(ref s) => s,
            Error::Http(ref e) => e.description(),
            Error::Io(ref e) => e.description(),
            Error::Json(ref e) => e.description(),
            Error::Parsing(ref s) => s,
            Error::__Nonexhaustive(ref void) =>  match *void {}
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::Http(ref e) => Some(e),
            Error::Io(ref e) => Some(e),
            Error::Json(ref e) => Some(e),
            _ => None,
        }
    }
}

impl Error {
    pub fn parsing(source: &str, string: &str) -> Error {
        Error::Parsing(format!("Error while parsing \"{}\" as {}", string, source))
    }

    pub fn game<A: Into<String>>(cause: Option<A>) -> Error {
        match cause {
            Some(string) => Error::Game(string.into()),
            None => Error::Game("Unknown server error".to_owned())
        }
    }
}

impl From<IoError> for Error {
    fn from(err: IoError) -> Error {
        Error::Io(err)
    }
}

impl From<HyperError> for Error {
    fn from(err: HyperError) -> Error {
        Error::Http(err)
    }
}

impl From<SerdeJsonError> for Error {
    fn from(err: SerdeJsonError) -> Error {
        Error::Json(err)
    }
}

<commit_msg>remove void thingy<commit_after>use std::error::Error as StdError;
use std::fmt;

use std::io::Error as IoError;
use serde_json::error::Error as SerdeJsonError;
use hyper::error::Error as HyperError;

pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    Game(String),
    Http(HyperError),
    Io(IoError),
    Json(SerdeJsonError),
    Parsing(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Game(ref s) => s,
            Error::Http(ref e) => e.description(),
            Error::Io(ref e) => e.description(),
            Error::Json(ref e) => e.description(),
            Error::Parsing(ref s) => s,
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::Http(ref e) => Some(e),
            Error::Io(ref e) => Some(e),
            Error::Json(ref e) => Some(e),
            _ => None,
        }
    }
}

impl Error {
    pub fn parsing(source: &str, string: &str) -> Error {
        Error::Parsing(format!("Error while parsing \"{}\" as {}", string, source))
    }

    pub fn game<A: Into<String>>(cause: Option<A>) -> Error {
        match cause {
            Some(string) => Error::Game(string.into()),
            None => Error::Game("Unknown server error".to_owned())
        }
    }
}

impl From<IoError> for Error {
    fn from(err: IoError) -> Error {
        Error::Io(err)
    }
}

impl From<HyperError> for Error {
    fn from(err: HyperError) -> Error {
        Error::Http(err)
    }
}

impl From<SerdeJsonError> for Error {
    fn from(err: SerdeJsonError) -> Error {
        Error::Json(err)
    }
}

<|endoftext|>


<commit_before>use crate::error::{nvml_sym, nvml_try, NvmlError};
use crate::ffi::bindings::*;
use crate::NVML;

use std::{
    io::{self, Write},
    mem,
};

use crate::struct_wrappers::event::EventData;

/**
Handle to a set of events.

**Operations on a set are not thread-safe.** It does not, therefore, implement `Sync`.

You can get yourself an `EventSet` via `NVML.create_event_set()`. Once again, Rust's
lifetimes will ensure that it does not outlive the `NVML` instance that it was created
from.
*/
// Checked against local
#[derive(Debug)]
pub struct EventSet<'nvml> {
    set: nvmlEventSet_t,
    pub nvml: &'nvml NVML,
}

unsafe impl<'nvml> Send for EventSet<'nvml> {}

impl<'nvml> EventSet<'nvml> {
    /**
    Create a new `EventSet` wrapper.

    You will most likely never need to call this; see the methods available to you
    on the `NVML` struct to get one.
    */
    // TODO: move constructor to this struct?
    pub fn new(set: nvmlEventSet_t, nvml: &'nvml NVML) -> Self {
        Self { set, nvml }
    }

    /**
    Use this to release the set's events if you care about handling
    potential errors (*the `Drop` implementation ignores errors!*).

    # Errors

    * `Uninitialized`, if the library has not been successfully initialized
    * `Unknown`, on any unexpected error
    */
    // Checked against local
    pub fn release_events(self) -> Result<(), NvmlError> {
        let sym = nvml_sym(self.nvml.lib.nvmlEventSetFree.as_ref())?;

        unsafe {
            nvml_try(sym(self.set))?;
        }

        mem::forget(self);
        Ok(())
    }

    /**
    Waits on events for the given timeout (in ms) and delivers one when it arrives.

    See the `high_level::event_loop` module for an abstracted version of this.

    This method returns immediately if an event is ready to be delivered when it
    is called. If no events are ready it will sleep until an event arrives, but
    not longer than the specified timeout. In certain conditions, this method
    could return before the timeout passes (e.g. when an interrupt arrives).

    In the case of an XID error, the function returns the most recent XID error
    type seen by the system. If there are multiple XID errors generated before
    this method is called, the last seen XID error type will be returned for
    all XID error events.

    # Errors

    * `Uninitialized`, if the library has not been successfully initialized
    * `Timeout`, if no event arrived in the specified timeout or an interrupt
    arrived
    * `GpuLost`, if a GPU has fallen off the bus or is otherwise inaccessible
    * `Unknown`, on any unexpected error

    # Device Support

    Supports Fermi and newer fully supported devices.
    */
    // Checked against local
    pub fn wait(&self, timeout_ms: u32) -> Result<EventData<'nvml>, NvmlError> {
        let sym = nvml_sym(self.nvml.lib.nvmlEventSetWait_v2.as_ref())?;

        unsafe {
            let mut data: nvmlEventData_t = mem::zeroed();
            nvml_try(sym(self.set, &mut data, timeout_ms))?;

            Ok(EventData::new(data, self.nvml))
        }
    }

    /// Get the raw device handle contained in this struct
    ///
    /// Sometimes necessary for C interop.
    ///
    /// # Safety
    ///
    /// This is unsafe to prevent it from being used without care. In
    /// particular, you must avoid creating a new `EventSet` from this handle
    /// and allowing both this `EventSet` and the newly created one to drop
    /// (which would result in a double-free).
    pub unsafe fn handle(&self) -> nvmlEventSet_t {
        self.set
    }
}

/// This `Drop` implementation ignores errors! Use the `.release_events()`
/// method on the `EventSet` struct if you care about handling them.
impl<'nvml> Drop for EventSet<'nvml> {
    fn drop(&mut self) {
        let sym = nvml_sym(self.nvml.lib.nvmlEventSetFree.as_ref()).unwrap();

        unsafe {
            #[allow(unused_must_use)]
            match nvml_try(sym(self.set)) {
                Ok(()) => (),
                Err(e) => {
                    io::stderr().write(
                        format!(
                            "WARNING: Error returned by `nvmlEventSetFree()` in Drop \
                             implementation: {:?}",
                            e
                        )
                        .as_bytes(),
                    );
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    #[cfg(target_os = "linux")]
    use crate::bitmasks::event::*;
    use crate::test_utils::*;

    #[cfg(target_os = "linux")]
    #[test]
    fn release_events() {
        let nvml = nvml();
        test_with_device(3, &nvml, |device| {
            let set = nvml.create_event_set()?;
            let set = device
                .register_events(
                    EventTypes::PSTATE_CHANGE
                        | EventTypes::CRITICAL_XID_ERROR
                        | EventTypes::CLOCK_CHANGE,
                    set,
                )
                .map_err(|e| e.error)?;

            set.release_events()
        })
    }

    #[cfg(target_os = "linux")]
    #[cfg(feature = "test-local")]
    #[test]
    fn wait() {
        use crate::error::NvmlError;

        let nvml = nvml();
        let device = device(&nvml);
        let set = nvml.create_event_set().expect("event set");
        let set = device
            .register_events(
                EventTypes::PSTATE_CHANGE
                    | EventTypes::CRITICAL_XID_ERROR
                    | EventTypes::CLOCK_CHANGE,
                set,
            )
            .expect("registration");

        let data = match set.wait(10_000) {
            Err(NvmlError::Timeout) => return (),
            Ok(d) => d,
            _ => panic!("An error other than `Timeout` occurred"),
        };

        print!("{:?} ...", data);
    }
}
<commit_msg>Use convenience accessor in `drop` impl<commit_after>use crate::error::{nvml_sym, nvml_try, NvmlError};
use crate::ffi::bindings::*;
use crate::NVML;

use std::{
    io::{self, Write},
    mem,
};

use crate::struct_wrappers::event::EventData;

/**
Handle to a set of events.

**Operations on a set are not thread-safe.** It does not, therefore, implement `Sync`.

You can get yourself an `EventSet` via `NVML.create_event_set()`. Once again, Rust's
lifetimes will ensure that it does not outlive the `NVML` instance that it was created
from.
*/
// Checked against local
#[derive(Debug)]
pub struct EventSet<'nvml> {
    set: nvmlEventSet_t,
    pub nvml: &'nvml NVML,
}

unsafe impl<'nvml> Send for EventSet<'nvml> {}

impl<'nvml> EventSet<'nvml> {
    /**
    Create a new `EventSet` wrapper.

    You will most likely never need to call this; see the methods available to you
    on the `NVML` struct to get one.
    */
    // TODO: move constructor to this struct?
    pub fn new(set: nvmlEventSet_t, nvml: &'nvml NVML) -> Self {
        Self { set, nvml }
    }

    /**
    Use this to release the set's events if you care about handling
    potential errors (*the `Drop` implementation ignores errors!*).

    # Errors

    * `Uninitialized`, if the library has not been successfully initialized
    * `Unknown`, on any unexpected error
    */
    // Checked against local
    pub fn release_events(self) -> Result<(), NvmlError> {
        let sym = nvml_sym(self.nvml.lib.nvmlEventSetFree.as_ref())?;

        unsafe {
            nvml_try(sym(self.set))?;
        }

        mem::forget(self);
        Ok(())
    }

    /**
    Waits on events for the given timeout (in ms) and delivers one when it arrives.

    See the `high_level::event_loop` module for an abstracted version of this.

    This method returns immediately if an event is ready to be delivered when it
    is called. If no events are ready it will sleep until an event arrives, but
    not longer than the specified timeout. In certain conditions, this method
    could return before the timeout passes (e.g. when an interrupt arrives).

    In the case of an XID error, the function returns the most recent XID error
    type seen by the system. If there are multiple XID errors generated before
    this method is called, the last seen XID error type will be returned for
    all XID error events.

    # Errors

    * `Uninitialized`, if the library has not been successfully initialized
    * `Timeout`, if no event arrived in the specified timeout or an interrupt
    arrived
    * `GpuLost`, if a GPU has fallen off the bus or is otherwise inaccessible
    * `Unknown`, on any unexpected error

    # Device Support

    Supports Fermi and newer fully supported devices.
    */
    // Checked against local
    pub fn wait(&self, timeout_ms: u32) -> Result<EventData<'nvml>, NvmlError> {
        let sym = nvml_sym(self.nvml.lib.nvmlEventSetWait_v2.as_ref())?;

        unsafe {
            let mut data: nvmlEventData_t = mem::zeroed();
            nvml_try(sym(self.set, &mut data, timeout_ms))?;

            Ok(EventData::new(data, self.nvml))
        }
    }

    /// Get the raw device handle contained in this struct
    ///
    /// Sometimes necessary for C interop.
    ///
    /// # Safety
    ///
    /// This is unsafe to prevent it from being used without care. In
    /// particular, you must avoid creating a new `EventSet` from this handle
    /// and allowing both this `EventSet` and the newly created one to drop
    /// (which would result in a double-free).
    pub unsafe fn handle(&self) -> nvmlEventSet_t {
        self.set
    }
}

/// This `Drop` implementation ignores errors! Use the `.release_events()`
/// method on the `EventSet` struct if you care about handling them.
impl<'nvml> Drop for EventSet<'nvml> {
    fn drop(&mut self) {
        unsafe {
            #[allow(unused_must_use)]
            match nvml_try(self.nvml.lib.nvmlEventSetFree(self.set)) {
                Ok(()) => (),
                Err(e) => {
                    io::stderr().write(
                        format!(
                            "WARNING: Error returned by `nvmlEventSetFree()` in Drop \
                             implementation: {:?}",
                            e
                        )
                        .as_bytes(),
                    );
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    #[cfg(target_os = "linux")]
    use crate::bitmasks::event::*;
    use crate::test_utils::*;

    #[cfg(target_os = "linux")]
    #[test]
    fn release_events() {
        let nvml = nvml();
        test_with_device(3, &nvml, |device| {
            let set = nvml.create_event_set()?;
            let set = device
                .register_events(
                    EventTypes::PSTATE_CHANGE
                        | EventTypes::CRITICAL_XID_ERROR
                        | EventTypes::CLOCK_CHANGE,
                    set,
                )
                .map_err(|e| e.error)?;

            set.release_events()
        })
    }

    #[cfg(target_os = "linux")]
    #[cfg(feature = "test-local")]
    #[test]
    fn wait() {
        use crate::error::NvmlError;

        let nvml = nvml();
        let device = device(&nvml);
        let set = nvml.create_event_set().expect("event set");
        let set = device
            .register_events(
                EventTypes::PSTATE_CHANGE
                    | EventTypes::CRITICAL_XID_ERROR
                    | EventTypes::CLOCK_CHANGE,
                set,
            )
            .expect("registration");

        let data = match set.wait(10_000) {
            Err(NvmlError::Timeout) => return (),
            Ok(d) => d,
            _ => panic!("An error other than `Timeout` occurred"),
        };

        print!("{:?} ...", data);
    }
}
<|endoftext|>