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

#![cfg_attr(feature = "unstable", feature(asm, repr_simd, test))]

//! A collection of strongly typed math tools for computer graphics with an inclination
//! towards 2d graphics and layout.
//!
//! All types are generic over the scalar type of their component (`f32`, `i32`, etc.),
//! and tagged with a generic Unit parameter which is useful to prevent mixing
//! values from different spaces. For example it should not be legal to translate
//! a screen-space position by a world-space vector and this can be expressed using
//! the generic Unit parameter.
//!
//! This unit system is not mandatory and all Typed* structures have an alias
//! with the default unit: `UnknownUnit`.
//! for example ```Point2D<T>``` is equivalent to ```TypedPoint2D<T, UnknownUnit>```.
//! Client code typically creates a set of aliases for each type and doesn't need
//! to deal with the specifics of typed units further. For example:
//!
//! All euclid types are marked `#[repr(C)]` in order to facilitate exposing them to
//! foreign function interfaces (provided the underlying scalar type is also `repr(C)`).
//!
//! ```rust
//! use euclid::*;
//! pub struct ScreenSpace;
//! pub type ScreenPoint = TypedPoint2D<f32, ScreenSpace>;
//! pub type ScreenSize = TypedSize2D<f32, ScreenSpace>;
//! pub struct WorldSpace;
//! pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
//! pub type ProjectionMatrix = TypedMatrix4D<f32, WorldSpace, ScreenSpace>;
//! // etc...
//! ```
//!
//! Components are accessed in their scalar form by default for convenience, and most
//! types additionally implement strongly typed accessors which return typed ```Length``` wrappers.
//! For example:
//!
//! ```rust
//! # use euclid::*;
//! # pub struct WorldSpace;
//! # pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
//! let p = WorldPoint::new(0.0, 1.0, 1.0);
//! // p.x is an f32.
//! println!("p.x = {:?} ", p.x);
//! // p.x is a Length<f32, WorldSpace>.
//! println!("p.x_typed() = {:?} ", p.x_typed());
//! // Length::get returns the scalar value (f32).
//! assert_eq!(p.x, p.x_typed().get());
//! ```

extern crate heapsize;

#[cfg_attr(test, macro_use)]
extern crate log;
extern crate serde;

#[cfg(test)]
extern crate rand;
#[cfg(feature = "unstable")]
extern crate test;
extern crate num_traits;

pub use length::Length;
pub use scale_factor::ScaleFactor;
pub use transform2d::{Transform2D, TypedTransform2D};
pub use transform3d::{Transform3D, TypedTransform3D};
pub use point::{
    Point2D, TypedPoint2D, point2,
    Point3D, TypedPoint3D, point3,
};
pub use vector::{
    Vector2D, TypedVector2D, vec2,
    Vector3D, TypedVector3D, vec3,
};

pub use rect::{Rect, TypedRect, rect};
pub use side_offsets::{SideOffsets2D, TypedSideOffsets2D};
#[cfg(feature = "unstable")] pub use side_offsets::SideOffsets2DSimdI32;
pub use size::{Size2D, TypedSize2D, size2};
pub use trig::Trig;

pub mod approxeq;
pub mod num;
mod length;
#[macro_use]
mod macros;
mod transform2d;
mod transform3d;
mod point;
mod rect;
mod scale_factor;
mod side_offsets;
mod size;
mod trig;
mod vector;

/// The default unit.
#[derive(Clone, Copy)]
pub struct UnknownUnit;

/// Unit for angles in radians.
pub struct Rad;

/// Unit for angles in degrees.
pub struct Deg;

/// A value in radians.
pub type Radians<T> = Length<T, Rad>;

/// A value in Degrees.
pub type Degrees<T> = Length<T, Deg>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type Matrix2D<T> = Transform2D<T>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type TypedMatrix2D<T, Src, Dst> = TypedTransform2D<T, Src, Dst>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type Matrix4D<T> = Transform3D<T>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type TypedMatrix4D<T, Src, Dst> = TypedTransform3D<T, Src, Dst>;

<commit_msg>Auto merge of #213 - servo:SimonSapin-patch-1, r=nical<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg_attr(feature = "unstable", feature(asm, repr_simd, test))]

//! A collection of strongly typed math tools for computer graphics with an inclination
//! towards 2d graphics and layout.
//!
//! All types are generic over the scalar type of their component (`f32`, `i32`, etc.),
//! and tagged with a generic Unit parameter which is useful to prevent mixing
//! values from different spaces. For example it should not be legal to translate
//! a screen-space position by a world-space vector and this can be expressed using
//! the generic Unit parameter.
//!
//! This unit system is not mandatory and all Typed* structures have an alias
//! with the default unit: `UnknownUnit`.
//! for example ```Point2D<T>``` is equivalent to ```TypedPoint2D<T, UnknownUnit>```.
//! Client code typically creates a set of aliases for each type and doesn't need
//! to deal with the specifics of typed units further. For example:
//!
//! ```rust
//! use euclid::*;
//! pub struct ScreenSpace;
//! pub type ScreenPoint = TypedPoint2D<f32, ScreenSpace>;
//! pub type ScreenSize = TypedSize2D<f32, ScreenSpace>;
//! pub struct WorldSpace;
//! pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
//! pub type ProjectionMatrix = TypedTransform3D<f32, WorldSpace, ScreenSpace>;
//! // etc...
//! ```
//!
//! All euclid types are marked `#[repr(C)]` in order to facilitate exposing them to
//! foreign function interfaces (provided the underlying scalar type is also `repr(C)`).
//!
//! Components are accessed in their scalar form by default for convenience, and most
//! types additionally implement strongly typed accessors which return typed ```Length``` wrappers.
//! For example:
//!
//! ```rust
//! # use euclid::*;
//! # pub struct WorldSpace;
//! # pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
//! let p = WorldPoint::new(0.0, 1.0, 1.0);
//! // p.x is an f32.
//! println!("p.x = {:?} ", p.x);
//! // p.x is a Length<f32, WorldSpace>.
//! println!("p.x_typed() = {:?} ", p.x_typed());
//! // Length::get returns the scalar value (f32).
//! assert_eq!(p.x, p.x_typed().get());
//! ```

extern crate heapsize;

#[cfg_attr(test, macro_use)]
extern crate log;
extern crate serde;

#[cfg(test)]
extern crate rand;
#[cfg(feature = "unstable")]
extern crate test;
extern crate num_traits;

pub use length::Length;
pub use scale_factor::ScaleFactor;
pub use transform2d::{Transform2D, TypedTransform2D};
pub use transform3d::{Transform3D, TypedTransform3D};
pub use point::{
    Point2D, TypedPoint2D, point2,
    Point3D, TypedPoint3D, point3,
};
pub use vector::{
    Vector2D, TypedVector2D, vec2,
    Vector3D, TypedVector3D, vec3,
};

pub use rect::{Rect, TypedRect, rect};
pub use side_offsets::{SideOffsets2D, TypedSideOffsets2D};
#[cfg(feature = "unstable")] pub use side_offsets::SideOffsets2DSimdI32;
pub use size::{Size2D, TypedSize2D, size2};
pub use trig::Trig;

pub mod approxeq;
pub mod num;
mod length;
#[macro_use]
mod macros;
mod transform2d;
mod transform3d;
mod point;
mod rect;
mod scale_factor;
mod side_offsets;
mod size;
mod trig;
mod vector;

/// The default unit.
#[derive(Clone, Copy)]
pub struct UnknownUnit;

/// Unit for angles in radians.
pub struct Rad;

/// Unit for angles in degrees.
pub struct Deg;

/// A value in radians.
pub type Radians<T> = Length<T, Rad>;

/// A value in Degrees.
pub type Degrees<T> = Length<T, Deg>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type Matrix2D<T> = Transform2D<T>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type TypedMatrix2D<T, Src, Dst> = TypedTransform2D<T, Src, Dst>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type Matrix4D<T> = Transform3D<T>;

/// Temporary alias to facilitate the transition to the new naming scheme
#[deprecated]
pub type TypedMatrix4D<T, Src, Dst> = TypedTransform3D<T, Src, Dst>;

<|endoftext|>


<commit_before>/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

extern crate regex;
use regex::Regex;

extern crate reqwest;
use reqwest::Url;

extern crate select;
use select::document::Document;
use select::predicate::Name;

use std::io::Read;

pub struct Inspirer {
    logger: slog::Logger,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        Inspirer {
            logger: logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!())),
        }
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ## biber
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r"(\\citation|\\abx@aux@cite)\{([a-zA-Z]+:\d{4}[a-z]{2,3})\}")
            .unwrap();

        regex.captures_iter(&input_data)
            .map(|c| {
                     c.get(2)
                         .unwrap()
                         .as_str()
                         .to_string()
                 })
            .collect()
    }

    /// # The blg2key function extracts missing references from bibtex logs
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r#"(Warning--|WARN - )I didn't find a database entry for ["']([a-zA-Z]+:\d{4}[a-z]{2,3})["']"#)
            .unwrap();

        regex.captures_iter(&input_data)
            .map(|c| {
                     c.get(2)
                         .unwrap()
                         .as_str()
                         .to_string()
                 })
            .collect()
    }

    /// Fetches BibTeX entries from inspire.net.
    ///
    /// # Examples
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// println!("{}", inspirer.fetch_bibtex_with_key(
    ///     "Abramovici:1992ah".to_string()).expect("Error"));
    /// ```
    pub fn fetch_bibtex_with_key(&self, key: String) -> Option<String> {

        let mut api_url: Url = Url::parse("https://inspirehep.net")
            .expect("Unable to parse API URL")
            .join("search")
            .unwrap();
        api_url.query_pairs_mut().append_pair("of", "hx").append_pair("p", &key);

        debug!(self.logger, "Querying inspire API";
               "URL" => api_url.to_string());
        let mut response = reqwest::get(api_url).expect("Failed to send get request");
        debug!(self.logger, "GET request completed";
               "HTTP response status" => response.status().to_string());

        let mut html = String::new();
        response.read_to_string(&mut html).expect("Failed to read response.");

        let document = Document::from(html.as_str());

        Some(document.find(Name("pre"))
                 .first()
                 .expect("No text found.")
                 .text())
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah"]);
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah", "Thorne:1992sdb"]);
    }
}
<commit_msg>chore: rustfmt<commit_after>/// Re-export slog
///
/// Users of this library can, but don't have to use slog to build their own loggers
#[macro_use]
pub extern crate slog ;
extern crate slog_stdlog;

use slog::DrainExt;

extern crate regex;
use regex::Regex;

extern crate reqwest;
use reqwest::Url;

extern crate select;
use select::document::Document;
use select::predicate::Name;

use std::io::Read;

pub struct Inspirer {
    logger: slog::Logger,
}

impl Inspirer {
    /// Initialize 'Inspirer'
    ///
    /// Either provide a custom slog::Logger or default to the standard `log`
    /// crate.
    ///
    /// # Examples
    /// ```
    /// inspirer::Inspirer::init(None);
    /// ```
    pub fn init(logger: Option<slog::Logger>) -> Self {
        Inspirer {
            logger: logger.unwrap_or_else(|| slog::Logger::root(slog_stdlog::StdLog.fuse(), o!())),
        }
    }

    /// The `aux2key` function extracts TeX keys from LaTeX .aux files. These can be for either
    /// BibTeX or BibLaTeX.
    ///
    /// # Examples
    ///
    /// ## bibtex
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \citation{Abramovici:1992ah}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Abramovici:1992ah"));
    /// ```
    ///
    /// ## biber
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// let input =
    /// r"\relax
    /// \abx@aux@cite{Cutler:1992tc}".to_string();
    ///
    /// assert_eq!(inspirer.aux2key(input), vec!("Cutler:1992tc"));
    /// ```
    pub fn aux2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r"(\\citation|\\abx@aux@cite)\{([a-zA-Z]+:\d{4}[a-z]{2,3})\}")
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    /// # The blg2key function extracts missing references from bibtex logs
    pub fn blg2key(&self, input_data: String) -> Vec<String> {

        let regex = Regex::new(r#"(Warning--|WARN - )I didn't find a database entry for ["']([a-zA-Z]+:\d{4}[a-z]{2,3})["']"#)
            .unwrap();

        regex
            .captures_iter(&input_data)
            .map(|c| c.get(2).unwrap().as_str().to_string())
            .collect()
    }

    /// Fetches BibTeX entries from inspire.net.
    ///
    /// # Examples
    ///
    /// ```
    /// let inspirer = inspirer::Inspirer::init(None);
    ///
    /// println!("{}", inspirer.fetch_bibtex_with_key(
    ///     "Abramovici:1992ah".to_string()).expect("Error"));
    /// ```
    pub fn fetch_bibtex_with_key(&self, key: String) -> Option<String> {

        let mut api_url: Url = Url::parse("https://inspirehep.net")
            .expect("Unable to parse API URL")
            .join("search")
            .unwrap();
        api_url
            .query_pairs_mut()
            .append_pair("of", "hx")
            .append_pair("p", &key);

        debug!(self.logger, "Querying inspire API";
               "URL" => api_url.to_string());
        let mut response = reqwest::get(api_url).expect("Failed to send get request");
        debug!(self.logger, "GET request completed";
               "HTTP response status" => response.status().to_string());

        let mut html = String::new();
        response
            .read_to_string(&mut html)
            .expect("Failed to read response.");

        let document = Document::from(html.as_str());

        Some(document
                 .find(Name("pre"))
                 .first()
                 .expect("No text found.")
                 .text())
    }
}

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

    #[test]
    fn test_aux_bibtex_0_citations() {
        let input = r"\relax ".to_string();

        let output: Vec<String> = Vec::new();
        assert_eq!(Inspirer::init(None).aux2key(input), output);
    }

    #[test]
    fn test_aux_bibtex_1_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah"]);
    }

    #[test]
    fn test_aux_bibtex_2_citation() {
        let input = r"\relax
            \citation{Abramovici:1992ah}
            \citation{Thorne:1992sdb}"
                .to_string();

        assert_eq!(Inspirer::init(None).aux2key(input),
                   vec!["Abramovici:1992ah", "Thorne:1992sdb"]);
    }
}
<|endoftext|>


<commit_before>//! Rsure is a set of utilities for capturing information about files, and later verifying it is
//! still true.
//!
//! The easiest way to use Rsure is to build the `rsure` executable contained in this crate.  This
//! program allows you to use most of the functionality of the crate.
//!
//! However, it is also possible to use the crate programmatically.  At the top level of the crate
//! as some utility functions for the most common operations.
//!
//! For example, to scan a directory or do an update use `update`.
//!
//! This example makes use of several of the building blocks necessary to use the store.  First is
//! the store itself.  `parse_store` is able to decode options that are passed to the command line.
//! it is also possible to build a `store::Plain` store directly.
//!
//! Next are the tags for the snapshot.  Generally, this should hold some kind of information about
//! the snapshot itself.  For the `Plain` store, it can be just an empty map.  Other store types
//! may require certain tags to be present.

extern crate chrono;
extern crate flate2;
extern crate libc;
extern crate openssl;
extern crate regex;
extern crate rustc_serialize;
extern crate time;
extern crate weave;

#[macro_use]
extern crate log;

#[macro_use] extern crate failure;
#[macro_use] extern crate failure_derive;

use std::path::Path;

pub use surefs::scan_fs;
pub use hashes::SureHash;
pub use suretree::SureTree;
pub use comp::{TreeCompare, TreeUpdate};
pub use compvisit::{CompareVisitor, CompareType, CompareAction, PrintVisitor, stdout_visitor,
                    stderr_visitor};
pub use show::show_tree;
pub use progress::Progress;

pub use errors::{Error, WeaveError, Result};

pub use store::{StoreTags, Store, StoreVersion, Version, parse_store, BkSureFile, BkStore,
                bk_setup};

mod errors;
mod escape;
mod show;
mod suretree;
mod surefs;
mod hashes;
mod comp;
mod compvisit;
mod progress;
mod store;

// Some common operations, abstracted here.

/// Perform an update scan, using the given store.
///
/// If 'update' is true, use the hashes from a previous run, otherwise perform a fresh scan.
/// Depending on the [`Store`] type, the tags may be kept, or ignored.
///
/// [`Store`]: trait.Store.html
///
/// A simple example:
///
/// ```rust
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// let store = rsure::parse_store("2sure.dat.gz")?;
/// rsure::update(".", &*store, false, &rsure::StoreTags::new())?;
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
/// ```
pub fn update<P: AsRef<Path>>(
    dir: P,
    store: &Store,
    is_update: bool,
    tags: &StoreTags,
) -> Result<()> {
    let dir = dir.as_ref();

    let mut new_tree = scan_fs(dir)?;

    if is_update {
        let old_tree = store.load(Version::Latest)?;
        new_tree.update_from(&old_tree);
    }

    let estimate = new_tree.hash_estimate();
    let mut progress = Progress::new(estimate.files, estimate.bytes);
    new_tree.hash_update(dir, &mut progress);
    progress.flush();

    store.write_new(&new_tree, tags)?;
    Ok(())
}
<commit_msg>Fix the `update` example<commit_after>//! Rsure is a set of utilities for capturing information about files, and later verifying it is
//! still true.
//!
//! The easiest way to use Rsure is to build the `rsure` executable contained in this crate.  This
//! program allows you to use most of the functionality of the crate.
//!
//! However, it is also possible to use the crate programmatically.  At the top level of the crate
//! as some utility functions for the most common operations.
//!
//! For example, to scan a directory or do an update use `update`.
//!
//! This example makes use of several of the building blocks necessary to use the store.  First is
//! the store itself.  `parse_store` is able to decode options that are passed to the command line.
//! it is also possible to build a `store::Plain` store directly.
//!
//! Next are the tags for the snapshot.  Generally, this should hold some kind of information about
//! the snapshot itself.  For the `Plain` store, it can be just an empty map.  Other store types
//! may require certain tags to be present.

extern crate chrono;
extern crate flate2;
extern crate libc;
extern crate openssl;
extern crate regex;
extern crate rustc_serialize;
extern crate time;
extern crate weave;

#[macro_use]
extern crate log;

#[macro_use] extern crate failure;
#[macro_use] extern crate failure_derive;

use std::path::Path;

pub use surefs::scan_fs;
pub use hashes::SureHash;
pub use suretree::SureTree;
pub use comp::{TreeCompare, TreeUpdate};
pub use compvisit::{CompareVisitor, CompareType, CompareAction, PrintVisitor, stdout_visitor,
                    stderr_visitor};
pub use show::show_tree;
pub use progress::Progress;

pub use errors::{Error, WeaveError, Result};

pub use store::{StoreTags, Store, StoreVersion, Version, parse_store, BkSureFile, BkStore,
                bk_setup};

mod errors;
mod escape;
mod show;
mod suretree;
mod surefs;
mod hashes;
mod comp;
mod compvisit;
mod progress;
mod store;

// Some common operations, abstracted here.

/// Perform an update scan, using the given store.
///
/// If 'update' is true, use the hashes from a previous run, otherwise perform a fresh scan.
/// Depending on the [`Store`] type, the tags may be kept, or ignored.
///
/// [`Store`]: trait.Store.html
///
/// A simple example:
///
/// ```rust
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// let mut tags = rsure::StoreTags::new();
/// tags.insert("name".into(), "sample".into());
/// let store = rsure::parse_store("2sure.dat.gz")?;
/// rsure::update(".", &*store, false, &tags)?;
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
/// ```
pub fn update<P: AsRef<Path>>(
    dir: P,
    store: &Store,
    is_update: bool,
    tags: &StoreTags,
) -> Result<()> {
    let dir = dir.as_ref();

    let mut new_tree = scan_fs(dir)?;

    if is_update {
        let old_tree = store.load(Version::Latest)?;
        new_tree.update_from(&old_tree);
    }

    let estimate = new_tree.hash_estimate();
    let mut progress = Progress::new(estimate.files, estimate.bytes);
    new_tree.hash_update(dir, &mut progress);
    progress.flush();

    store.write_new(&new_tree, tags)?;
    Ok(())
}
<|endoftext|>


<commit_before>#![feature(catch_panic)]
#[macro_use]
extern crate lazy_static;
use std::string::ToString;
use std::thread::{JoinHandle, spawn, catch_panic};
use std::sync::*;
use std::any::{Any};
use std::io::{self, Write};

pub struct ExampleGroup {
    description: String,
    running_examples: Vec<JoinHandle<Result<(), Box<Any + Send>>>>,
}

pub struct ExampleGroupAndBlock {
    group: ExampleGroup,
    block: Box<Fn(&mut ExampleGroup) + Sync + Send + 'static>,
}

pub struct Example {
    description: String,
}

impl ExampleGroup {
    pub fn it<F>(&mut self, description: &'static str, example_definition_block: F) where F: Fn() + Sync + Send + 'static {
        self.running_examples.push(spawn(move || {
            let result = catch_panic(move || {
                example_definition_block();
            });

            with_world(|world| {
                if result.is_err() {
                    world.reporter.example_failed();
                } else {
                    world.reporter.example_passed();
                }
            });

            return result;
        }));
    }

    fn block_on_all_examples(self) -> Result<(), ()> {
        let mut failed = false;
        for jh in self.running_examples.into_iter() {
            if jh.join().unwrap().is_err() {
                failed = true;
            }
        }

        if failed {
            return Err(());
        } else {
            return Ok(());
        }
    }

    fn run(mut self, block: Box<Fn(&mut ExampleGroup) + Send + Sync + 'static>) -> bool {
        block(&mut self);

        let result = self.block_on_all_examples();
        return result.is_ok();
    }
}

pub struct Reporter;

impl Reporter {
    pub fn example_failed(&self) {
        print!("F");
        io::stdout().flush();
    }

    pub fn example_passed(&self) {
        print!(".");
        io::stdout().flush();
    }
}

struct World {
    reporter: Reporter,
    failed: bool,
    example_groups: Vec<ExampleGroupAndBlock>,
}

fn with_world<F>(blk: F) where F: FnOnce(&mut World) -> () {
    let c = WORLD.clone();
    let mut guard = c.lock().unwrap();
    blk(&mut guard);
}

impl World {
    fn describe<F>(&mut self, description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
        self.example_groups.push(
            ExampleGroupAndBlock {
                group: ExampleGroup {
                    description: description.to_string(),
                    running_examples: Vec::new(),
                },
                block: Box::new(example_group_definition_block)
            }
        );
    }
}

lazy_static! {
    static ref WORLD: Arc<Mutex<World>> = Arc::new(Mutex::new(World { failed: false, reporter: Reporter, example_groups: Vec::new() }));
}

pub fn describe<F>(description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
    with_world(|world| {
        world.describe(description, example_group_definition_block);
    });
}

fn get_examples_from_world() -> Vec<ExampleGroupAndBlock> {
    let mut result = Vec::new();

    with_world(|world| {
        while !world.example_groups.is_empty() {
            result.push(world.example_groups.remove(0));
        }
    });

    return result;

}

pub fn descriptor_main() {
    let mut example_groups = get_examples_from_world();
    let mut join_handles = Vec::new();

    while !example_groups.is_empty() {
        let example_group_and_block = example_groups.remove(0);
        let example_group = example_group_and_block.group;
        let block = example_group_and_block.block;
        join_handles.push(spawn(|| -> Result<(), ()> {
            if example_group.run(block) {
                return Ok(());
            } else {
                return Err(());
            }
        }));
    }

    for join_handle in join_handles.into_iter() {
        let result = join_handle.join().unwrap();
        if result.is_err() {
            with_world(|world| {
                world.failed = true;
            });
        }
    }
    with_world(|world| {
        println!("{}", world.failed);
    });
}
<commit_msg>Make descriptor main more refactored<commit_after>#![feature(catch_panic)]
#[macro_use]
extern crate lazy_static;
use std::string::ToString;
use std::thread::{JoinHandle, spawn, catch_panic};
use std::sync::*;
use std::any::{Any};
use std::io::{self, Write};

pub struct ExampleGroup {
    description: String,
    running_examples: Vec<JoinHandle<Result<(), Box<Any + Send>>>>,
}

pub struct ExampleGroupAndBlock {
    group: ExampleGroup,
    block: Box<Fn(&mut ExampleGroup) + Sync + Send + 'static>,
}

pub struct Example {
    description: String,
}

impl ExampleGroup {
    pub fn it<F>(&mut self, description: &'static str, example_definition_block: F) where F: Fn() + Sync + Send + 'static {
        self.running_examples.push(spawn(move || {
            let result = catch_panic(move || {
                example_definition_block();
            });

            with_world(|world| {
                if result.is_err() {
                    world.reporter.example_failed();
                } else {
                    world.reporter.example_passed();
                }
            });

            return result;
        }));
    }

    fn block_on_all_examples(self) -> Result<(), ()> {
        let mut failed = false;
        for jh in self.running_examples.into_iter() {
            if jh.join().unwrap().is_err() {
                failed = true;
            }
        }

        if failed {
            return Err(());
        } else {
            return Ok(());
        }
    }

    fn run(mut self, block: Box<Fn(&mut ExampleGroup) + Send + Sync + 'static>) -> bool {
        block(&mut self);

        let result = self.block_on_all_examples();
        return result.is_ok();
    }
}

pub struct Reporter;

impl Reporter {
    pub fn example_failed(&self) {
        print!("F");
        io::stdout().flush();
    }

    pub fn example_passed(&self) {
        print!(".");
        io::stdout().flush();
    }
}

struct World {
    reporter: Reporter,
    failed: bool,
    example_groups: Vec<ExampleGroupAndBlock>,
}

fn with_world<F, T>(blk: F) -> T where F: FnOnce(&mut World) -> T {
    let c = WORLD.clone();
    let mut guard = c.lock().unwrap();
    blk(&mut guard)
}

impl World {
    fn describe<F>(&mut self, description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
        self.example_groups.push(
            ExampleGroupAndBlock {
                group: ExampleGroup {
                    description: description.to_string(),
                    running_examples: Vec::new(),
                },
                block: Box::new(example_group_definition_block)
            }
        );
    }
}

lazy_static! {
    static ref WORLD: Arc<Mutex<World>> = Arc::new(Mutex::new(World { failed: false, reporter: Reporter, example_groups: Vec::new() }));
}

pub fn describe<F>(description: &str, example_group_definition_block: F) where F: Fn(&mut ExampleGroup) + Sync + Send + 'static {
    with_world(|world| {
        world.describe(description, example_group_definition_block);
    });
}

fn get_examples_from_world() -> Vec<ExampleGroupAndBlock> {
    let mut result = Vec::new();

    with_world(|world| {
        ::std::mem::replace(&mut world.example_groups, result)
    })
}

pub fn descriptor_main() {
    let mut example_groups = get_examples_from_world();
    let join_handles: Vec<JoinHandle<Result<(), ()>>> = example_groups.into_iter().map({ |ExampleGroupAndBlock { group: example_group, block: block }|
        spawn(|| -> Result<(), ()> {
            if example_group.run(block) {
                Ok(())
            } else {
                Err(())
            }
        })
    }).collect();

    let results = join_handles.into_iter().map(|jh| { jh.join().unwrap() });
    let failed = results.into_iter().any(|r| { r.is_err() });

    with_world(|world| {
        world.failed = failed;
        println!("{}", world.failed);
    });
}
<|endoftext|>


<commit_before>#![feature(step_by)]

extern crate libc;
extern crate posix_ipc as ipc;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate enum_primitive;

use enum_primitive::FromPrimitive;
use std::io;
use std::ptr;
use std::default::Default;
use std::vec::Vec;
use std::mem;

pub type Address = u64;
pub type Word = u64;

#[derive(Clone, Copy)]
pub enum Action {
  Allow,
  Kill
}

#[derive(Debug, Clone, Copy)]
pub enum Request {
  TraceMe = 0,
  PeekText = 1,
  PeekData = 2,
  PeekUser = 3,
  PokeText = 4,
  PokeData = 5,
  PokeUser = 6,
  Continue = 7,
  Kill = 8,
  SingleStep = 9,
  GetRegs = 12,
  SetRegs = 13,
  Attach = 16,
  Detatch = 17,
  SetOptions = 0x4200,
  Seize = 0x4206
}

enum_from_primitive!{
#[derive(Clone, Copy, Debug)]
pub enum Event {
  Fork = 1,
  VFork = 2,
  Clone = 3,
  Exec = 4,
  VForkDone = 5,
  Exit = 6,
  Seccomp = 7,
  Stop = 128
}
}

impl Event {
    pub fn from_wait_status(st: i32) -> Option<Event> {
        let e: Option<Event> = Event::from_i32(((st >> 8) & !5) >> 8);
        return e;
    }
}

#[derive(Clone, Copy, Default, Debug)]
pub struct Registers {
  pub r15: Word,
  pub r14: Word,
  pub r13: Word,
  pub r12: Word,
  pub rbp: Word,
  pub rbx: Word,
  pub r11: Word,
  pub r10: Word,
  pub r9: Word,
  pub r8: Word,
  pub rax: Word,
  pub rcx: Word,
  pub rdx: Word,
  pub rsi: Word,
  pub rdi: Word,
  pub orig_rax: Word,
  pub rip: Word,
  pub cs: Word,
  pub eflags: Word,
  pub rsp: Word,
  pub ss: Word,
  pub fs_base: Word,
  pub gs_base: Word,
  pub ds: Word,
  pub es: Word,
  pub fs: Word,
  pub gs: Word
}

bitflags! {
  flags Options: u32 {
    const SysGood = 1,
    const TraceFork = 1 << 1,
    const TraceVFork = 1 << 2,
    const TraceClone = 1 << 3,
    const TraceExec = 1 << 4,
    const TraceVForkDone = 1 << 5,
    const TraceExit = 1 << 6,
    const TraceSeccomp = 1 << 7,
    const ExitKill = 1 << 20
  }
}

fn os_errno() -> usize {
    return io::Error::last_os_error().raw_os_error().unwrap_or(0) as usize;
}

pub fn setoptions(pid: libc::pid_t, opts: Options) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::SetOptions, pid, ptr::null_mut(), opts.bits as *mut
    libc::c_void)
  }
}

pub fn getregs(pid: libc::pid_t) -> Result<Registers, usize> {
  let mut buf: Registers = Default::default();
  let buf_mut: *mut Registers = &mut buf;

  match unsafe {
    raw (Request::GetRegs, pid, ptr::null_mut(), buf_mut as *mut libc::c_void)
  } {
      Ok(_) => Ok(buf),
      Err(e) => Err(e)
  }
}

pub fn setregs(pid: libc::pid_t, regs: &Registers) -> Result<libc::c_long, usize> {
    unsafe {
        let buf: *mut libc::c_void = mem::transmute(regs);
        raw (Request::SetRegs, pid, ptr::null_mut(), buf)
    }
}

pub fn seize(pid: libc::pid_t) -> Result<libc::c_long, usize> {
    unsafe {
        raw (Request::Seize, pid, ptr::null_mut(), ptr::null_mut())
    }
}

pub fn attach(pid: libc::pid_t) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Attach, pid, ptr::null_mut(), ptr::null_mut())
  }
}

pub fn release(pid: libc::pid_t, signal: ipc::signals::Signal) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Detatch, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void)
  }
}

pub fn cont(pid: libc::pid_t, signal: ipc::signals::Signal) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Continue, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void)
  }
}

pub fn traceme() -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::TraceMe, 0, ptr::null_mut(), ptr::null_mut())
  }
}

unsafe fn raw(request: Request,
       pid: libc::pid_t,
       addr: *mut libc::c_void,
       data: *mut libc::c_void) -> Result<libc::c_long, usize> {
  let v = ptrace (request as libc::c_int, pid, addr, data);
  match v {
      -1 => Result::Err(os_errno()),
      _ => Result::Ok(v)
  }
}

extern {
  fn ptrace(request: libc::c_int,
            pid: libc::pid_t,
            addr: *mut libc::c_void,
            data: *mut libc::c_void) -> libc::c_long;
}

#[derive(Clone, Copy, Debug)]
pub struct Syscall {
  pub args: [Word; 6],
  pub call: u64,
  pub pid: libc::pid_t,
  pub return_val: Word
}

impl Syscall {
  pub fn from_pid(pid: libc::pid_t) -> Result<Syscall, usize> {
    match getregs (pid) {
        Ok(regs) =>
            Ok(Syscall {
              pid: pid,
              call: regs.orig_rax,
              args: [regs.rdi, regs.rsi, regs.rdx, regs.rcx, regs.r8, regs.r9],
              return_val: 0
            }),
        Err(e) => Err(e)
    }
  }

  pub fn write(&self) -> Result<libc::c_long, usize> {
      match getregs(self.pid) {
          Ok(mut regs) => {
              regs.rdi = self.args[0];
              regs.rsi = self.args[1];
              regs.rdx = self.args[2];
              regs.rcx = self.args[3];
              regs.r8 = self.args[4];
              regs.r9 = self.args[5];
              regs.orig_rax = self.call;
              regs.rax = self.return_val;
              setregs(self.pid, &regs)
          },
          Err(e) => Err(e)
      }
  }
}

#[derive(Clone, Copy)]
pub struct Reader {
  pub pid: libc::pid_t
}

#[derive(Clone, Copy)]
pub struct Writer {
    pub pid: libc::pid_t
}

impl Writer {
    pub fn new(pid: libc::pid_t) -> Self {
        Writer {
            pid: pid
        }
    }

    pub fn poke_data(&self, address: Address, data: Word) -> Result<Word, usize> {
        match unsafe {
            raw (Request::PokeData, self.pid, address as *mut libc::c_void, data as *mut libc::c_void)
        } {
            Err(e) => Err(e),
            Ok(r) => Ok(r as Word)
        }
    }

    pub fn write_object<T: Sized>(&self, address: Address, data: &T) -> Result<(), usize> {
        let mut buf = Vec::with_capacity(mem::size_of::<T>());
        unsafe {
            let tptr: *const T = data;
            let p: *const u8 = mem::transmute(tptr);
            for i in 0..buf.capacity() {
                buf.push(*p.offset(i as isize));
            }
        }

        Ok(())
    }

    pub fn write_data(&self, address: Address, buf: &Vec<u8>) -> Result<(), usize> {
        // The end of our range
        let max_addr = address + buf.len() as Address;
        // The last word we can completely overwrite
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        for write_addr in (address..align_end).step_by(mem::size_of::<Word>() as Address) {
            let mut d: Word = 0;
            let buf_idx = (write_addr - address) as usize;
            for word_idx in 0..mem::size_of::<Word>() {
                d = set_byte(d, word_idx, buf[buf_idx + word_idx]);
            }
            match self.poke_data(write_addr, d) {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }
        // Handle a partial word overwrite
        if max_addr > align_end {
            let buf_start = buf.len() - (max_addr - align_end) as usize;
            let r = Reader::new(self.pid);
            let mut d = match r.peek_data(align_end) {
                Ok(v) => v,
                Err(e) => return Err(e)
            };
            for word_idx in 0..mem::size_of::<Word>()-2 {
                let buf_idx = buf_start + word_idx;
                d = set_byte(d, word_idx, buf[buf_idx]);
            }
            match self.poke_data(align_end, d) {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }
        Ok(())
    }
}

impl Reader {
  pub fn new(pid: libc::pid_t) -> Reader {
    Reader {
      pid: pid
    }
  }

    pub fn peek_data(&self, address: Address) -> Result<Word, usize> {
        let l;
        unsafe {
            l = raw (Request::PeekData, self.pid, address as *mut libc::c_void, ptr::null_mut())
        }
        match l {
            Result::Err(e) => Result::Err(e),
            _ => Result::Ok(l.unwrap() as Word)
        }
    }

    pub fn read_string(&self, address: Address) -> Result<Vec<u8>, usize> {
        let mut end_of_str = false;
        let mut buf: Vec<u8> = Vec::with_capacity(1024);
        let max_addr = address + buf.capacity() as Address;
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        'finish: for read_addr in (address..align_end).step_by(mem::size_of::<Word>() as Address) {
            let d;
            match self.peek_data(read_addr) {
                Ok(v) => d = v,
                Err(e) => return Err(e)
            }
            for word_idx in 0..mem::size_of::<Word>() {
                let chr = get_byte(d, word_idx);
                if chr == 0 {
                    end_of_str = true;
                    break 'finish;
                }
                buf.push (chr);
            }
        }
        if !end_of_str {
            let d;
            match self.peek_data(align_end) {
                Ok(v) => d = v,
                Err(e) => return Err(e)
            }
            for word_idx in 0..mem::size_of::<Word>() {
                let chr = get_byte(d, word_idx);
                if chr == 0 {
                    break;
                }
                buf.push (chr);
            }
        }
        return Ok(buf);
    }
}

fn get_byte(d: Word, byte_idx: usize) -> u8 {
    assert!(byte_idx < mem::size_of::<Word>());
    ((d >> (byte_idx * 8)) & 0xff) as u8
}

fn set_byte(d: Word, byte_idx: usize, value: u8) -> Word {
    assert!(byte_idx < mem::size_of::<Word>());
    let shift = mem::size_of::<u8>() * 8 * byte_idx;
    let mask = 0xff << shift;
    (d & !mask) | (((value as Word) << shift) & mask)
}

#[test]
pub fn test_set_byte() {
    assert_eq!(set_byte(0, 0, 0), 0);
    assert_eq!(set_byte(0xffffffffffff, 0, 0xff), 0xffffffffffff);
    assert_eq!(set_byte(0xffffffffffff, 0, 0),    0xffffffffff00);
    assert_eq!(set_byte(0xffffffffffff, 0, 0xaa), 0xffffffffffaa);
    assert_eq!(set_byte(0xffffffffffff, 1, 0x00), 0xffffffff00ff);
    assert_eq!(set_byte(0xffffffffffff, 4, 0xaa), 0xffaaffffffff);
}

#[test]
pub fn test_get_byte() {
    assert_eq!(get_byte(0, 0), 0);
    assert_eq!(get_byte(0xffffffffffff, 0), 0xff);
    assert_eq!(get_byte(0xffffffffffaa, 0), 0xaa);
    assert_eq!(get_byte(0x0123456789ab, 1), 0x89);
    assert_eq!(get_byte(0x0123456789ab, 4), 0x23);
}
<commit_msg>Reformat code<commit_after>#![feature(step_by)]

extern crate libc;
extern crate posix_ipc as ipc;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate enum_primitive;

use enum_primitive::FromPrimitive;
use std::io;
use std::ptr;
use std::default::Default;
use std::vec::Vec;
use std::mem;

pub type Address = u64;
pub type Word = u64;

#[derive(Clone, Copy)]
pub enum Action {
    Allow,
    Kill
}

#[derive(Debug, Clone, Copy)]
pub enum Request {
    TraceMe = 0,
    PeekText = 1,
    PeekData = 2,
    PeekUser = 3,
    PokeText = 4,
    PokeData = 5,
    PokeUser = 6,
    Continue = 7,
    Kill = 8,
    SingleStep = 9,
    GetRegs = 12,
    SetRegs = 13,
    Attach = 16,
    Detatch = 17,
    SetOptions = 0x4200,
    Seize = 0x4206
}

enum_from_primitive! {
#[derive(Clone, Copy, Debug)]
pub enum Event {
  Fork = 1,
  VFork = 2,
  Clone = 3,
  Exec = 4,
  VForkDone = 5,
  Exit = 6,
  Seccomp = 7,
  Stop = 128
}
}

impl Event {
    pub fn from_wait_status(st: i32) -> Option<Event> {
        let e: Option<Event> = Event::from_i32(((st >> 8) & !5) >> 8);
        return e;
    }
}

#[derive(Clone, Copy, Default, Debug)]
pub struct Registers {
    pub r15: Word,
    pub r14: Word,
    pub r13: Word,
    pub r12: Word,
    pub rbp: Word,
    pub rbx: Word,
    pub r11: Word,
    pub r10: Word,
    pub r9: Word,
    pub r8: Word,
    pub rax: Word,
    pub rcx: Word,
    pub rdx: Word,
    pub rsi: Word,
    pub rdi: Word,
    pub orig_rax: Word,
    pub rip: Word,
    pub cs: Word,
    pub eflags: Word,
    pub rsp: Word,
    pub ss: Word,
    pub fs_base: Word,
    pub gs_base: Word,
    pub ds: Word,
    pub es: Word,
    pub fs: Word,
    pub gs: Word
}

bitflags! {
  flags Options: u32 {
    const SysGood = 1,
    const TraceFork = 1 << 1,
    const TraceVFork = 1 << 2,
    const TraceClone = 1 << 3,
    const TraceExec = 1 << 4,
    const TraceVForkDone = 1 << 5,
    const TraceExit = 1 << 6,
    const TraceSeccomp = 1 << 7,
    const ExitKill = 1 << 20
  }
}

fn os_errno() -> usize {
    return io::Error::last_os_error().raw_os_error().unwrap_or(0) as usize;
}

pub fn setoptions(pid: libc::pid_t, opts: Options) -> Result<libc::c_long, usize> {
    unsafe {
        raw(Request::SetOptions, pid, ptr::null_mut(), opts.bits as *mut
        libc::c_void)
    }
}

pub fn getregs(pid: libc::pid_t) -> Result<Registers, usize> {
    let mut buf: Registers = Default::default();
    let buf_mut: *mut Registers = &mut buf;

    match unsafe {
        raw(Request::GetRegs, pid, ptr::null_mut(), buf_mut as *mut libc::c_void)
    } {
        Ok(_) => Ok(buf),
        Err(e) => Err(e)
    }
}

pub fn setregs(pid: libc::pid_t, regs: &Registers) -> Result<libc::c_long, usize> {
    unsafe {
        let buf: *mut libc::c_void = mem::transmute(regs);
        raw(Request::SetRegs, pid, ptr::null_mut(), buf)
    }
}

pub fn seize(pid: libc::pid_t) -> Result<libc::c_long, usize> {
    unsafe {
        raw(Request::Seize, pid, ptr::null_mut(), ptr::null_mut())
    }
}

pub fn attach(pid: libc::pid_t) -> Result<libc::c_long, usize> {
    unsafe {
        raw(Request::Attach, pid, ptr::null_mut(), ptr::null_mut())
    }
}

pub fn release(pid: libc::pid_t, signal: ipc::signals::Signal) -> Result<libc::c_long, usize> {
    unsafe {
        raw(Request::Detatch, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void)
    }
}

pub fn cont(pid: libc::pid_t, signal: ipc::signals::Signal) -> Result<libc::c_long, usize> {
    unsafe {
        raw(Request::Continue, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void)
    }
}

pub fn traceme() -> Result<libc::c_long, usize> {
    unsafe {
        raw(Request::TraceMe, 0, ptr::null_mut(), ptr::null_mut())
    }
}

unsafe fn raw(request: Request,
              pid: libc::pid_t,
              addr: *mut libc::c_void,
              data: *mut libc::c_void) -> Result<libc::c_long, usize> {
    let v = ptrace(request as libc::c_int, pid, addr, data);
    match v {
        - 1 => Result::Err(os_errno()),
        _ => Result::Ok(v)
    }
}

extern {
    fn ptrace(request: libc::c_int,
              pid: libc::pid_t,
              addr: *mut libc::c_void,
              data: *mut libc::c_void) -> libc::c_long;
}

#[derive(Clone, Copy, Debug)]
pub struct Syscall {
    pub args: [Word; 6],
    pub call: u64,
    pub pid: libc::pid_t,
    pub return_val: Word
}

impl Syscall {
    pub fn from_pid(pid: libc::pid_t) -> Result<Syscall, usize> {
        match getregs(pid) {
            Ok(regs) =>
                Ok(Syscall {
                    pid: pid,
                    call: regs.orig_rax,
                    args: [regs.rdi, regs.rsi, regs.rdx, regs.rcx, regs.r8, regs.r9],
                    return_val: 0
                }),
            Err(e) => Err(e)
        }
    }

    pub fn write(&self) -> Result<libc::c_long, usize> {
        match getregs(self.pid) {
            Ok(mut regs) => {
                regs.rdi = self.args[0];
                regs.rsi = self.args[1];
                regs.rdx = self.args[2];
                regs.rcx = self.args[3];
                regs.r8 = self.args[4];
                regs.r9 = self.args[5];
                regs.orig_rax = self.call;
                regs.rax = self.return_val;
                setregs(self.pid, &regs)
            },
            Err(e) => Err(e)
        }
    }
}

#[derive(Clone, Copy)]
pub struct Reader {
    pub pid: libc::pid_t
}

#[derive(Clone, Copy)]
pub struct Writer {
    pub pid: libc::pid_t
}

impl Writer {
    pub fn new(pid: libc::pid_t) -> Self {
        Writer {
            pid: pid
        }
    }

    pub fn poke_data(&self, address: Address, data: Word) -> Result<Word, usize> {
        match unsafe {
            raw(Request::PokeData, self.pid, address as *mut libc::c_void, data as *mut libc::c_void)
        } {
            Err(e) => Err(e),
            Ok(r) => Ok(r as Word)
        }
    }

    pub fn write_object<T: Sized>(&self, address: Address, data: &T) -> Result<(), usize> {
        let mut buf = Vec::with_capacity(mem::size_of::<T>());
        unsafe {
            let tptr: *const T = data;
            let p: *const u8 = mem::transmute(tptr);
            for i in 0..buf.capacity() {
                buf.push(*p.offset(i as isize));
            }
        }

        Ok(())
    }

    pub fn write_data(&self, address: Address, buf: &Vec<u8>) -> Result<(), usize> {
        // The end of our range
        let max_addr = address + buf.len() as Address;
        // The last word we can completely overwrite
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        for write_addr in (address..align_end).step_by(mem::size_of::<Word>() as Address) {
            let mut d: Word = 0;
            let buf_idx = (write_addr - address) as usize;
            for word_idx in 0..mem::size_of::<Word>() {
                d = set_byte(d, word_idx, buf[buf_idx + word_idx]);
            }
            match self.poke_data(write_addr, d) {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }
        // Handle a partial word overwrite
        if max_addr > align_end {
            let buf_start = buf.len() - (max_addr - align_end) as usize;
            let r = Reader::new(self.pid);
            let mut d = match r.peek_data(align_end) {
                Ok(v) => v,
                Err(e) => return Err(e)
            };
            for word_idx in 0..mem::size_of::<Word>() - 2 {
                let buf_idx = buf_start + word_idx;
                d = set_byte(d, word_idx, buf[buf_idx]);
            }
            match self.poke_data(align_end, d) {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }
        Ok(())
    }
}

impl Reader {
    pub fn new(pid: libc::pid_t) -> Reader {
        Reader {
            pid: pid
        }
    }

    pub fn peek_data(&self, address: Address) -> Result<Word, usize> {
        let l;
        unsafe {
            l = raw(Request::PeekData, self.pid, address as *mut libc::c_void, ptr::null_mut())
        }
        match l {
            Result::Err(e) => Result::Err(e),
            _ => Result::Ok(l.unwrap() as Word)
        }
    }

    pub fn read_string(&self, address: Address) -> Result<Vec<u8>, usize> {
        let mut end_of_str = false;
        let mut buf: Vec<u8> = Vec::with_capacity(1024);
        let max_addr = address + buf.capacity() as Address;
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        'finish: for read_addr in (address..align_end).step_by(mem::size_of::<Word>() as Address) {
            let d;
            match self.peek_data(read_addr) {
                Ok(v) => d = v,
                Err(e) => return Err(e)
            }
            for word_idx in 0..mem::size_of::<Word>() {
                let chr = get_byte(d, word_idx);
                if chr == 0 {
                    end_of_str = true;
                    break 'finish;
                }
                buf.push(chr);
            }
        }
        if !end_of_str {
            let d;
            match self.peek_data(align_end) {
                Ok(v) => d = v,
                Err(e) => return Err(e)
            }
            for word_idx in 0..mem::size_of::<Word>() {
                let chr = get_byte(d, word_idx);
                if chr == 0 {
                    break;
                }
                buf.push(chr);
            }
        }
        return Ok(buf);
    }
}

fn get_byte(d: Word, byte_idx: usize) -> u8 {
    assert!(byte_idx < mem::size_of::<Word>());
    ((d >> (byte_idx * 8)) & 0xff) as u8
}

fn set_byte(d: Word, byte_idx: usize, value: u8) -> Word {
    assert!(byte_idx < mem::size_of::<Word>());
    let shift = mem::size_of::<u8>() * 8 * byte_idx;
    let mask = 0xff << shift;
    (d & !mask) | (((value as Word) << shift) & mask)
}

#[test]
pub fn test_set_byte() {
    assert_eq!(set_byte(0, 0, 0), 0);
    assert_eq!(set_byte(0xffffffffffff, 0, 0xff), 0xffffffffffff);
    assert_eq!(set_byte(0xffffffffffff, 0, 0),    0xffffffffff00);
    assert_eq!(set_byte(0xffffffffffff, 0, 0xaa), 0xffffffffffaa);
    assert_eq!(set_byte(0xffffffffffff, 1, 0x00), 0xffffffff00ff);
    assert_eq!(set_byte(0xffffffffffff, 4, 0xaa), 0xffaaffffffff);
}

#[test]
pub fn test_get_byte() {
    assert_eq!(get_byte(0, 0), 0);
    assert_eq!(get_byte(0xffffffffffff, 0), 0xff);
    assert_eq!(get_byte(0xffffffffffaa, 0), 0xaa);
    assert_eq!(get_byte(0x0123456789ab, 1), 0x89);
    assert_eq!(get_byte(0x0123456789ab, 4), 0x23);
}
<|endoftext|>


<commit_before>//! Parse and write Iridium Short Burst Data (SBD) messages.
//!
//! Iridium is both a [satellite constellation](https://en.wikipedia.org/wiki/Iridium_satellite_constellation)
//! and a [company](https://en.wikipedia.org/wiki/Iridium_Communications) that provides satellite
//! communications. The Iridium network is used by phones, modems, and other communication devices.
//!
//! One mode of transmitting data over the Iridium network is via Short Burst Data (SBD) messages.
//! These messages carry a payload of some small number of bytes, usually less than one thousand.
//! Messages can be Mobile-Originated (MO), meaning that they are sent *from* an Iridium modem, or
//! Mobile-Terminated (MT), meaning that the are sent *to* an Iridium modem. Mobile-originated
//! messages are delivered either to an email address via MIME attachment, or directly to a given
//! IP address and port via TCP; this second method is called DirectIP.
//!
//! This is a simple library for reading mobile originated SBD messages from a stream, decoding
//! their headers and data payloads, and writing them back to a stream. This library does not
//! handle mobile terminated messages.
//!
//! Most of the functionality of this library is exposed by a single executable, named `sbd` that
//! is part of this package. Use the `sbd` executable to inspect raw sbd files stores on a
//! filesystem, discover sbd files on a filesystem, and start a forever-running server to receive
//! Iridium SBD DirectIP messages.

pub mod directip;
mod information_element;
pub mod logger;
pub mod filesystem;
pub mod message;

pub use message::Message;

extern crate byteorder;
extern crate chrono;
#[macro_use] extern crate enum_primitive;
extern crate glob;
#[macro_use] extern crate log;
extern crate num;

use std::result;

/// Crate-specific errors
#[derive(Debug)]
pub enum Error {
    /// An error while reading bytes from a stream with the byteorder crate.
    ByteorderError(byteorder::Error),
    /// A wrapper around a std::io::Error.
    IoError(std::io::Error),
    /// Invalid IMEI number.
    InvalidImei,
    /// Invalid protocol revision number.
    InvalidProtocolRevisionNumber(u8),
    /// Wrapper around a glob error.
    GlobError(glob::GlobError),
    /// Missing mobile originated header.
    MissingMobileOriginatedHeader,
    /// Missing mobile originated payload.
    MissingMobileOriginatedPayload,
    /// An oversized message.
    ///
    /// Oversized doesn't demand a size since we don't want to find out how much there really is.
    Oversized,
    /// Wrapper around a glob::PatternError.
    PatternError(glob::PatternError),
    /// An undersized message.
    Undersized(usize),
}

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        Error::ByteorderError(err)
    }
}

impl From<glob::PatternError> for Error {
    fn from(err: glob::PatternError) -> Error {
        Error::PatternError(err)
    }
}

impl From<glob::GlobError> for Error {
    fn from(err: glob::GlobError) -> Error {
        Error::GlobError(err)
    }
}

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

/// Create-specific `Result`.
pub type Result<T> = result::Result<T, Error>;
<commit_msg>Turn on a lot of warnings<commit_after>//! Parse and write Iridium Short Burst Data (SBD) messages.
//!
//! Iridium is both a [satellite constellation](https://en.wikipedia.org/wiki/Iridium_satellite_constellation)
//! and a [company](https://en.wikipedia.org/wiki/Iridium_Communications) that provides satellite
//! communications. The Iridium network is used by phones, modems, and other communication devices.
//!
//! One mode of transmitting data over the Iridium network is via Short Burst Data (SBD) messages.
//! These messages carry a payload of some small number of bytes, usually less than one thousand.
//! Messages can be Mobile-Originated (MO), meaning that they are sent *from* an Iridium modem, or
//! Mobile-Terminated (MT), meaning that the are sent *to* an Iridium modem. Mobile-originated
//! messages are delivered either to an email address via MIME attachment, or directly to a given
//! IP address and port via TCP; this second method is called DirectIP.
//!
//! This is a simple library for reading mobile originated SBD messages from a stream, decoding
//! their headers and data payloads, and writing them back to a stream. This library does not
//! handle mobile terminated messages.
//!
//! Most of the functionality of this library is exposed by a single executable, named `sbd` that
//! is part of this package. Use the `sbd` executable to inspect raw sbd files stores on a
//! filesystem, discover sbd files on a filesystem, and start a forever-running server to receive
//! Iridium SBD DirectIP messages.

#![deny(missing_copy_implementations, missing_debug_implementations, missing_docs, trivial_casts,
        trivial_numeric_casts, unsafe_code, unstable_features, unused_extern_crates,
        unused_import_braces, unused_qualifications)]

pub mod directip;
mod information_element;
pub mod logger;
pub mod filesystem;
pub mod message;

pub use message::Message;

extern crate byteorder;
extern crate chrono;
#[macro_use] extern crate enum_primitive;
extern crate glob;
#[macro_use] extern crate log;
extern crate num;

use std::result;

/// Crate-specific errors
#[derive(Debug)]
pub enum Error {
    /// An error while reading bytes from a stream with the byteorder crate.
    ByteorderError(byteorder::Error),
    /// A wrapper around a std::io::Error.
    IoError(std::io::Error),
    /// Invalid IMEI number.
    InvalidImei,
    /// Invalid protocol revision number.
    InvalidProtocolRevisionNumber(u8),
    /// Wrapper around a glob error.
    GlobError(glob::GlobError),
    /// Missing mobile originated header.
    MissingMobileOriginatedHeader,
    /// Missing mobile originated payload.
    MissingMobileOriginatedPayload,
    /// An oversized message.
    ///
    /// Oversized doesn't demand a size since we don't want to find out how much there really is.
    Oversized,
    /// Wrapper around a glob::PatternError.
    PatternError(glob::PatternError),
    /// An undersized message.
    Undersized(usize),
}

impl From<byteorder::Error> for Error {
    fn from(err: byteorder::Error) -> Error {
        Error::ByteorderError(err)
    }
}

impl From<glob::PatternError> for Error {
    fn from(err: glob::PatternError) -> Error {
        Error::PatternError(err)
    }
}

impl From<glob::GlobError> for Error {
    fn from(err: glob::GlobError) -> Error {
        Error::GlobError(err)
    }
}

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

/// Create-specific `Result`.
pub type Result<T> = result::Result<T, Error>;
<|endoftext|>


<commit_before>#![crate_type = "lib"]

#![crate_name = "histogram"]

/*
	This crate is inspired by HdrHistogram
*/

#[test]
fn it_works() {
}

<commit_msg>building out functions<commit_after>#![crate_type = "lib"]

#![crate_name = "histogram"]

/*
	This crate is inspired by HdrHistogram.

	WORK IN PROGRESS
*/

use std::collections::HashMap;

pub struct Histogram {
    total: u64,
    data: HashMap<u64, u64>
}

impl Histogram {
    /// return nil or empty Histogram
    pub fn nil() -> Histogram {
        Histogram {
            total: 0,
            data: HashMap::new(),
        }
    }

    /// return a new Histogram
    pub fn new() -> Option<Histogram> {
        let histogram = Histogram::nil();
        Some(histogram)
    }

    pub fn store(&mut self, value: u64) {
        self.total += 1;
        let count = self.data.entry(value).or_insert(0);
        *count += 1;
    }

    pub fn bucket_count(&mut self, value: u64) -> u64 {
        let key: u64 = value;
        let count = self.data.get(&key);
        match count {
            Some(v) => *v,
            None => 0,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Histogram};

    #[test]
    fn it_works() {
    }

    #[test]
    fn test_nil() {
        let nil = Histogram::nil();

        assert!(nil.total == 0);
    }

    #[test]
    fn test_new() {
        let histogram = Histogram::new().unwrap();

        assert!(histogram.total == 0);
    }

    #[test]
    fn test_store() {
        let mut histogram = Histogram::new().unwrap();

        histogram.store(0);
        assert!(histogram.total == 1);
        histogram.store(0);
        assert!(histogram.total == 2);
    }

    #[test]
    fn test_get_count() {
        let mut histogram = Histogram::new().unwrap();

        histogram.store(0);
        assert!(histogram.bucket_count(0) == 1);

        histogram.store(0);
        assert!(histogram.bucket_count(0) == 2);

        histogram.store(1);
        assert!(histogram.bucket_count(1) == 1);

        assert!(histogram.bucket_count(2) == 0);
    }
}
<|endoftext|>


<commit_before>//! Temporal quantification using floating-point quantities.
//!
//! This crate provides quantification for spans of time. Unlike the standard
//! [`std::time`](https://doc.rust-lang.org/std/time/index.html) or the
//! [chrono](https://crates.io/crates/chrono) crate, this crate aims
//! to provide a fully featured Duration type which exposes and uses floating-point
//! values instead of integer ones.
//!
//! The existing solutions for time spans are high precision and good for displaying
//! and storing time values, but they are less than convenient to use in simulations or
//! mathematical contexts where a single fractional value in some unit is needed. Thus,
//! this crate was developed in order to fill that need while being maximally compatible
//! with the existing time libraries and not re-inventing the wheel. The interface aims to
//! be very similar to these libraries, just using floating point values so it may be
//! used as a near drop-in replacement for existing programs that
//! would benefit from floating point durations.
//!
//! The goal is to provide a type with the same set of features and flexibility as
//! `std::chrono::duration` in C++ while being "Rusty" in design.
//!
//! # Usage
//! Put this in your `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! float_duration = "0.1"
//! ```
//! # Overview
//!
//! This crate provides a single primary type:
//! [`FloatDuration`](duration/struct.FloatDuration.html) which represents an
//! arbitrary distance in time with no defined start or end point.
//! Internally, it stores a single `f64` holding the number of seconds the duration
//! represents, which can be negative for a "backward" duration. It provides accessors
//! methods to create and read the value in various units, as well as `impl`s for many
//! arithmetic operators in `std::ops`.
//!
//! ```rust
//! # use float_duration::*;
//! let timespan = FloatDuration::hours(2.5) + FloatDuration::seconds(30.0);
//! assert_eq!(timespan, FloatDuration::seconds(9030.0));
//! assert_eq!(timespan, FloatDuration::minutes(150.5));
//! ```
//! Additionally, a [`TimePoint`](duration/trait.TimePoint.html) trait is provided
//! for computing a `FloatDuration` between two objects representing a point in time.
//!
//! # Example Usage
//!
//! Compute the number of blocks in a larger interval:
//!
//! ```rust
//! use float_duration::FloatDuration;
//!
//! let time_block = FloatDuration::minutes(5.0);
//! let blocks_per_hour = FloatDuration::hours(1.0) / time_block;
//!
//! assert_eq!(blocks_per_hour, 12.0);
//! ```
//!
//! Perform a basic numerical integration of a mass on a spring:
//!
//! ```rust
//! use float_duration::FloatDuration;
//!
//! fn acceleration(m: f64, x: f64, t: FloatDuration) -> f64 {
//!     0.5*m*x*x
//! }
//!
//! fn main() {
//!     let mut sim_time = FloatDuration::zero();
//!     let end_time = FloatDuration::minutes(2.0);
//!     let dt = FloatDuration::milliseconds(50.0);
//!
//!     let mut x = 2.0;
//!     let mut v = 0.0;
//!     let m = 1.0;
//!
//!     while sim_time < end_time {
//!         let acc = acceleration(m, x, sim_time);
//!         v += acc*dt.as_seconds();
//!         x += v*dt.as_seconds();
//!         sim_time += dt;
//!     }
//! }
//! ```
//!
//! # Library Support
//!
//! Currently `float_duration` can be compiled without any dependencies, but it
//! provides optional features for interfacing with other libraries.
//!
//! ## std::time
//! The `std::time` module is supported and `FloatDuration`
//! can be used directly with `SystemTime` and `Instant`:
//!
//! ```rust
//! // TimePoint needed for `float_duration_since`.
//! use float_duration::{FloatDuration, TimePoint};
//! use std::time::{Instant, SystemTime};
//!
//!
//! let start_time = Instant::now();
//! //Do lengthy operation...
//! let end_time = Instant::now();
//!
//! println!("Took {}.", end_time.float_duration_since(start_time).unwrap());
//! ```
//!
//! `FloatDuration` may also be converted to/from `std::time::Duration` via the
//! `to_std` and `from_std` methods.
//!
//! ## [approx](https://crates.io/crates/approx)
//! `FloatDuration` provides an implementation of `approx::ApproxEq`
//! for near-equality comparisons of `FloatDuration` if the `approx` feature is enabled.
//! Since `FloatDuration` uses floating point values, this should be the
//! preferred way to establish equality between two duration objects.
//!
//! ## [chrono](https://crates.io/crates/chrono)
//!
//! Similar to `std::time`, computing a `FloatDuration` between any two of the same type of
//! date or time objects
//! is supported via `TimePoint` trait impls, assuming the feature
//! "chrono" is enabled.
//! Additionally, `FloatDuration` objects can be converted to/from
//! `chrono::Duration` objects via the `to_chrono` and `from_chrono` methods.

#[cfg(feature = "chrono")]
extern crate chrono;
#[cfg(feature = "time")]
extern crate time;
#[cfg(feature = "approx")]
extern crate approx;
#[cfg(feature = "serde")]
extern crate serde;
#[cfg(all(test, feature = "serde"))]
extern crate serde_test;

pub mod duration;
pub mod error;

pub use duration::{FloatDuration, TimePoint};
pub use error::OutOfRangeError;
<commit_msg>Added a section to crate level docs about serde support.<commit_after>//! Temporal quantification using floating-point quantities.
//!
//! This crate provides quantification for spans of time. Unlike the standard
//! [`std::time`](https://doc.rust-lang.org/std/time/index.html) or the
//! [chrono](https://crates.io/crates/chrono) crate, this crate aims
//! to provide a fully featured Duration type which exposes and uses floating-point
//! values instead of integer ones.
//!
//! The existing solutions for time spans are high precision and good for displaying
//! and storing time values, but they are less than convenient to use in simulations or
//! mathematical contexts where a single fractional value in some unit is needed. Thus,
//! this crate was developed in order to fill that need while being maximally compatible
//! with the existing time libraries and not re-inventing the wheel. The interface aims to
//! be very similar to these libraries, just using floating point values so it may be
//! used as a near drop-in replacement for existing programs that
//! would benefit from floating point durations.
//!
//! The goal is to provide a type with the same set of features and flexibility as
//! `std::chrono::duration` in C++ while being "Rusty" in design.
//!
//! # Usage
//! Put this in your `Cargo.toml`:
//!
//! ```ignore
//! [dependencies]
//! float_duration = "0.1"
//! ```
//! # Overview
//!
//! This crate provides a single primary type:
//! [`FloatDuration`](duration/struct.FloatDuration.html) which represents an
//! arbitrary distance in time with no defined start or end point.
//! Internally, it stores a single `f64` holding the number of seconds the duration
//! represents, which can be negative for a "backward" duration. It provides accessors
//! methods to create and read the value in various units, as well as `impl`s for many
//! arithmetic operators in `std::ops`.
//!
//! ```rust
//! # use float_duration::*;
//! let timespan = FloatDuration::hours(2.5) + FloatDuration::seconds(30.0);
//! assert_eq!(timespan, FloatDuration::seconds(9030.0));
//! assert_eq!(timespan, FloatDuration::minutes(150.5));
//! ```
//! Additionally, a [`TimePoint`](duration/trait.TimePoint.html) trait is provided
//! for computing a `FloatDuration` between two objects representing a point in time.
//!
//! # Example Usage
//!
//! Compute the number of blocks in a larger interval:
//!
//! ```rust
//! use float_duration::FloatDuration;
//!
//! let time_block = FloatDuration::minutes(5.0);
//! let blocks_per_hour = FloatDuration::hours(1.0) / time_block;
//!
//! assert_eq!(blocks_per_hour, 12.0);
//! ```
//!
//! Perform a basic numerical integration of a mass on a spring:
//!
//! ```rust
//! use float_duration::FloatDuration;
//!
//! fn acceleration(m: f64, x: f64, t: FloatDuration) -> f64 {
//!     0.5*m*x*x
//! }
//!
//! fn main() {
//!     let mut sim_time = FloatDuration::zero();
//!     let end_time = FloatDuration::minutes(2.0);
//!     let dt = FloatDuration::milliseconds(50.0);
//!
//!     let mut x = 2.0;
//!     let mut v = 0.0;
//!     let m = 1.0;
//!
//!     while sim_time < end_time {
//!         let acc = acceleration(m, x, sim_time);
//!         v += acc*dt.as_seconds();
//!         x += v*dt.as_seconds();
//!         sim_time += dt;
//!     }
//! }
//! ```
//!
//! # Library Support
//!
//! Currently `float_duration` can be compiled without any dependencies, but it
//! provides optional features for interfacing with other libraries.
//!
//! ## std::time
//! The `std::time` module is supported and `FloatDuration`
//! can be used directly with `SystemTime` and `Instant`:
//!
//! ```rust
//! // TimePoint needed for `float_duration_since`.
//! use float_duration::{FloatDuration, TimePoint};
//! use std::time::{Instant, SystemTime};
//!
//!
//! let start_time = Instant::now();
//! //Do lengthy operation...
//! let end_time = Instant::now();
//!
//! println!("Took {}.", end_time.float_duration_since(start_time).unwrap());
//! ```
//!
//! `FloatDuration` may also be converted to/from `std::time::Duration` via the
//! `to_std` and `from_std` methods.
//!
//! ## [approx](https://crates.io/crates/approx)
//! `FloatDuration` provides an implementation of `approx::ApproxEq`
//! for near-equality comparisons of `FloatDuration` if the `approx` feature is enabled.
//! Since `FloatDuration` uses floating point values, this should be the
//! preferred way to establish equality between two duration objects.
//!
//! ## [chrono](https://crates.io/crates/chrono)
//!
//! Similar to `std::time`, computing a `FloatDuration` between any two of the same type of
//! date or time objects
//! is supported via `TimePoint` trait impls, assuming the feature
//! "chrono" is enabled.
//! Additionally, `FloatDuration` objects can be converted to/from
//! `chrono::Duration` objects via the `to_chrono` and `from_chrono` methods.
//!
//! ## [serde](https://crates.io/crates/serde)
//!
//! `FloatDuration` supports serialization with `serde`. Presently, a `FloatDuration`
//! is serialized to a single `f64` value representing the number of seconds in the
//! duration.

#[cfg(feature = "chrono")]
extern crate chrono;
#[cfg(feature = "time")]
extern crate time;
#[cfg(feature = "approx")]
extern crate approx;
#[cfg(feature = "serde")]
extern crate serde;
#[cfg(all(test, feature = "serde"))]
extern crate serde_test;

pub mod duration;
pub mod error;

pub use duration::{FloatDuration, TimePoint};
pub use error::OutOfRangeError;
<|endoftext|>


<commit_before>//! Hubcaps provides a set of building blocks for interacting with the Github API

#[macro_use]
extern crate serializable_enum;
#[macro_use]
extern crate log;
extern crate hyper;
extern crate serde;
extern crate serde_json;
extern crate url;

use serde::de::Deserialize;
pub mod keys;
pub mod gists;
pub mod deployments;
pub mod errors;
pub mod issues;
pub mod labels;
pub mod rep;
pub mod releases;
pub mod repositories;
pub mod statuses;
pub mod pulls;

pub use rep::*;
pub use errors::Error;
use gists::{Gists, UserGists};
use hyper::Client;
use hyper::client::RequestBuilder;
use hyper::method::Method;
use hyper::header::{Authorization, ContentLength, UserAgent};
use hyper::status::StatusCode;
use repositories::{Repository, Repositories, UserRepositories};
use std::fmt;
use std::io::Read;
use url::Url;

const DEFAULT_HOST: &'static str = "https://api.github.com";

/// alias for Result that infers hubcaps::Error as Err
pub type Result<T> = std::result::Result<T, Error>;

/// enum representation of github pull and issue state
#[derive(Clone, Debug, PartialEq)]
pub enum State {
    /// Only open issues
    Open,
    /// Only closed issues
    Closed,
    /// All issues, open or closed
    All,
}

impl fmt::Display for State {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}",
               match *self {
                   State::Open => "open",
                   State::Closed => "closed",
                   State::All => "all",
               })
    }
}

impl Default for State {
    fn default() -> State {
        State::Open
    }
}

/// enum representation of Github list sorting options
#[derive(Clone, Debug, PartialEq)]
pub enum SortDirection {
    /// Sort in ascending order
    Asc,
    /// Sort in descending order
    Desc,
}

impl fmt::Display for SortDirection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}",
               match *self {
                   SortDirection::Asc => "asc",
                   SortDirection::Desc => "desc",
               })
    }
}

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

/// Various forms of authentication credentials supported by Github
pub enum Credentials {
    /// No authentication
    None,
    /// Oauth token string
    /// https://developer.github.com/v3/#oauth2-token-sent-in-a-header
    Token(String),
    /// Oauth client id and secret
    /// https://developer.github.com/v3/#oauth2-keysecret
    Client(String, String)
}

impl Default for Credentials {
    fn default() -> Credentials {
        Credentials::None
    }
}

/// Entry point interface for interacting with Github API
pub struct Github<'a> {
    host: String,
    agent: String,
    client: &'a Client,
    credentials: Credentials
}

impl<'a> Github<'a> {
    /// Create a new Github instance
    pub fn new<A>(agent: A, client: &'a Client, credentials: Credentials) -> Github<'a>
        where A: Into<String>
    {
        Github::host(DEFAULT_HOST, agent, client, credentials)
    }

    /// Create a new Github instance hosted at a custom location.
    /// Useful for github enterprise installations ( yourdomain.com/api/v3/ )
    pub fn host<H, A>(host: H, agent: A, client: &'a Client, credentials: Credentials) -> Github<'a>
        where H: Into<String>,
              A: Into<String>
    {
        Github {
            host: host.into(),
            agent: agent.into(),
            client: client,
            credentials: credentials
        }
    }

    /// Return a reference to a Github reposistory
    pub fn repo<O, R>(&self, owner: O, repo: R) -> Repository
        where O: Into<String>,
              R: Into<String>
    {
        Repository::new(self, owner, repo)
    }

    /// Return a reference to the collection of repositories owned by an
    /// associated with an owner
    pub fn user_repos<S>(&self, owner: S) -> UserRepositories
        where S: Into<String>
    {
        UserRepositories::new(self, owner)
    }

    /// Return a reference to  the collection of repositores owned by the user
    /// associated with the current authentication credentials
    pub fn repos(&self) -> Repositories {
        Repositories::new(self)
    }

    /// Return a reference to an interface that provides access to a user's gists
    pub fn user_gists<O>(&self, owner: O) -> UserGists
        where O: Into<String>
    {
        UserGists::new(self, owner)
    }

    /// Return a reference to an interface that provides access to the
    /// gists belonging to the owner of the token used to configure this client
    pub fn gists(&self) -> Gists {
        Gists::new(self)
    }

    fn authenticate(&self, method: Method, uri: &str) -> RequestBuilder {
        let url = format!("{}{}", self.host, uri);
        match self.credentials {
            Credentials::Token(ref token) =>
                self.client.request(method, &url).header(
                    Authorization(
                        format!("token {}", token)
                            )
                        ),
            Credentials::Client(ref id, ref secret) => {
                let mut parsed = Url::parse(&url).unwrap();
                let mut query = parsed.query_pairs().unwrap_or(vec![]);
                query.push(("client_id".to_owned(), id.to_owned()));
                query.push(("client_secret".to_owned(), secret.to_owned()));
                parsed.set_query_from_pairs(query);
                self.client.request(method, parsed)
            },
            Credentials::None => self.client.request(method, &url)
        }
    }

    fn request<D>(&self, method: Method, uri: &str, body: Option<&'a [u8]>) -> Result<D>
        where D: Deserialize
    {
        let builder = self.authenticate(method, uri).header(UserAgent(self.agent.to_owned()));
        let mut res = try!(match body {
            Some(ref bod) => builder.body(*bod).send(),
            _ => builder.send(),
        });
        let mut body = match res.headers.clone().get::<ContentLength>() {
            Some(&ContentLength(len)) => String::with_capacity(len as usize),
            _ => String::new(),
        };
        try!(res.read_to_string(&mut body));
        debug!("rev response {:#?} {:#?} {:#?}", res.status, res.headers, body);
        match res.status {
            StatusCode::Conflict |
            StatusCode::BadRequest |
            StatusCode::UnprocessableEntity |
            StatusCode::Unauthorized |
            StatusCode::NotFound |
            StatusCode::Forbidden => {
                Err(Error::Fault {
                    code: res.status,
                    error: try!(serde_json::from_str::<ClientError>(&body)),
                })
            }
            _ => Ok(try!(serde_json::from_str::<D>(&body))),
        }
    }

    fn get<D>(&self, uri: &str) -> Result<D>
        where D: Deserialize
    {
        self.request(Method::Get, uri, None)
    }

    fn delete(&self, uri: &str) -> Result<()> {
        match self.request::<()>(Method::Delete, uri, None) {
            Err(Error::Codec(_)) => Ok(()),
            otherwise => otherwise,
        }
    }

    fn post<D>(&self, uri: &str, message: &[u8]) -> Result<D>
        where D: Deserialize
    {
        self.request(Method::Post, uri, Some(message))
    }

    fn patch<D>(&self, uri: &str, message: &[u8]) -> Result<D>
        where D: Deserialize
    {
        self.request(Method::Patch, uri, Some(message))
    }

    fn put<D>(&self, uri: &str, message: &[u8]) -> Result<D>
        where D: Deserialize
    {
        self.request(Method::Put, uri, Some(message))
    }
}

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

    #[test]
    fn default_state() {
        let default: State = Default::default();
        assert_eq!(default, State::Open)
    }

    #[test]
    fn default_sort_direction() {
        let default: SortDirection = Default::default();
        assert_eq!(default, SortDirection::Asc)
    }
}
<commit_msg>test something<commit_after>//! Hubcaps provides a set of building blocks for interacting with the Github API

#[macro_use]
extern crate serializable_enum;
#[macro_use]
extern crate log;
extern crate hyper;
extern crate serde;
extern crate serde_json;
extern crate url;

use serde::de::Deserialize;
pub mod keys;
pub mod gists;
pub mod deployments;
pub mod errors;
pub mod issues;
pub mod labels;
pub mod rep;
pub mod releases;
pub mod repositories;
pub mod statuses;
pub mod pulls;

pub use rep::*;
pub use errors::Error;
use gists::{Gists, UserGists};
use hyper::Client;
use hyper::client::RequestBuilder;
use hyper::method::Method;
use hyper::header::{Authorization, ContentLength, UserAgent};
use hyper::status::StatusCode;
use repositories::{Repository, Repositories, UserRepositories};
use std::fmt;
use std::io::Read;
use url::Url;

const DEFAULT_HOST: &'static str = "https://api.github.com";

/// alias for Result that infers hubcaps::Error as Err
pub type Result<T> = std::result::Result<T, Error>;

/// enum representation of github pull and issue state
#[derive(Clone, Debug, PartialEq)]
pub enum State {
    /// Only open issues
    Open,
    /// Only closed issues
    Closed,
    /// All issues, open or closed
    All,
}

impl fmt::Display for State {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}",
               match *self {
                   State::Open => "open",
                   State::Closed => "closed",
                   State::All => "all",
               })
    }
}

impl Default for State {
    fn default() -> State {
        State::Open
    }
}

/// enum representation of Github list sorting options
#[derive(Clone, Debug, PartialEq)]
pub enum SortDirection {
    /// Sort in ascending order
    Asc,
    /// Sort in descending order
    Desc,
}

impl fmt::Display for SortDirection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}",
               match *self {
                   SortDirection::Asc => "asc",
                   SortDirection::Desc => "desc",
               })
    }
}

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

/// Various forms of authentication credentials supported by Github
#[derive(Debug, PartialEq)]
pub enum Credentials {
    /// No authentication
    None,
    /// Oauth token string
    /// https://developer.github.com/v3/#oauth2-token-sent-in-a-header
    Token(String),
    /// Oauth client id and secret
    /// https://developer.github.com/v3/#oauth2-keysecret
    Client(String, String)
}

impl Default for Credentials {
    fn default() -> Credentials {
        Credentials::None
    }
}

/// Entry point interface for interacting with Github API
pub struct Github<'a> {
    host: String,
    agent: String,
    client: &'a Client,
    credentials: Credentials
}

impl<'a> Github<'a> {
    /// Create a new Github instance
    pub fn new<A>(agent: A, client: &'a Client, credentials: Credentials) -> Github<'a>
        where A: Into<String>
    {
        Github::host(DEFAULT_HOST, agent, client, credentials)
    }

    /// Create a new Github instance hosted at a custom location.
    /// Useful for github enterprise installations ( yourdomain.com/api/v3/ )
    pub fn host<H, A>(host: H, agent: A, client: &'a Client, credentials: Credentials) -> Github<'a>
        where H: Into<String>,
              A: Into<String>
    {
        Github {
            host: host.into(),
            agent: agent.into(),
            client: client,
            credentials: credentials
        }
    }

    /// Return a reference to a Github reposistory
    pub fn repo<O, R>(&self, owner: O, repo: R) -> Repository
        where O: Into<String>,
              R: Into<String>
    {
        Repository::new(self, owner, repo)
    }

    /// Return a reference to the collection of repositories owned by an
    /// associated with an owner
    pub fn user_repos<S>(&self, owner: S) -> UserRepositories
        where S: Into<String>
    {
        UserRepositories::new(self, owner)
    }

    /// Return a reference to  the collection of repositores owned by the user
    /// associated with the current authentication credentials
    pub fn repos(&self) -> Repositories {
        Repositories::new(self)
    }

    /// Return a reference to an interface that provides access to a user's gists
    pub fn user_gists<O>(&self, owner: O) -> UserGists
        where O: Into<String>
    {
        UserGists::new(self, owner)
    }

    /// Return a reference to an interface that provides access to the
    /// gists belonging to the owner of the token used to configure this client
    pub fn gists(&self) -> Gists {
        Gists::new(self)
    }

    fn authenticate(&self, method: Method, uri: &str) -> RequestBuilder {
        let url = format!("{}{}", self.host, uri);
        match self.credentials {
            Credentials::Token(ref token) =>
                self.client.request(method, &url).header(
                    Authorization(
                        format!("token {}", token)
                            )
                        ),
            Credentials::Client(ref id, ref secret) => {
                let mut parsed = Url::parse(&url).unwrap();
                let mut query = parsed.query_pairs().unwrap_or(vec![]);
                query.push(("client_id".to_owned(), id.to_owned()));
                query.push(("client_secret".to_owned(), secret.to_owned()));
                parsed.set_query_from_pairs(query);
                self.client.request(method, parsed)
            },
            Credentials::None => self.client.request(method, &url)
        }
    }

    fn request<D>(&self, method: Method, uri: &str, body: Option<&'a [u8]>) -> Result<D>
        where D: Deserialize
    {
        let builder = self.authenticate(method, uri).header(UserAgent(self.agent.to_owned()));
        let mut res = try!(match body {
            Some(ref bod) => builder.body(*bod).send(),
            _ => builder.send(),
        });
        let mut body = match res.headers.clone().get::<ContentLength>() {
            Some(&ContentLength(len)) => String::with_capacity(len as usize),
            _ => String::new(),
        };
        try!(res.read_to_string(&mut body));
        debug!("rev response {:#?} {:#?} {:#?}", res.status, res.headers, body);
        match res.status {
            StatusCode::Conflict |
            StatusCode::BadRequest |
            StatusCode::UnprocessableEntity |
            StatusCode::Unauthorized |
            StatusCode::NotFound |
            StatusCode::Forbidden => {
                Err(Error::Fault {
                    code: res.status,
                    error: try!(serde_json::from_str::<ClientError>(&body)),
                })
            }
            _ => Ok(try!(serde_json::from_str::<D>(&body))),
        }
    }

    fn get<D>(&self, uri: &str) -> Result<D>
        where D: Deserialize
    {
        self.request(Method::Get, uri, None)
    }

    fn delete(&self, uri: &str) -> Result<()> {
        match self.request::<()>(Method::Delete, uri, None) {
            Err(Error::Codec(_)) => Ok(()),
            otherwise => otherwise,
        }
    }

    fn post<D>(&self, uri: &str, message: &[u8]) -> Result<D>
        where D: Deserialize
    {
        self.request(Method::Post, uri, Some(message))
    }

    fn patch<D>(&self, uri: &str, message: &[u8]) -> Result<D>
        where D: Deserialize
    {
        self.request(Method::Patch, uri, Some(message))
    }

    fn put<D>(&self, uri: &str, message: &[u8]) -> Result<D>
        where D: Deserialize
    {
        self.request(Method::Put, uri, Some(message))
    }
}

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

    #[test]
    fn default_state() {
        let default: State = Default::default();
        assert_eq!(default, State::Open)
    }

    #[test]
    fn default_sort_direction() {
        let default: SortDirection = Default::default();
        assert_eq!(default, SortDirection::Asc)
    }

    #[test]
    fn default_credentials() {
        let default: Credentials = Default::default();
        assert_eq!(default, Credentials::None)
    }
}
<|endoftext|>