<commit_before>/// Macro to duplicate code a per-storage type basis. The given code is duplicated in new modules
/// named for each storage type. A type alias, `V`, is generated that code can use for the type.
/// `@...` match arms are considered private.
///
/// * `$attr`: Module attributes. Generally used to set documentation comments for storage type
///   modules generated by the macro.
/// * `$T`: Types to generate a module for. Accepts all underlying storage types along with a number
///   of different categories:
///   * `All`: `usize`, `u8`, `u16`, `u32`, `u64`, `isize`, `i8`, `i16`, `i32`, `i64`, `BigInt`,
///     `BigUint`, `Rational`, `Rational32`, `Rational64`, `BigRational`, `f32`, and `f64`.
///   * `PrimInt`: `usize`, `u8`, `u16`, `u32`, `u64`, `isize`, `i8`, `i16`, `i32`, `i64`.
///   * `Ratio`: `Rational`, `Rational32`, `Rational64`, and `BigRational`.
///   * `Float`: `f32` and `f64`.
///   * `Signed`: `isize`, `i8`, `i16`, `i32`, `i64`, `BigInt`, `Rational`, `Rational32`,
///     `Rational64`, `BigRational`, `f32`, and `f64`.
///   * `Unsigned`: `usize`, `u8`, `u16`, `u32`, `u64`, and `BigUint`.
/// * `$tt`: Code to place into each storage type module.
///
#[cfg_attr(all(feature = "f32", feature = "f64"), doc = " ```rust")]
#[cfg_attr(not(all(feature = "f32", feature = "f64")), doc = " ```rust,ignore")]
/// #[macro_use]
/// extern crate uom;
///
/// fn main() {
///     f32::do_work(1.234_f32);
///     f64::do_work(1.234_f64);
/// }
///
/// storage_types! {
///     /// Type modules.
///     pub types: Float;
///
///     pub fn do_work(_v: V) {}
/// }
/// ```
#[macro_export]
macro_rules! storage_types {
    ($(#[$attr:meta])* types: $($T:ident),+; $($tt:tt)*) => {
        storage_types!(@types ($(#[$attr])*) @mod $($T),+; ($($tt)*));
    };
    ($(#[$attr:meta])* pub types: $($T:ident),+; $($tt:tt)*) => {
        storage_types!(@types ($(#[$attr])*) @pub_mod $($T),+; ($($tt)*));
    };
    (@types $attr:tt @$M:ident $($T:ident),+; $tt:tt) => {
        $(storage_types!(@type $attr @$M $T $tt);)+
    };
    (@type ($(#[$attr:meta])*) @$M:ident usize ($($tt:tt)*)) => {
        #[cfg(feature = "usize")]
        storage_types!(@$M $(#[$attr])* usize, usize; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident u8 ($($tt:tt)*)) => {
        #[cfg(feature = "u8")]
        storage_types!(@$M $(#[$attr])* u8, u8; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident u16 ($($tt:tt)*)) => {
        #[cfg(feature = "u16")]
        storage_types!(@$M $(#[$attr])* u16, u16; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident u32 ($($tt:tt)*)) => {
        #[cfg(feature = "u32")]
        storage_types!(@$M $(#[$attr])* u32, u32; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident u64 ($($tt:tt)*)) => {
        #[cfg(feature = "u64")]
        storage_types!(@$M $(#[$attr])* u64, u64; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident isize ($($tt:tt)*)) => {
        #[cfg(feature = "isize")]
        storage_types!(@$M $(#[$attr])* isize, isize; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident i8 ($($tt:tt)*)) => {
        #[cfg(feature = "i8")]
        storage_types!(@$M $(#[$attr])* i8, i8; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident i16 ($($tt:tt)*)) => {
        #[cfg(feature = "i16")]
        storage_types!(@$M $(#[$attr])* i16, i16; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident i32 ($($tt:tt)*)) => {
        #[cfg(feature = "i32")]
        storage_types!(@$M $(#[$attr])* i32, i32; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident i64 ($($tt:tt)*)) => {
        #[cfg(feature = "i64")]
        storage_types!(@$M $(#[$attr])* i64, i64; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident BigInt ($($tt:tt)*)) => {
        #[cfg(feature = "bigint")]
        storage_types!(@$M $(#[$attr])* bigint, $crate::num::BigInt; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident BigUint ($($tt:tt)*)) => {
        #[cfg(feature = "biguint")]
        storage_types!(@$M $(#[$attr])* biguint, $crate::num::BigUint; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident Rational ($($tt:tt)*)) => {
        #[cfg(feature = "rational")]
        storage_types!(@$M $(#[$attr])* rational, $crate::num::Rational; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident Rational32 ($($tt:tt)*)) => {
        #[cfg(feature = "rational32")]
        storage_types!(@$M $(#[$attr])* rational32, $crate::num::rational::Rational32; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident Rational64 ($($tt:tt)*)) => {
        #[cfg(feature = "rational64")]
        storage_types!(@$M $(#[$attr])* rational64, $crate::num::rational::Rational64; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident BigRational ($($tt:tt)*)) => {
        #[cfg(feature = "bigrational")]
        storage_types!(@$M $(#[$attr])* bigrational, $crate::num::BigRational; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident f32 ($($tt:tt)*)) => {
        #[cfg(feature = "f32")]
        storage_types!(@$M $(#[$attr])* f32, f32; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident f64 ($($tt:tt)*)) => {
        #[cfg(feature = "f64")]
        storage_types!(@$M $(#[$attr])* f64, f64; $($tt)*);
    };
    (@type ($(#[$attr:meta])*) @$M:ident All ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M usize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M isize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigInt ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigUint ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigRational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f64 ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident PrimInt ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M usize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M isize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i64 ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Ratio ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M Rational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigRational ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Float ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M f32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f64 ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Signed ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M isize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigInt ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigRational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f64 ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Unsigned ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M usize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigUint ($($tt)*));
    };
    (@mod $(#[$attr:meta])* $M:ident, $V:ty; $($tt:tt)*) => {
        $(#[$attr])*
        mod $M {
            #[allow(dead_code)]
            type V = $V;

            $($tt)*
        }
    };
    (@pub_mod $(#[$attr:meta])* $M:ident, $V:ty; $($tt:tt)*) => {
        $(#[$attr])*
        pub mod $M {
            #[allow(dead_code)]
            type V = $V;

            $($tt)*
        }
    };
    ($($tt:tt)*) => {
        storage_types! {
            types: All;

            $($tt)*
        }
    };
}
<commit_msg>Use separate macro for each storage type<commit_after>/// Macro to duplicate code a per-storage type basis. The given code is duplicated in new modules
/// named for each storage type. A type alias, `V`, is generated that code can use for the type.
/// `@...` match arms are considered private.
///
/// * `$attr`: Module attributes. Generally used to set documentation comments for storage type
///   modules generated by the macro.
/// * `$T`: Types to generate a module for. Accepts all underlying storage types along with a number
///   of different categories:
///   * `All`: `usize`, `u8`, `u16`, `u32`, `u64`, `isize`, `i8`, `i16`, `i32`, `i64`, `BigInt`,
///     `BigUint`, `Rational`, `Rational32`, `Rational64`, `BigRational`, `f32`, and `f64`.
///   * `PrimInt`: `usize`, `u8`, `u16`, `u32`, `u64`, `isize`, `i8`, `i16`, `i32`, `i64`.
///   * `Ratio`: `Rational`, `Rational32`, `Rational64`, and `BigRational`.
///   * `Float`: `f32` and `f64`.
///   * `Signed`: `isize`, `i8`, `i16`, `i32`, `i64`, `BigInt`, `Rational`, `Rational32`,
///     `Rational64`, `BigRational`, `f32`, and `f64`.
///   * `Unsigned`: `usize`, `u8`, `u16`, `u32`, `u64`, and `BigUint`.
/// * `$tt`: Code to place into each storage type module.
///
#[cfg_attr(all(feature = "f32", feature = "f64"), doc = " ```rust")]
#[cfg_attr(not(all(feature = "f32", feature = "f64")), doc = " ```rust,ignore")]
/// #[macro_use]
/// extern crate uom;
///
/// fn main() {
///     f32::do_work(1.234_f32);
///     f64::do_work(1.234_f64);
/// }
///
/// storage_types! {
///     /// Type modules.
///     pub types: Float;
///
///     pub fn do_work(_v: V) {}
/// }
/// ```
#[macro_export]
macro_rules! storage_types {
    ($(#[$attr:meta])* types: $($T:ident),+; $($tt:tt)*) => {
        storage_types!(@types ($(#[$attr])*) @mod $($T),+; ($($tt)*));
    };
    ($(#[$attr:meta])* pub types: $($T:ident),+; $($tt:tt)*) => {
        storage_types!(@types ($(#[$attr])*) @pub_mod $($T),+; ($($tt)*));
    };
    (@types $attr:tt @$M:ident $($T:ident),+; $tt:tt) => {
        $(storage_types!(@type $attr @$M $T $tt);)+
    };
    (@type ($(#[$attr:meta])*) @$M:ident usize ($($tt:tt)*)) => {
        storage_type_usize!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident u8 ($($tt:tt)*)) => {
        storage_type_u8!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident u16 ($($tt:tt)*)) => {
        storage_type_u16!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident u32 ($($tt:tt)*)) => {
        storage_type_u32!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident u64 ($($tt:tt)*)) => {
        storage_type_u64!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident isize ($($tt:tt)*)) => {
        storage_type_isize!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident i8 ($($tt:tt)*)) => {
        storage_type_i8!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident i16 ($($tt:tt)*)) => {
        storage_type_i16!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident i32 ($($tt:tt)*)) => {
        storage_type_i32!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident i64 ($($tt:tt)*)) => {
        storage_type_i64!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident BigInt ($($tt:tt)*)) => {
        storage_type_bigint!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident BigUint ($($tt:tt)*)) => {
        storage_type_biguint!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Rational ($($tt:tt)*)) => {
        storage_type_rational!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Rational32 ($($tt:tt)*)) => {
        storage_type_rational32!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Rational64 ($($tt:tt)*)) => {
        storage_type_rational64!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident BigRational ($($tt:tt)*)) => {
        storage_type_bigrational!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident f32 ($($tt:tt)*)) => {
        storage_type_f32!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident f64 ($($tt:tt)*)) => {
        storage_type_f64!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident All ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M usize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M isize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigInt ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigUint ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigRational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f64 ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident PrimInt ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M usize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M isize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i64 ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Ratio ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M Rational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigRational ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Float ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M f32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f64 ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Signed ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M isize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M i64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigInt ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M Rational64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigRational ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M f64 ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident Unsigned ($($tt:tt)*)) => {
        storage_types!(@type ($(#[$attr])*) @$M usize ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u8 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u16 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u32 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M u64 ($($tt)*));
        storage_types!(@type ($(#[$attr])*) @$M BigUint ($($tt)*));
    };
    (@mod ($(#[$attr:meta])*) $M:ident, $V:ty; ($($tt:tt)*)) => {
        $(#[$attr])*
        mod $M {
            #[allow(dead_code)]
            type V = $V;

            $($tt)*
        }
    };
    (@pub_mod ($(#[$attr:meta])*) $M:ident, $V:ty; ($($tt:tt)*)) => {
        $(#[$attr])*
        pub mod $M {
            #[allow(dead_code)]
            type V = $V;

            $($tt)*
        }
    };
    ($($tt:tt)*) => {
        storage_types! {
            types: All;

            $($tt)*
        }
    };
}

macro_rules! storage_type_types {
    ($($macro_name:ident!($feature:tt, $name:ident, $($type:tt)+);)+) => {
        $(#[macro_export]
        #[doc(hidden)]
        #[cfg(feature = $feature)]
        macro_rules! $macro_name {
            ($attr:tt @$M:ident $tt:tt) => {
                storage_types!(@$M $attr $name, $($type)+; $tt);
            };
        }

        #[macro_export]
        #[doc(hidden)]
        #[cfg(not(feature = $feature))]
        macro_rules! $macro_name {
            ($attr:tt @$M:ident $tt:tt) => {
            };
        })+
    };
}

storage_type_types! {
    storage_type_usize!("usize", usize, usize);
    storage_type_u8!("u8", u8, u8);
    storage_type_u16!("u16", u16, u16);
    storage_type_u32!("u32", u32, u32);
    storage_type_u64!("u64", u64, u64);
    storage_type_isize!("isize", isize, isize);
    storage_type_i8!("i8", i8, i8);
    storage_type_i16!("i16", i16, i16);
    storage_type_i32!("i32", i32, i32);
    storage_type_i64!("i64", i64, i64);
    storage_type_bigint!("bigint", bigint, $crate::num::BigInt);
    storage_type_biguint!("biguint", biguint, $crate::num::BigUint);
    storage_type_rational!("rational", rational, $crate::num::Rational);
    storage_type_rational32!("rational32", rational32, $crate::num::rational::Rational32);
    storage_type_rational64!("rational64", rational64, $crate::num::rational::Rational64);
    storage_type_bigrational!("bigrational", bigrational, $crate::num::BigRational);
    storage_type_f32!("f32", f32, f32);
    storage_type_f64!("f64", f64, f64);
}
<|endoftext|>


<commit_before>use endpoint::Endpoint;
use options::Options;
use result::ZmqResult;
use socket_base::{SocketBase, SocketMessage};

use std::io::extensions;
use std::io::TcpStream;
use std::sync::{RWLock, Arc};

static V2_GREETING_SIZE: uint = 12;
static NO_PROGRESS_LIMIT: uint = 1000;
static SIGNATURE_SIZE: uint = 10;
static ZMTP_1_0: u8 = 0;
static ZMTP_2_0: u8 = 1;

fn proxy_write(chan: Receiver<Box<Vec<u8>>>, mut stream: TcpStream) {
    loop {
        match chan.recv_opt() {
            Ok(buf) => match stream.write(buf.as_slice()) {
                Err(_) => break,
                _ => ()
            },
            _ => break
        }
    }
}

struct InnerStreamEngine {
    chan: Sender<ZmqResult<SocketMessage>>,
    stream: TcpStream,
    options: Arc<RWLock<Options>>,
    sender: Sender<Box<Vec<u8>>>,
}

impl InnerStreamEngine {
    fn run(&mut self) {
        let mut signature = box vec!();
        signature.push(0xffu8);
        extensions::u64_to_be_bytes(
            (self.options.read().identity_size + 1) as u64, 8, |v| signature.push_all(v));
        signature.push(0x7fu8);
        println!(">>> Sending signature: {}", signature);
        self.sender.send(signature);

        let mut greeting_recv = [0u8, ..V2_GREETING_SIZE];
        let mut greeting_bytes_read = 0;
        let mut zeros = 0;
        while greeting_bytes_read < V2_GREETING_SIZE {
            match self.stream.read(greeting_recv.mut_slice_from(greeting_bytes_read)) {
                Ok(0) => {
                    println!("ZERO");
                    zeros += 1;
                    if zeros > NO_PROGRESS_LIMIT {
                        return;
                    } else {
                        continue;
                    }
                }
                Ok(n) => {
                    greeting_bytes_read += n;
                }
                _ => return,
            }
            println!(">>> Greeting bytes so far: {}", greeting_recv.as_slice());

            //  We have received at least one byte from the peer.
            //  If the first byte is not 0xff, we know that the
            //  peer is using unversioned protocol.
            if greeting_recv[0] != 0xff {
                return;
            }

            if greeting_bytes_read < SIGNATURE_SIZE {
                continue;
            }

            //  Inspect the right-most bit of the 10th byte (which coincides
            //  with the 'flags' field if a regular message was sent).
            //  Zero indicates this is a header of identity message
            //  (i.e. the peer is using the unversioned protocol).
            if greeting_recv[9] & 0x01 == 0 {
                return;
            }

            //  The peer is using versioned protocol.
            //  Send the version number.
            self.sender.send(box [1u8].into_owned());

            if greeting_bytes_read > SIGNATURE_SIZE {
                match greeting_recv[10] {
                    ZMTP_1_0 | ZMTP_2_0 => {
                        println!(">>> ZMTP 2.0");
                        // TODO: send options.type
                    }
                    _ => {
                        println!(">>> ZMTP 3.0");
                    }
                }
            }
        }

        loop {
            println!(">>> {}", self.stream.read_exact(1));
        }
    }
}

pub struct StreamEngine {
    chan: Receiver<ZmqResult<SocketMessage>>,
    sender: Sender<Box<Vec<u8>>>,
}

impl StreamEngine {
    pub fn new(stream: TcpStream, options: Arc<RWLock<Options>>) -> StreamEngine {
        let (tx, rx) = channel();
        let receiver = stream.clone();
        let (stx, srx) = channel();
        let stx2 = stx.clone();
        spawn(proc() {
            let mut engine = InnerStreamEngine {
                chan: tx,
                stream: receiver,
                options: options,
                sender: stx2,
            };
            engine.run();
            engine.stream.close_read();
            engine.stream.close_write();
        });
        spawn(proc() {
            proxy_write(srx, stream);
        });

        StreamEngine {
            chan: rx,
            sender: stx,
        }
    }
}

impl Endpoint for StreamEngine {
    fn get_chan<'a>(&'a self) -> &'a Receiver<ZmqResult<SocketMessage>> {
        &self.chan
    }

    fn in_event(&mut self, msg: ZmqResult<SocketMessage>, socket: &mut SocketBase) {
    }

    fn is_critical(&self) -> bool {
        false
    }
}
<commit_msg>fn handshake() and TODO comments<commit_after>use endpoint::Endpoint;
use options::Options;
use result::ZmqResult;
use socket_base::{SocketBase, SocketMessage};

use std::io::extensions;
use std::io::TcpStream;
use std::sync::{RWLock, Arc};

static V2_GREETING_SIZE: uint = 12;
static NO_PROGRESS_LIMIT: uint = 1000;
static SIGNATURE_SIZE: uint = 10;
static ZMTP_1_0: u8 = 0;
static ZMTP_2_0: u8 = 1;

fn proxy_write(chan: Receiver<Box<Vec<u8>>>, mut stream: TcpStream) {
    loop {
        match chan.recv_opt() {
            Ok(buf) => match stream.write(buf.as_slice()) {
                Err(_) => break,
                _ => ()
            },
            _ => break
        }
    }
}

struct InnerStreamEngine {
    chan: Sender<ZmqResult<SocketMessage>>,
    stream: TcpStream,
    options: Arc<RWLock<Options>>,
    sender: Sender<Box<Vec<u8>>>,
}

impl InnerStreamEngine {
    fn run(&mut self) {
        let mut signature = box vec!();
        signature.push(0xffu8);
        extensions::u64_to_be_bytes(
            (self.options.read().identity_size + 1) as u64, 8, |v| signature.push_all(v));
        signature.push(0x7fu8);
        println!(">>> Sending signature: {}", signature);
        self.sender.send(signature);

        self.handshake();

        loop {
            println!(">>> {}", self.stream.read_exact(1));
        }
    }

    fn handshake(&mut self) {
        let mut greeting_recv = [0u8, ..V2_GREETING_SIZE];
        let mut greeting_bytes_read = 0;
        let mut zeros = 0;
        while greeting_bytes_read < V2_GREETING_SIZE {
            match self.stream.read(greeting_recv.mut_slice_from(greeting_bytes_read)) {
                Ok(0) => {
                    println!("ZERO");
                    zeros += 1;
                    if zeros > NO_PROGRESS_LIMIT {
                        return; // TODO: error
                    } else {
                        continue;
                    }
                }
                Ok(n) => {
                    greeting_bytes_read += n;
                }
                _ => return, // TODO: error
            }
            println!(">>> Greeting bytes so far: {}", greeting_recv.as_slice());

            //  We have received at least one byte from the peer.
            //  If the first byte is not 0xff, we know that the
            //  peer is using unversioned protocol.
            if greeting_recv[0] != 0xff {
                return; // TODO: error or ZMTP 1.0
            }

            if greeting_bytes_read < SIGNATURE_SIZE {
                continue;
            }

            //  Inspect the right-most bit of the 10th byte (which coincides
            //  with the 'flags' field if a regular message was sent).
            //  Zero indicates this is a header of identity message
            //  (i.e. the peer is using the unversioned protocol).
            if greeting_recv[9] & 0x01 == 0 {
                return; // TODO: error or ZMTP 1.0
            }

            //  The peer is using versioned protocol.
            //  Send the version number.
            self.sender.send(box [1u8].into_owned());

            if greeting_bytes_read > SIGNATURE_SIZE {
                match greeting_recv[10] {
                    ZMTP_1_0 | ZMTP_2_0 => {
                        println!(">>> ZMTP 2.0");
                        // TODO: send options.type
                    }
                    _ => {
                        println!(">>> ZMTP 3.0");
                    }
                }
            }
        }
    }
}

pub struct StreamEngine {
    chan: Receiver<ZmqResult<SocketMessage>>,
    sender: Sender<Box<Vec<u8>>>,
}

impl StreamEngine {
    pub fn new(stream: TcpStream, options: Arc<RWLock<Options>>) -> StreamEngine {
        let (tx, rx) = channel();
        let receiver = stream.clone();
        let (stx, srx) = channel();
        let stx2 = stx.clone();
        spawn(proc() {
            let mut engine = InnerStreamEngine {
                chan: tx,
                stream: receiver,
                options: options,
                sender: stx2,
            };
            engine.run();
            engine.stream.close_read();
            engine.stream.close_write();
        });
        spawn(proc() {
            proxy_write(srx, stream);
        });

        StreamEngine {
            chan: rx,
            sender: stx,
        }
    }
}

impl Endpoint for StreamEngine {
    fn get_chan<'a>(&'a self) -> &'a Receiver<ZmqResult<SocketMessage>> {
        &self.chan
    }

    fn in_event(&mut self, msg: ZmqResult<SocketMessage>, socket: &mut SocketBase) {
    }

    fn is_critical(&self) -> bool {
        false
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Fabian Schuiki

//! The high-level intermediate representation for SystemVerilog. After name
//! resolution, the AST is lowered into this representation, eliminating a lot
//! of the syntactic sugar represented in the AST, and resolving default and
//! implicit values.

mod lowering;
mod nodes;

pub(crate) use self::lowering::hir_of;
pub use self::nodes::*;

make_arenas!(
    /// An arena to allocate HIR nodes into.
    pub struct Arena<'hir> {
        modules: Module<'hir>,
        ports: Port,
        types: Type,
        inst_target: InstTarget,
        insts: Inst<'hir>,
        type_params: TypeParam,
    }
);
<commit_msg>hir: update module doc<commit_after>// Copyright (c) 2017 Fabian Schuiki

//! The high-level intermediate representation for SystemVerilog.
//!
//! After parsing the AST is lowered into this representation, eliminating a lot
//! of syntactic sugar and resolving any syntactic ambiguities.

mod lowering;
mod nodes;

pub(crate) use self::lowering::hir_of;
pub use self::nodes::*;

make_arenas!(
    /// An arena to allocate HIR nodes into.
    pub struct Arena<'hir> {
        modules: Module<'hir>,
        ports: Port,
        types: Type,
        inst_target: InstTarget,
        insts: Inst<'hir>,
        type_params: TypeParam,
    }
);
<|endoftext|>


<commit_before>
extern crate chrono;
extern crate rustc_serialize;

mod daterecord;
mod direction;
mod error;
mod timeentry;
mod traits;
mod iterators;

use chrono::*;
use csv;
pub use self::daterecord::DateRecord;
pub use self::direction::Direction;
pub use self::error::TimeClockError;
pub use self::iterators::*;
pub use self::timeentry::{TimeEntry, TimeEntryPair};
pub use self::traits::*;
use std::fs::File;
use std::io::SeekFrom;
use std::io::prelude::*;

pub fn read_timesheet<R: Read>(file: R)
                               -> Result<Vec<TimeEntry>, TimeClockError> {
    let mut rdr = csv::Reader::from_reader(file).has_headers(false);
    let mut in_v = rdr.decode().collect::<csv::Result<Vec<TimeEntry>>>()?;
    in_v.sort_by_key(|k| k.time);

    Ok(in_v)
}

/// Reduce pairs of `TimeEntrys` into `DateRecords`
pub fn collect_date_records(records: Vec<TimeEntry>) -> Vec<DateRecord> {
    let mut res: Vec<DateRecord> = Vec::new();
    for rec in timeentry_pairs(records.into_iter()).daterecords() {
        match res.pop() {
            Some(mut r) => {
                if r.combine(&rec) {
                    res.push(r);
                } else {
                    res.push(rec);
                }
            }
            None => res.push(rec),
        }
    }
    res
}

/// Marks the time.
pub fn mark_time(d: Direction,
                 time: DateTime<FixedOffset>,
                 memo: String,
                 mut file: File) {
    let record = TimeEntry {
        dir: d,
        time: time,
        memo: memo,
    };
    // seek in case we write without reading first
    let _ = file.seek(SeekFrom::End(0));
    let mut wtr = csv::Writer::from_writer(file);
    let _ = wtr.encode(record);
}

/// Get the current date and time as a `DateTime`<`FixedOffset`>
pub fn now() -> DateTime<FixedOffset> {
    let lt: DateTime<Local> = Local::now();
    DateTime::parse_from_rfc3339(lt.to_rfc3339().as_ref()).unwrap()
}

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

    #[test]
    fn read_timesheet_test() {
        // test for sorting and general function
        let s = "Out,2016-12-18T16:53:33-0600,\n\
                 In,2016-12-19T20:54:53-0600,\n\
                 In,2016-12-18T13:01:50-0600,\n\
                 Out,2016-12-19T20:54:57-0600,";
        let vs = s.as_bytes();
        let buff = Cursor::new(vs);
        let records = read_timesheet(buff).unwrap();
        for slc in records.chunks(2) {
            assert!(slc[0].dir == Direction::In);
            assert!(slc[1].dir == Direction::Out);
        }
        // test ordering
        assert!(records[0].time < records[1].time);
        assert!(records[1].time < records[2].time);
        assert!(records[2].time < records[3].time);
    }

    #[test]
    #[should_panic(expected = "called `Result::unwrap()` on an `Err` value")]
    fn read_timesheet_haggis_test() {
        // test for sorting and general function
        let s = "Fair fa' your honest, sonsie face,\n\
                 Great chieftain o' the pudding-race!\n\
                 Aboon them a' ye tak your place,\n\
                 Painch, tripe, or thairm:\n\
                 Weel are ye wordy o' a grace\n\
                 As lang's my arm.";
        let vs = s.as_bytes();
        let buff = Cursor::new(vs);
        let records = read_timesheet(buff).unwrap();
        assert!(records[0].dir == Direction::In);
    }

    #[test]
    fn pair_time_entries_test() {
        let s = "Out,2016-12-18T13:01:50-0600,\n\
                 In,2016-12-19T20:54:57-0600,\n\
                 Out,2016-12-20T20:50:57-0600,\n\
                 Out,2016-12-20T20:50:59-0600,\n\
                 In,2016-12-20T21:04:57-0600,";
        let vs = s.as_bytes();
        let buff = Cursor::new(vs);
        let entries = read_timesheet(buff).unwrap();
        let records = timeentry_pairs(entries.into_iter())
            .collect::<Vec<TimeEntryPair>>();

        assert!(records.len() == 4);

        for tep in records {
            assert!(tep.start().dir == Direction::In);
            assert!(tep.end().dir == Direction::Out);
        }
    }

    #[test]
    fn pair_time_entries_double_in_test() {
        let s = "In,2016-12-20T21:01:57-0600,\n\
                 In,2016-12-20T21:04:57-0600,";
        let vs = s.as_bytes();
        let buff = Cursor::new(vs);
        let entries = read_timesheet(buff).unwrap();
        let records = timeentry_pairs(entries.into_iter())
            .collect::<Vec<TimeEntryPair>>();

        assert!(records.len() == 2);

        for tep in records {
            assert!(tep.start().dir == Direction::In);
            assert!(tep.end().dir == Direction::Out);
        }
    }

    #[test]
    fn collect_date_records_test() {
        let time = now();
        let records = vec![TimeEntry::new(Direction::In, time, "In"),
                           TimeEntry::new(Direction::Out, time, "Out")];

        let res = collect_date_records(records);
        assert_eq!(res.len(), 1);
        let dr = res.first().unwrap();
        assert_eq!(dr.date(), time.date());
        assert_eq!(dr.hours(), 0.0);
    }

    #[test]
    fn collect_date_records_tz_test() {
        // test mismatched timezones
        let s = "In,2016-12-18T13:01:50-0500,\n\
                 Out,2016-12-18T13:01:50-0600,";
        let vs = s.as_bytes();
        let buff = Cursor::new(vs);
        let entries = read_timesheet(buff).unwrap();
        let records = collect_date_records(entries);

        assert!(records.len() == 1);
        println!("\n{}", records[0].seconds());
        assert!(records[0].seconds() == 3600.0);
    }
}
<commit_msg>Clean up some tests<commit_after>
extern crate chrono;
extern crate rustc_serialize;

mod daterecord;
mod direction;
mod error;
mod timeentry;
mod traits;
mod iterators;

use chrono::*;
use csv;
pub use self::daterecord::DateRecord;
pub use self::direction::Direction;
pub use self::error::TimeClockError;
pub use self::iterators::*;
pub use self::timeentry::{TimeEntry, TimeEntryPair};
pub use self::traits::*;
use std::fs::File;
use std::io::SeekFrom;
use std::io::prelude::*;

pub fn read_timesheet<R: Read>(file: R)
                               -> Result<Vec<TimeEntry>, TimeClockError> {
    let mut rdr = csv::Reader::from_reader(file).has_headers(false);
    let mut in_v = rdr.decode().collect::<csv::Result<Vec<TimeEntry>>>()?;
    in_v.sort_by_key(|k| k.time);

    Ok(in_v)
}

/// Reduce pairs of `TimeEntrys` into `DateRecords`
pub fn collect_date_records(records: Vec<TimeEntry>) -> Vec<DateRecord> {
    let mut res: Vec<DateRecord> = Vec::new();
    for rec in timeentry_pairs(records.into_iter()).daterecords() {
        match res.pop() {
            Some(mut r) => {
                if r.combine(&rec) {
                    res.push(r);
                } else {
                    res.push(rec);
                }
            }
            None => res.push(rec),
        }
    }
    res
}

/// Marks the time.
pub fn mark_time(d: Direction,
                 time: DateTime<FixedOffset>,
                 memo: String,
                 mut file: File) {
    let record = TimeEntry {
        dir: d,
        time: time,
        memo: memo,
    };
    // seek in case we write without reading first
    let _ = file.seek(SeekFrom::End(0));
    let mut wtr = csv::Writer::from_writer(file);
    let _ = wtr.encode(record);
}

/// Get the current date and time as a `DateTime`<`FixedOffset`>
pub fn now() -> DateTime<FixedOffset> {
    let lt: DateTime<Local> = Local::now();
    DateTime::parse_from_rfc3339(lt.to_rfc3339().as_ref()).unwrap()
}

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

    #[test]
    fn read_timesheet_test() {
        // test for sorting and general function
        let s = "Out,2016-12-18T16:53:33-0600,\n\
                 In,2016-12-19T20:54:53-0600,\n\
                 In,2016-12-18T13:01:50-0600,\n\
                 Out,2016-12-19T20:54:57-0600,";
        let buff = Cursor::new(s.as_bytes());
        let records = read_timesheet(buff).unwrap();
        for slc in records.chunks(2) {
            assert!(slc[0].dir == Direction::In);
            assert!(slc[1].dir == Direction::Out);
        }
        // test ordering
        assert!(records[0].time < records[1].time);
        assert!(records[1].time < records[2].time);
        assert!(records[2].time < records[3].time);
    }

    #[test]
    fn read_timesheet_haggis_test() {
        // test for sorting and general function
        let s = "Fair fa' your honest, sonsie face,\n\
                 Great chieftain o' the pudding-race!\n\
                 Aboon them a' ye tak your place,\n\
                 Painch, tripe, or thairm:\n\
                 Weel are ye wordy o' a grace\n\
                 As lang's my arm.";
        let buff = Cursor::new(s.as_bytes());
        let records = read_timesheet(buff);
        assert!(records.is_err());
    }

    #[test]
    fn pair_time_entries_test() {
        let s = "Out,2016-12-18T13:01:50-0600,\n\
                 In,2016-12-19T20:54:57-0600,\n\
                 Out,2016-12-20T20:50:57-0600,\n\
                 Out,2016-12-20T20:50:59-0600,\n\
                 In,2016-12-20T21:04:57-0600,";
        let buff = Cursor::new(s.as_bytes());
        let entries = read_timesheet(buff).unwrap();
        let records = timeentry_pairs(entries.into_iter())
            .collect::<Vec<TimeEntryPair>>();

        assert!(records.len() == 4);

        for tep in records {
            assert!(tep.start().dir == Direction::In);
            assert!(tep.end().dir == Direction::Out);
        }
    }

    #[test]
    fn pair_time_entries_double_in_test() {
        let s = "In,2016-12-20T21:01:57-0600,\n\
                 In,2016-12-20T21:04:57-0600,";
        let buff = Cursor::new(s.as_bytes());
        let entries = read_timesheet(buff).unwrap();
        let records = timeentry_pairs(entries.into_iter())
            .collect::<Vec<TimeEntryPair>>();

        assert!(records.len() == 2);

        for tep in records {
            assert!(tep.start().dir == Direction::In);
            assert!(tep.end().dir == Direction::Out);
        }
    }

    #[test]
    fn collect_date_records_test() {
        let time = now();
        let records = vec![TimeEntry::new(Direction::In, time, "In"),
                           TimeEntry::new(Direction::Out, time, "Out")];

        let res = collect_date_records(records);
        assert_eq!(res.len(), 1);
        let dr = res.first().unwrap();
        assert_eq!(dr.date(), time.date());
        assert_eq!(dr.hours(), 0.0);
    }

    #[test]
    fn collect_date_records_tz_test() {
        // test mismatched timezones
        let s = "In,2016-12-18T13:01:50-0500,\n\
                 Out,2016-12-18T13:01:50-0600,";
        let buff = Cursor::new(s.as_bytes());
        let entries = read_timesheet(buff).unwrap();
        let records = collect_date_records(entries);

        assert!(records.len() == 1);
        println!("\n{}", records[0].seconds());
        assert!(records[0].seconds() == 3600.0);
    }
}
<|endoftext|>


<commit_before>//! Document feature set
//!

use c_signatures::*;
use libc;
use libc::{c_int, c_void};
use std::cell::RefCell;
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::ptr;
use std::rc::Rc;
use std::str;

use tree::node::Node;

pub(crate) type DocumentRef = Rc<RefCell<_Document>>;

#[derive(Debug)]
pub(crate) struct _Document {
  /// libxml's `DocumentPtr`
  doc_ptr: *mut c_void,
  nodes: HashMap<*mut c_void, Node>,
}

impl _Document {
  /// Internal bookkeeping function, so far only used by `Node::wrap`
  pub(crate) fn insert_node(&mut self, node_ptr: *mut c_void, node: Node) {
    self.nodes.insert(node_ptr, node);
  }
}

/// A libxml2 Document
#[derive(Clone)]
pub struct Document(pub(crate) DocumentRef);

impl Drop for Document {
  ///Free document when it goes out of scope
  fn drop(&mut self) {
    unsafe {
      xmlFreeDoc(self.doc_ptr());
    }
  }
}

impl Document {
  /// Creates a new empty libxml2 document
  pub fn new() -> Result<Self, ()> {
    unsafe {
      let c_version = CString::new("1.0").unwrap();
      let doc_ptr = xmlNewDoc(c_version.as_ptr());
      if doc_ptr.is_null() {
        Err(())
      } else {
        let doc = _Document {
          doc_ptr,
          nodes: HashMap::new(),
        };
        Ok(Document(Rc::new(RefCell::new(doc))))
      }
    }
  }

  pub(crate) fn doc_ptr(&self) -> *mut c_void {
    self.0.borrow().doc_ptr
  }

  /// Creates a new `Document` from an existing libxml2 pointer
  pub fn new_ptr(doc_ptr: *mut c_void) -> Self {
    let doc = _Document {
      doc_ptr,
      nodes: HashMap::new(),
    };
    Document(Rc::new(RefCell::new(doc)))
  }
  /// Write document to `filename`
  pub fn save_file(&self, filename: &str) -> Result<c_int, ()> {
    let c_filename = CString::new(filename).unwrap();
    unsafe {
      let retval = xmlSaveFile(c_filename.as_ptr(), self.doc_ptr());
      if retval < 0 {
        return Err(());
      }
      Ok(retval)
    }
  }

  pub(crate) fn register_node(&self, node_ptr: *mut c_void) -> Node {
    Node::wrap(node_ptr, self.0.clone())
  }

  /// Get the root element of the document
  pub fn get_root_element(&self) -> Option<Node> {
    unsafe {
      let node_ptr = xmlDocGetRootElement(self.doc_ptr());
      if node_ptr.is_null() {
        None
      } else {
        Some(self.register_node(node_ptr))
      }
    }
  }

  /// Sets the root element of the document
  pub fn set_root_element(&mut self, root: &Node) {
    unsafe {
      xmlDocSetRootElement(self.doc_ptr(), root.node_ptr());
      // root.node_is_inserted = true;
    }
  }

  fn ptr_as_result(&mut self, node_ptr: *mut c_void) -> Result<Node, ()> {
    if node_ptr.is_null() {
      Err(())
    } else {
      let node = self.register_node(node_ptr);
      Ok(node)
    }
  }

  /// Import a `Node` from another `Document`
  pub fn import_node(&mut self, node: &mut Node) -> Result<Node, ()> {
    if !node.is_unlinked() {
      return Err(());
    }

    let node_ptr = unsafe { xmlDocCopyNode(node.node_ptr(), self.doc_ptr(), 1) };
    self.ptr_as_result(node_ptr)
  }

  /// Serializes the `Document`
  pub fn to_string(&self, format: bool) -> String {
    unsafe {
      // allocate a buffer to dump into
      let mut receiver = ptr::null_mut();
      let size: c_int = 0;
      let c_utf8 = CString::new("UTF-8").unwrap();

      if !format {
        xmlDocDumpMemoryEnc(self.doc_ptr(), &mut receiver, &size, c_utf8.as_ptr(), 1);
      } else {
        let current_indent = getIndentTreeOutput();
        setIndentTreeOutput(1);
        xmlDocDumpFormatMemoryEnc(self.doc_ptr(), &mut receiver, &size, c_utf8.as_ptr(), 1);
        setIndentTreeOutput(current_indent);
      }

      let c_string = CStr::from_ptr(receiver);
      let node_string = c_string.to_string_lossy().into_owned();
      libc::free(receiver as *mut c_void);

      node_string
    }
  }

  /// Serializes a `Node` owned by this `Document
  pub fn node_to_string(&self, node: &Node) -> String {
    unsafe {
      // allocate a buffer to dump into
      let buf = xmlBufferCreate();

      // dump the node
      xmlNodeDump(
        buf,
        self.doc_ptr(),
        node.node_ptr(),
        1, // level of indentation
        0, /* disable formatting */
      );
      let result_ptr = xmlBufferContent(buf);
      let c_string = CStr::from_ptr(result_ptr);
      let node_string = c_string.to_string_lossy().into_owned();
      xmlBufferFree(buf);

      node_string
    }
  }

  /// Creates a node for an XML processing instruction
  pub fn create_processing_instruction(&mut self, name: &str, content: &str) -> Result<Node, ()> {
    unsafe {
      let c_name = CString::new(name).unwrap();
      let c_content = CString::new(content).unwrap();

      let node_ptr = xmlNewDocPI(self.doc_ptr(), c_name.as_ptr(), c_content.as_ptr());
      if node_ptr.is_null() {
        Err(())
      } else {
        Ok(self.register_node(node_ptr))
      }
    }
  }

  // TODO: Discuss use case, this could probably cause problems
  /// Cast the document as a libxml Node
  pub fn as_node(&self) -> Node {
    // TODO: Memory management? Could be a major pain...
    self.register_node(self.doc_ptr())
  }

  /// Duplicates the libxml2 Document into a new instance
  pub fn dup(&self) -> Result<Self, ()> {
    let doc_ptr = unsafe { xmlCopyDoc(self.doc_ptr(), 1) };
    if doc_ptr.is_null() {
      Err(())
    } else {
      let doc = _Document {
        doc_ptr,
        nodes: HashMap::new(),
      };
      Ok(Document(Rc::new(RefCell::new(doc))))
    }
  }

  /// Duplicates a source libxml2 Document into the empty Document self
  pub fn dup_from(&mut self, source: &Self) -> Result<(), ()> {
    if !self.doc_ptr().is_null() {
      return Err(());
    }

    let doc_ptr = unsafe { xmlCopyDoc(source.doc_ptr(), 1) };
    if doc_ptr.is_null() {
      return Err(());
    }
    self.0.borrow_mut().doc_ptr = doc_ptr;
    Ok(())
  }
}
<commit_msg>explain as_node method for Document<commit_after>//! Document feature set
//!

use c_signatures::*;
use libc;
use libc::{c_int, c_void};
use std::cell::RefCell;
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::ptr;
use std::rc::Rc;
use std::str;

use tree::node::Node;

pub(crate) type DocumentRef = Rc<RefCell<_Document>>;

#[derive(Debug)]
pub(crate) struct _Document {
  /// libxml's `DocumentPtr`
  doc_ptr: *mut c_void,
  nodes: HashMap<*mut c_void, Node>,
}

impl _Document {
  /// Internal bookkeeping function, so far only used by `Node::wrap`
  pub(crate) fn insert_node(&mut self, node_ptr: *mut c_void, node: Node) {
    self.nodes.insert(node_ptr, node);
  }
}

/// A libxml2 Document
#[derive(Clone)]
pub struct Document(pub(crate) DocumentRef);

impl Drop for Document {
  ///Free document when it goes out of scope
  fn drop(&mut self) {
    unsafe {
      xmlFreeDoc(self.doc_ptr());
    }
  }
}

impl Document {
  /// Creates a new empty libxml2 document
  pub fn new() -> Result<Self, ()> {
    unsafe {
      let c_version = CString::new("1.0").unwrap();
      let doc_ptr = xmlNewDoc(c_version.as_ptr());
      if doc_ptr.is_null() {
        Err(())
      } else {
        let doc = _Document {
          doc_ptr,
          nodes: HashMap::new(),
        };
        Ok(Document(Rc::new(RefCell::new(doc))))
      }
    }
  }

  pub(crate) fn doc_ptr(&self) -> *mut c_void {
    self.0.borrow().doc_ptr
  }

  /// Creates a new `Document` from an existing libxml2 pointer
  pub fn new_ptr(doc_ptr: *mut c_void) -> Self {
    let doc = _Document {
      doc_ptr,
      nodes: HashMap::new(),
    };
    Document(Rc::new(RefCell::new(doc)))
  }
  /// Write document to `filename`
  pub fn save_file(&self, filename: &str) -> Result<c_int, ()> {
    let c_filename = CString::new(filename).unwrap();
    unsafe {
      let retval = xmlSaveFile(c_filename.as_ptr(), self.doc_ptr());
      if retval < 0 {
        return Err(());
      }
      Ok(retval)
    }
  }

  pub(crate) fn register_node(&self, node_ptr: *mut c_void) -> Node {
    Node::wrap(node_ptr, self.0.clone())
  }

  /// Get the root element of the document
  pub fn get_root_element(&self) -> Option<Node> {
    unsafe {
      let node_ptr = xmlDocGetRootElement(self.doc_ptr());
      if node_ptr.is_null() {
        None
      } else {
        Some(self.register_node(node_ptr))
      }
    }
  }

  /// Sets the root element of the document
  pub fn set_root_element(&mut self, root: &Node) {
    unsafe {
      xmlDocSetRootElement(self.doc_ptr(), root.node_ptr());
      // root.node_is_inserted = true;
    }
  }

  fn ptr_as_result(&mut self, node_ptr: *mut c_void) -> Result<Node, ()> {
    if node_ptr.is_null() {
      Err(())
    } else {
      let node = self.register_node(node_ptr);
      Ok(node)
    }
  }

  /// Import a `Node` from another `Document`
  pub fn import_node(&mut self, node: &mut Node) -> Result<Node, ()> {
    if !node.is_unlinked() {
      return Err(());
    }

    let node_ptr = unsafe { xmlDocCopyNode(node.node_ptr(), self.doc_ptr(), 1) };
    self.ptr_as_result(node_ptr)
  }

  /// Serializes the `Document`
  pub fn to_string(&self, format: bool) -> String {
    unsafe {
      // allocate a buffer to dump into
      let mut receiver = ptr::null_mut();
      let size: c_int = 0;
      let c_utf8 = CString::new("UTF-8").unwrap();

      if !format {
        xmlDocDumpMemoryEnc(self.doc_ptr(), &mut receiver, &size, c_utf8.as_ptr(), 1);
      } else {
        let current_indent = getIndentTreeOutput();
        setIndentTreeOutput(1);
        xmlDocDumpFormatMemoryEnc(self.doc_ptr(), &mut receiver, &size, c_utf8.as_ptr(), 1);
        setIndentTreeOutput(current_indent);
      }

      let c_string = CStr::from_ptr(receiver);
      let node_string = c_string.to_string_lossy().into_owned();
      libc::free(receiver as *mut c_void);

      node_string
    }
  }

  /// Serializes a `Node` owned by this `Document
  pub fn node_to_string(&self, node: &Node) -> String {
    unsafe {
      // allocate a buffer to dump into
      let buf = xmlBufferCreate();

      // dump the node
      xmlNodeDump(
        buf,
        self.doc_ptr(),
        node.node_ptr(),
        1, // level of indentation
        0, /* disable formatting */
      );
      let result_ptr = xmlBufferContent(buf);
      let c_string = CStr::from_ptr(result_ptr);
      let node_string = c_string.to_string_lossy().into_owned();
      xmlBufferFree(buf);

      node_string
    }
  }

  /// Creates a node for an XML processing instruction
  pub fn create_processing_instruction(&mut self, name: &str, content: &str) -> Result<Node, ()> {
    unsafe {
      let c_name = CString::new(name).unwrap();
      let c_content = CString::new(content).unwrap();

      let node_ptr = xmlNewDocPI(self.doc_ptr(), c_name.as_ptr(), c_content.as_ptr());
      if node_ptr.is_null() {
        Err(())
      } else {
        Ok(self.register_node(node_ptr))
      }
    }
  }

  /// Cast the document as a libxml Node
  pub fn as_node(&self) -> Node {
    // Note: this method is important to keep, as it enables certain low-level libxml2 idioms
    // In particular, method dispatch based on NodeType is only possible when the document can be cast as a Node
    //
    // Memory management is not an issue, as a document node can not be unbound/removed, and does not require
    // any additional deallocation than the Drop of a Document object.
    self.register_node(self.doc_ptr())
  }

  /// Duplicates the libxml2 Document into a new instance
  pub fn dup(&self) -> Result<Self, ()> {
    let doc_ptr = unsafe { xmlCopyDoc(self.doc_ptr(), 1) };
    if doc_ptr.is_null() {
      Err(())
    } else {
      let doc = _Document {
        doc_ptr,
        nodes: HashMap::new(),
      };
      Ok(Document(Rc::new(RefCell::new(doc))))
    }
  }

  /// Duplicates a source libxml2 Document into the empty Document self
  pub fn dup_from(&mut self, source: &Self) -> Result<(), ()> {
    if !self.doc_ptr().is_null() {
      return Err(());
    }

    let doc_ptr = unsafe { xmlCopyDoc(source.doc_ptr(), 1) };
    if doc_ptr.is_null() {
      return Err(());
    }
    self.0.borrow_mut().doc_ptr = doc_ptr;
    Ok(())
  }
}
<|endoftext|>


<commit_before>//! Middleware interfaces for the pathfinder project
//!

use super::super::error::{PathfinderError};
use super::super::engine::serializer::{JsonMessage};

use cli::{CliOptions};
use futures::{Future};
use futures::future::{lazy};

/// Type alias for future result type.
pub type MiddlewareFuture = Box<Future<Item=(), Error=PathfinderError> + 'static>;

/// A trait for types which can be used as middleware during processing a request from a client.
pub trait Middleware {
    /// Applied transforms and checks to an incoming request. If it failed,
    /// then should return a `PathfinderError` instance.
    fn process_request(&self, message: JsonMessage) -> MiddlewareFuture;
}

/// Default struct which is used for reverse proxy without an authentication
/// layer.
pub struct EmptyMiddleware;

impl EmptyMiddleware {
    pub fn new(_cli: &CliOptions) -> EmptyMiddleware {
        EmptyMiddleware {}
    }
}

impl Middleware for EmptyMiddleware {
    /// Returns an empty future which is doesn't doing anything.
    fn process_request(&self, _message: JsonMessage) -> MiddlewareFuture {
        Box::new(lazy(move || Ok(())))
    }
}
<commit_msg>Added Send and Sync markers for Middleware future<commit_after>//! Middleware interfaces for the pathfinder project
//!

use super::super::error::{PathfinderError};
use super::super::engine::serializer::{JsonMessage};

use cli::{CliOptions};
use futures::{Future};
use futures::future::{lazy};

/// Type alias for future result type.
pub type MiddlewareFuture = Box<Future<Item=(), Error=PathfinderError> + Sync + Send + 'static>;

/// A trait for types which can be used as middleware during processing a request from a client.
pub trait Middleware {
    /// Applied transforms and checks to an incoming request. If it failed,
    /// then should return a `PathfinderError` instance.
    fn process_request(&self, message: JsonMessage) -> MiddlewareFuture;
}

/// Default struct which is used for reverse proxy without an authentication
/// layer.
pub struct EmptyMiddleware;

impl EmptyMiddleware {
    pub fn new(_cli: &CliOptions) -> EmptyMiddleware {
        EmptyMiddleware {}
    }
}

impl Middleware for EmptyMiddleware {
    /// Returns an empty future which is doesn't doing anything.
    fn process_request(&self, _message: JsonMessage) -> MiddlewareFuture {
        Box::new(lazy(move || Ok(())))
    }
}
<|endoftext|>


<commit_before>
extern crate rand;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use file_stream_iter::FileStream;
use std::io::Error;
use tftp_specific::PacketType;
use std::str::FromStr;
use std::net::AddrParseError;
use std::error;

pub struct EndPoint{
    local_connection : SocketAddrV4,
    remote_connection : SocketAddrV4
}

impl EndPoint{

    pub fn new(remote : &str) -> Result<EndPoint, AddrParseError>{

        let ipv4 = try!(get_ip_from(remote));
        Ok(EndPoint{
            local_connection : SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 6900),
            remote_connection : SocketAddrV4::new(ipv4, 9990)
        })
    }

    fn start_listen(){

    }

    pub fn recv(&mut self) -> Result<(), Error> {
        // Define the local connection information
        //let ip = Ipv4Addr::new(127, 0, 0, 1);
        //TODO we want to use port 69 here
        //let connection = SocketAddrV4::new(ip, 6900);

        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Read from the socket
        let mut buf = [0u8; 516]; //UDP packet is 516 bytes
        let (amt, src) = try!(socket.recv_from(&mut buf));
        match buf[1]{
            3 =>{
                let block_num : u16 = 0u16 | (buf[2] as u16) << 8 |  buf[3] as u16;
                let block_size = amt - 4;
                println!("{:?}", block_size);
                if block_size < 512{
                    println!("recvr recvd: {:?}", &buf[0 .. amt]);
                    println!("Last block of the file received");
                }
                //send ACK

                let low = block_num & 0x00FF;
                let high = (block_num & 0xFF00) >> 8;

                socket.send_to(&[0,PacketType::ACK as u8, high as u8, low as u8], src);
            },
            _ => {}
        }

        Ok(())
    }

    pub fn send(&mut self) -> Result<(), Error> {
        // Define the local connection (to send the data from)
        //let ip = Ipv4Addr::new(127, 0, 0, 1);
        //TODO generate port # using rand
        //let connection = SocketAddrV4::new(ip, 9992);

        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Define the remote connection (to send the data to)
        //let connection2 = SocketAddrV4::new(ip, 6900);

        // Send data via the socket
        let mut fs = FileStream::new("/home/abhi/code/rust/fei/target/debug/foo.txt".to_string()).unwrap();
        let (buf, num_bytes_read) = fs.next().unwrap();
        let mut v = Vec::with_capacity(num_bytes_read + 4);
        v.push(0);
        v.push(3);
        v.push(0xFF);
        let mut cnt = 0xFF;
        v.push(cnt);
        v.extend_from_slice(&buf[0..num_bytes_read]);
        try!(socket.send_to(v.as_slice(), self.remote_connection));

        let mut buf  = [0; 10];
        socket.recv_from(&mut buf);

        println!("sender recvd {:?}", buf);
        Ok(())
    }

    fn send_file(&mut self, filename : &str) {

    }

    fn create_rrq_wrq_packet(&self, p_type: PacketType, file_name: &str, mode : &'static str)->Vec<u8>{
        let mut v = Vec::with_capacity(2+file_name.len()+1+mode.len()+1);
        v.push(0);
        v.push(p_type as u8);
        v.extend(file_name.as_bytes());
        v.push(0);//zero terminator
        v.extend(mode.as_bytes());
        v.push(0);//zero terminator
        v
    }

    fn get(&mut self, files : &[&str], mode : &'static str) -> Result<(), Error>{
        let socket = try!(UdpSocket::bind(self.local_connection));
        let mut buf  = [0; 516];
        for file in files{
            //start with a RRQ
            let packet = self.create_rrq_wrq_packet(PacketType::RRQ, file, mode);
            try!(socket.send_to(packet.as_slice(), self.remote_connection));

            loop{
                //get the first block of the requested file
                let (amt, src) = try!(socket.recv_from(&mut buf));
                match buf[1]{
                    3 =>{
                        let block_num : u16 = 0u16 | (buf[2] as u16) << 8 |  buf[3] as u16;
                        let block_size = amt - 4;
                        println!("{:?}", block_size);
                        if block_size < 512{
                            println!("recvr recvd: {:?}", &buf[0 .. amt]);
                            println!("Last block of the file received");
                        }
                        //send ACK

                        let low = block_num & 0x00FF;
                        let high = (block_num & 0xFF00) >> 8;

                        socket.send_to(&[0,PacketType::ACK as u8, high as u8, low as u8], src);
                    },
                    _ => {}
                }
                //Flush buf for next read
                //TODO fix this:
                for i in 0..516{
                    buf[0] = 0;
                }
            }

        }

        Ok(())
    }
}

fn get_ip_from(ip : &str) -> Result<Ipv4Addr, AddrParseError>{
    Ipv4Addr::from_str(ip)
}

<commit_msg>Parse filename from the RRQ packet and pass it to the FileStream<commit_after>
extern crate rand;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use file_stream_iter::FileStream;
use std::io::Error;
use tftp_specific::PacketType;
use std::str::FromStr;
use std::net::AddrParseError;
use std::error;
use std::str;

pub struct EndPoint{
    local_connection : SocketAddrV4,
    remote_connection : SocketAddrV4
}

impl EndPoint{

    pub fn new(remote : &str) -> Result<EndPoint, AddrParseError>{

        let ipv4 = try!(get_ip_from(remote));
        Ok(EndPoint{
            local_connection : SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 6900),
            remote_connection : SocketAddrV4::new(ipv4, 9990)
        })
    }

    fn start_listen(&mut self)->Result<(), Error>{
        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Start servicing requests from a client
        // Read from the socket
        let mut buf = [0u8; 516]; //UDP packet is 516 bytes
        let (amt, src) = try!(socket.recv_from(&mut buf));
        match buf[1]{
            1 => { //RRQ
                //Get filename to be sent from the packet
                let mut  i = 2;
                while buf[i] != '\0' as u8{
                    i += 1;
                }
                let filename = str::from_utf8(&buf[2..i]);
                // Send data via the socket
                let mut fs = FileStream::new(String::from(filename.unwrap())).unwrap();
                let (buf, num_bytes_read) = fs.next().unwrap();
                let mut v = Vec::with_capacity(num_bytes_read + 4);
                v.push(0);
                v.push(3);
                v.push(0xFF);
                let mut cnt = 0xFF;
                v.push(cnt);
                v.extend_from_slice(&buf[0..num_bytes_read]);
                try!(socket.send_to(v.as_slice(), self.remote_connection));

            },
            _ => {panic!("unrecognized packet type")}
        }

        Ok(())

    }

    pub fn recv(&mut self) -> Result<(), Error> {
        // Define the local connection information
        //let ip = Ipv4Addr::new(127, 0, 0, 1);
        //TODO we want to use port 69 here
        //let connection = SocketAddrV4::new(ip, 6900);

        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Read from the socket
        let mut buf = [0u8; 516]; //UDP packet is 516 bytes
        let (amt, src) = try!(socket.recv_from(&mut buf));
        match buf[1]{
            3 =>{
                let block_num : u16 = 0u16 | (buf[2] as u16) << 8 |  buf[3] as u16;
                let block_size = amt - 4;
                println!("{:?}", block_size);
                if block_size < 512{
                    println!("recvr recvd: {:?}", &buf[0 .. amt]);
                    println!("Last block of the file received");
                }
                //send ACK

                let low = block_num & 0x00FF;
                let high = (block_num & 0xFF00) >> 8;

                socket.send_to(&[0,PacketType::ACK as u8, high as u8, low as u8], src);
            },
            _ => {}
        }

        Ok(())
    }

    pub fn send(&mut self) -> Result<(), Error> {
        // Define the local connection (to send the data from)
        //let ip = Ipv4Addr::new(127, 0, 0, 1);
        //TODO generate port # using rand
        //let connection = SocketAddrV4::new(ip, 9992);

        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Define the remote connection (to send the data to)
        //let connection2 = SocketAddrV4::new(ip, 6900);

        // Send data via the socket
        let mut fs = FileStream::new("/home/abhi/code/rust/fei/target/debug/foo.txt".to_string()).unwrap();
        let (buf, num_bytes_read) = fs.next().unwrap();
        let mut v = Vec::with_capacity(num_bytes_read + 4);
        v.push(0);
        v.push(3);
        v.push(0xFF);
        let mut cnt = 0xFF;
        v.push(cnt);
        v.extend_from_slice(&buf[0..num_bytes_read]);
        try!(socket.send_to(v.as_slice(), self.remote_connection));

        let mut buf  = [0; 10];
        socket.recv_from(&mut buf);

        println!("sender recvd {:?}", buf);
        Ok(())
    }

    fn send_file(&mut self, filename : &str) {

    }

    fn create_rrq_wrq_packet(&self, p_type: PacketType, file_name: &str, mode : &'static str)->Vec<u8>{
        let mut v = Vec::with_capacity(2+file_name.len()+1+mode.len()+1);
        v.push(0);
        v.push(p_type as u8);
        v.extend(file_name.as_bytes());
        v.push(0);//zero terminator
        v.extend(mode.as_bytes());
        v.push(0);//zero terminator
        v
    }

    fn get(&mut self, files : &[&str], mode : &'static str) -> Result<(), Error>{
        let socket = try!(UdpSocket::bind(self.local_connection));
        let mut buf  = [0; 516];
        for file in files{
            //start with a RRQ
            let packet = self.create_rrq_wrq_packet(PacketType::RRQ, file, mode);
            try!(socket.send_to(packet.as_slice(), self.remote_connection));

            loop{
                //get the first block of the requested file
                let (amt, src) = try!(socket.recv_from(&mut buf));
                match buf[1]{
                    3 =>{
                        let block_num : u16 = 0u16 | (buf[2] as u16) << 8 |  buf[3] as u16;
                        let block_size = amt - 4;
                        println!("{:?}", block_size);
                        if block_size < 512{
                            println!("recvr recvd: {:?}", &buf[0 .. amt]);
                            println!("Last block of the file received");
                        }
                        //send ACK

                        let low = block_num & 0x00FF;
                        let high = (block_num & 0xFF00) >> 8;

                        socket.send_to(&[0,PacketType::ACK as u8, high as u8, low as u8], src);
                    },
                    _ => {}
                }
                //Flush buf for next read
                //TODO fix this:
                for i in 0..516{
                    buf[0] = 0;
                }
            }

        }

        Ok(())
    }
}

fn get_ip_from(ip : &str) -> Result<Ipv4Addr, AddrParseError>{
    Ipv4Addr::from_str(ip)
}

<|endoftext|>


<commit_before>/*

  This struct essentially encapsulates the "instance variables"

*/
pub struct SimpleHdrHistogram {
    pub leading_zeros_count_base: i32,
    pub sub_bucket_mask: i64,
    pub unit_magnitude: i32,
    pub sub_bucket_count: i32,
    pub sub_bucket_half_count: i32,
    pub sub_bucket_half_count_magnitude: i32,
    pub counts: Vec<u64>,
}

/*

  Implementing this trait (Default) for our struct gives us a nice way to
  initialize an instance using default args instead of having to provide all of them

 */
impl Default for SimpleHdrHistogram {
    fn default () -> SimpleHdrHistogram {
        SimpleHdrHistogram {
            leading_zeros_count_base: 0,
            sub_bucket_mask: 0,
            unit_magnitude: 0,
            sub_bucket_count: 0,
            sub_bucket_half_count: 0,
            sub_bucket_half_count_magnitude: 0,
            counts: Vec::new(),
        }
    }
}

pub trait HistogramBase {

    //FIXME this stuff could be mostly unsigned

    //TODO should be default impl of this trait
    fn record_single_value(&self, value: i64) -> Result<(), String>;

    //TODO should be default impl of this trait
    fn counts_array_index(&self, value: i64) -> Result<i32, String>;

    //TODO should be default impl of this trait
    fn counts_array_index_sub(&self, bucket_index: i32, sub_bucket_index: i32) -> i32;

    //TODO should be default impl of this trait
    fn get_bucket_index(&self, value: i64) -> i32;

    //TODO should be default impl of this trait
    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32;

    fn increment_count_at_index(&self, index: i32) -> Result<(), String>;
    fn normalize_index(&self, index: i32, normalizing_index_offset: i32, array_length: i32) ->
        Result<i32, String>;

}

impl HistogramBase for SimpleHdrHistogram {

    fn normalize_index(&self, index: i32, normalizing_index_offset: i32, array_length: i32) ->
Result<i32, String> {

        match normalizing_index_offset {
            0 => Ok(index),
            _ =>
                if ((index > array_length) || (index < 0)) {
                    Err(String::from("index out of covered range"))
                } else {
                    let mut normalized_index = index - normalizing_index_offset;
                    if (normalized_index < 0) {
                        normalized_index += array_length;
                    } else if (normalized_index >= array_length) {
                        normalized_index -=array_length;
                    }
                    Ok(normalized_index)
                }
        }

    }

    fn increment_count_at_index(&self, index: i32) -> Result<(), String> {
        Ok(())
    }

    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32 {
        let sum = bucket_index + self.unit_magnitude;
        value.rotate_right(sum as u32) as i32
    }

    fn get_bucket_index(&self, value: i64) -> i32 {
        let valueOrred = value | self.sub_bucket_mask;
        self.leading_zeros_count_base - valueOrred.leading_zeros() as i32
    }

    fn record_single_value(&self, value: i64) -> Result<(), String> {

        match self.counts_array_index(value) {
            Ok(counts_index) =>
                match self.increment_count_at_index(counts_index) {
                    Ok(_) =>
                    if true {
                        Ok(())
                    } else {
                        Err(String::from("Could not record single value"))
                    },
                    Err(err) => Err(String::from("Could not increment stuff"))
                },
            Err(err) => Err(String::from("Could not get index"))
        }

    }

    fn counts_array_index(&self, value: i64) -> Result<i32, String> {
        if value < 0 {
            Err(String::from("Histogram recorded values cannot be negative."))
        } else {
            let bucket_index = self.get_bucket_index(value);
            let sub_bucket_index = self.get_sub_bucket_index(value, bucket_index);
            let result = self.counts_array_index_sub(bucket_index, sub_bucket_index);
            Ok(result)
        }
    }

    fn counts_array_index_sub(&self, bucket_index: i32, sub_bucket_index: i32) -> i32 {
        assert!(sub_bucket_index < self.sub_bucket_count);
        assert!(bucket_index == 0 || (sub_bucket_index >= self.sub_bucket_half_count));

        let bucket_base_index = (bucket_index + 1) << self.sub_bucket_half_count_magnitude;
        let offset_in_bucket = sub_bucket_index - self.sub_bucket_half_count;

        bucket_base_index + offset_in_bucket
    }
}

#[test]
fn can_record_single_value() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.record_single_value(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }
}

#[test]
fn can_compute_counts_array_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.counts_array_index(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not compute counts array index because error: {}", err))
    }
}

#[test]
fn can_get_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_bucket_index(99);
    assert_eq!(result, 0)
}

#[test]
fn can_get_sub_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_sub_bucket_index(99, 1);
    assert_eq!(result, 0)
}<commit_msg>wip not compiling<commit_after>/*

  This struct essentially encapsulates the "instance variables"

*/
pub struct SimpleHdrHistogram {
    pub leading_zeros_count_base: i32,
    pub sub_bucket_mask: i64,
    pub unit_magnitude: i32,
    pub sub_bucket_count: i32,
    pub sub_bucket_half_count: i32,
    pub sub_bucket_half_count_magnitude: i32,
    pub counts: Vec<u64>,
    pub counts_array_length: i32,
    pub normalizing_index_offset: i32,
}

/*

  Implementing this trait (Default) for our struct gives us a nice way to
  initialize an instance using default args instead of having to provide all of them

 */
impl Default for SimpleHdrHistogram {
    fn default () -> SimpleHdrHistogram {
        SimpleHdrHistogram {
            leading_zeros_count_base: 0,
            sub_bucket_mask: 0,
            unit_magnitude: 0,
            sub_bucket_count: 0,
            sub_bucket_half_count: 0,
            sub_bucket_half_count_magnitude: 0,
            counts: Vec::new(),
            counts_array_length: 0,
            normalizing_index_offset: 0,
        }
    }
}

pub trait HistogramBase {

    //FIXME this stuff could be mostly unsigned

    //TODO should be default impl of this trait
    fn record_single_value(&self, value: i64) -> Result<(), String>;

    //TODO should be default impl of this trait
    fn counts_array_index(&self, value: i64) -> Result<i32, String>;

    //TODO should be default impl of this trait
    fn counts_array_index_sub(&self, bucket_index: i32, sub_bucket_index: i32) -> i32;

    //TODO should be default impl of this trait
    fn get_bucket_index(&self, value: i64) -> i32;

    //TODO should be default impl of this trait
    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32;

    fn increment_count_at_index(&self, index: i32) -> Result<(), String>;
    fn normalize_index(&self, index: i32, normalizing_index_offset: i32, array_length: i32) ->
        Result<i32, String>;

}

impl HistogramBase for SimpleHdrHistogram {

    fn normalize_index(&self, index: i32, normalizing_index_offset: i32, array_length: i32) ->
Result<i32, String> {

        match normalizing_index_offset {
            0 => Ok(index),
            _ =>
                if ((index > array_length) || (index < 0)) {
                    Err(String::from("index out of covered range"))
                } else {
                    let mut normalized_index = index - normalizing_index_offset;
                    if (normalized_index < 0) {
                        normalized_index += array_length;
                    } else if (normalized_index >= array_length) {
                        normalized_index -=array_length;
                    }
                    Ok(normalized_index)
                }
        }

    }

    fn increment_count_at_index(&self, index: i32) -> Result<(), String> {
        let normalized_index =
            self.normalize_index(index, self.normalizing_index_offset, self.counts_array_length);
        match normalized_index {
            Ok(the_index) =>
                self.counts[the_index] = self.counts[the_index] + 1;
                Ok(()),
            Err(err) =>
                Err(err)
        }
    }

    fn get_sub_bucket_index(&self, value: i64, bucket_index: i32) -> i32 {
        let sum = bucket_index + self.unit_magnitude;
        value.rotate_right(sum as u32) as i32
    }

    fn get_bucket_index(&self, value: i64) -> i32 {
        let valueOrred = value | self.sub_bucket_mask;
        self.leading_zeros_count_base - valueOrred.leading_zeros() as i32
    }

    fn record_single_value(&self, value: i64) -> Result<(), String> {

        match self.counts_array_index(value) {
            Ok(counts_index) =>
                match self.increment_count_at_index(counts_index) {
                    Ok(_) =>
                        if true {
                            Ok(())
                        } else {
                            Err(String::from("Could not record single value"))
                        },
                    Err(err) => Err(String::from("Could not increment stuff"))
                },
            Err(err) => Err(String::from("Could not get index"))
        }

    }

    fn counts_array_index(&self, value: i64) -> Result<i32, String> {
        if value < 0 {
            Err(String::from("Histogram recorded values cannot be negative."))
        } else {
            let bucket_index = self.get_bucket_index(value);
            let sub_bucket_index = self.get_sub_bucket_index(value, bucket_index);
            let result = self.counts_array_index_sub(bucket_index, sub_bucket_index);
            Ok(result)
        }
    }

    fn counts_array_index_sub(&self, bucket_index: i32, sub_bucket_index: i32) -> i32 {
        assert!(sub_bucket_index < self.sub_bucket_count);
        assert!(bucket_index == 0 || (sub_bucket_index >= self.sub_bucket_half_count));

        let bucket_base_index = (bucket_index + 1) << self.sub_bucket_half_count_magnitude;
        let offset_in_bucket = sub_bucket_index - self.sub_bucket_half_count;

        bucket_base_index + offset_in_bucket
    }
}

#[test]
fn can_record_single_value() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.record_single_value(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not add single record to histogram because error: {}", err))
    }
}

#[test]
fn can_compute_counts_array_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.counts_array_index(99);

    match result {
        Ok(_) => (),
        Err(err) => panic!(format!("could not compute counts array index because error: {}", err))
    }
}

#[test]
fn can_get_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_bucket_index(99);
    assert_eq!(result, 0)
}

#[test]
fn can_get_sub_bucket_index() {
    let the_hist = SimpleHdrHistogram { ..Default::default() };
    let result = the_hist.get_sub_bucket_index(99, 1);
    assert_eq!(result, 0)
}<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io::Write;
use std::iter;
use std::path::Path;

/*
#[doc(hidden)]
#[macro_export]
macro_rules! count {
    () => { proc_macro_call_0!() };
    (!) => { proc_macro_call_1!() };
    (!!) => { proc_macro_call_2!() };
    ...
}
*/

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("count.rs");
    let mut f = File::create(&dest_path).unwrap();

    let mut content = String::new();
    content += "
        #[doc(hidden)]
        #[macro_export]
        macro_rules! count {
    ";
    for i in 0..=64 {
        let bangs = iter::repeat("!").take(i).collect::<String>();
        content += &format!("({}) => {{ proc_macro_call_{}!() }};", bangs, i);
    }
    content += "
        }
    ";

    f.write_all(content.as_bytes()).unwrap();
}
<commit_msg>Add error message for nested macros above the limit<commit_after>use std::env;
use std::fs::File;
use std::io::Write;
use std::iter;
use std::path::Path;

/*
#[doc(hidden)]
#[macro_export]
macro_rules! count {
    () => { proc_macro_call_0!() };
    (!) => { proc_macro_call_1!() };
    (!!) => { proc_macro_call_2!() };
    ...
}
*/

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("count.rs");
    let mut f = File::create(&dest_path).unwrap();

    let mut content = String::new();
    content += "
        #[doc(hidden)]
        #[macro_export]
        macro_rules! count {
    ";
    for i in 0..=64 {
        let bangs = iter::repeat("!").take(i).collect::<String>();
        content += &format!("({}) => {{ proc_macro_call_{}!() }};", bangs, i);
    }
    content += "
            ($(!)+) => {
                compile_error!(\"this macro does not support >64 nested macro invocations\")
            };
        }
    ";

    f.write_all(content.as_bytes()).unwrap();
}
<|endoftext|>


<commit_before>use ndarray::*;
use ndarray_linalg::*;

#[test]
fn solveh_random() {
    let a: Array2<f64> = random_hpd(3);
    let x: Array1<f64> = random(3);
    let b = a.dot(&x);
    let y = a.solveh_into(b).unwrap();
    assert_close_l2!(&x, &y, 1e-7);

    let b = a.dot(&x);
    let f = a.factorizeh_into().unwrap();
    let y = f.solveh_into(b).unwrap();
    assert_close_l2!(&x, &y, 1e-7);
}

#[test]
fn solveh_random_t() {
    let a: Array2<f64> = random_hpd(3).reversed_axes();
    let x: Array1<f64> = random(3);
    let b = a.dot(&x);
    let y = a.solveh_into(b).unwrap();
    assert_close_l2!(&x, &y, 1e-7);

    let b = a.dot(&x);
    let f = a.factorizeh_into().unwrap();
    let y = f.solveh_into(b).unwrap();
    assert_close_l2!(&x, &y, 1e-7);
}
<commit_msg>Add tests for matching shape checks in SolveH<commit_after>use ndarray::*;
use ndarray_linalg::*;

#[should_panic]
#[test]
fn solveh_shape_mismatch() {
    let a: Array2<f64> = random_hpd(3);
    let b: Array1<f64> = random(2);
    let _ = a.solveh_into(b);
}

#[should_panic]
#[test]
fn factorizeh_solveh_shape_mismatch() {
    let a: Array2<f64> = random_hpd(3);
    let b: Array1<f64> = random(2);
    let f = a.factorizeh_into().unwrap();
    let _ = f.solveh_into(b);
}

#[test]
fn solveh_random() {
    let a: Array2<f64> = random_hpd(3);
    let x: Array1<f64> = random(3);
    let b = a.dot(&x);
    let y = a.solveh_into(b).unwrap();
    assert_close_l2!(&x, &y, 1e-7);

    let b = a.dot(&x);
    let f = a.factorizeh_into().unwrap();
    let y = f.solveh_into(b).unwrap();
    assert_close_l2!(&x, &y, 1e-7);
}

#[should_panic]
#[test]
fn solveh_t_shape_mismatch() {
    let a: Array2<f64> = random_hpd(3).reversed_axes();
    let b: Array1<f64> = random(2);
    let _ = a.solveh_into(b);
}

#[should_panic]
#[test]
fn factorizeh_solveh_t_shape_mismatch() {
    let a: Array2<f64> = random_hpd(3).reversed_axes();
    let b: Array1<f64> = random(2);
    let f = a.factorizeh_into().unwrap();
    let _ = f.solveh_into(b);
}

#[test]
fn solveh_random_t() {
    let a: Array2<f64> = random_hpd(3).reversed_axes();
    let x: Array1<f64> = random(3);
    let b = a.dot(&x);
    let y = a.solveh_into(b).unwrap();
    assert_close_l2!(&x, &y, 1e-7);

    let b = a.dot(&x);
    let f = a.factorizeh_into().unwrap();
    let y = f.solveh_into(b).unwrap();
    assert_close_l2!(&x, &y, 1e-7);
}
<|endoftext|>


<commit_before>// macOS needs FS access for its HashMap:
// compile-flags: -Zmiri-disable-isolation

use std::collections::{self, HashMap};
use std::hash::{BuildHasherDefault, BuildHasher};

fn test_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
    map.insert(0, 0);
    assert_eq!(map.values().fold(0, |x, y| x+y), 0);

    let num = 25;
    for i in 1..num {
        map.insert(i, i);
    }
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2); // check the right things are in the table now

    // Inserting again replaces the existing entries
    for i in 0..num {
        map.insert(i, num-1-i);
    }
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2);

    // TODO: Test Entry API, Iterators, ...
}

fn main() {
    test_map(HashMap::new());
}
<commit_msg>fix imports<commit_after>// macOS needs FS access for its HashMap:
// compile-flags: -Zmiri-disable-isolation

use std::collections::HashMap;
use std::hash::BuildHasher;

fn test_map<S: BuildHasher>(mut map: HashMap<i32, i32, S>) {
    map.insert(0, 0);
    assert_eq!(map.values().fold(0, |x, y| x+y), 0);

    let num = 25;
    for i in 1..num {
        map.insert(i, i);
    }
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2); // check the right things are in the table now

    // Inserting again replaces the existing entries
    for i in 0..num {
        map.insert(i, num-1-i);
    }
    assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2);

    // TODO: Test Entry API, Iterators, ...
}

fn main() {
    test_map(HashMap::new());
}
<|endoftext|>


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

use LinkerFlavor;
use target::{LinkArgs, TargetOptions, RelroLevel};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Gcc, vec![
        "-Wl,-Bstatic".to_string(),
        "-Wl,--no-dynamic-linker".to_string(),
        "-Wl,--eh-frame-hdr".to_string(),
        "-Wl,--gc-sections".to_string(),
    ]);

    TargetOptions {
        executables: true,
        target_family: None,
        linker_is_gnu: true,
        pre_link_args: args,
        position_independent_executables: true,
        tls_model: "local-exec".to_string(),
        relro_level: RelroLevel::Full,
        exe_allocation_crate: super::maybe_jemalloc(),
        .. Default::default()
    }
}
<commit_msg>Explain why local-exec is used by CloudABI.<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use LinkerFlavor;
use target::{LinkArgs, TargetOptions, RelroLevel};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Gcc, vec![
        "-Wl,-Bstatic".to_string(),
        "-Wl,--no-dynamic-linker".to_string(),
        "-Wl,--eh-frame-hdr".to_string(),
        "-Wl,--gc-sections".to_string(),
    ]);

    TargetOptions {
        executables: true,
        target_family: None,
        linker_is_gnu: true,
        pre_link_args: args,
        position_independent_executables: true,
        // As CloudABI only supports static linkage, there is no need
        // for dynamic TLS. The C library therefore does not provide
        // __tls_get_addr(), which is normally used to perform dynamic
        // TLS lookups by programs that make use of dlopen(). Only the
        // "local-exec" and "initial-exec" TLS models can be used.
        //
        // "local-exec" is more efficient than "initial-exec", as the
        // latter has one more level of indirection: it accesses the GOT
        // (Global Offset Table) to obtain the effective address of a
        // thread-local variable. Using a GOT is useful only when doing
        // dynamic linking.
        tls_model: "local-exec".to_string(),
        relro_level: RelroLevel::Full,
        exe_allocation_crate: super::maybe_jemalloc(),
        .. Default::default()
    }
}
<|endoftext|>