<commit_before>//! **Plexus** is a library for 2D and 3D mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable! Use exact version constraints when specifying a dependency to
//! avoid spurious breakage.
#![allow(unknown_lints)] // Allow clippy lints.

extern crate arrayvec;
#[cfg(feature = "geometry-cgmath")]
extern crate cgmath;
extern crate decorum;
#[macro_use]
extern crate derivative;
extern crate either;
#[macro_use]
extern crate failure;
extern crate fnv;
extern crate fool;
#[macro_use]
extern crate itertools;
#[cfg(feature = "geometry-mint")]
extern crate mint;
#[cfg(feature = "geometry-nalgebra")]
extern crate nalgebra;
extern crate num;
extern crate smallvec;
extern crate typenum;

use decorum::Real;
use num::{One, Zero};
use std::fmt::Debug;
use std::ops::Div;

pub mod buffer;
pub mod geometry;
pub mod graph;
pub mod index;
pub mod primitive;

// TODO: Documentation comments include static image content from the GitHub
//       repository. This is fragile and difficult to maintain. Use a mechanism
//       provided by rustdoc or doxidize for this instead.

pub mod prelude {
    //! Re-exports commonly used types and traits.
    //!
    //! Importing the contents of this module is recommended when working with
    //! generators and iterator expressions, as those operations are expressed
    //! mostly through traits.
    //!
    //! # Traits
    //!
    //! This module re-exports numerous traits. Traits from the `primitive`
    //! module for generating, decomposing, and indexing iterators over
    //! topological data (e.g., `Triangle`, `Quad`, etc.) are re-exported so
    //! that functions in iterator expressions can be used without lengthy
    //! imports.
    //!
    //! Basic traits for (de)constructing `MeshBuffer`s and `MeshGraph`s are
    //! also re-exported. These traits allow mesh types to be constructed from
    //! raw buffers and buffers to be re-indexed.
    //!
    //! # Types
    //!
    //! The `Selector` enum and its variants are re-exported for convenience.
    //! `Selector` is often used when mutating `MeshGraph`s.
    //!
    //! The geometric `Duplet` and `Triplet` types are also re-exported. These
    //! types are emitted by generators and support various conversions.

    pub use crate::buffer::{IntoFlatIndex as _, IntoStructuredIndex as _};
    pub use crate::geometry::{Duplet, Triplet};
    pub use crate::graph::Selector;
    pub use crate::index::{CollectWithIndexer as _, OpenIndexVertices as _};
    pub use crate::primitive::decompose::{
        Edges as _, IntoEdges as _, IntoSubdivisions as _, IntoTetrahedrons as _,
        IntoTriangles as _, IntoVertices as _, Subdivide as _, Tetrahedrons as _, Triangulate as _,
        Vertices as _,
    };
    pub use crate::primitive::generate::{
        IndicesForNormal as _, IndicesForPosition as _, PolygonGenerator as _,
        PolygonsWithNormal as _, PolygonsWithPosition as _, PolygonsWithUvMap as _,
        VerticesWithNormal as _, VerticesWithPosition as _,
    };
    pub use crate::primitive::{Converged as _, Map as _, MapVertices as _, Zip as _};
    pub use crate::IteratorExt as _;
    pub use crate::{FromRawBuffers as _, FromRawBuffersWithArity as _};

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub trait FromRawBuffers<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers<I, J>(indices: I, vertices: J) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

pub trait FromRawBuffersWithArity<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers_with_arity<I, J>(
        indices: I,
        vertices: J,
        arity: usize,
    ) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection with ordered elements `a`, `b`, and `c`, this
    /// iterator yeilds the ordered items `(a, b)`, `(b, c)`, `(c, a)`.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone;
}

impl<I> IteratorExt for I
where
    I: Iterator,
{
    fn perimeter(self) -> Perimeter<I>
    where
        I::Item: Clone,
    {
        Perimeter::new(self)
    }
}

pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

impl<I> Iterator for Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}

trait Half {
    fn half() -> Self;
}

impl<T> Half for T
where
    T: Div<T, Output = T> + One + Real + Zero,
{
    fn half() -> Self {
        let one = T::one();
        one / (one + one)
    }
}
<commit_msg>Update documentation.<commit_after>//! **Plexus** is a library for 2D and 3D mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable! Use exact version constraints when specifying a dependency to
//! avoid spurious breakage.
#![allow(unknown_lints)] // Allow clippy lints.

extern crate arrayvec;
#[cfg(feature = "geometry-cgmath")]
extern crate cgmath;
extern crate decorum;
#[macro_use]
extern crate derivative;
extern crate either;
#[macro_use]
extern crate failure;
extern crate fnv;
extern crate fool;
#[macro_use]
extern crate itertools;
#[cfg(feature = "geometry-mint")]
extern crate mint;
#[cfg(feature = "geometry-nalgebra")]
extern crate nalgebra;
extern crate num;
extern crate smallvec;
extern crate typenum;

use decorum::Real;
use num::{One, Zero};
use std::fmt::Debug;
use std::ops::Div;

pub mod buffer;
pub mod geometry;
pub mod graph;
pub mod index;
pub mod primitive;

// TODO: Documentation comments include static image content from the GitHub
//       repository. This is fragile and difficult to maintain. Use a mechanism
//       provided by rustdoc or doxidize for this instead.

pub mod prelude {
    //! Re-exports commonly used types and traits.
    //!
    //! Importing the contents of this module is recommended when working with
    //! generators and iterator expressions, as those operations are expressed
    //! mostly through traits.
    //!
    //! # Traits
    //!
    //! This module re-exports numerous traits. Traits from the `primitive`
    //! module for generating and decomposing iterators over topological data
    //! (e.g., `Triangle`, `Quad`, etc.) are re-exported so that functions in
    //! iterator expressions can be used without lengthy imports.
    //!
    //! Basic traits for (de)constructing `MeshBuffer`s and `MeshGraph`s are
    //! also re-exported. These traits allow mesh types to be constructed from
    //! raw buffers and buffers to be re-indexed.
    //!
    //! # Types
    //!
    //! The `Selector` enum and its variants are re-exported for convenience.
    //! `Selector` is often used when mutating `MeshGraph`s.
    //!
    //! The geometric `Duplet` and `Triplet` types are also re-exported. These
    //! types are emitted by generators and support various conversions.

    pub use crate::buffer::{IntoFlatIndex as _, IntoStructuredIndex as _};
    pub use crate::geometry::{Duplet, Triplet};
    pub use crate::graph::Selector;
    pub use crate::index::{CollectWithIndexer as _, OpenIndexVertices as _};
    pub use crate::primitive::decompose::{
        Edges as _, IntoEdges as _, IntoSubdivisions as _, IntoTetrahedrons as _,
        IntoTriangles as _, IntoVertices as _, Subdivide as _, Tetrahedrons as _, Triangulate as _,
        Vertices as _,
    };
    pub use crate::primitive::generate::{
        IndicesForNormal as _, IndicesForPosition as _, PolygonGenerator as _,
        PolygonsWithNormal as _, PolygonsWithPosition as _, PolygonsWithUvMap as _,
        VerticesWithNormal as _, VerticesWithPosition as _,
    };
    pub use crate::primitive::{Converged as _, Map as _, MapVertices as _, Zip as _};
    pub use crate::IteratorExt as _;
    pub use crate::{FromRawBuffers as _, FromRawBuffersWithArity as _};

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub trait FromRawBuffers<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers<I, J>(indices: I, vertices: J) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

pub trait FromRawBuffersWithArity<N, G>: Sized {
    type Error: Debug;

    fn from_raw_buffers_with_arity<I, J>(
        indices: I,
        vertices: J,
        arity: usize,
    ) -> Result<Self, Self::Error>
    where
        I: IntoIterator<Item = N>,
        J: IntoIterator<Item = G>;
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection with ordered elements `a`, `b`, and `c`, this
    /// iterator yeilds the ordered items `(a, b)`, `(b, c)`, `(c, a)`.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone;
}

impl<I> IteratorExt for I
where
    I: Iterator,
{
    fn perimeter(self) -> Perimeter<I>
    where
        I::Item: Clone,
    {
        Perimeter::new(self)
    }
}

pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

impl<I> Iterator for Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}

trait Half {
    fn half() -> Self;
}

impl<T> Half for T
where
    T: Div<T, Output = T> + One + Real + Zero,
{
    fn half() -> Self {
        let one = T::one();
        one / (one + one)
    }
}
<|endoftext|>


<commit_before>// Future TimeSteward API goals:
//
// – groups
// I made up API functions for this before, but I'm not sure they were perfect.
// We can use RowId's for group ids, but what kinds of things can be stored IN a group? Previously I said only RowId's could, which doesn't seem ideal. I think it would work to allow anything hashable. That would basically make a group behave like a HashSet. But then, why not make it behave like a HashMap instead? But accessor itself already behaves like a HashMap over RowId's – the essential thing groups do is to allow iterating particular subsets of that HashMap.
//
// – conveniences for serializing snapshots (not sure what)
//
// – be able to construct a new TimeSteward from any snapshot
// Issues: should snapshots expose the predictors? Also, the predictors can't be serialized. So you'd probably actually have to construct a TimeSteward from snapshot + predictors. This requires a way to iterate all fields (and group data if we add groups) in a snapshot, which is similar to the previous 2 items (iterating the whole set, which is a special case of iterating a subset; and serializing requires you to iterate everything as well)
//
// – parallelism support for predictors and events
// When an event or predictor gets invalidated while it is still running, it would be nice for it to save time by exiting early.
// Moreover, it would probably be more efficient to discard invalidated fields than to preserve them for predictors/events that are in process. The natural way for the accessors to handle this is to have get() return None, which would mean that you can never safely unwrap() the result. We could provide a "unwrap or return" macro.
//
// – Optimization features
// one possibility: user can provide a function FieldId->[(PredictorId, RowId)] that lists predictors you KNOW will be invalidated by a change to that field, then have that predictor run its get() calls with an input called "promise_inferred" or something so that we don't spend time and memory recording the dependency
// another: a predictor might have a costly computation to find the exact time of a future event, which it won't need to do if it gets invalidated long before that time comes. For that, we can provide a defer_until(time) method
//
//
//

#![feature(unboxed_closures, specialization, never_type, raw, get_type_id, try_trait)]
// #![feature (shared)]
// #![feature (plugin, custom_derive)]
// #![plugin (serde_macros)]
// #![plugin (quickcheck_macros)]
//#![cfg_attr(test,feature(core_intrinsics))]

extern crate rand;
extern crate rand_core;
extern crate num;
extern crate nalgebra;
extern crate siphasher;
extern crate array_ext;
extern crate rpds;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
//extern crate crossbeam;
#[cfg_attr(test, macro_use)]
extern crate quickcheck;
#[cfg_attr(test, macro_use)]
extern crate proptest;
#[macro_use]
extern crate derivative;
#[macro_use]
extern crate failure;
#[macro_use]
extern crate smallvec;

macro_rules! printlnerr(
    ($($arg:tt)*) => { {use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

/// Used by TimeSteward implementations.
///
/// These are public in case someone wants to try implementing a TimeSteward
/// outside of this crate, sharing some of the details with my own implementations.
/// However, anything inside this module should be
/// considered very unstable at present.
#[macro_use]
pub mod implementation_support {
  pub mod insert_only;
  pub mod data_structures;
  #[macro_use]
  pub mod common;
}

/*#[macro_use]
/// Allows dynamic dispatch to object-unsafe traits, with some caveats.
pub mod dynamic {
  #[macro_use]
  pub mod list_of_types;
  pub mod thin_arc;
}*/

mod deterministic_random_id;
pub use deterministic_random_id::*;

#[macro_use]
mod api;
pub use api::*;
pub mod api_impls;

#[macro_use]
pub mod support {
  pub mod rounding_error_tolerant_math;
  pub mod time_functions;
  pub mod integer_math;
  #[macro_use] pub mod simple_timeline;
  #[macro_use] pub mod bbox_collision_detection;
}

#[macro_use]
pub mod serialization;

pub mod stewards {
  pub mod simple_flat;
  #[macro_use]
  pub mod simple_full;
  pub mod auditing;
}

<commit_msg>Actually include the new trajectories module, since it now compiles<commit_after>// Future TimeSteward API goals:
//
// – groups
// I made up API functions for this before, but I'm not sure they were perfect.
// We can use RowId's for group ids, but what kinds of things can be stored IN a group? Previously I said only RowId's could, which doesn't seem ideal. I think it would work to allow anything hashable. That would basically make a group behave like a HashSet. But then, why not make it behave like a HashMap instead? But accessor itself already behaves like a HashMap over RowId's – the essential thing groups do is to allow iterating particular subsets of that HashMap.
//
// – conveniences for serializing snapshots (not sure what)
//
// – be able to construct a new TimeSteward from any snapshot
// Issues: should snapshots expose the predictors? Also, the predictors can't be serialized. So you'd probably actually have to construct a TimeSteward from snapshot + predictors. This requires a way to iterate all fields (and group data if we add groups) in a snapshot, which is similar to the previous 2 items (iterating the whole set, which is a special case of iterating a subset; and serializing requires you to iterate everything as well)
//
// – parallelism support for predictors and events
// When an event or predictor gets invalidated while it is still running, it would be nice for it to save time by exiting early.
// Moreover, it would probably be more efficient to discard invalidated fields than to preserve them for predictors/events that are in process. The natural way for the accessors to handle this is to have get() return None, which would mean that you can never safely unwrap() the result. We could provide a "unwrap or return" macro.
//
// – Optimization features
// one possibility: user can provide a function FieldId->[(PredictorId, RowId)] that lists predictors you KNOW will be invalidated by a change to that field, then have that predictor run its get() calls with an input called "promise_inferred" or something so that we don't spend time and memory recording the dependency
// another: a predictor might have a costly computation to find the exact time of a future event, which it won't need to do if it gets invalidated long before that time comes. For that, we can provide a defer_until(time) method
//
//
//

#![feature(unboxed_closures, specialization, never_type, raw, get_type_id, try_trait)]
// #![feature (shared)]
// #![feature (plugin, custom_derive)]
// #![plugin (serde_macros)]
// #![plugin (quickcheck_macros)]
//#![cfg_attr(test,feature(core_intrinsics))]

extern crate rand;
extern crate rand_core;
extern crate num;
extern crate nalgebra;
extern crate siphasher;
extern crate array_ext;
extern crate rpds;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
//extern crate crossbeam;
#[cfg_attr(test, macro_use)]
extern crate quickcheck;
#[cfg_attr(test, macro_use)]
extern crate proptest;
#[macro_use]
extern crate derivative;
#[macro_use]
extern crate failure;
#[macro_use]
extern crate smallvec;

macro_rules! printlnerr(
    ($($arg:tt)*) => { {use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

/// Used by TimeSteward implementations.
///
/// These are public in case someone wants to try implementing a TimeSteward
/// outside of this crate, sharing some of the details with my own implementations.
/// However, anything inside this module should be
/// considered very unstable at present.
#[macro_use]
pub mod implementation_support {
  pub mod insert_only;
  pub mod data_structures;
  #[macro_use]
  pub mod common;
}

/*#[macro_use]
/// Allows dynamic dispatch to object-unsafe traits, with some caveats.
pub mod dynamic {
  #[macro_use]
  pub mod list_of_types;
  pub mod thin_arc;
}*/

mod deterministic_random_id;
pub use deterministic_random_id::*;

#[macro_use]
mod api;
pub use api::*;
pub mod api_impls;

#[macro_use]
pub mod support {
  pub mod rounding_error_tolerant_math;
  pub mod time_functions;
  pub mod integer_math;
  pub mod trajectories;
  #[macro_use] pub mod simple_timeline;
  #[macro_use] pub mod bbox_collision_detection;
}

#[macro_use]
pub mod serialization;

pub mod stewards {
  pub mod simple_flat;
  #[macro_use]
  pub mod simple_full;
  pub mod auditing;
}

<|endoftext|>


<commit_before>#![crate_name = "urlencoded"]
#![license = "MIT"]

#![feature(default_type_params)]

//! URL Encoded Plugin for Iron.
//!
//! Parses "url encoded" data from client requests.
//! Capable of parsing both URL query strings and POST request bodies.

extern crate iron;
extern crate url;
extern crate serialize;

extern crate plugin;
extern crate typemap;

use iron::Request;

use url::form_urlencoded;
use std::collections::hash_map::{HashMap, Occupied, Vacant};
use std::str;

use plugin::{PluginFor, Phantom};
use typemap::Assoc;

/// Plugin for `Request` that extracts URL encoded data from the URL query string.
///
/// Use it like this: `req.get_ref::<UrlEncodedQuery>()`
pub struct UrlEncodedQuery;

/// Plugin for `Request` that extracts URL encoded data from the request body.
///
/// Use it like this: `req.get_ref::<UrlEncodedBody>()`
pub struct UrlEncodedBody;

/// Hashmap mapping strings to vectors of strings.
pub type QueryMap = HashMap<String, Vec<String>>;

impl Assoc<QueryMap> for UrlEncodedQuery {}
impl Assoc<QueryMap> for UrlEncodedBody {}

impl PluginFor<Request, QueryMap> for UrlEncodedQuery {
    fn eval(req: &mut Request, _: Phantom<UrlEncodedQuery>) -> Option<QueryMap> {
        match req.url.query {
            Some(ref query) => create_param_hashmap(query.as_slice()),
            None => None
        }
    }
}

impl PluginFor<Request, HashMap<String, Vec<String>>> for UrlEncodedBody {
    fn eval(req: &mut Request, _: Phantom<UrlEncodedBody>) -> Option<QueryMap> {
        str::from_utf8(req.body.as_slice()).and_then(create_param_hashmap)
    }
}

/// Parse a urlencoded string into an optional HashMap.
fn create_param_hashmap(data: &str) -> Option<HashMap<String, Vec<String>>> {
    match data {
        "" => None,
        _ => Some(combine_duplicates(form_urlencoded::parse_str(data)))
    }
}

/// Convert a list of (key, value) pairs into a hashmap with vector values.
fn combine_duplicates(q: Vec<(String, String)>) -> HashMap<String, Vec<String>> {

    let mut deduplicated: HashMap<String, Vec<String>> = HashMap::new();

    for (k, v) in q.into_iter() {
        match deduplicated.entry(k) {
            // Already a Vec here, push onto it
            Occupied(entry) => { entry.into_mut().push(v); },

            // No value, create a one-element Vec.
            Vacant(entry) => { entry.set(vec![v]); }
        };
    }

    deduplicated
}

#[test]
fn test_combine_duplicates() {
    let my_vec = vec!(("band".to_string(), "arctic monkeys".to_string()),
                      ("band".to_string(), "temper trap".to_string()),
                      ("color".to_string(),"green".to_string()));
    let answer = combine_duplicates(my_vec);
    let mut control = HashMap::new();
    control.insert("band".to_string(),
                   vec!("arctic monkeys".to_string(), "temper trap".to_string()));
    control.insert("color".to_string(), vec!("green".to_string()));
    assert_eq!(answer, control);
}
<commit_msg>(fix) remove unused attribute<commit_after>#![crate_name = "urlencoded"]

#![feature(default_type_params)]

//! URL Encoded Plugin for Iron.
//!
//! Parses "url encoded" data from client requests.
//! Capable of parsing both URL query strings and POST request bodies.

extern crate iron;
extern crate url;
extern crate serialize;

extern crate plugin;
extern crate typemap;

use iron::Request;

use url::form_urlencoded;
use std::collections::hash_map::{HashMap, Occupied, Vacant};
use std::str;

use plugin::{PluginFor, Phantom};
use typemap::Assoc;

/// Plugin for `Request` that extracts URL encoded data from the URL query string.
///
/// Use it like this: `req.get_ref::<UrlEncodedQuery>()`
pub struct UrlEncodedQuery;

/// Plugin for `Request` that extracts URL encoded data from the request body.
///
/// Use it like this: `req.get_ref::<UrlEncodedBody>()`
pub struct UrlEncodedBody;

/// Hashmap mapping strings to vectors of strings.
pub type QueryMap = HashMap<String, Vec<String>>;

impl Assoc<QueryMap> for UrlEncodedQuery {}
impl Assoc<QueryMap> for UrlEncodedBody {}

impl PluginFor<Request, QueryMap> for UrlEncodedQuery {
    fn eval(req: &mut Request, _: Phantom<UrlEncodedQuery>) -> Option<QueryMap> {
        match req.url.query {
            Some(ref query) => create_param_hashmap(query.as_slice()),
            None => None
        }
    }
}

impl PluginFor<Request, HashMap<String, Vec<String>>> for UrlEncodedBody {
    fn eval(req: &mut Request, _: Phantom<UrlEncodedBody>) -> Option<QueryMap> {
        str::from_utf8(req.body.as_slice()).and_then(create_param_hashmap)
    }
}

/// Parse a urlencoded string into an optional HashMap.
fn create_param_hashmap(data: &str) -> Option<HashMap<String, Vec<String>>> {
    match data {
        "" => None,
        _ => Some(combine_duplicates(form_urlencoded::parse_str(data)))
    }
}

/// Convert a list of (key, value) pairs into a hashmap with vector values.
fn combine_duplicates(q: Vec<(String, String)>) -> HashMap<String, Vec<String>> {

    let mut deduplicated: HashMap<String, Vec<String>> = HashMap::new();

    for (k, v) in q.into_iter() {
        match deduplicated.entry(k) {
            // Already a Vec here, push onto it
            Occupied(entry) => { entry.into_mut().push(v); },

            // No value, create a one-element Vec.
            Vacant(entry) => { entry.set(vec![v]); }
        };
    }

    deduplicated
}

#[test]
fn test_combine_duplicates() {
    let my_vec = vec!(("band".to_string(), "arctic monkeys".to_string()),
                      ("band".to_string(), "temper trap".to_string()),
                      ("color".to_string(),"green".to_string()));
    let answer = combine_duplicates(my_vec);
    let mut control = HashMap::new();
    control.insert("band".to_string(),
                   vec!("arctic monkeys".to_string(), "temper trap".to_string()));
    control.insert("color".to_string(), vec!("green".to_string()));
    assert_eq!(answer, control);
}
<|endoftext|>


<commit_before>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub trait WithLen {
    fn match_len(&self) -> usize;
}

impl<T> WithLen for Vec<T> {
    fn match_len(&self) -> usize { self.len() }
}

impl WithLen for String {
    fn match_len(&self) -> usize { self.chars().count() }
}

impl<'a> WithLen for &'a str {
    fn match_len(&self) -> usize { self.chars().count() }
}

pub struct Contains<T>(T);

impl<T: Debug + PartialEq> Matcher<Vec<T>> for Contains<T> {
    fn matches(&self, lhs: &Vec<T>) -> bool {
        lhs.iter().any(|i| *i == self.0)
    }

    fn fail_msg(&self, lhs: &Vec<T>) -> String {
        format!("expected {:?} to contain {:?}", lhs, self.0)
    }
}

impl Matcher<String> for Contains<char> {
    fn matches(&self, lhs: &String) -> bool {
        lhs.chars().any(|i| i == self.0)
    }

    fn fail_msg(&self, lhs: &String) -> String {
        format!("expected \"{:?}\" to contain '{:?}'", lhs, self.0)
    }
}

impl Matcher<String> for Contains<String> {
    fn matches(&self, lhs: &String) -> bool {
        lhs.contains(&*self.0)
    }

    fn fail_msg(&self, lhs: &String) -> String {
        format!("expected \"{:?}\" to contain \"{:?}\"", lhs, self.0)
    }
}

pub struct Empty;

impl<Lhs: Debug + WithLen> Matcher<Lhs> for Empty {
    fn matches(&self, rhs: &Lhs) -> bool {
        rhs.match_len() == 0
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to be empty", rhs)
    }
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: T) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

pub fn empty() -> Empty {
    Empty
}

pub fn contain<T: Debug>(rhs: T) -> Contains<T> {
    Contains(rhs)
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not, empty, contain};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }

    #[test]
    fn test_empty() {
        let v: Vec<usize> = Vec::new();
        expect(v).is(empty());
    }

    #[test]
    fn test_not_empty() {
        let v = vec![1, 2, 3];
        expect(v).is(not(empty()));
    }

    #[test]
    fn test_empty_string() {
        expect("".to_string()).is(empty());
    }

    #[test]
    fn test_not_empty_string() {
        expect("not-empty".to_string()).is(not(empty()));
    }

    #[test]
    fn test_empty_str() {
        expect("").is(empty());
    }

    #[test]
    fn test_not_empty_str() {
        expect("not-empty").is(not(empty()));
    }

    #[test]
    fn test_contains() {
        expect(vec![1, 2, 3]).to(contain(1));
    }

    #[test]
    fn test_not_contains() {
        expect(vec![1, 2, 3]).to(not(contain(10)));
    }

    #[test]
    fn test_contains_string_char() {
        expect("Hello, world!".to_string()).to(contain('H'));
    }

    #[test]
    fn test_not_contains_string_char() {
        expect("Hello, world!".to_string()).to(not(contain('Z')));
    }

    #[test]
    fn test_contains_string_substring() {
        expect("Hello, world!".to_string()).to(contain("Hello".to_string()));
    }

    #[test]
    fn test_not_contains_string_substring() {
        expect("Hello, world!".to_string()).to(not(contain("not-in-there".to_string())));
    }
}
<commit_msg>Add `greater_than`<commit_after>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub trait WithLen {
    fn match_len(&self) -> usize;
}

impl<T> WithLen for Vec<T> {
    fn match_len(&self) -> usize { self.len() }
}

impl WithLen for String {
    fn match_len(&self) -> usize { self.chars().count() }
}

impl<'a> WithLen for &'a str {
    fn match_len(&self) -> usize { self.chars().count() }
}

pub struct Contains<T>(T);

impl<T: Debug + PartialEq> Matcher<Vec<T>> for Contains<T> {
    fn matches(&self, lhs: &Vec<T>) -> bool {
        lhs.iter().any(|i| *i == self.0)
    }

    fn fail_msg(&self, lhs: &Vec<T>) -> String {
        format!("expected {:?} to contain {:?}", lhs, self.0)
    }
}

impl Matcher<String> for Contains<char> {
    fn matches(&self, lhs: &String) -> bool {
        lhs.chars().any(|i| i == self.0)
    }

    fn fail_msg(&self, lhs: &String) -> String {
        format!("expected \"{:?}\" to contain '{:?}'", lhs, self.0)
    }
}

impl Matcher<String> for Contains<String> {
    fn matches(&self, lhs: &String) -> bool {
        lhs.contains(&*self.0)
    }

    fn fail_msg(&self, lhs: &String) -> String {
        format!("expected \"{:?}\" to contain \"{:?}\"", lhs, self.0)
    }
}

pub struct Empty;

impl<Lhs: Debug + WithLen> Matcher<Lhs> for Empty {
    fn matches(&self, rhs: &Lhs) -> bool {
        rhs.match_len() == 0
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to be empty", rhs)
    }
}

pub struct GreaterThan<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialOrd> Matcher<Lhs> for GreaterThan<Lhs> {
    fn matches(&self, lhs: &Lhs) -> bool {
        *lhs > self.0
    }

    fn fail_msg(&self, lhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", self.0, lhs)
    }
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: T) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

pub fn empty() -> Empty {
    Empty
}

pub fn contain<T: Debug>(rhs: T) -> Contains<T> {
    Contains(rhs)
}

pub fn greater_than<T: Debug>(rhs: T) -> GreaterThan<T> {
    GreaterThan(rhs)
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not, empty, contain, greater_than};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }

    #[test]
    fn test_empty() {
        let v: Vec<usize> = Vec::new();
        expect(v).is(empty());
    }

    #[test]
    fn test_not_empty() {
        let v = vec![1, 2, 3];
        expect(v).is(not(empty()));
    }

    #[test]
    fn test_empty_string() {
        expect("".to_string()).is(empty());
    }

    #[test]
    fn test_not_empty_string() {
        expect("not-empty".to_string()).is(not(empty()));
    }

    #[test]
    fn test_empty_str() {
        expect("").is(empty());
    }

    #[test]
    fn test_not_empty_str() {
        expect("not-empty").is(not(empty()));
    }

    #[test]
    fn test_contains() {
        expect(vec![1, 2, 3]).to(contain(1));
    }

    #[test]
    fn test_not_contains() {
        expect(vec![1, 2, 3]).to(not(contain(10)));
    }

    #[test]
    fn test_contains_string_char() {
        expect("Hello, world!".to_string()).to(contain('H'));
    }

    #[test]
    fn test_not_contains_string_char() {
        expect("Hello, world!".to_string()).to(not(contain('Z')));
    }

    #[test]
    fn test_contains_string_substring() {
        expect("Hello, world!".to_string()).to(contain("Hello".to_string()));
    }

    #[test]
    fn test_not_contains_string_substring() {
        expect("Hello, world!".to_string()).to(not(contain("not-in-there".to_string())));
    }

    #[test]
    fn test_greater_than_int() {
        expect(5).is(greater_than(1));
    }

    #[test]
    fn test_not_greater_than_int() {
        expect(5).is(not(greater_than(10)));
    }
}
<|endoftext|>


<commit_before>#![deny(
    absolute_paths_not_starting_with_crate,
    ambiguous_associated_items,
    anonymous_parameters,
    arithmetic_overflow,
    array_into_iter,
    asm_sub_register,
    bad_asm_style,
    bindings_with_variant_name,
    break_with_label_and_loop,
    cenum_impl_drop_cast,
    clashing_extern_declarations,
    coherence_leak_check,
    conflicting_repr_hints,
    confusable_idents,
    const_err,
    const_evaluatable_unchecked,
    const_item_mutation,
    dead_code,
    deprecated,
    deprecated_cfg_attr_crate_type_name,
    deprecated_in_future,
    deprecated_where_clause_location,
    deref_into_dyn_supertrait,
    deref_nullptr,
    drop_bounds,
    duplicate_macro_attributes,
    dyn_drop,
    ellipsis_inclusive_range_patterns,
    enum_intrinsics_non_enums,
    explicit_outlives_requirements,
    exported_private_dependencies,
    forbidden_lint_groups,
    function_item_references,
    ill_formed_attribute_input,
    illegal_floating_point_literal_pattern,
    improper_ctypes,
    improper_ctypes_definitions,
    incomplete_features,
    incomplete_include,
    indirect_structural_match,
    ineffective_unstable_trait_impl,
    inline_no_sanitize,
    invalid_atomic_ordering,
    invalid_doc_attributes,
    invalid_type_param_default,
    invalid_value,
    irrefutable_let_patterns,
    keyword_idents,
    large_assignments,
    late_bound_lifetime_arguments,
    legacy_derive_helpers,
    macro_expanded_macro_exports_accessed_by_absolute_paths,
    meta_variable_misuse,
    missing_abi,
    missing_copy_implementations,
    missing_docs,
    missing_fragment_specifier,
    mixed_script_confusables,
    mutable_transmutes,
    named_asm_labels,
    no_mangle_const_items,
    no_mangle_generic_items,
    non_ascii_idents,
    non_camel_case_types,
    non_fmt_panics,
    non_shorthand_field_patterns,
    non_snake_case,
    non_upper_case_globals,
    nontrivial_structural_match,
    noop_method_call,
    order_dependent_trait_objects,
    overflowing_literals,
    overlapping_range_endpoints,
    path_statements,
    patterns_in_fns_without_body,
    pointer_structural_match,
    private_in_public,
    proc_macro_back_compat,
    proc_macro_derive_resolution_fallback,
    pub_use_of_private_extern_crate,
    redundant_semicolons,
    rust_2021_incompatible_closure_captures,
    rust_2021_incompatible_or_patterns,
    rust_2021_prefixes_incompatible_syntax,
    rust_2021_prelude_collisions,
    semicolon_in_expressions_from_macros,
    soft_unstable,
    stable_features,
    suspicious_auto_trait_impls,
    temporary_cstring_as_ptr,
    text_direction_codepoint_in_comment,
    text_direction_codepoint_in_literal,
    trivial_bounds,
    trivial_casts,
    trivial_numeric_casts,
    type_alias_bounds,
    tyvar_behind_raw_pointer,
    unaligned_references,
    uncommon_codepoints,
    unconditional_panic,
    unconditional_recursion,
    unexpected_cfgs,
    uninhabited_static,
    unknown_crate_types,
    unnameable_test_items,
    unreachable_code,
    unreachable_patterns,
    unreachable_pub,
    unsafe_code,
    unsafe_op_in_unsafe_fn,
    unstable_features,
    unstable_name_collisions,
    unsupported_calling_conventions,
    unused_allocation,
    unused_assignments,
    unused_assignments,
    unused_attributes,
    unused_braces,
    unused_comparisons,
    unused_crate_dependencies,
    unused_doc_comments,
    unused_extern_crates,
    unused_features,
    unused_import_braces,
    unused_imports,
    unused_labels,
    unused_lifetimes,
    unused_macro_rules,
    unused_macros,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_qualifications,
    unused_unsafe,
    unused_variables,
    useless_deprecated,
    where_clauses_object_safety,
    while_true
)]
#![warn(macro_use_extern_crate, unknown_lints)]
#![allow(
    bare_trait_objects,
    box_pointers,
    elided_lifetimes_in_paths,
    missing_debug_implementations,
    single_use_lifetimes,
    unused_results,
    variant_size_differences,
    warnings,
    renamed_and_removed_lints
)]

//! # simple_redis
//!
//! Simple and resilient [redis](https://redis.io/) client based on [redis-rs](https://crates.io/crates/redis) with
//! internal connection and subscription handling.
//!
//! This library provides a very basic, simple API for the most common redis operations.

//! While not as comprehensive or flexiable as [redis-rs](https://crates.io/crates/redis),
//! it does provide a simpler api for most common use cases and operations as well as automatic and resilient internal
//! connection and subscription (pubsub) handling.

//! In addition, the entire API is accessible via redis client and there is no need to manage connection or pubsub
//! instances in parallel.

//!
//! ## Connection Resiliency
//!
//! Connection resiliency is managed by verifying the internally managed connection before every operation against the
//! redis server.

//! In case of any connection issue, a new connection will be allocated to ensure the operation is invoked on a valid
//! connection only.

//! However, this comes at a small performance cost of PING operation to the redis server.

//!
//! ## Subscription Resiliency
//!
//! Subscription resiliency is ensured by recreating the internal pubsub and issuing new subscription requests
//! automatically in case of any error while fetching a message from the subscribed channels.
//!
//! # Examples
//!
//! ## Initialization and Simple Operations
//!
//! ```
//! fn main() {
//!     match simple_redis::create("redis://127.0.0.1:6379/") {
//!         Ok(mut client) =>  {
//!             println!("Created Redis Client");
//!
//!             match client.set("my_key", "my_value") {
//!                 Err(error) => println!("Unable to set value in Redis: {}", error),
//!                 _ => println!("Value set in Redis")
//!             };
//!
//!             match client.get_string("my_key") {
//!                 Ok(value) => println!("Read value from Redis: {}", value),
//!                 Err(error) => println!("Unable to get value from Redis: {}", error)
//!             };
//!
//!             match client.set("my_numeric_key", 255.5) {
//!                 Err(error) => println!("Unable to set value in Redis: {}", error),
//!                 _ => println!("Value set in Redis")
//!             };
//!
//!             match client.get::<f32>("my_numeric_key") {
//!                 Ok(value) => println!("Read value from Redis: {}", value),
//!                 Err(error) => println!("Unable to get value from Redis: {}", error)
//!             };
//!
//!             match client.hgetall("my_map") {
//!                 Ok(map) => {
//!                     match map.get("my_field") {
//!                         Some(value) => println!("Got field value from map: {}", value),
//!                         None => println!("Map field is emtpy"),
//!                     }
//!                 },
//!                 Err(error) => println!("Unable to read map from Redis: {}", error),
//!             };
//!
//!             /// run some command that is not built in the library
//!             match client.run_command::<String>("ECHO", vec!["testing"]) {
//!                 Ok(value) => assert_eq!(value, "testing"),
//!                 _ => panic!("test error"),
//!             };
//!
//!             /// publish messages
//!             let result = client.publish("news_channel", "test message");
//!             assert!(result.is_ok());
//!         },
//!         Err(error) => println!("Unable to create Redis client: {}", error)
//!     }
//! }
//! ```
//!
//! ## Subscription Flow
//!
//! ```rust,no_run
//! use simple_redis::{Interrupts, Message};
//!
//! fn main() {
//!     match simple_redis::create("redis://127.0.0.1:6379/") {
//!         Ok(mut client) =>  {
//!             println!("Created Redis Client");
//!
//!             let mut result = client.subscribe("important_notifications");
//!             assert!(result.is_ok());
//!             result = client.psubscribe("*_notifications");
//!             assert!(result.is_ok());
//!
//!             // fetch messages from all subscriptions
//!             client.fetch_messages(
//!                 &mut |message: Message| -> bool {
//!                     let payload : String = message.get_payload().unwrap();
//!                     println!("Got message: {}", payload);
//!
//!                     // continue fetching
//!                     false
//!                 },
//!                 &mut || -> Interrupts { Interrupts::new() },
//!             ).unwrap();
//!         },
//!         Err(error) => println!("Unable to create Redis client: {}", error)
//!     }
//! }
//! ```
//!
//! ## Closing Connection
//!
//! ```rust
//! fn main() {
//!     match simple_redis::create("redis://127.0.0.1:6379/") {
//!         Ok(mut client) =>  {
//!             println!("Created Redis Client");
//!
//!             match client.set("my_key", "my_value") {
//!                 Err(error) => println!("Unable to set value in Redis: {}", error),
//!                 _ => println!("Value set in Redis")
//!             };
//!
//!             match client.quit() {
//!                 Err(error) => println!("Error: {}", error),
//!                 _ => println!("Connection Closed.")
//!             }
//!         },
//!         Err(error) => println!("Unable to create Redis client: {}", error)
//!     }
//! }
//! ```
//!
//! # Installation
//! In order to use this library, just add it as a dependency:
//!
//! ```ini
//! [dependencies]
//! simple_redis = "*"
//! ```
//!
//! # Contributing
//! See [contributing guide](https://github.com/sagiegurari/simple_redis/blob/master/.github/CONTRIBUTING.md)
//!
//! # License
//! Developed by Sagie Gur-Ari and licensed under the
//! [Apache 2](https://github.com/sagiegurari/simple_redis/blob/master/LICENSE) open source license.
//!

#[cfg(test)]
#[path = "./lib_test.rs"]
mod lib_test;

#[cfg(doctest)]
doc_comment::doctest!("../README.md");

pub mod client;
mod commands;
mod connection;
mod subscriber;
pub mod types;

/// Error Type
pub type RedisError = types::RedisError;

/// PubSub message
pub type Message = types::Message;

/// Blocking operations interrupts
pub type Interrupts = types::Interrupts;

/// Redis result which either holds a value or a Redis error
pub type RedisResult<T> = types::RedisResult<T>;

/// Constructs a new redis client.

/// The redis connection string must be in the following format: `redis://[:<passwd>@]<hostname>[:port][/<db>]`
///
/// # Arguments
///
/// * `connection_string` - The connection string in the format of: `redis://[:<passwd>@]<hostname>[:port][/<db>]`
///
/// # Example
///
/// ```
/// extern crate simple_redis;
///
/// fn main() {
///     match simple_redis::create("redis://127.0.0.1:6379/") {
///         Ok(client) => println!("Created Redis Client"),
///         Err(error) => println!("Unable to create Redis client: {}", error)
///     }
/// }
/// ```
pub fn create(connection_string: &str) -> Result<client::Client, RedisError> {
    client::create(connection_string)
}
<commit_msg>rust upgrade<commit_after>#![deny(
    absolute_paths_not_starting_with_crate,
    ambiguous_associated_items,
    anonymous_parameters,
    arithmetic_overflow,
    array_into_iter,
    asm_sub_register,
    bad_asm_style,
    bindings_with_variant_name,
    break_with_label_and_loop,
    cenum_impl_drop_cast,
    clashing_extern_declarations,
    coherence_leak_check,
    conflicting_repr_hints,
    confusable_idents,
    const_err,
    const_evaluatable_unchecked,
    const_item_mutation,
    dead_code,
    deprecated,
    deprecated_cfg_attr_crate_type_name,
    deprecated_in_future,
    deprecated_where_clause_location,
    deref_into_dyn_supertrait,
    deref_nullptr,
    drop_bounds,
    duplicate_macro_attributes,
    dyn_drop,
    ellipsis_inclusive_range_patterns,
    enum_intrinsics_non_enums,
    explicit_outlives_requirements,
    exported_private_dependencies,
    forbidden_lint_groups,
    function_item_references,
    ill_formed_attribute_input,
    illegal_floating_point_literal_pattern,
    improper_ctypes,
    improper_ctypes_definitions,
    incomplete_features,
    incomplete_include,
    indirect_structural_match,
    ineffective_unstable_trait_impl,
    inline_no_sanitize,
    invalid_atomic_ordering,
    invalid_doc_attributes,
    invalid_type_param_default,
    invalid_value,
    irrefutable_let_patterns,
    keyword_idents,
    large_assignments,
    late_bound_lifetime_arguments,
    legacy_derive_helpers,
    macro_expanded_macro_exports_accessed_by_absolute_paths,
    meta_variable_misuse,
    missing_abi,
    missing_copy_implementations,
    missing_docs,
    missing_fragment_specifier,
    mixed_script_confusables,
    mutable_transmutes,
    named_arguments_used_positionally,
    named_asm_labels,
    no_mangle_const_items,
    no_mangle_generic_items,
    non_ascii_idents,
    non_camel_case_types,
    non_fmt_panics,
    non_shorthand_field_patterns,
    non_snake_case,
    non_upper_case_globals,
    nontrivial_structural_match,
    noop_method_call,
    order_dependent_trait_objects,
    overflowing_literals,
    overlapping_range_endpoints,
    path_statements,
    patterns_in_fns_without_body,
    pointer_structural_match,
    private_in_public,
    proc_macro_back_compat,
    proc_macro_derive_resolution_fallback,
    pub_use_of_private_extern_crate,
    redundant_semicolons,
    repr_transparent_external_private_fields,
    rust_2021_incompatible_closure_captures,
    rust_2021_incompatible_or_patterns,
    rust_2021_prefixes_incompatible_syntax,
    rust_2021_prelude_collisions,
    semicolon_in_expressions_from_macros,
    soft_unstable,
    stable_features,
    suspicious_auto_trait_impls,
    temporary_cstring_as_ptr,
    text_direction_codepoint_in_comment,
    text_direction_codepoint_in_literal,
    trivial_bounds,
    trivial_casts,
    trivial_numeric_casts,
    type_alias_bounds,
    tyvar_behind_raw_pointer,
    unaligned_references,
    uncommon_codepoints,
    unconditional_panic,
    unconditional_recursion,
    unexpected_cfgs,
    uninhabited_static,
    unknown_crate_types,
    unnameable_test_items,
    unreachable_code,
    unreachable_patterns,
    unreachable_pub,
    unsafe_code,
    unsafe_op_in_unsafe_fn,
    unstable_features,
    unstable_name_collisions,
    unsupported_calling_conventions,
    unused_allocation,
    unused_assignments,
    unused_assignments,
    unused_attributes,
    unused_braces,
    unused_comparisons,
    unused_crate_dependencies,
    unused_doc_comments,
    unused_extern_crates,
    unused_features,
    unused_import_braces,
    unused_imports,
    unused_labels,
    unused_lifetimes,
    unused_macro_rules,
    unused_macros,
    unused_must_use,
    unused_mut,
    unused_parens,
    unused_qualifications,
    unused_unsafe,
    unused_variables,
    useless_deprecated,
    where_clauses_object_safety,
    while_true
)]
#![warn(macro_use_extern_crate, unknown_lints)]
#![allow(
    bare_trait_objects,
    box_pointers,
    elided_lifetimes_in_paths,
    missing_debug_implementations,
    single_use_lifetimes,
    unused_results,
    variant_size_differences,
    warnings,
    renamed_and_removed_lints
)]

//! # simple_redis
//!
//! Simple and resilient [redis](https://redis.io/) client based on [redis-rs](https://crates.io/crates/redis) with
//! internal connection and subscription handling.
//!
//! This library provides a very basic, simple API for the most common redis operations.

//! While not as comprehensive or flexiable as [redis-rs](https://crates.io/crates/redis),
//! it does provide a simpler api for most common use cases and operations as well as automatic and resilient internal
//! connection and subscription (pubsub) handling.

//! In addition, the entire API is accessible via redis client and there is no need to manage connection or pubsub
//! instances in parallel.

//!
//! ## Connection Resiliency
//!
//! Connection resiliency is managed by verifying the internally managed connection before every operation against the
//! redis server.

//! In case of any connection issue, a new connection will be allocated to ensure the operation is invoked on a valid
//! connection only.

//! However, this comes at a small performance cost of PING operation to the redis server.

//!
//! ## Subscription Resiliency
//!
//! Subscription resiliency is ensured by recreating the internal pubsub and issuing new subscription requests
//! automatically in case of any error while fetching a message from the subscribed channels.
//!
//! # Examples
//!
//! ## Initialization and Simple Operations
//!
//! ```
//! fn main() {
//!     match simple_redis::create("redis://127.0.0.1:6379/") {
//!         Ok(mut client) =>  {
//!             println!("Created Redis Client");
//!
//!             match client.set("my_key", "my_value") {
//!                 Err(error) => println!("Unable to set value in Redis: {}", error),
//!                 _ => println!("Value set in Redis")
//!             };
//!
//!             match client.get_string("my_key") {
//!                 Ok(value) => println!("Read value from Redis: {}", value),
//!                 Err(error) => println!("Unable to get value from Redis: {}", error)
//!             };
//!
//!             match client.set("my_numeric_key", 255.5) {
//!                 Err(error) => println!("Unable to set value in Redis: {}", error),
//!                 _ => println!("Value set in Redis")
//!             };
//!
//!             match client.get::<f32>("my_numeric_key") {
//!                 Ok(value) => println!("Read value from Redis: {}", value),
//!                 Err(error) => println!("Unable to get value from Redis: {}", error)
//!             };
//!
//!             match client.hgetall("my_map") {
//!                 Ok(map) => {
//!                     match map.get("my_field") {
//!                         Some(value) => println!("Got field value from map: {}", value),
//!                         None => println!("Map field is emtpy"),
//!                     }
//!                 },
//!                 Err(error) => println!("Unable to read map from Redis: {}", error),
//!             };
//!
//!             /// run some command that is not built in the library
//!             match client.run_command::<String>("ECHO", vec!["testing"]) {
//!                 Ok(value) => assert_eq!(value, "testing"),
//!                 _ => panic!("test error"),
//!             };
//!
//!             /// publish messages
//!             let result = client.publish("news_channel", "test message");
//!             assert!(result.is_ok());
//!         },
//!         Err(error) => println!("Unable to create Redis client: {}", error)
//!     }
//! }
//! ```
//!
//! ## Subscription Flow
//!
//! ```rust,no_run
//! use simple_redis::{Interrupts, Message};
//!
//! fn main() {
//!     match simple_redis::create("redis://127.0.0.1:6379/") {
//!         Ok(mut client) =>  {
//!             println!("Created Redis Client");
//!
//!             let mut result = client.subscribe("important_notifications");
//!             assert!(result.is_ok());
//!             result = client.psubscribe("*_notifications");
//!             assert!(result.is_ok());
//!
//!             // fetch messages from all subscriptions
//!             client.fetch_messages(
//!                 &mut |message: Message| -> bool {
//!                     let payload : String = message.get_payload().unwrap();
//!                     println!("Got message: {}", payload);
//!
//!                     // continue fetching
//!                     false
//!                 },
//!                 &mut || -> Interrupts { Interrupts::new() },
//!             ).unwrap();
//!         },
//!         Err(error) => println!("Unable to create Redis client: {}", error)
//!     }
//! }
//! ```
//!
//! ## Closing Connection
//!
//! ```rust
//! fn main() {
//!     match simple_redis::create("redis://127.0.0.1:6379/") {
//!         Ok(mut client) =>  {
//!             println!("Created Redis Client");
//!
//!             match client.set("my_key", "my_value") {
//!                 Err(error) => println!("Unable to set value in Redis: {}", error),
//!                 _ => println!("Value set in Redis")
//!             };
//!
//!             match client.quit() {
//!                 Err(error) => println!("Error: {}", error),
//!                 _ => println!("Connection Closed.")
//!             }
//!         },
//!         Err(error) => println!("Unable to create Redis client: {}", error)
//!     }
//! }
//! ```
//!
//! # Installation
//! In order to use this library, just add it as a dependency:
//!
//! ```ini
//! [dependencies]
//! simple_redis = "*"
//! ```
//!
//! # Contributing
//! See [contributing guide](https://github.com/sagiegurari/simple_redis/blob/master/.github/CONTRIBUTING.md)
//!
//! # License
//! Developed by Sagie Gur-Ari and licensed under the
//! [Apache 2](https://github.com/sagiegurari/simple_redis/blob/master/LICENSE) open source license.
//!

#[cfg(test)]
#[path = "./lib_test.rs"]
mod lib_test;

#[cfg(doctest)]
doc_comment::doctest!("../README.md");

pub mod client;
mod commands;
mod connection;
mod subscriber;
pub mod types;

/// Error Type
pub type RedisError = types::RedisError;

/// PubSub message
pub type Message = types::Message;

/// Blocking operations interrupts
pub type Interrupts = types::Interrupts;

/// Redis result which either holds a value or a Redis error
pub type RedisResult<T> = types::RedisResult<T>;

/// Constructs a new redis client.

/// The redis connection string must be in the following format: `redis://[:<passwd>@]<hostname>[:port][/<db>]`
///
/// # Arguments
///
/// * `connection_string` - The connection string in the format of: `redis://[:<passwd>@]<hostname>[:port][/<db>]`
///
/// # Example
///
/// ```
/// extern crate simple_redis;
///
/// fn main() {
///     match simple_redis::create("redis://127.0.0.1:6379/") {
///         Ok(client) => println!("Created Redis Client"),
///         Err(error) => println!("Unable to create Redis client: {}", error)
///     }
/// }
/// ```
pub fn create(connection_string: &str) -> Result<client::Client, RedisError> {
    client::create(connection_string)
}
<|endoftext|>


<commit_before>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_root_url = "https://docs.rs/itoa/0.3.4")]

#![cfg_attr(not(feature = "std"), no_std)]

#![cfg_attr(feature = "i128", feature(i128_type, i128))]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, unreadable_literal))]

#[cfg(feature = "i128")]
mod udiv128;

#[cfg(feature = "std")]
use std::{fmt, io, mem, ptr, slice, str};

#[cfg(not(feature = "std"))]
use core::{fmt, mem, ptr, slice, str};

#[cfg(feature = "std")]
#[inline]
pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> {
    value.write(wr)
}

#[inline]
pub fn fmt<W: fmt::Write, V: Integer>(wr: W, value: V) -> fmt::Result {
    value.fmt(wr)
}

// Seal to prevent downstream implementations of the Integer trait.
mod private {
    pub trait Sealed {}
}

pub trait Integer: private::Sealed {
    #[cfg(feature = "std")]
    fn write<W: io::Write>(self, W) -> io::Result<usize>;

    fn fmt<W: fmt::Write>(self, W) -> fmt::Result;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

const MAX_LEN: usize = 40; // i128::MIN (including minus sign)

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_IntegerCommon {
    ($t:ident) => {
        impl Integer for $t {
            #[cfg(feature = "std")]
            fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
                let mut buf = unsafe { mem::uninitialized() };
                let bytes = self.write_to(&mut buf);
                try!(wr.write_all(bytes));
                Ok(bytes.len())
            }

            fn fmt<W: fmt::Write>(self, mut wr: W) -> fmt::Result {
                let mut buf = unsafe { mem::uninitialized() };
                let bytes = self.write_to(&mut buf);
                wr.write_str(unsafe { str::from_utf8_unchecked(bytes) })
            }
        }

        impl private::Sealed for $t {}
    };
}

macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => {$(
        impl_IntegerCommon!($t);

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let mut n = if is_nonnegative {
                    self as $conv_fn
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as $conv_fn)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();
                let lut_ptr = DEC_DIGITS_LUT.as_ptr();

                unsafe {
                    // need at least 16 bits for the 4-characters-at-a-time to work.
                    if mem::size_of::<$t>() >= 2 {
                        // eagerly decode 4 characters at a time
                        while n >= 10000 {
                            let rem = (n % 10000) as isize;
                            n /= 10000;

                            let d1 = (rem / 100) << 1;
                            let d2 = (rem % 100) << 1;
                            curr -= 4;
                            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                        }
                    }

                    // if we reach here numbers are <= 9999, so at most 4 chars long
                    let mut n = n as isize; // possibly reduce 64bit math

                    // decode 2 more chars, if > 2 chars
                    if n >= 100 {
                        let d1 = (n % 100) << 1;
                        n /= 100;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    // decode last 1 or 2 chars
                    if n < 10 {
                        curr -= 1;
                        *buf_ptr.offset(curr) = (n as u8) + b'0';
                    } else {
                        let d1 = n << 1;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }
                }

                let len = buf.len() - curr as usize;
                unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
            }
        }
    )*};
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($t:ident),*) => {$(
        impl_IntegerCommon!($t);

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    curr -= rem.write_to(buf).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - buf.len() as isize) as *mut _;
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
impl_Integer128!(i128, u128);
<commit_msg>Remove trait methods from public API<commit_after>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_root_url = "https://docs.rs/itoa/0.3.4")]

#![cfg_attr(not(feature = "std"), no_std)]

#![cfg_attr(feature = "i128", feature(i128_type, i128))]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, unreadable_literal))]

#[cfg(feature = "i128")]
mod udiv128;

#[cfg(feature = "std")]
use std::{fmt, io, mem, ptr, slice, str};

#[cfg(not(feature = "std"))]
use core::{fmt, mem, ptr, slice, str};

#[cfg(feature = "std")]
#[inline]
pub fn write<W: io::Write, V: Integer>(wr: W, value: V) -> io::Result<usize> {
    value.write(wr)
}

#[inline]
pub fn fmt<W: fmt::Write, V: Integer>(wr: W, value: V) -> fmt::Result {
    value.fmt(wr)
}

// Seal to prevent downstream implementations of the Integer trait.
mod private {
    pub trait Sealed {}
}

pub trait Integer: private::Sealed {
    // Not public API.
    #[doc(hidden)]
    #[cfg(feature = "std")]
    fn write<W: io::Write>(self, W) -> io::Result<usize>;

    // Not public API.
    #[doc(hidden)]
    fn fmt<W: fmt::Write>(self, W) -> fmt::Result;
}

trait IntegerPrivate {
    fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

const MAX_LEN: usize = 40; // i128::MIN (including minus sign)

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_IntegerCommon {
    ($t:ident) => {
        impl Integer for $t {
            #[cfg(feature = "std")]
            fn write<W: io::Write>(self, mut wr: W) -> io::Result<usize> {
                let mut buf = unsafe { mem::uninitialized() };
                let bytes = self.write_to(&mut buf);
                try!(wr.write_all(bytes));
                Ok(bytes.len())
            }

            fn fmt<W: fmt::Write>(self, mut wr: W) -> fmt::Result {
                let mut buf = unsafe { mem::uninitialized() };
                let bytes = self.write_to(&mut buf);
                wr.write_str(unsafe { str::from_utf8_unchecked(bytes) })
            }
        }

        impl private::Sealed for $t {}
    };
}

macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => {$(
        impl_IntegerCommon!($t);

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let mut n = if is_nonnegative {
                    self as $conv_fn
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as $conv_fn)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();
                let lut_ptr = DEC_DIGITS_LUT.as_ptr();

                unsafe {
                    // need at least 16 bits for the 4-characters-at-a-time to work.
                    if mem::size_of::<$t>() >= 2 {
                        // eagerly decode 4 characters at a time
                        while n >= 10000 {
                            let rem = (n % 10000) as isize;
                            n /= 10000;

                            let d1 = (rem / 100) << 1;
                            let d2 = (rem % 100) << 1;
                            curr -= 4;
                            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                        }
                    }

                    // if we reach here numbers are <= 9999, so at most 4 chars long
                    let mut n = n as isize; // possibly reduce 64bit math

                    // decode 2 more chars, if > 2 chars
                    if n >= 100 {
                        let d1 = (n % 100) << 1;
                        n /= 100;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    // decode last 1 or 2 chars
                    if n < 10 {
                        curr -= 1;
                        *buf_ptr.offset(curr) = (n as u8) + b'0';
                    } else {
                        let d1 = n << 1;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }
                }

                let len = buf.len() - curr as usize;
                unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
            }
        }
    )*};
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($t:ident),*) => {$(
        impl_IntegerCommon!($t);

        impl IntegerPrivate for $t {
            #[allow(unused_comparisons)]
            fn write_to(self, buf: &mut [u8; MAX_LEN]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    curr -= rem.write_to(buf).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - buf.len() as isize) as *mut _;
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
impl_Integer128!(i128, u128);
<|endoftext|>


<commit_before>#![feature(std_misc)]
use std::sync::Semaphore;
use std::thread;

pub struct ScopedThreadPool {
    sem: std::sync::Semaphore,
}

impl ScopedThreadPool {
    pub fn new(size: isize) -> ScopedThreadPool {
       ScopedThreadPool { sem: std::sync::Semaphore::new(size) }
    }

    pub fn execute<'a, T, F>(&'a self, func: F) -> std::thread::JoinGuard<'a, T>
        where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
    {
       let guard = self.sem.access();
       thread::scoped(move || {
           let _guard = guard;
           func()
       })
    }
}

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

    #[test]
    // TODO find a better way to test than have someone pay attention to the commandline...
    fn it_works() {
        let pool = ScopedThreadPool::new(2);

        let mut guards: Vec<thread::JoinGuard<()>> = Vec::new();

        for _ in (0..3) {
            guards.push(pool.execute(move || {
                thread::sleep_ms(1000);
                println!("Things are happening!");
            }));
        }
    }
}
<commit_msg>fix(pool-size) only allow unsigned pool sizes<commit_after>#![feature(std_misc)]
use std::sync::Semaphore;
use std::thread;

pub struct ScopedThreadPool {
    sem: std::sync::Semaphore,
}

impl ScopedThreadPool {
    pub fn new(size: u32) -> ScopedThreadPool {
       ScopedThreadPool { sem: std::sync::Semaphore::new(size as isize) /* as safe here? */}
    }

    pub fn execute<'a, T, F>(&'a self, func: F) -> std::thread::JoinGuard<'a, T>
        where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
    {
       let guard = self.sem.access();
       thread::scoped(move || {
           let _guard = guard;
           func()
       })
    }
}

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

    #[test]
    // TODO find a better way to test than have someone pay attention to the commandline...
    fn it_works() {
        let pool = ScopedThreadPool::new(2);

        let mut guards: Vec<thread::JoinGuard<()>> = Vec::new();

        for _ in (0..3) {
            guards.push(pool.execute(move || {
                thread::sleep_ms(1000);
                println!("Things are happening!");
            }));
        }
    }
}
<|endoftext|>


<commit_before>use std::ops;
use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};

type RefCount = u16;

struct StorageInner<T> {
    data: Vec<T>,
    meta: Vec<RefCount>,
    free_list: Vec<usize>,
}

struct Pending {
    add_ref: Vec<usize>,
    sub_ref: Vec<usize>,
}

type StorageRef<T> = Arc<RwLock<StorageInner<T>>>;
type PendingRef = Arc<Mutex<Pending>>;
pub struct Storage<T>(StorageRef<T>, PendingRef);

pub struct Pointer<T> {
    index: usize,
    target: StorageRef<T>,
    pending: PendingRef,
}

pub struct ReadLock<'a, T: 'a> {
    guard: RwLockReadGuard<'a, StorageInner<T>>,
    storage: StorageRef<T>,
    pending: PendingRef,
}

pub struct WriteLock<'a, T: 'a> {
    guard: RwLockWriteGuard<'a, StorageInner<T>>,
    storage: StorageRef<T>,
    pending: PendingRef,
}

impl<T> Storage<T> {
    /// Create a new empty storage.
    pub fn new() -> Storage<T> {
        let inner = StorageInner {
            data: Vec::new(),
            meta: Vec::new(),
            free_list: Vec::new(),
        };
        let pending = Pending {
            add_ref: Vec::new(),
            sub_ref: Vec::new(),
        };
        Storage(Arc::new(RwLock::new(inner)), Arc::new(Mutex::new(pending)))
    }

    pub fn read(&self) -> ReadLock<T> {
        ReadLock {
            guard: self.0.read().unwrap(),
            storage: self.0.clone(),
            pending: self.1.clone(),
        }
    }

    pub fn write(&mut self) -> WriteLock<T> {
        let mut s = self.0.write().unwrap();
        // process the pending refcount changes
        let mut pending = self.1.lock().unwrap();
        for index in pending.add_ref.drain(..) {
            s.meta[index] += 1;
        }
        for index in pending.sub_ref.drain(..) {
            s.meta[index] -= 1;
            if s.meta[index] == 0 {
                s.free_list.push(index);
            }
        }
        // return the lock
        WriteLock {
            guard: s,
            storage: self.0.clone(),
            pending: self.1.clone(),
        }
    }
}

impl<T> Clone for Pointer<T> {
    fn clone(&self) -> Pointer<T> {
        Pointer {
            index: self.index,
            target: self.target.clone(),
            pending: self.pending.clone(),
        }
    }
}

impl<T> PartialEq for Pointer<T> {
    fn eq(&self, other: &Pointer<T>) -> bool {
        self.index == other.index &&
        &*self.target as *const _ == &*other.target as *const _
    }
}

impl<T> Drop for Pointer<T> {
    fn drop(&mut self) {
        self.pending.lock().unwrap().sub_ref.push(self.index);
    }
}

// Warning: this exposes deleted entries
impl<'a, T> ops::Deref for ReadLock<'a, T> {
    type Target = [T];
    fn deref(&self) -> &Self::Target {
        &self.guard.data
    }
}

impl<'a, T> ReadLock<'a, T> {
    pub fn access(&self, ptr: &Pointer<T>) -> &T {
        debug_assert_eq!(&*self.storage as *const _, &*ptr.target as *const _);
        &self.guard.data[ptr.index]
    }

    pub fn pin(&self, index: usize) -> Option<Pointer<T>> {
        if index < self.guard.data.len() && self.guard.meta[index] != 0 {
            self.pending.lock().unwrap().add_ref.push(index);
            Some(Pointer {
                index: index,
                target: self.storage.clone(),
                pending: self.pending.clone(),
            })
        } else {
            None
        }
    }
}

// Warning: this exposes deleted entries
impl<'a, T> ops::Deref for WriteLock<'a, T> {
    type Target = [T];
    fn deref(&self) -> &Self::Target {
        &self.guard.data
    }
}

// Warning: this exposes deleted entries
impl<'a, T> ops::DerefMut for WriteLock<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.guard.data
    }
}

impl<'a, T> WriteLock<'a, T> {
    pub fn access(&mut self, ptr: &Pointer<T>) -> &mut T {
        debug_assert_eq!(&*self.storage as *const _, &*ptr.target as *const _);
        &mut self.guard.data[ptr.index]
    }

    pub fn create(&mut self, value: T) -> Pointer<T> {
        let index = match self.guard.free_list.pop() {
            Some(i) => {
                debug_assert_eq!(self.guard.meta[i], 0);
                self.guard.data[i] = value;
                self.guard.meta[i] = 1;
                i
            },
            None => {
                debug_assert_eq!(self.guard.data.len(), self.guard.meta.len());
                self.guard.data.push(value);
                self.guard.meta.push(1);
                self.guard.meta.len() - 1
            },
        };
        Pointer {
            index: index,
            target: self.storage.clone(),
            pending: self.pending.clone(),
        }
    }
}
<commit_msg>Added Storage::with_capacity constructor<commit_after>use std::ops;
use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};

type RefCount = u16;

struct StorageInner<T> {
    data: Vec<T>,
    meta: Vec<RefCount>,
    free_list: Vec<usize>,
}

struct Pending {
    add_ref: Vec<usize>,
    sub_ref: Vec<usize>,
}

type StorageRef<T> = Arc<RwLock<StorageInner<T>>>;
type PendingRef = Arc<Mutex<Pending>>;
pub struct Storage<T>(StorageRef<T>, PendingRef);

pub struct Pointer<T> {
    index: usize,
    target: StorageRef<T>,
    pending: PendingRef,
}

pub struct ReadLock<'a, T: 'a> {
    guard: RwLockReadGuard<'a, StorageInner<T>>,
    storage: StorageRef<T>,
    pending: PendingRef,
}

pub struct WriteLock<'a, T: 'a> {
    guard: RwLockWriteGuard<'a, StorageInner<T>>,
    storage: StorageRef<T>,
    pending: PendingRef,
}

impl<T> Storage<T> {
    fn from_inner(inner: StorageInner<T>) -> Storage<T> {
        let pending = Pending {
            add_ref: Vec::new(),
            sub_ref: Vec::new(),
        };
        Storage(Arc::new(RwLock::new(inner)),
                Arc::new(Mutex::new(pending)))
    }

    /// Create a new empty storage.
    pub fn new() -> Storage<T> {
        Self::from_inner(StorageInner {
            data: Vec::new(),
            meta: Vec::new(),
            free_list: Vec::new(),
        })
    }

    /// Create a new empty storage with specified capacity.
    pub fn with_capacity(capacity: usize) -> Storage<T> {
        Self::from_inner(StorageInner {
            data: Vec::with_capacity(capacity),
            meta: Vec::with_capacity(capacity),
            free_list: Vec::new(),
        })
    }

    pub fn read(&self) -> ReadLock<T> {
        ReadLock {
            guard: self.0.read().unwrap(),
            storage: self.0.clone(),
            pending: self.1.clone(),
        }
    }

    pub fn write(&self) -> WriteLock<T> {
        let mut s = self.0.write().unwrap();
        // process the pending refcount changes
        let mut pending = self.1.lock().unwrap();
        for index in pending.add_ref.drain(..) {
            s.meta[index] += 1;
        }
        for index in pending.sub_ref.drain(..) {
            s.meta[index] -= 1;
            if s.meta[index] == 0 {
                s.free_list.push(index);
            }
        }
        // return the lock
        WriteLock {
            guard: s,
            storage: self.0.clone(),
            pending: self.1.clone(),
        }
    }
}

impl<T> Clone for Pointer<T> {
    fn clone(&self) -> Pointer<T> {
        Pointer {
            index: self.index,
            target: self.target.clone(),
            pending: self.pending.clone(),
        }
    }
}

impl<T> PartialEq for Pointer<T> {
    fn eq(&self, other: &Pointer<T>) -> bool {
        self.index == other.index &&
        &*self.target as *const _ == &*other.target as *const _
    }
}

impl<T> Drop for Pointer<T> {
    fn drop(&mut self) {
        self.pending.lock().unwrap().sub_ref.push(self.index);
    }
}

// Warning: this exposes deleted entries
impl<'a, T> ops::Deref for ReadLock<'a, T> {
    type Target = [T];
    fn deref(&self) -> &Self::Target {
        &self.guard.data
    }
}

impl<'a, T> ReadLock<'a, T> {
    pub fn access(&self, ptr: &Pointer<T>) -> &T {
        debug_assert_eq!(&*self.storage as *const _, &*ptr.target as *const _);
        &self.guard.data[ptr.index]
    }

    pub fn pin(&self, index: usize) -> Option<Pointer<T>> {
        if index < self.guard.data.len() && self.guard.meta[index] != 0 {
            self.pending.lock().unwrap().add_ref.push(index);
            Some(Pointer {
                index: index,
                target: self.storage.clone(),
                pending: self.pending.clone(),
            })
        } else {
            None
        }
    }
}

// Warning: this exposes deleted entries
impl<'a, T> ops::Deref for WriteLock<'a, T> {
    type Target = [T];
    fn deref(&self) -> &Self::Target {
        &self.guard.data
    }
}

// Warning: this exposes deleted entries
impl<'a, T> ops::DerefMut for WriteLock<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.guard.data
    }
}

impl<'a, T> WriteLock<'a, T> {
    pub fn access(&mut self, ptr: &Pointer<T>) -> &mut T {
        debug_assert_eq!(&*self.storage as *const _, &*ptr.target as *const _);
        &mut self.guard.data[ptr.index]
    }

    pub fn create(&mut self, value: T) -> Pointer<T> {
        let index = match self.guard.free_list.pop() {
            Some(i) => {
                debug_assert_eq!(self.guard.meta[i], 0);
                self.guard.data[i] = value;
                self.guard.meta[i] = 1;
                i
            },
            None => {
                debug_assert_eq!(self.guard.data.len(), self.guard.meta.len());
                self.guard.data.push(value);
                self.guard.meta.push(1);
                self.guard.meta.len() - 1
            },
        };
        Pointer {
            index: index,
            target: self.storage.clone(),
            pending: self.pending.clone(),
        }
    }
}
<|endoftext|>


<commit_before>extern crate num;
#[macro_use]
extern crate lazy_static;

#[cfg(feature = "postgres")]
#[macro_use]
extern crate postgres as pg_crate;

#[cfg(feature = "serde")]
extern crate serde;
#[cfg(feature = "serde")]
#[cfg(test)]
extern crate serde_json;
#[cfg(feature = "serde")]
#[cfg(test)]
#[macro_use]
extern crate serde_derive;

mod decimal;
mod error;

#[cfg(feature = "postgres")]
mod postgres;
#[cfg(feature = "serde")]
mod serde_types;

pub use decimal::Decimal;
pub use error::Error;
<commit_msg>Added README to RustDocs<commit_after>//!
//! A Decimal implementation written in pure Rust suitable
//! for financial calculations that require significant integral
//! and fractional digits with no round-off errors.
//!
//! The binary representation consists of a 96 bit integer number,
//! a scaling factor used to specify the decimal fraction and a 1
//! bit sign. Because of this representation, trailing zeros are
//! preserved and may be exposed when in string form. These can be
//! truncated using the `round_dp` function.
//!
//! ## Usage
//!
//! Decimal numbers can be created in a few distinct ways, depending
//! on the rust compiler version you're targeting.
//!
//! ### Stable
//!
//! The stable version of rust requires you to create a Decimal number
//! using one of it's convenience methods.
//!
//! ```rust
//! use rust_decimal::Decimal;
//!
//! // Using an integer followed by the decimal points
//! let scaled = Decimal::new(202, 2); // 2.02
//!
//! // From a string representation
//! let from_string = Decimal::from_str("2.02").unwrap(); // 2.02
//!
//! // Using the `Into` trait
//! let my_int : Decimal = 3i32.into();
//!
//! // Using the raw decimal representation
//! // 3.1415926535897932384626433832
//! let pi = Decimal::from_parts(1102470952, 185874565, 1703060790, false, 28);
//! ```
//!
//! ### Nightly
//!
//! With the nightly version of rust you can use a procedural macro using
//! the rust_decimal_macros crate. The advantage of this method is that the
//! decimal numbers are parsed at compile time.
//!
//! ```rust
//! // Procedural macros need importing directly
//! use rust_decimal_macros::*;
//!
//! let number = dec!(-1.23);
//!
//! ```
//!
extern crate num;
#[macro_use]
extern crate lazy_static;

#[cfg(feature = "postgres")]
#[macro_use]
extern crate postgres as pg_crate;

#[cfg(feature = "serde")]
extern crate serde;
#[cfg(feature = "serde")]
#[cfg(test)]
extern crate serde_json;
#[cfg(feature = "serde")]
#[cfg(test)]
#[macro_use]
extern crate serde_derive;

mod decimal;
mod error;

#[cfg(feature = "postgres")]
mod postgres;
#[cfg(feature = "serde")]
mod serde_types;

pub use decimal::Decimal;
pub use error::Error;
<|endoftext|>


<commit_before>/// ! # multihash
/// !
/// ! Implementation of [multihash](https://github.com/multiformats/multihash)
/// ! in Rust.
/// Representation of a Multiaddr.

extern crate ring;
extern crate tiny_keccak;

use std::fmt::Write;

use tiny_keccak::Keccak;
use ring::digest;

mod hashes;
pub use hashes::*;

mod errors;
pub use errors::*;

// Helper macro for encoding input into output using either ring or tiny_keccak
macro_rules! encode {
    (ring, $algorithm:ident, $input:expr, $output:expr) => ({
        let result = digest::digest(&digest::$algorithm, $input);
        debug_assert!($output.len() == result.as_ref().len());
        $output.copy_from_slice(result.as_ref());
    });
    (tiny, $constructor:ident, $input:expr, $output:expr) => ({
        let mut kec = Keccak::$constructor();
        kec.update($input);
        kec.finalize($output);
    })
}

// And another one to keep the matching DRY
macro_rules! match_encoder {
    ($hash:ident for ($input:expr, $output:expr) {
        $( $hashtype:ident => $lib:ident :: $method:ident, )*
    }) => ({
        match $hash {
            $(
                Hash::$hashtype => encode!($lib, $method, $input, $output),
            )*

            _ => return Err(Error::UnsupportedType)
        }
    })
}

/// Encodes data into a multihash.
///
/// The returned data is raw bytes.  To make is more human-friendly, you can encode it (hex,
/// base58, base64, etc).
///
/// # Errors
///
/// Will return an error if the specified hash type is not supported.  See the docs for `Hash`
/// to see what is supported.
///
/// # Examples
///
/// ```
/// use multihash::{encode, Hash};
///
/// assert_eq!(
///     encode(Hash::SHA2256, b"hello world").unwrap(),
///     vec![18, 32, 185, 77, 39, 185, 147, 77, 62, 8, 165, 46, 82, 215, 218, 125, 171, 250, 196,
///     132, 239, 227, 122, 83, 128, 238, 144, 136, 247, 172, 226, 239, 205, 233]
/// );
/// ```
///
pub fn encode(hash: Hash, input: &[u8]) -> Result<Vec<u8>, Error> {
    let size = hash.size();
    let mut output = Vec::new();
    output.resize(2 + size as usize, 0);
    output[0] = hash.code();
    output[1] = size;

    match_encoder!(hash for (input, &mut output[2..]) {
        SHA1 => ring::SHA1,
        SHA2256 => ring::SHA256,
        SHA2512 => ring::SHA512,
        SHA3224 => tiny::new_sha3_224,
        SHA3256 => tiny::new_sha3_256,
        SHA3384 => tiny::new_sha3_384,
        SHA3512 => tiny::new_sha3_512,
        Keccak224 => tiny::new_keccak224,
        Keccak256 => tiny::new_keccak256,
        Keccak384 => tiny::new_keccak384,
        Keccak512 => tiny::new_keccak512,
    });

    Ok(output)
}

/// Decodes bytes into a multihash
///
/// # Errors
///
/// Returns an error if the bytes are not a valid multihash.
///
/// # Examples
///
/// ```
/// use multihash::{decode, Hash, Multihash};
///
/// // use the data from the `encode` example
/// let data = vec![18, 32, 185, 77, 39, 185, 147, 77, 62, 8, 165, 46, 82, 215, 218,
/// 125, 171, 250, 196, 132, 239, 227, 122, 83, 128, 238, 144, 136, 247, 172, 226, 239, 205, 233];
///
/// assert_eq!(
///     decode(&data).unwrap(),
///     Multihash {
///         alg: Hash::SHA2256,
///         digest: &data[2..]
///     }
/// );
/// ```
///
pub fn decode(input: &[u8]) -> Result<Multihash, Error> {
    let code = input[0];

    let alg = Hash::from_code(code)?;
    let hash_len = alg.size() as usize;

    // length of input should be exactly hash_len + 2
    if input.len() != hash_len + 2 {
        return Err(Error::BadInputLength);
    }

    Ok(Multihash {
        alg: alg,
        digest: &input[2..],
    })
}

/// Represents a valid multihash, by associating the hash algorithm with the data
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct Multihash<'a> {
    pub alg: Hash,
    pub digest: &'a [u8],
}

/// Convert bytes to a hex representation
pub fn to_hex(bytes: &[u8]) -> String {
    let mut hex = String::with_capacity(bytes.len() * 2);

    for byte in bytes {
        write!(hex, "{:02x}", byte).expect("Can't fail on writing to string");
    }

    hex
}
<commit_msg>Fix a panic when decoding empty input<commit_after>/// ! # multihash
/// !
/// ! Implementation of [multihash](https://github.com/multiformats/multihash)
/// ! in Rust.
/// Representation of a Multiaddr.

extern crate ring;
extern crate tiny_keccak;

use std::fmt::Write;

use tiny_keccak::Keccak;
use ring::digest;

mod hashes;
pub use hashes::*;

mod errors;
pub use errors::*;

// Helper macro for encoding input into output using either ring or tiny_keccak
macro_rules! encode {
    (ring, $algorithm:ident, $input:expr, $output:expr) => ({
        let result = digest::digest(&digest::$algorithm, $input);
        debug_assert!($output.len() == result.as_ref().len());
        $output.copy_from_slice(result.as_ref());
    });
    (tiny, $constructor:ident, $input:expr, $output:expr) => ({
        let mut kec = Keccak::$constructor();
        kec.update($input);
        kec.finalize($output);
    })
}

// And another one to keep the matching DRY
macro_rules! match_encoder {
    ($hash:ident for ($input:expr, $output:expr) {
        $( $hashtype:ident => $lib:ident :: $method:ident, )*
    }) => ({
        match $hash {
            $(
                Hash::$hashtype => encode!($lib, $method, $input, $output),
            )*

            _ => return Err(Error::UnsupportedType)
        }
    })
}

/// Encodes data into a multihash.
///
/// The returned data is raw bytes.  To make is more human-friendly, you can encode it (hex,
/// base58, base64, etc).
///
/// # Errors
///
/// Will return an error if the specified hash type is not supported.  See the docs for `Hash`
/// to see what is supported.
///
/// # Examples
///
/// ```
/// use multihash::{encode, Hash};
///
/// assert_eq!(
///     encode(Hash::SHA2256, b"hello world").unwrap(),
///     vec![18, 32, 185, 77, 39, 185, 147, 77, 62, 8, 165, 46, 82, 215, 218, 125, 171, 250, 196,
///     132, 239, 227, 122, 83, 128, 238, 144, 136, 247, 172, 226, 239, 205, 233]
/// );
/// ```
///
pub fn encode(hash: Hash, input: &[u8]) -> Result<Vec<u8>, Error> {
    let size = hash.size();
    let mut output = Vec::new();
    output.resize(2 + size as usize, 0);
    output[0] = hash.code();
    output[1] = size;

    match_encoder!(hash for (input, &mut output[2..]) {
        SHA1 => ring::SHA1,
        SHA2256 => ring::SHA256,
        SHA2512 => ring::SHA512,
        SHA3224 => tiny::new_sha3_224,
        SHA3256 => tiny::new_sha3_256,
        SHA3384 => tiny::new_sha3_384,
        SHA3512 => tiny::new_sha3_512,
        Keccak224 => tiny::new_keccak224,
        Keccak256 => tiny::new_keccak256,
        Keccak384 => tiny::new_keccak384,
        Keccak512 => tiny::new_keccak512,
    });

    Ok(output)
}

/// Decodes bytes into a multihash
///
/// # Errors
///
/// Returns an error if the bytes are not a valid multihash.
///
/// # Examples
///
/// ```
/// use multihash::{decode, Hash, Multihash};
///
/// // use the data from the `encode` example
/// let data = vec![18, 32, 185, 77, 39, 185, 147, 77, 62, 8, 165, 46, 82, 215, 218,
/// 125, 171, 250, 196, 132, 239, 227, 122, 83, 128, 238, 144, 136, 247, 172, 226, 239, 205, 233];
///
/// assert_eq!(
///     decode(&data).unwrap(),
///     Multihash {
///         alg: Hash::SHA2256,
///         digest: &data[2..]
///     }
/// );
/// ```
///
pub fn decode(input: &[u8]) -> Result<Multihash, Error> {
    if input.is_empty() {
        return Err(Error::BadInputLength);
    }

    let code = input[0];

    let alg = Hash::from_code(code)?;
    let hash_len = alg.size() as usize;

    // length of input should be exactly hash_len + 2
    if input.len() != hash_len + 2 {
        return Err(Error::BadInputLength);
    }

    Ok(Multihash {
        alg: alg,
        digest: &input[2..],
    })
}

/// Represents a valid multihash, by associating the hash algorithm with the data
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct Multihash<'a> {
    pub alg: Hash,
    pub digest: &'a [u8],
}

/// Convert bytes to a hex representation
pub fn to_hex(bytes: &[u8]) -> String {
    let mut hex = String::with_capacity(bytes.len() * 2);

    for byte in bytes {
        write!(hex, "{:02x}", byte).expect("Can't fail on writing to string");
    }

    hex
}
<|endoftext|>