<commit_before>//! Macro for declaring/implementing traits with fake associated consts (in stable Rust)
//!
//! Currently very fragile in terms of syntax: does not support traits/impls with _any_ kind of
//! generic parameters (either lifetimes or types).
//!
//! The same macro is used for declaring a trait with associated consts, implementing such a trait,
//! and accessing the consts.
//!
//! The syntax is the same as that proposed for associated consts, _except_ that:
//!
//! - all consts must be at the beginning of the trait/impl, before any functions
//!
//! See the tests for example usage.
//!
//! At the moment they are not consts at all -- they simply expand to static functions with the
//! same name as the declared const. You may therefore access the const by calling
//! `Trait::CONST()`, or (for future proofing, in case the macro implementation changes), call the
//! macro again to access the const, as `guilty!(Trait::CONST)`.

#![cfg_attr(not(test), no_std)]

/// Macro for declaring/implementing traits with fake associated consts
///
/// See the [crate-level documentation](index.html) for more.
#[macro_export]
macro_rules! guilty {
    // These are the user facing invocations:

    // 1. define a private trait
    ($(#[$attr:meta])* trait $traitname:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [trait] [$traitname], $body);
    };
    // 2. define a private trait with inheritance
    ($(#[$attr:meta])* trait $traitname:ident : $parent:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub trait] [$traitname : $parent], $body);
    };
    // 3a. define a public trait
    ($(#[$attr:meta])* pub trait $traitname:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub trait] [$traitname], $body);
    };
    // 3b. define a public restricted trait
    ($(#[$attr:meta])* pub $restr:tt trait $traitname:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub $restr trait] [$traitname], $body);
    };
    // 4a. define a public trait with inheritance
    ($(#[$attr:meta])* pub trait $traitname:ident : $parent:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub trait] [$traitname : $parent], $body);
    };
    // 4b. define a public restricted trait with inheritance
    ($(#[$attr:meta])* pub $restr:tt trait $traitname:ident : $parent:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub $restr trait] [$traitname : $parent], $body);
    };
    // 5. implement a trait (public or private)
    (impl $traitname:ident for $structname:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE IMPL, $traitname, $structname, $body);
    };
    // 6a. access a const declared with this macro (mentioning trait)
    (<$structname:ident as $traitname:ident> :: $constname:ident) => {
        guilty!(INTERNAL: ACCESS CONST, (<$structname as $traitname>), $constname);
    };
    // 6b. access a const declared with this macro (w/o mentioning trait)
    ($structname:ident :: $constname:ident) => {
        guilty!(INTERNAL: ACCESS CONST, ($structname), $constname);
    };

    // Following are the internal macro calls
    // Since you can't export a macro which calls other unexported macros, guilty! calls itself
    // recursively in order to continue parsing. The invocation syntax for all these recursive
    // calls starts with the tokens `INTERNAL:`.
    //
    // The general strategy for parsing these declarations is we parse one const declaration from
    // the beginning of the trait/impl at a time, turning it into a static function which is
    // appended to the end of the trait/impl. When there are no more consts, the recursion stops
    // and the trait/impl is outputted (with an indirection through AS ITEM to appease the parser).

    // parse-trait-defconst: parse a trait with a const (that has a default value) as the first declaration
    // the square brackets contain [trait Trait] or [pub trait Trait]
    // this calls on to:
    //  - itself if there is another default-valued const
    //  - parse-trait-nodefconst if there is another const with no default value
    //  - def-trait-fn/def-trait-attr/def-trait-ty if there are no more consts
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         $(#[$cattr:meta])* const $constname:ident : $consttype:ty = $constdefault:expr;
         $($body:tt)*
     }) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [$($before)+] [$($traitname)*],
                {
                    $($body)*
                    $(#[$cattr])* #[allow(non_snake_case)] fn $constname() -> $consttype { $constdefault }
                });
    };
    // parse-trait-nodefconst: parse a trait with a const (that has no default value) as the first declaration
    // this calls on to:
    //  - itself is there is another non-default-valued const
    //  - parse-trait-defconst if there is another default-valued const
    //  - def-trait-fn/def-trait-attr/def-trait-ty if there are no more consts
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         $(#[$cattr:meta])* const $constname:ident : $consttype:ty;
         $($body:tt)*
     }) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [$($before)+] [$($traitname)*],
                {
                    $($body)*
                    $(#[$cattr])* #[allow(non_snake_case)] fn $constname() -> $consttype;
                });
    };
    // def-trait-fn: output a trait that has no consts at the beginning (starts with an unadorned fn)
    // indirection through item-redir
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         $(#[$fattr:meta])* fn $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, $(#[$attr])* $($before)+ $($traitname)* { $(#[$fattr])* fn $($body)* });
    };
    // def-trait-attr: output a trait that has no consts at the beginning (starts with fn that has
    //    docs/attributes)
    // indirection through item-redir
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         # $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, $(#[$attr])* $($before)+ $($traitname)* { # $($body)* });
    };
    // def-trait-ty: output a trait that has no consts at the beginning (starts with an associated type)
    // indirection through item-redir
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         $(#[$tattr:meta])* type $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, $(#[$attr])* $($before)+ $($traitname)* { $(#[$tattr])* type $($body)* });
    };
    // def-trait-empty: output a trait that has no items
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
     }) => {
        guilty!(INTERNAL: AS ITEM, $(#[$attr])* $($before)+ $($traitname)* { });
    };

    // parse-impl-const: parse an impl with a const as the first declaration
    // calls on to:
    //  - itself if there is another const
    //  - def-impl-fn/def-impl-ty if there are no more consts
    (INTERNAL: DEFINE IMPL, $traitname:ty, $structname:ident,
     {
         $(#[$cattr:meta])* const $constname:ident : $consttype:ty = $constvalue:expr;
         $($body:tt)*
     }) => {
        guilty!(INTERNAL: DEFINE IMPL, $traitname, $structname,
                {
                    $($body)*
                    $(#[$cattr])* #[allow(non_snake_case)] fn $constname() -> $consttype { $constvalue }
                });
    };
    // def-impl-fn: output an impl that has no consts at the beginning (starts with fn)
    // indirection through item-redir
    (INTERNAL: DEFINE IMPL, $traitname:ty, $structname:ident,
     {
         $(#[$fattr:meta])* fn $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, impl $traitname for $structname { $(#[$fattr])* fn $($body)* });
    };
    // def-impl-ty: output an impl that has no consts at the beginning (starts with type)
    // indirection through item-redir
    (INTERNAL: DEFINE IMPL, $traitname:ty, $structname:ident,
     {
         $(#[$tattr:meta])* type $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, impl $traitname for $structname { $(#[$tattr])* type $($body)* });
    };
    // def-impl-empty: output an impl that has no items in it
    (INTERNAL: DEFINE IMPL, $traitname:ty, $structname:ident,
     {
     }) => {
        guilty!(INTERNAL: AS ITEM, impl $traitname for $structname { });
    };

    // access: access a const defined with this macro
    // For now, it just calls the function, since we turn consts into functions. In the future, it
    // might do something more clever if the implementation changes.
    (INTERNAL: ACCESS CONST, ($($structname:tt)*), $constname:ident) => {{
        $($structname)* :: $constname ()
    }};

    // item-redir: Item redirection.
    // For some reason the parser sometimes complains "expected item" when you are trying to output
    // a perfectly good item. The solution (sometimes) is to redirect through a macro like this.
    (INTERNAL: AS ITEM, $i:item) => ($i)
}

#[cfg(test)]
mod tests {
    // some small tests
    guilty! { trait Empty { } }
    guilty! { trait JustFn { fn foo(&self); } }
    guilty! { trait JustType { type Foo; } }
    guilty! { pub trait JustConst { const FOO: (); } }
    guilty! { trait DocFn { #[doc="bar"] fn foo(&self); } }
    guilty! { pub(crate) trait DocType { #[doc="bar"] type Foo; } }
    guilty! { trait DocConst { #[doc="bar"] const FOO: (); } }
    struct Foo;
    guilty! { impl Empty for Foo { } }
    guilty! { impl JustFn for Foo { fn foo(&self) {} } }
    guilty! { impl JustType for Foo { type Foo = (); } }
    guilty! { impl JustConst for Foo { const FOO: () = (); } }
    guilty! { impl DocFn for Foo { #[doc="bar"] fn foo(&self) {} } }
    guilty! { impl DocType for Foo { #[doc="bar"] type Foo = (); } }
    guilty! { impl DocConst for Foo { #[doc="bar"] const FOO: () = (); } }

    #[test]
    fn small() {
        assert_eq!(guilty!(<Foo as JustConst>::FOO), ());
        assert_eq!(guilty!(<Foo as DocConst>::FOO), ());
    }

    // bigger integration test

    guilty! {
        /// A trait for things that do stuff
        trait Trait {
            /// An associated const with a default
            const WithDefault: i32 = 0;
            /// An associated const without a default
            const NoDefault: Self;

            /// An associated type
            type Type;

            /// A method with a default impl
            fn with_impl(&self) -> &Self { self }
            /// A method without a default impl
            fn no_impl(&self) -> &Self;
        }
    }

    #[derive(Debug, PartialEq, Eq)]
    struct Struct { i: i32 }

    guilty! {
        impl Trait for Struct {
            /// An associated const with a default
            const WithDefault: i32 = 42;
            /// An associated const without a default
            const NoDefault: Self = Struct { i: 42 };

            /// An associated type
            type Type = bool;

            /// A method without a default impl
            fn no_impl(&self) -> &Self { self }
        }
    }

    #[test]
    fn big() {
        use std::any::TypeId;

        let s = Struct { i: 42 };
        println!("{}", s.i);
        println!("{} {:?}", guilty!(Struct::WithDefault), guilty!(Struct::NoDefault));

        assert_eq!(s.i,                                     42);
        assert_eq!(s.with_impl(),                           &s);
        assert_eq!(s.no_impl(),                             &s);
        assert_eq!(TypeId::of::<<Struct as Trait>::Type>(), TypeId::of::<bool>());
        assert_eq!(guilty!(Struct::WithDefault),            42);
        assert_eq!(guilty!(Struct::NoDefault),              Struct { i: 42 });
        assert_eq!(guilty!(<Struct as Trait>::WithDefault), 42);
        assert_eq!(guilty!(<Struct as Trait>::NoDefault),   Struct { i: 42 });
    }

}

/*
 * BEFORE
 *
trait Trait {
    const WithDefault: i32 = 0;
    const NoDefault: Self;

    fn with_impl(&self) -> &Self { self }
    fn no_impl(&self) -> &Self;
}

struct Struct { i: i32 }

impl Trait for Struct {
    const WithDefault: i32 = 42;
    const NoDefault: Self = Self { i: 42 };

    fn no_impl(&self) -> &Self { self }
}
*/

/*
 * AFTER
 *
trait Trait {
    fn with_impl(&self) -> &Self { self }
    fn no_impl(&self) -> &Self;

    #[allow(non_snake_case)] fn WithDefault() -> i32 { 0 }
    #[allow(non_snake_case)] fn NoDefault() -> Self;
}

struct Struct { i: i32 }

impl Trait for Struct {
    fn no_impl(&self) -> &Self { self }

    fn WithDefault() -> i32 { 42 }
    fn NoDefault() -> Self { Struct { i: 42 } }
}
*/

<commit_msg>Don't use types as traits in macros<commit_after>//! Macro for declaring/implementing traits with fake associated consts (in stable Rust)
//!
//! Currently very fragile in terms of syntax: does not support traits/impls with _any_ kind of
//! generic parameters (either lifetimes or types).
//!
//! The same macro is used for declaring a trait with associated consts, implementing such a trait,
//! and accessing the consts.
//!
//! The syntax is the same as that proposed for associated consts, _except_ that:
//!
//! - all consts must be at the beginning of the trait/impl, before any functions
//!
//! See the tests for example usage.
//!
//! At the moment they are not consts at all -- they simply expand to static functions with the
//! same name as the declared const. You may therefore access the const by calling
//! `Trait::CONST()`, or (for future proofing, in case the macro implementation changes), call the
//! macro again to access the const, as `guilty!(Trait::CONST)`.

#![cfg_attr(not(test), no_std)]

/// Macro for declaring/implementing traits with fake associated consts
///
/// See the [crate-level documentation](index.html) for more.
#[macro_export]
macro_rules! guilty {
    // These are the user facing invocations:

    // 1. define a private trait
    ($(#[$attr:meta])* trait $traitname:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [trait] [$traitname], $body);
    };
    // 2. define a private trait with inheritance
    ($(#[$attr:meta])* trait $traitname:ident : $parent:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub trait] [$traitname : $parent], $body);
    };
    // 3a. define a public trait
    ($(#[$attr:meta])* pub trait $traitname:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub trait] [$traitname], $body);
    };
    // 3b. define a public restricted trait
    ($(#[$attr:meta])* pub $restr:tt trait $traitname:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub $restr trait] [$traitname], $body);
    };
    // 4a. define a public trait with inheritance
    ($(#[$attr:meta])* pub trait $traitname:ident : $parent:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub trait] [$traitname : $parent], $body);
    };
    // 4b. define a public restricted trait with inheritance
    ($(#[$attr:meta])* pub $restr:tt trait $traitname:ident : $parent:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [pub $restr trait] [$traitname : $parent], $body);
    };
    // 5. implement a trait (public or private)
    (impl $traitname:ident for $structname:ident $body:tt) => {
        guilty!(INTERNAL: DEFINE IMPL, $traitname, $structname, $body);
    };
    // 6a. access a const declared with this macro (mentioning trait)
    (<$structname:ident as $traitname:ident> :: $constname:ident) => {
        guilty!(INTERNAL: ACCESS CONST, (<$structname as $traitname>), $constname);
    };
    // 6b. access a const declared with this macro (w/o mentioning trait)
    ($structname:ident :: $constname:ident) => {
        guilty!(INTERNAL: ACCESS CONST, ($structname), $constname);
    };

    // Following are the internal macro calls
    // Since you can't export a macro which calls other unexported macros, guilty! calls itself
    // recursively in order to continue parsing. The invocation syntax for all these recursive
    // calls starts with the tokens `INTERNAL:`.
    //
    // The general strategy for parsing these declarations is we parse one const declaration from
    // the beginning of the trait/impl at a time, turning it into a static function which is
    // appended to the end of the trait/impl. When there are no more consts, the recursion stops
    // and the trait/impl is outputted (with an indirection through AS ITEM to appease the parser).

    // parse-trait-defconst: parse a trait with a const (that has a default value) as the first declaration
    // the square brackets contain [trait Trait] or [pub trait Trait]
    // this calls on to:
    //  - itself if there is another default-valued const
    //  - parse-trait-nodefconst if there is another const with no default value
    //  - def-trait-fn/def-trait-attr/def-trait-ty if there are no more consts
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         $(#[$cattr:meta])* const $constname:ident : $consttype:ty = $constdefault:expr;
         $($body:tt)*
     }) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [$($before)+] [$($traitname)*],
                {
                    $($body)*
                    $(#[$cattr])* #[allow(non_snake_case)] fn $constname() -> $consttype { $constdefault }
                });
    };
    // parse-trait-nodefconst: parse a trait with a const (that has no default value) as the first declaration
    // this calls on to:
    //  - itself is there is another non-default-valued const
    //  - parse-trait-defconst if there is another default-valued const
    //  - def-trait-fn/def-trait-attr/def-trait-ty if there are no more consts
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         $(#[$cattr:meta])* const $constname:ident : $consttype:ty;
         $($body:tt)*
     }) => {
        guilty!(INTERNAL: DEFINE TRAIT, [$(#[$attr])*] [$($before)+] [$($traitname)*],
                {
                    $($body)*
                    $(#[$cattr])* #[allow(non_snake_case)] fn $constname() -> $consttype;
                });
    };
    // def-trait-fn: output a trait that has no consts at the beginning (starts with an unadorned fn)
    // indirection through item-redir
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         $(#[$fattr:meta])* fn $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, $(#[$attr])* $($before)+ $($traitname)* { $(#[$fattr])* fn $($body)* });
    };
    // def-trait-attr: output a trait that has no consts at the beginning (starts with fn that has
    //    docs/attributes)
    // indirection through item-redir
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         # $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, $(#[$attr])* $($before)+ $($traitname)* { # $($body)* });
    };
    // def-trait-ty: output a trait that has no consts at the beginning (starts with an associated type)
    // indirection through item-redir
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
         $(#[$tattr:meta])* type $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, $(#[$attr])* $($before)+ $($traitname)* { $(#[$tattr])* type $($body)* });
    };
    // def-trait-empty: output a trait that has no items
    (INTERNAL: DEFINE TRAIT, [$(#[$attr:meta])*] [$($before:tt)+] [$($traitname:tt)*],
     {
     }) => {
        guilty!(INTERNAL: AS ITEM, $(#[$attr])* $($before)+ $($traitname)* { });
    };

    // parse-impl-const: parse an impl with a const as the first declaration
    // calls on to:
    //  - itself if there is another const
    //  - def-impl-fn/def-impl-ty if there are no more consts
    (INTERNAL: DEFINE IMPL, $traitname:path, $structname:ident,
     {
         $(#[$cattr:meta])* const $constname:ident : $consttype:ty = $constvalue:expr;
         $($body:tt)*
     }) => {
        guilty!(INTERNAL: DEFINE IMPL, $traitname, $structname,
                {
                    $($body)*
                    $(#[$cattr])* #[allow(non_snake_case)] fn $constname() -> $consttype { $constvalue }
                });
    };
    // def-impl-fn: output an impl that has no consts at the beginning (starts with fn)
    // indirection through item-redir
    (INTERNAL: DEFINE IMPL, $traitname:path, $structname:ident,
     {
         $(#[$fattr:meta])* fn $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, impl $traitname for $structname { $(#[$fattr])* fn $($body)* });
    };
    // def-impl-ty: output an impl that has no consts at the beginning (starts with type)
    // indirection through item-redir
    (INTERNAL: DEFINE IMPL, $traitname:path, $structname:ident,
     {
         $(#[$tattr:meta])* type $($body:tt)*
     }) => {
        guilty!(INTERNAL: AS ITEM, impl $traitname for $structname { $(#[$tattr])* type $($body)* });
    };
    // def-impl-empty: output an impl that has no items in it
    (INTERNAL: DEFINE IMPL, $traitname:path, $structname:ident,
     {
     }) => {
        guilty!(INTERNAL: AS ITEM, impl $traitname for $structname { });
    };

    // access: access a const defined with this macro
    // For now, it just calls the function, since we turn consts into functions. In the future, it
    // might do something more clever if the implementation changes.
    (INTERNAL: ACCESS CONST, ($($structname:tt)*), $constname:ident) => {{
        $($structname)* :: $constname ()
    }};

    // item-redir: Item redirection.
    // For some reason the parser sometimes complains "expected item" when you are trying to output
    // a perfectly good item. The solution (sometimes) is to redirect through a macro like this.
    (INTERNAL: AS ITEM, $i:item) => ($i)
}

#[cfg(test)]
mod tests {
    // some small tests
    guilty! { trait Empty { } }
    guilty! { trait JustFn { fn foo(&self); } }
    guilty! { trait JustType { type Foo; } }
    guilty! { pub trait JustConst { const FOO: (); } }
    guilty! { trait DocFn { #[doc="bar"] fn foo(&self); } }
    guilty! { pub(crate) trait DocType { #[doc="bar"] type Foo; } }
    guilty! { trait DocConst { #[doc="bar"] const FOO: (); } }
    struct Foo;
    guilty! { impl Empty for Foo { } }
    guilty! { impl JustFn for Foo { fn foo(&self) {} } }
    guilty! { impl JustType for Foo { type Foo = (); } }
    guilty! { impl JustConst for Foo { const FOO: () = (); } }
    guilty! { impl DocFn for Foo { #[doc="bar"] fn foo(&self) {} } }
    guilty! { impl DocType for Foo { #[doc="bar"] type Foo = (); } }
    guilty! { impl DocConst for Foo { #[doc="bar"] const FOO: () = (); } }

    #[test]
    fn small() {
        assert_eq!(guilty!(<Foo as JustConst>::FOO), ());
        assert_eq!(guilty!(<Foo as DocConst>::FOO), ());
    }

    // bigger integration test

    guilty! {
        /// A trait for things that do stuff
        trait Trait {
            /// An associated const with a default
            const WithDefault: i32 = 0;
            /// An associated const without a default
            const NoDefault: Self;

            /// An associated type
            type Type;

            /// A method with a default impl
            fn with_impl(&self) -> &Self { self }
            /// A method without a default impl
            fn no_impl(&self) -> &Self;
        }
    }

    #[derive(Debug, PartialEq, Eq)]
    struct Struct { i: i32 }

    guilty! {
        impl Trait for Struct {
            /// An associated const with a default
            const WithDefault: i32 = 42;
            /// An associated const without a default
            const NoDefault: Self = Struct { i: 42 };

            /// An associated type
            type Type = bool;

            /// A method without a default impl
            fn no_impl(&self) -> &Self { self }
        }
    }

    #[test]
    fn big() {
        use std::any::TypeId;

        let s = Struct { i: 42 };
        println!("{}", s.i);
        println!("{} {:?}", guilty!(Struct::WithDefault), guilty!(Struct::NoDefault));

        assert_eq!(s.i,                                     42);
        assert_eq!(s.with_impl(),                           &s);
        assert_eq!(s.no_impl(),                             &s);
        assert_eq!(TypeId::of::<<Struct as Trait>::Type>(), TypeId::of::<bool>());
        assert_eq!(guilty!(Struct::WithDefault),            42);
        assert_eq!(guilty!(Struct::NoDefault),              Struct { i: 42 });
        assert_eq!(guilty!(<Struct as Trait>::WithDefault), 42);
        assert_eq!(guilty!(<Struct as Trait>::NoDefault),   Struct { i: 42 });
    }

}

/*
 * BEFORE
 *
trait Trait {
    const WithDefault: i32 = 0;
    const NoDefault: Self;

    fn with_impl(&self) -> &Self { self }
    fn no_impl(&self) -> &Self;
}

struct Struct { i: i32 }

impl Trait for Struct {
    const WithDefault: i32 = 42;
    const NoDefault: Self = Self { i: 42 };

    fn no_impl(&self) -> &Self { self }
}
*/

/*
 * AFTER
 *
trait Trait {
    fn with_impl(&self) -> &Self { self }
    fn no_impl(&self) -> &Self;

    #[allow(non_snake_case)] fn WithDefault() -> i32 { 0 }
    #[allow(non_snake_case)] fn NoDefault() -> Self;
}

struct Struct { i: i32 }

impl Trait for Struct {
    fn no_impl(&self) -> &Self { self }

    fn WithDefault() -> i32 { 42 }
    fn NoDefault() -> Self { Struct { i: 42 } }
}
*/

<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;

extern crate bincode;
extern crate rustc_serialize;
#[macro_use]
extern crate log;

use std::collections::HashMap;
use std::thread;
use std::fs;
use std::fs::File;
use std::io::prelude::*;

use bincode::SizeLimit;
use bincode::rustc_serialize::{ encode, decode };

use rustc_serialize::{ Encodable, Decodable };

/// A default value type to use with KV
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum Value {
    String(String),
    Int(i32),
    Float(f32),
    Map(HashMap<String, Value>),
}

/// Type alias for results from KV
type KVResult = Result<bool, &'static str>;

/// The type that represents the key-value store
pub struct KV<V> {
    cab: HashMap<String, V>,
    path: &'static str,
}

impl<V: Clone + Encodable + Decodable> KV<V> {
    /// Creates a new instance of the KV store
    pub fn new(p:&'static str) -> KV<V> {
        let mut store = KV {
            cab: HashMap::new(),
            path: p,
        };

        match store.load_from_persist() {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                warn!("{}", e);
                let _ = File::create(p);
            },
        };

        KV::<V>::lock_cab(p, true);

        store
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: String, value: V) -> KVResult {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: String) -> Option<V> {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Some((*v).clone()),
            None => None
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: String) -> KVResult {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Vec<String> {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // create a vec from the cabs keys
        self.cab.keys().map(|k| k.clone()).collect()
    }

    /// Locks/unlocks cab for writing purposes
    fn lock_cab(path:&'static str, readonly:bool) {
        // set not readonly while writing
        let mut perms = fs::metadata(path).unwrap().permissions();
        perms.set_readonly(readonly);
        fs::set_permissions(path, perms).unwrap();
    }

    /// Waits for the cab to become free
    fn wait_for_free(&self, lock:bool) -> KVResult {
        loop {
            // check if the cab is being written to
            let metadata = match fs::metadata(self.path) {
                Ok(m) => m,
                Err(_) => return Err("File doesn't exist or is not readeable"),
            };

            if metadata.permissions().readonly() {
                if lock {
                    // don't call KV::lock_cab(self.path, false)
                    // to avoid grabbing metadata again
                    let mut perms = metadata.permissions();
                    perms.set_readonly(false);
                    fs::set_permissions(self.path, perms).unwrap();
                }
                break;
            }
        }

        Ok(true)
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        if !self.wait_for_free(true).is_ok() {
            return Err("File doesn't exist or is not readeable");
        }

        // encode the cab as a u8 vec
        let byte_vec: Vec<u8> = match encode(&mut self.cab, SizeLimit::Infinite) {
            Ok(bv) => bv,
            Err(e) => {
                warn!("{}", e);
                return Err("Could not encode cab");
            },
        };

        // create the file
        let mut f = match File::create(self.path) {
            Ok(f) => f,
            Err(e) => {
                // TODO limit retries
                error!("File::create/write_to_persist: {}", e);
                return self.write_to_persist();
            }
        };
        // write the bytes to it
        f.write_all(byte_vec.as_slice()).unwrap();
        let _ = f.flush();

        KV::<V>::lock_cab(self.path, true);

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        if !self.wait_for_free(false).is_ok() {
            return Err("File doesn't exist or is not readeable");
        }

        // open the cab
        let mut f = File::open(self.path).unwrap();

        // read the bytes
        let mut byte_vec = Vec::new();
        let _ = f.read_to_end(&mut byte_vec);

        // decode u8 vec back into HashMap
        let decoded: HashMap<String, V> = match decode(byte_vec.as_slice()) {
            Ok(f) => f,
            Err(e) => {
                warn!("{}", e);
                return Err("Couldn't decode cab");
            },
        };
        // assign read HashMap back to self
        self.cab = decoded;

        Ok(true)
    }
}

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

    macro_rules! bench_teardown {
        ( $p:ident ) => {
            use std::{thread, time};

            thread::sleep(time::Duration::from_secs(2));
            let _ = std::fs::remove_file($p);
        }
    }

    #[bench]
    fn bench_get_int(b: &mut Bencher) {
        let test_cab_path = "./bench_get_many.cab";
        let mut test_store = KV::<Value>::new(test_cab_path);

        let _ = test_store.insert("test".to_string(), Value::Int(1));

        b.iter(|| {
            test_store.get("test".to_string());
        });

        bench_teardown!(test_cab_path);
    }

    #[bench]
    fn bench_insert_int(b: &mut Bencher) {
        let test_cab_path = "./bench_insert_many.cab";
        let mut test_store = KV::<Value>::new(test_cab_path);

        b.iter(|| {
            let _ = test_store.insert("test".to_string(), Value::Int(1));
        });

        bench_teardown!(test_cab_path);
    }
}
<commit_msg>removed unused thread import<commit_after>#![feature(test)]
extern crate test;

extern crate bincode;
extern crate rustc_serialize;
#[macro_use]
extern crate log;

use std::collections::HashMap;
use std::fs;
use std::fs::File;
use std::io::prelude::*;

use bincode::SizeLimit;
use bincode::rustc_serialize::{ encode, decode };

use rustc_serialize::{ Encodable, Decodable };

/// A default value type to use with KV
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub enum Value {
    String(String),
    Int(i32),
    Float(f32),
    Map(HashMap<String, Value>),
}

/// Type alias for results from KV
type KVResult = Result<bool, &'static str>;

/// The type that represents the key-value store
pub struct KV<V> {
    cab: HashMap<String, V>,
    path: &'static str,
}

impl<V: Clone + Encodable + Decodable> KV<V> {
    /// Creates a new instance of the KV store
    pub fn new(p:&'static str) -> KV<V> {
        let mut store = KV {
            cab: HashMap::new(),
            path: p,
        };

        match store.load_from_persist() {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                warn!("{}", e);
                let _ = File::create(p);
            },
        };

        KV::<V>::lock_cab(p, true);

        store
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: String, value: V) -> KVResult {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: String) -> Option<V> {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Some((*v).clone()),
            None => None
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: String) -> KVResult {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Vec<String> {
        // make sure mem version up to date
        let _ = self.load_from_persist();
        // create a vec from the cabs keys
        self.cab.keys().map(|k| k.clone()).collect()
    }

    /// Locks/unlocks cab for writing purposes
    fn lock_cab(path:&'static str, readonly:bool) {
        // set not readonly while writing
        let mut perms = fs::metadata(path).unwrap().permissions();
        perms.set_readonly(readonly);
        fs::set_permissions(path, perms).unwrap();
    }

    /// Waits for the cab to become free
    fn wait_for_free(&self, lock:bool) -> KVResult {
        loop {
            // check if the cab is being written to
            let metadata = match fs::metadata(self.path) {
                Ok(m) => m,
                Err(_) => return Err("File doesn't exist or is not readeable"),
            };

            if metadata.permissions().readonly() {
                if lock {
                    // don't call KV::lock_cab(self.path, false)
                    // to avoid grabbing metadata again
                    let mut perms = metadata.permissions();
                    perms.set_readonly(false);
                    fs::set_permissions(self.path, perms).unwrap();
                }
                break;
            }
        }

        Ok(true)
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        if !self.wait_for_free(true).is_ok() {
            return Err("File doesn't exist or is not readeable");
        }

        // encode the cab as a u8 vec
        let byte_vec: Vec<u8> = match encode(&mut self.cab, SizeLimit::Infinite) {
            Ok(bv) => bv,
            Err(e) => {
                warn!("{}", e);
                return Err("Could not encode cab");
            },
        };

        // create the file
        let mut f = match File::create(self.path) {
            Ok(f) => f,
            Err(e) => {
                // TODO limit retries
                error!("File::create/write_to_persist: {}", e);
                return self.write_to_persist();
            }
        };
        // write the bytes to it
        f.write_all(byte_vec.as_slice()).unwrap();
        let _ = f.flush();

        KV::<V>::lock_cab(self.path, true);

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        if !self.wait_for_free(false).is_ok() {
            return Err("File doesn't exist or is not readeable");
        }

        // open the cab
        let mut f = File::open(self.path).unwrap();

        // read the bytes
        let mut byte_vec = Vec::new();
        let _ = f.read_to_end(&mut byte_vec);

        // decode u8 vec back into HashMap
        let decoded: HashMap<String, V> = match decode(byte_vec.as_slice()) {
            Ok(f) => f,
            Err(e) => {
                warn!("{}", e);
                return Err("Couldn't decode cab");
            },
        };
        // assign read HashMap back to self
        self.cab = decoded;

        Ok(true)
    }
}

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

    macro_rules! bench_teardown {
        ( $p:ident ) => {
            use std::{thread, time};

            thread::sleep(time::Duration::from_secs(2));
            let _ = std::fs::remove_file($p);
        }
    }

    #[bench]
    fn bench_get_int(b: &mut Bencher) {
        let test_cab_path = "./bench_get_many.cab";
        let mut test_store = KV::<Value>::new(test_cab_path);

        let _ = test_store.insert("test".to_string(), Value::Int(1));

        b.iter(|| {
            test_store.get("test".to_string());
        });

        bench_teardown!(test_cab_path);
    }

    #[bench]
    fn bench_insert_int(b: &mut Bencher) {
        let test_cab_path = "./bench_insert_many.cab";
        let mut test_store = KV::<Value>::new(test_cab_path);

        b.iter(|| {
            let _ = test_store.insert("test".to_string(), Value::Int(1));
        });

        bench_teardown!(test_cab_path);
    }
}
<|endoftext|>


<commit_before>#![feature(untagged_unions)]
#![feature(conservative_impl_trait)]
#[macro_use]
extern crate bitflags;
extern crate libc;
use std::slice;
pub mod raw;
pub mod command;

#[macro_export]
macro_rules! redis_module (
    ($name:expr,$module_version:expr, $commands:expr) => (

        #[no_mangle]
        #[allow(non_snake_case)]
        pub extern "C" fn RedisModule_OnLoad(ctx: *mut redismodule::raw::RedisModuleCtx) -> redismodule::raw::Status {
            unsafe {
              if redismodule::raw::RedisModule_Init(ctx,format!("{}\0",$name).as_ptr() as *const i8, $module_version, redismodule::raw::REDISMODULE_APIVER_1) == redismodule::raw::Status::Err {
                  return redismodule::raw::Status::Err;
              }
              for command in $commands {

                if redismodule::raw::RedisModule_CreateCommand(ctx,
                                                            format!("{}\0", command.name).as_ptr() as *const i8,
                                                            command.handler,
                                                            format!("write\0").as_ptr() as *const i8,
                                                            1,
                                                            1,
                                                            1) == redismodule::raw::Status::Err {
                    return redismodule::raw::Status::Err;
                }
              }
              return redismodule::raw::Status::Ok;
            }
        }
    )
);

pub fn wrap_command(command: fn(ctx: *mut raw::RedisModuleCtx, args: &[&str]) -> RedisResult)
                -> impl Fn(*mut raw::RedisModuleCtx, *mut *mut raw::RedisModuleString, libc::c_int) -> raw::Status{

    move |ctx: *mut raw::RedisModuleCtx,
          argv: *mut *mut raw::RedisModuleString,
          argc: libc::c_int|
          -> raw::Status {
        match command(ctx, &["a"]) {
            Ok(redisvalue) => raw::Status::Ok,
            Err(e) => raw::Status::Err,
        }
    }
}

pub type RedisError = &'static str;
pub type RedisResult = Result<RedisValue, RedisError>;

#[derive(Debug)]
pub enum RedisValue {
    String(String),
    Integer(isize),
    Array(Vec<RedisValue>),
}

// pub struct Context {
//     ctx: *mut raw::RedisModuleCtx,
// }

// impl Context {
//      pub fn name(arg: Type) -> RetType {
//          unimplemented!();
//      }
// }

//  #[derive(Debug)]

// pub enum RedisError {
//     Error(String),
//     WrongArity,
// }<commit_msg>command<commit_after>#![feature(untagged_unions)]
#![feature(conservative_impl_trait)]
#[macro_use]
extern crate bitflags;
extern crate libc;
use std::slice;
pub mod raw;
pub mod command;

// #[macro_export]
// macro_rules! command (
//      ($name:expr) => (
//         fn $name() {
//             // match cmd(ctx, &["a"]) {
//             //     Ok(redisvalue) => raw::Status::Ok,
//             //     Err(e) => raw::Status::Err,
//             // }
//         };
//      )
// );

#[macro_export]
macro_rules! redis_module (
    ($name:expr,$module_version:expr, $commands:expr) => (

        #[no_mangle]
        #[allow(non_snake_case)]
        pub extern "C" fn RedisModule_OnLoad(ctx: *mut redismodule::raw::RedisModuleCtx) -> redismodule::raw::Status {
            unsafe {
              if redismodule::raw::RedisModule_Init(ctx,format!("{}\0",$name).as_ptr() as *const i8, $module_version, redismodule::raw::REDISMODULE_APIVER_1) == redismodule::raw::Status::Err {
                  return redismodule::raw::Status::Err;
              }
              for command in $commands {

                if redismodule::raw::RedisModule_CreateCommand(ctx,
                                                            format!("{}\0", command.name).as_ptr() as *const i8,
                                                            command.handler,
                                                            format!("write\0").as_ptr() as *const i8,
                                                            1,
                                                            1,
                                                            1) == redismodule::raw::Status::Err {
                    return redismodule::raw::Status::Err;
                }
              }
              return redismodule::raw::Status::Ok;
            }
        }
    )
);

pub fn wrap_command(command: fn(ctx: *mut raw::RedisModuleCtx, args: &[&str]) -> RedisResult)
                -> impl Fn(*mut raw::RedisModuleCtx, *mut *mut raw::RedisModuleString, libc::c_int) -> raw::Status{

    move |ctx: *mut raw::RedisModuleCtx,
          argv: *mut *mut raw::RedisModuleString,
          argc: libc::c_int|
          -> raw::Status {
        match command(ctx, &["a"]) {
            Ok(redisvalue) => raw::Status::Ok,
            Err(e) => raw::Status::Err,
        }
    }
}

pub type RedisError = &'static str;
pub type RedisResult = Result<RedisValue, RedisError>;

#[derive(Debug)]
pub enum RedisValue {
    String(String),
    Integer(isize),
    Array(Vec<RedisValue>),
}

// pub struct Context {
//     ctx: *mut raw::RedisModuleCtx,
// }

// impl Context {
//      pub fn name(arg: Type) -> RetType {
//          unimplemented!();
//      }
// }

//  #[derive(Debug)]

// pub enum RedisError {
//     Error(String),
//     WrongArity,
// }<|endoftext|>


<commit_before>//! Contains an implementation of splay trees where each node has a key/value
//! pair to be used in maps and sets. The only requirement is that the key must
//! implement the Ord trait.
//!
//! # Example
//!
//! ```rust
//! use splay::SplayMap;
//!
//! let mut map = SplayMap::new();
//! map.insert("foo", "bar");
//! map.insert("hello", "world");
//! map.insert("splay", "tree");
//!
//! for (k, v) in map.into_iter() {
//!     println!("{} => {}", k, v);
//! }
//! ```

#![doc(html_root_url = "http://alexcrichton.com/splay-rs")]
#![feature(unsafe_destructor, core)]
#![cfg_attr(test, deny(warnings))]

#[cfg(test)] extern crate rand;

pub use self::set::SplaySet;
pub use self::map::SplayMap;

pub mod set;
pub mod map;
mod node;

#[cfg(test)]
mod test {
    use super::{SplayMap, SplaySet};

    // Lots of these are shamelessly stolen from the TreeMap tests, it'd be
    // awesome if they could share them...

    #[test]
    fn insert_simple() {
        let mut t = SplayMap::new();
        assert_eq!(t.insert(1, 2), None);
        assert_eq!(t.insert(1, 3), Some(2));
        assert_eq!(t.insert(2, 3), None);
    }

    #[test]
    fn remove_simple() {
        let mut t = SplayMap::new();
        assert_eq!(t.insert(1, 2), None);
        assert_eq!(t.insert(2, 3), None);
        assert_eq!(t.insert(3, 4), None);
        assert_eq!(t.insert(0, 5), None);
        assert_eq!(t.remove(&1), Some(2));
    }

    #[test]
    fn pop_simple() {
        let mut t = SplayMap::new();
        assert_eq!(t.insert(1, 2), None);
        assert_eq!(t.insert(2, 3), None);
        assert_eq!(t.insert(3, 4), None);
        assert_eq!(t.insert(0, 5), None);
        assert_eq!(t.remove(&1), Some(2));
        assert_eq!(t.remove(&1), None);
        assert_eq!(t.remove(&0), Some(5));
    }

    #[test]
    fn find_mut_simple() {
        let mut t = SplayMap::new();
        assert_eq!(t.insert(1, 2), None);
        assert_eq!(t.insert(2, 3), None);
        assert_eq!(t.insert(3, 4), None);
        assert_eq!(t.insert(0, 5), None);

        {
            let ptr = t.get_mut(&1);
            assert!(ptr.is_some());
            let ptr = ptr.unwrap();
            assert_eq!(*ptr, 2);
            *ptr = 4;
        }

        let ptr = t.get_mut(&1);
        assert!(ptr.is_some());
        assert_eq!(*ptr.unwrap(), 4);
    }

    #[test]
    fn test_len() {
        let mut m = SplayMap::new();
        assert_eq!(m.insert(3, 6), None);
        assert_eq!(m.len(), 1);
        assert_eq!(m.insert(0, 0), None);
        assert_eq!(m.len(), 2);
        assert_eq!(m.insert(4, 8), None);
        assert_eq!(m.len(), 3);
        assert_eq!(m.remove(&3), Some(6));
        assert_eq!(m.len(), 2);
        assert_eq!(m.remove(&5), None);
        assert_eq!(m.len(), 2);
        assert_eq!(m.insert(2, 4), None);
        assert_eq!(m.len(), 3);
        assert_eq!(m.insert(1, 2), None);
        assert_eq!(m.len(), 4);
    }

    #[test]
    fn test_clear() {
        let mut m = SplayMap::new();
        m.clear();
        assert_eq!(m.insert(5, 11), None);
        assert_eq!(m.insert(12, -3), None);
        assert_eq!(m.insert(19, 2), None);
        m.clear();
        assert_eq!(m.get(&5), None);
        assert_eq!(m.get(&12), None);
        assert_eq!(m.get(&19), None);
        assert!(m.is_empty());
    }

    #[test]
    fn insert_replace() {
        let mut m = SplayMap::new();
        assert_eq!(m.insert(5, 2), None);
        assert_eq!(m.insert(2, 9), None);
        assert_eq!(m.insert(2, 11), Some(9));
        assert_eq!(m[2], 11);
    }

    #[test]
    fn find_empty() {
        let m: SplayMap<i32, i32> = SplayMap::new();
        assert_eq!(m.get(&5), None);
    }

    #[test]
    fn find_not_found() {
        let mut m = SplayMap::new();
        assert_eq!(m.insert(1, 2), None);
        assert_eq!(m.insert(5, 3), None);
        assert_eq!(m.insert(9, 3), None);
        assert_eq!(m.get(&2), None);
    }

    #[test]
    fn get_works() {
        let mut m = SplayMap::new();
        m.insert(1, 1);
        assert_eq!(m[1], 1);
    }

    #[test]
    fn into_iter() {
        let mut m = SplayMap::new();
        m.insert(1, 1);
        m.insert(2, 1);
        m.insert(0, 1);
        let mut cur = 0;
        for (k, v) in m.into_iter() {
            assert_eq!(k, cur);
            assert_eq!(v, 1);
            cur += 1;
        }
    }

    #[test]
    fn into_iter_backwards() {
        let mut m = SplayMap::new();
        m.insert(1, 1);
        m.insert(2, 1);
        m.insert(0, 1);
        let mut cur = 2;
        for (k, v) in m.into_iter().rev() {
            assert_eq!(k, cur);
            assert_eq!(v, 1);
            cur -= 1;
        }
    }

    #[test] #[should_fail]
    fn get_panic_works() {
        let mut m = SplayMap::new();
        m.insert(2, 2);
        m[1];
    }

    #[test]
    fn large() {
        use rand::random;
        let mut m = SplaySet::new();
        let mut v = Vec::new();

        for _ in range(0, 400) {
            let i: i32 = random();
            m.insert(i);
            v.push(i);
        }

        for i in v.iter() {
            assert!(m.contains(i));
        }
    }
}
<commit_msg>Update to rust master<commit_after>//! Contains an implementation of splay trees where each node has a key/value
//! pair to be used in maps and sets. The only requirement is that the key must
//! implement the Ord trait.
//!
//! # Example
//!
//! ```rust
//! use splay::SplayMap;
//!
//! let mut map = SplayMap::new();
//! map.insert("foo", "bar");
//! map.insert("hello", "world");
//! map.insert("splay", "tree");
//!
//! for (k, v) in map.into_iter() {
//!     println!("{} => {}", k, v);
//! }
//! ```

#![doc(html_root_url = "http://alexcrichton.com/splay-rs")]
#![feature(unsafe_destructor)]
#![cfg_attr(test, deny(warnings))]

#[cfg(test)] extern crate rand;

pub use self::set::SplaySet;
pub use self::map::SplayMap;

pub mod set;
pub mod map;
mod node;

#[cfg(test)]
mod test {
    use super::{SplayMap, SplaySet};

    // Lots of these are shamelessly stolen from the TreeMap tests, it'd be
    // awesome if they could share them...

    #[test]
    fn insert_simple() {
        let mut t = SplayMap::new();
        assert_eq!(t.insert(1, 2), None);
        assert_eq!(t.insert(1, 3), Some(2));
        assert_eq!(t.insert(2, 3), None);
    }

    #[test]
    fn remove_simple() {
        let mut t = SplayMap::new();
        assert_eq!(t.insert(1, 2), None);
        assert_eq!(t.insert(2, 3), None);
        assert_eq!(t.insert(3, 4), None);
        assert_eq!(t.insert(0, 5), None);
        assert_eq!(t.remove(&1), Some(2));
    }

    #[test]
    fn pop_simple() {
        let mut t = SplayMap::new();
        assert_eq!(t.insert(1, 2), None);
        assert_eq!(t.insert(2, 3), None);
        assert_eq!(t.insert(3, 4), None);
        assert_eq!(t.insert(0, 5), None);
        assert_eq!(t.remove(&1), Some(2));
        assert_eq!(t.remove(&1), None);
        assert_eq!(t.remove(&0), Some(5));
    }

    #[test]
    fn find_mut_simple() {
        let mut t = SplayMap::new();
        assert_eq!(t.insert(1, 2), None);
        assert_eq!(t.insert(2, 3), None);
        assert_eq!(t.insert(3, 4), None);
        assert_eq!(t.insert(0, 5), None);

        {
            let ptr = t.get_mut(&1);
            assert!(ptr.is_some());
            let ptr = ptr.unwrap();
            assert_eq!(*ptr, 2);
            *ptr = 4;
        }

        let ptr = t.get_mut(&1);
        assert!(ptr.is_some());
        assert_eq!(*ptr.unwrap(), 4);
    }

    #[test]
    fn test_len() {
        let mut m = SplayMap::new();
        assert_eq!(m.insert(3, 6), None);
        assert_eq!(m.len(), 1);
        assert_eq!(m.insert(0, 0), None);
        assert_eq!(m.len(), 2);
        assert_eq!(m.insert(4, 8), None);
        assert_eq!(m.len(), 3);
        assert_eq!(m.remove(&3), Some(6));
        assert_eq!(m.len(), 2);
        assert_eq!(m.remove(&5), None);
        assert_eq!(m.len(), 2);
        assert_eq!(m.insert(2, 4), None);
        assert_eq!(m.len(), 3);
        assert_eq!(m.insert(1, 2), None);
        assert_eq!(m.len(), 4);
    }

    #[test]
    fn test_clear() {
        let mut m = SplayMap::new();
        m.clear();
        assert_eq!(m.insert(5, 11), None);
        assert_eq!(m.insert(12, -3), None);
        assert_eq!(m.insert(19, 2), None);
        m.clear();
        assert_eq!(m.get(&5), None);
        assert_eq!(m.get(&12), None);
        assert_eq!(m.get(&19), None);
        assert!(m.is_empty());
    }

    #[test]
    fn insert_replace() {
        let mut m = SplayMap::new();
        assert_eq!(m.insert(5, 2), None);
        assert_eq!(m.insert(2, 9), None);
        assert_eq!(m.insert(2, 11), Some(9));
        assert_eq!(m[2], 11);
    }

    #[test]
    fn find_empty() {
        let m: SplayMap<i32, i32> = SplayMap::new();
        assert_eq!(m.get(&5), None);
    }

    #[test]
    fn find_not_found() {
        let mut m = SplayMap::new();
        assert_eq!(m.insert(1, 2), None);
        assert_eq!(m.insert(5, 3), None);
        assert_eq!(m.insert(9, 3), None);
        assert_eq!(m.get(&2), None);
    }

    #[test]
    fn get_works() {
        let mut m = SplayMap::new();
        m.insert(1, 1);
        assert_eq!(m[1], 1);
    }

    #[test]
    fn into_iter() {
        let mut m = SplayMap::new();
        m.insert(1, 1);
        m.insert(2, 1);
        m.insert(0, 1);
        let mut cur = 0;
        for (k, v) in m.into_iter() {
            assert_eq!(k, cur);
            assert_eq!(v, 1);
            cur += 1;
        }
    }

    #[test]
    fn into_iter_backwards() {
        let mut m = SplayMap::new();
        m.insert(1, 1);
        m.insert(2, 1);
        m.insert(0, 1);
        let mut cur = 2;
        for (k, v) in m.into_iter().rev() {
            assert_eq!(k, cur);
            assert_eq!(v, 1);
            cur -= 1;
        }
    }

    #[test] #[should_panic]
    fn get_panic_works() {
        let mut m = SplayMap::new();
        m.insert(2, 2);
        m[1];
    }

    #[test]
    fn large() {
        use rand::random;
        let mut m = SplaySet::new();
        let mut v = Vec::new();

        for _ in 0..400 {
            let i: i32 = random();
            m.insert(i);
            v.push(i);
        }

        for i in v.iter() {
            assert!(m.contains(i));
        }
    }
}
<|endoftext|>


<commit_before>#![feature(libc)]

extern crate libc;
extern crate "glib-2_0-sys" as glib;
extern crate "gobject-2_0-sys" as gobject;

pub mod notification;

pub use notification::*;

use libc::{
    c_char
};

use glib::types::{
    gboolean,
};

use glib::list::GList;

extern "C" {
    pub fn notify_init(app_name: *const c_char) -> gboolean;
    pub fn notify_uninit();
    pub fn notify_is_initted() -> gboolean;

    pub fn notify_get_app_name() -> *const c_char;
    pub fn notify_set_app_name(app_name: *const c_char);

    pub fn notify_get_server_caps() -> *mut GList;

    pub fn notify_get_server_info(ret_name: *mut *mut c_char,
                                  ret_vendor: *mut *mut c_char,
                                  ret_version: *mut *mut c_char,
                                  ret_spec_version: *mut *mut c_char);
}
<commit_msg>Use the new path to GList<commit_after>#![feature(libc)]

extern crate libc;
extern crate "glib-2_0-sys" as glib;
extern crate "gobject-2_0-sys" as gobject;

pub mod notification;

pub use notification::*;

use libc::{
    c_char
};

use glib::types::{
    gboolean,
};

use glib::GList;

extern "C" {
    pub fn notify_init(app_name: *const c_char) -> gboolean;
    pub fn notify_uninit();
    pub fn notify_is_initted() -> gboolean;

    pub fn notify_get_app_name() -> *const c_char;
    pub fn notify_set_app_name(app_name: *const c_char);

    pub fn notify_get_server_caps() -> *mut GList;

    pub fn notify_get_server_info(ret_name: *mut *mut c_char,
                                  ret_vendor: *mut *mut c_char,
                                  ret_version: *mut *mut c_char,
                                  ret_spec_version: *mut *mut c_char);
}
<|endoftext|>


<commit_before>pub mod raw;

mod error;
pub use error::*;
mod environment;
pub use environment::*;
mod data_source;
pub use data_source::*;
mod statement;
pub use statement::*;

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

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn list_tables() {
        use super::raw;

        let mut env = Environment::new().unwrap();
        let mut ds = DataSource::with_dsn_and_credentials(&mut env, "PostgreSQL", "postgres", "")
            .unwrap();
        let statement = Statement::with_tables(&mut ds).unwrap();
        assert_eq!(statement.num_result_cols().unwrap(), 4);
    }

    #[test]
    fn test_connection() {

        let mut environment = Environment::new().expect("Environment can be created");
        let conn =
            DataSource::with_dsn_and_credentials(&mut environment, "PostgreSQL", "postgres", "")
                .expect("Could not connect");

        assert!(!conn.read_only().unwrap());
    }

    #[test]
    fn list_drivers() {
        let environment = Environment::new();
        let drivers = environment.expect("Environment can be created")
            .drivers()
            .expect("Drivers can be iterated over");
        println!("{:?}", drivers);

        let expected = ["PostgreSQL ANSI", "PostgreSQL Unicode", "SQLite", "SQLite3"];
        assert!(drivers.iter().map(|d| &d.description).eq(expected.iter()));
    }

    #[test]
    fn list_data_sources() {
        let environment = Environment::new();
        let sources = environment.expect("Environment can be created")
            .data_sources()
            .expect("Data sources can be iterated over");
        println!("{:?}", sources);

        let expected = [DataSourceInfo {
                            server_name: "PostgreSQL".to_owned(),
                            description: "PostgreSQL Unicode".to_owned(),
                        }];
        assert!(sources.iter().eq(expected.iter()));
    }

    #[test]
    fn list_user_data_sources() {
        let environment = Environment::new();
        let sources = environment.expect("Environment can be created")
            .user_data_sources()
            .expect("Data sources can be iterated over");
        println!("{:?}", sources);

        let expected = [DataSourceInfo {
                            server_name: "PostgreSQL".to_owned(),
                            description: "PostgreSQL Unicode".to_owned(),
                        }];
        assert!(sources.iter().eq(expected.iter()));
    }

    #[test]
    fn list_system_data_sources() {
        let environment = Environment::new();
        let sources = environment.expect("Environment can be created")
            .system_data_sources()
            .expect("Data sources can be iterated over");
        println!("{:?}", sources);

        let expected: [DataSourceInfo; 0] = [];
        assert!(sources.iter().eq(expected.iter()));
    }

    #[test]
    fn provoke_error() {
        use std;
        let mut environment = Environment::new().unwrap();
        // let mut dbc: raw::SQLHDBC = 0;
        let error;
        unsafe {
            // We set the output pointer to zero. This is an error!
            raw::SQLAllocHandle(raw::SQL_HANDLE_DBC, environment.raw(), std::ptr::null_mut());
            // Let's create a diagnostic record describing that error
            error = Error::SqlError(DiagRec::create(raw::SQL_HANDLE_ENV, environment.raw()));
        }
        if cfg!(target_os = "windows") {
            assert_eq!(format!("{}", error),
                       "[Microsoft][ODBC Driver Manager] Invalid argument value");
        } else {
            assert_eq!(format!("{}", error),
                       "[unixODBC][Driver Manager]Invalid use of null pointer");
        }
    }
}<commit_msg>correct number of columns in test<commit_after>pub mod raw;

mod error;
pub use error::*;
mod environment;
pub use environment::*;
mod data_source;
pub use data_source::*;
mod statement;
pub use statement::*;

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

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn list_tables() {
        use super::raw;

        let mut env = Environment::new().unwrap();
        let mut ds = DataSource::with_dsn_and_credentials(&mut env, "PostgreSQL", "postgres", "")
            .unwrap();
        let statement = Statement::with_tables(&mut ds).unwrap();
        assert_eq!(statement.num_result_cols().unwrap(), 5);
    }

    #[test]
    fn test_connection() {

        let mut environment = Environment::new().expect("Environment can be created");
        let conn =
            DataSource::with_dsn_and_credentials(&mut environment, "PostgreSQL", "postgres", "")
                .expect("Could not connect");

        assert!(!conn.read_only().unwrap());
    }

    #[test]
    fn list_drivers() {
        let environment = Environment::new();
        let drivers = environment.expect("Environment can be created")
            .drivers()
            .expect("Drivers can be iterated over");
        println!("{:?}", drivers);

        let expected = ["PostgreSQL ANSI", "PostgreSQL Unicode", "SQLite", "SQLite3"];
        assert!(drivers.iter().map(|d| &d.description).eq(expected.iter()));
    }

    #[test]
    fn list_data_sources() {
        let environment = Environment::new();
        let sources = environment.expect("Environment can be created")
            .data_sources()
            .expect("Data sources can be iterated over");
        println!("{:?}", sources);

        let expected = [DataSourceInfo {
                            server_name: "PostgreSQL".to_owned(),
                            description: "PostgreSQL Unicode".to_owned(),
                        }];
        assert!(sources.iter().eq(expected.iter()));
    }

    #[test]
    fn list_user_data_sources() {
        let environment = Environment::new();
        let sources = environment.expect("Environment can be created")
            .user_data_sources()
            .expect("Data sources can be iterated over");
        println!("{:?}", sources);

        let expected = [DataSourceInfo {
                            server_name: "PostgreSQL".to_owned(),
                            description: "PostgreSQL Unicode".to_owned(),
                        }];
        assert!(sources.iter().eq(expected.iter()));
    }

    #[test]
    fn list_system_data_sources() {
        let environment = Environment::new();
        let sources = environment.expect("Environment can be created")
            .system_data_sources()
            .expect("Data sources can be iterated over");
        println!("{:?}", sources);

        let expected: [DataSourceInfo; 0] = [];
        assert!(sources.iter().eq(expected.iter()));
    }

    #[test]
    fn provoke_error() {
        use std;
        let mut environment = Environment::new().unwrap();
        // let mut dbc: raw::SQLHDBC = 0;
        let error;
        unsafe {
            // We set the output pointer to zero. This is an error!
            raw::SQLAllocHandle(raw::SQL_HANDLE_DBC, environment.raw(), std::ptr::null_mut());
            // Let's create a diagnostic record describing that error
            error = Error::SqlError(DiagRec::create(raw::SQL_HANDLE_ENV, environment.raw()));
        }
        if cfg!(target_os = "windows") {
            assert_eq!(format!("{}", error),
                       "[Microsoft][ODBC Driver Manager] Invalid argument value");
        } else {
            assert_eq!(format!("{}", error),
                       "[unixODBC][Driver Manager]Invalid use of null pointer");
        }
    }
}<|endoftext|>


<commit_before>extern crate ascii;

mod pascal_str;
mod pascal_string;

const PASCAL_STRING_BUF_SIZE: usize = 255;

pub use pascal_str::{Chars, CharsMut, PascalStr};
pub use pascal_string::{PascalString, PascalStringAppendError, PascalStringCreateError};

#[cfg(test)]
mod tests {
    use super::*;
    use ascii::*;
    #[test]
    fn test_string_creation() {
        let test = "Hello, my world!".to_owned();
        let test_pascal = PascalString::from(&test).unwrap();
        assert_eq!(&test, test_pascal.as_str());
    }

    #[test]
    fn test_character_append() {
        let mut string = PascalString::new();
        assert!(string.try_push('h').is_ok());
        string.push('e');
        string.push(76u8);
        string.push('l');
        string.push(AsciiChar::L);
        string.push('o');
        string.push(AsciiChar::Null);

        println!("{}", string);
        assert_eq!(string.as_str(), "heLlLo\0");
    }

    #[test]
    fn test_string_append() {
        let mut string = PascalString::new();
        string.push_str("Hola, ");
        string.push_str("Senor!");
        assert_eq!(string.as_str(), "Hola, Senor!");
    }

    #[test]
    fn test_string_indexing_and_char_iteration() {
        let mut string = PascalString::from("q").unwrap();
        assert_eq!(string[0u8], AsciiChar::q);

        let mut string2 = PascalString::from("WASD").unwrap();
        let mut iter = string2.chars();
        assert_eq!(iter.next(), Some(&AsciiChar::W));
        assert_eq!(iter.next(), Some(&AsciiChar::A));
        assert_eq!(iter.next(), Some(&AsciiChar::S));
        assert_eq!(iter.next(), Some(&AsciiChar::D));
    }
}
<commit_msg>Add test_as_cstr, and export AsciiError<commit_after>extern crate ascii;

mod pascal_str;
mod pascal_string;

const PASCAL_STRING_BUF_SIZE: usize = 255;

pub use pascal_str::{Chars, CharsMut, PascalStr};
pub use pascal_string::{PascalString, PascalStringAppendError, PascalStringCreateError, AsciiError};

#[cfg(test)]
mod tests {
    use super::*;
    use ascii::*;
    use std::borrow::Cow;
    use std::ffi::{CStr, CString};

    #[test]
    fn test_string_creation() {
        let test = "Hello, my world!".to_owned();
        let test_pascal = PascalString::from(&test).unwrap();
        assert_eq!(&test, test_pascal.as_str());
    }

    #[test]
    fn test_character_append() {
        let mut string = PascalString::new();
        assert!(string.try_push('h').is_ok());
        string.push('e');
        string.push(76u8);
        string.push('l');
        string.push(AsciiChar::L);
        string.push('o');
        string.push(AsciiChar::Null);

        println!("{}", string);
        assert_eq!(string.as_str(), "heLlLo\0");
    }

    #[test]
    fn test_string_append() {
        let mut string = PascalString::new();
        string.push_str("Hola, ");
        string.push_str("Senor!");
        assert_eq!(string.as_str(), "Hola, Senor!");
    }

    #[test]
    fn test_string_indexing_and_char_iteration() {
        let mut string = PascalString::from("q").unwrap();
        assert_eq!(string[0u8], AsciiChar::q);

        let mut string2 = PascalString::from("WASD").unwrap();
        let mut iter = string2.chars();
        assert_eq!(iter.next(), Some(&AsciiChar::W));
        assert_eq!(iter.next(), Some(&AsciiChar::A));
        assert_eq!(iter.next(), Some(&AsciiChar::S));
        assert_eq!(iter.next(), Some(&AsciiChar::D));
    }

    #[test]
    fn test_as_cstr() {
        let msg = "I am your favourite cookie monster >:-)\0";
        let pstr = PascalString::from(&msg).unwrap();
        let cstr = CStr::from_bytes_with_nul(msg.as_bytes()).unwrap();
        let pstr_as_cstr = pstr.as_cstr().unwrap();
        assert!(match pstr_as_cstr {
            Cow::Borrowed(_) => true,
            _ => false
        });
        assert_eq!(&*pstr_as_cstr, cstr);

        let oversized = ['l'; 255];
        let mut string_oversized = {
            let mut s = String::new();
            for i in 0..oversized.len() {
                s.push(oversized[i]);
            }
            s
        };
        let pstr_oversized = PascalString::from_fixed_ascii_array(255, oversized).unwrap();
        println!("oversized: {}", pstr_oversized.is_full());
        let cstr_from_pstr_oversized = pstr_oversized.as_cstr().unwrap();
        let cstr_from_string_oversized = CString::new(string_oversized).unwrap();
        assert!(match cstr_from_pstr_oversized {
            Cow::Owned(_) => true,
            _ => false
        });
        assert_eq!(cstr_from_pstr_oversized.into_owned(), cstr_from_string_oversized);
    }
}
<|endoftext|>


<commit_before>pub struct Nil;
pub struct Cons<H, T>(pub H, pub T);

#[allow(dead_code)]
pub enum Here {}
#[allow(dead_code)]
pub struct There<T>(std::marker::PhantomData<T>);

impl Nil {
    pub fn push<N>(self, item: N) -> Cons<N, Self> {
        Cons(item, self)
    }
}

impl<H, T> Cons<H, T> {
    pub fn push<N>(self, item: N) -> Cons<N, Self> {
        Cons(item, self)
    }
}

pub trait Find<T, I> {
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

impl<T, Tail> Find<T, Here> for Cons<T, Tail> {
    fn get(&self) -> &T {
        &self.0
    }
    fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<Head, T, Tail, TailI> Find<T, There<TailI>> for Cons<Head, Tail>
    where Tail: Find<T, TailI> {
    fn get(&self) -> &T {
        self.1.get()
    }
    fn get_mut(&mut self) -> &mut T {
        self.1.get_mut()
    }
}

#[test]
fn test_get() {
    let list = Nil.push(5i32).push("Foo");
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 5i32);
    assert!(b == "Foo");
}

#[test]
fn test_get_mut() {
    let mut list = Nil.push(5i32).push("Foo");
    *list.get_mut() = 6i32;
    *list.get_mut() = "Bar";
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 6i32);
    assert!(b == "Bar");
}
<commit_msg>TailI -> TailIndex<commit_after>pub struct Nil;
pub struct Cons<H, T>(pub H, pub T);

#[allow(dead_code)]
pub enum Here {}
#[allow(dead_code)]
pub struct There<T>(std::marker::PhantomData<T>);

impl Nil {
    pub fn push<N>(self, item: N) -> Cons<N, Self> {
        Cons(item, self)
    }
}

impl<H, T> Cons<H, T> {
    pub fn push<N>(self, item: N) -> Cons<N, Self> {
        Cons(item, self)
    }
}

pub trait Find<T, I> {
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

impl<T, Tail> Find<T, Here> for Cons<T, Tail> {
    fn get(&self) -> &T {
        &self.0
    }
    fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<Head, T, Tail, TailIndex> Find<T, There<TailIndex>> for Cons<Head, Tail>
    where Tail: Find<T, TailIndex> {
    fn get(&self) -> &T {
        self.1.get()
    }
    fn get_mut(&mut self) -> &mut T {
        self.1.get_mut()
    }
}

#[test]
fn test_get() {
    let list = Nil.push(5i32).push("Foo");
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 5i32);
    assert!(b == "Foo");
}

#[test]
fn test_get_mut() {
    let mut list = Nil.push(5i32).push("Foo");
    *list.get_mut() = 6i32;
    *list.get_mut() = "Bar";
    let a: i32 = *list.get();
    let b: &str = *list.get();
    assert!(a == 6i32);
    assert!(b == "Bar");
}
<|endoftext|>


<commit_before>//! This crate allows you to construct email messages in a way that assures that
//! they are compliant with relevant email standards (especially RFC 5322).  Invalid
//! data submitted will return a ParseError.
//!
//! ````
//! extern crate email_format;
//!
//! use email_format::Email;
//!
//! fn main() {
//!   let mut email = Email::new(
//!       "myself@mydomain.com",  // "From:"
//!       "Wed, 05 Jan 2015 15:13:05 +1300" // "Date:"
//!   ).unwrap();
//!   email.set_sender("from_myself@mydomain.com").unwrap();
//!   email.set_reply_to("My Mailer <no-reply@mydomain.com>").unwrap();
//!   email.set_to("You <you@yourdomain.com>").unwrap();
//!   email.set_cc("Our Friend <friend@frienddomain.com>").unwrap();
//!   email.set_message_id("<id/20161128115731.29084.maelstrom@mydomain.com>").unwrap();
//!   email.set_subject("Hello Friend").unwrap();
//!   email.set_body("Good to hear from you.\r\n\
//!                   I wish you the best.\r\n\
//!                   \r\n\
//!                   Your Friend").unwrap();
//!
//!   println!("{}", email);
//! }
//! ````

extern crate buf_read_ext;

#[cfg(test)]
mod tests;

pub mod rfc5322;

use std::io::Write;
use std::io::Error as IoError;

use rfc5322::{Message, Fields, Field};
use rfc5322::{Parsable, Streamable};
use rfc5322::error::ParseError;
use rfc5322::Body;
use rfc5322::headers::{From, OrigDate, Sender, ReplyTo, To, Cc, Bcc, MessageId,
                           InReplyTo, References, Subject, Comments, Keywords,
                           OptionalField};

/// Attempt to construct `Self` via a conversion.
///
/// This TryFrom trait is defined in the rust std library but is behind a
/// feature gate.  We place it here so that people using stable compilers
/// can still use our crate.  In the future, the std trait should be used.
pub trait TryFrom<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_from(T) -> Result<Self, Self::Err>;
}

// We implement TryFrom from T to T with our ParseError for crate ergonomics
// (Rust won't let it be implemented with an unconstrained error type)
impl<T> TryFrom<T> for T {
    type Err = ::rfc5322::error::ParseError;
    fn try_from(input: T) -> Result<T, Self::Err> {
        Ok(input)
    }
}

#[derive(Debug, Clone)]
pub struct Email {
    message: Message,
}

impl Email {
    pub fn new<F,D>(from: F, date: D) -> Result<Email, ParseError>
        where From: TryFrom<F, Err=ParseError>, OrigDate: TryFrom<D, Err=ParseError>
    {
        Ok(Email {
            message: Message {
                fields: Fields {
                    trace_blocks: vec![],
                    fields: vec![
                        Field::OrigDate(try!(TryFrom::try_from(date))),
                        Field::From(try!(TryFrom::try_from(from))) ],
                },
                body: None,
            }
        })
    }

    pub fn set_date<D>(&mut self, date: D) -> Result<(), ParseError>
        where OrigDate: TryFrom<D, Err=ParseError>
    {
        let value: OrigDate = try!(TryFrom::try_from(date));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::OrigDate(_) = *field {
                *field = Field::OrigDate(value);
                return Ok(())
            }
        }
        unreachable!()
    }
    pub fn get_date(&self) -> OrigDate {
        for field in self.message.fields.fields.iter() {
            if let Field::OrigDate(ref d) = *field {
                return d.clone();
            }
        }
        unreachable!()
    }

    pub fn set_from<F>(&mut self, from: F) -> Result<(), ParseError>
        where From: TryFrom<F, Err=ParseError>
    {
        let value: From = try!(TryFrom::try_from(from));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::From(_) = *field {
                *field = Field::From(value);
                return Ok(());
            }
        }
        unreachable!()
    }
    pub fn get_from(&self) -> From {
        for field in self.message.fields.fields.iter() {
            if let Field::From(ref f) = *field {
                return f.clone()
            }
        }
        unreachable!()
    }

    pub fn set_sender<S>(&mut self, sender: S) -> Result<(), ParseError>
        where Sender: TryFrom<S, Err=ParseError>
    {
        let value: Sender = try!(TryFrom::try_from(sender));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::Sender(_) = *field {
                *field = Field::Sender(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::Sender(value));
        Ok(())
    }
    pub fn get_sender(&self) -> Option<Sender> {
        for field in self.message.fields.fields.iter() {
            if let Field::Sender(ref s) = *field {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_reply_to<R>(&mut self, reply_to: R) -> Result<(), ParseError>
        where ReplyTo: TryFrom<R, Err=ParseError>
    {
        let value: ReplyTo = try!(TryFrom::try_from(reply_to));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::ReplyTo(_) = *field {
                *field = Field::ReplyTo(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::ReplyTo(value));
        Ok(())
    }
    pub fn get_reply_to(&self) -> Option<ReplyTo> {
        for field in self.message.fields.fields.iter() {
            if let Field::ReplyTo(ref rt) = *field {
                return Some(rt.clone())
            }
        }
        None
    }

    pub fn set_to<T>(&mut self, to: T) -> Result<(), ParseError>
        where To: TryFrom<T, Err=ParseError>
    {
        let value: To = try!(TryFrom::try_from(to));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::To(_) = *field {
                *field = Field::To(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::To(value));
        Ok(())
    }
    pub fn get_to(&self) -> Option<To> {
        for field in self.message.fields.fields.iter() {
            if let Field::To(ref t) = *field {
                return Some(t.clone())
            }
        }
        None
    }

    pub fn set_cc<C>(&mut self, cc: C) -> Result<(), ParseError>
        where Cc: TryFrom<C, Err=ParseError>
    {
        let value: Cc = try!(TryFrom::try_from(cc));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::Cc(_) = *field {
                *field = Field::Cc(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::Cc(value));
        Ok(())
    }
    pub fn get_cc(&self) -> Option<Cc> {
        for field in self.message.fields.fields.iter() {
            if let Field::Cc(ref cc) = *field {
                return Some(cc.clone())
            }
        }
        None
    }

    pub fn set_bcc<B>(&mut self, bcc: B) -> Result<(), ParseError>
        where Bcc: TryFrom<B, Err=ParseError>
    {
        let value: Bcc = try!(TryFrom::try_from(bcc));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::Bcc(_) = *field {
                *field = Field::Bcc(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::Bcc(value));
        Ok(())
    }
    pub fn get_bcc(&self) -> Option<Bcc> {
        for field in self.message.fields.fields.iter() {
            if let Field::Bcc(ref b) = *field {
                return Some(b.clone())
            }
        }
        None
    }

    pub fn set_message_id<M>(&mut self, message_id: M) -> Result<(), ParseError>
        where MessageId: TryFrom<M, Err=ParseError>
    {
        let value: MessageId = try!(TryFrom::try_from(message_id));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::MessageId(_) = *field {
                *field = Field::MessageId(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::MessageId(value));
        Ok(())
    }
    pub fn get_message_id(&self) -> Option<MessageId> {
        for field in self.message.fields.fields.iter() {
            if let Field::MessageId(ref m) = *field {
                return Some(m.clone())
            }
        }
        None
    }

    pub fn set_in_reply_to<I>(&mut self, in_reply_to: I) -> Result<(), ParseError>
        where InReplyTo: TryFrom<I, Err=ParseError>
    {
        let value: InReplyTo = try!(TryFrom::try_from(in_reply_to));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::InReplyTo(_) = *field {
                *field = Field::InReplyTo(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::InReplyTo(value));
        Ok(())
    }
    pub fn get_in_reply_to(&self) -> Option<InReplyTo> {
        for field in self.message.fields.fields.iter() {
            if let Field::InReplyTo(ref x) = *field {
                return Some(x.clone())
            }
        }
        None
    }

    pub fn set_references<R>(&mut self, references: R) -> Result<(), ParseError>
        where References: TryFrom<R, Err=ParseError>
    {
        let value: References = try!(TryFrom::try_from(references));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::References(_) = *field {
                *field = Field::References(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::References(value));
        Ok(())
    }
    pub fn get_references(&self) -> Option<References> {
        for field in self.message.fields.fields.iter() {
            if let Field::References(ref x) = *field {
                return Some(x.clone())
            }
        }
        None
    }

    pub fn set_subject<S>(&mut self, subject: S) -> Result<(), ParseError>
        where Subject: TryFrom<S, Err=ParseError>
    {
        let value: Subject = try!(TryFrom::try_from(subject));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::Subject(_) = *field {
                *field = Field::Subject(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::Subject(value));
        Ok(())
    }
    pub fn get_subject(&self) -> Option<Subject> {
        for field in self.message.fields.fields.iter() {
            if let Field::Subject(ref x) = *field {
                return Some(x.clone())
            }
        }
        None
    }

    pub fn add_comments<C>(&mut self, comments: C) -> Result<(), ParseError>
        where Comments: TryFrom<C, Err=ParseError>
    {
        let value: Comments = try!(TryFrom::try_from(comments));
        self.message.fields.fields.push(Field::Comments(value));
        Ok(())
    }
    pub fn get_comments(&self) -> Vec<Comments> {
        let mut output: Vec<Comments> = Vec::new();
        for field in self.message.fields.fields.iter() {
            if let Field::Comments(ref x) = *field {
                output.push(x.clone());
            }
        }
        output
    }

    pub fn add_keywords<K>(&mut self, keywords: K) -> Result<(), ParseError>
        where Keywords: TryFrom<K, Err=ParseError>
    {
        let value: Keywords = try!(TryFrom::try_from(keywords));
        self.message.fields.fields.push(Field::Keywords(value));
        Ok(())
    }
    pub fn get_keywords(&self) -> Vec<Keywords> {
        let mut output: Vec<Keywords> = Vec::new();
        for field in self.message.fields.fields.iter() {
            if let Field::Keywords(ref x) = *field {
                output.push(x.clone());
            }
        }
        output
    }

    pub fn add_optional_field<O>(&mut self, optional_field: O) -> Result<(), ParseError>
        where OptionalField: TryFrom<O, Err=ParseError>
    {
        let value: OptionalField = try!(TryFrom::try_from(optional_field));
        self.message.fields.fields.push(Field::OptionalField(value));
        Ok(())
    }
    pub fn get_optional_fields(&self) -> Vec<OptionalField> {
        let mut output: Vec<OptionalField> = Vec::new();
        for field in self.message.fields.fields.iter() {
            if let Field::OptionalField(ref x) = *field {
                output.push(x.clone());
            }
        }
        output
    }

    // TBD: trace
    // TBD: resent-date
    // TBD: resent-from
    // TBD: resent-sender
    // TBD: resent-to
    // TBD: resent-cc
    // TBD: resent-bcc
    // TBD: resent-msg-id

    pub fn set_body<B>(&mut self, body: B) -> Result<(), ParseError>
        where Body: TryFrom<B, Err=ParseError>
    {
        let value: Body = try!(TryFrom::try_from(body));
        self.message.body = Some(value);
        Ok(())
    }
    pub fn get_body(&self) -> Option<Body> {
        self.message.body.clone()
    }
}

impl Parsable for Email {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        let mut rem = input;
        if let Ok(message) = Message::parse(rem).map(|(value, r)| { rem = r; value }) {
            Ok((Email {
                message: message
            }, rem))
        } else {
            Err(ParseError::NotFound)
        }
    }
}

impl Streamable for Email {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        self.message.stream(w)
    }
}
<commit_msg>impl Display for Email<commit_after>//! This crate allows you to construct email messages in a way that assures that
//! they are compliant with relevant email standards (especially RFC 5322).  Invalid
//! data submitted will return a ParseError.
//!
//! ````
//! extern crate email_format;
//!
//! use email_format::Email;
//!
//! fn main() {
//!   let mut email = Email::new(
//!       "myself@mydomain.com",  // "From:"
//!       "Wed, 05 Jan 2015 15:13:05 +1300" // "Date:"
//!   ).unwrap();
//!   email.set_sender("from_myself@mydomain.com").unwrap();
//!   email.set_reply_to("My Mailer <no-reply@mydomain.com>").unwrap();
//!   email.set_to("You <you@yourdomain.com>").unwrap();
//!   email.set_cc("Our Friend <friend@frienddomain.com>").unwrap();
//!   email.set_message_id("<id/20161128115731.29084.maelstrom@mydomain.com>").unwrap();
//!   email.set_subject("Hello Friend").unwrap();
//!   email.set_body("Good to hear from you.\r\n\
//!                   I wish you the best.\r\n\
//!                   \r\n\
//!                   Your Friend").unwrap();
//!
//!   println!("{}", email);
//! }
//! ````

extern crate buf_read_ext;

#[cfg(test)]
mod tests;

pub mod rfc5322;

use std::io::Write;
use std::io::Error as IoError;
use std::fmt;

use rfc5322::{Message, Fields, Field};
use rfc5322::{Parsable, Streamable};
use rfc5322::error::ParseError;
use rfc5322::Body;
use rfc5322::headers::{From, OrigDate, Sender, ReplyTo, To, Cc, Bcc, MessageId,
                           InReplyTo, References, Subject, Comments, Keywords,
                           OptionalField};

/// Attempt to construct `Self` via a conversion.
///
/// This TryFrom trait is defined in the rust std library but is behind a
/// feature gate.  We place it here so that people using stable compilers
/// can still use our crate.  In the future, the std trait should be used.
pub trait TryFrom<T>: Sized {
    /// The type returned in the event of a conversion error.
    type Err;

    /// Performs the conversion.
    fn try_from(T) -> Result<Self, Self::Err>;
}

// We implement TryFrom from T to T with our ParseError for crate ergonomics
// (Rust won't let it be implemented with an unconstrained error type)
impl<T> TryFrom<T> for T {
    type Err = ::rfc5322::error::ParseError;
    fn try_from(input: T) -> Result<T, Self::Err> {
        Ok(input)
    }
}

#[derive(Debug, Clone)]
pub struct Email {
    message: Message,
}

impl Email {
    pub fn new<F,D>(from: F, date: D) -> Result<Email, ParseError>
        where From: TryFrom<F, Err=ParseError>, OrigDate: TryFrom<D, Err=ParseError>
    {
        Ok(Email {
            message: Message {
                fields: Fields {
                    trace_blocks: vec![],
                    fields: vec![
                        Field::OrigDate(try!(TryFrom::try_from(date))),
                        Field::From(try!(TryFrom::try_from(from))) ],
                },
                body: None,
            }
        })
    }

    pub fn set_date<D>(&mut self, date: D) -> Result<(), ParseError>
        where OrigDate: TryFrom<D, Err=ParseError>
    {
        let value: OrigDate = try!(TryFrom::try_from(date));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::OrigDate(_) = *field {
                *field = Field::OrigDate(value);
                return Ok(())
            }
        }
        unreachable!()
    }
    pub fn get_date(&self) -> OrigDate {
        for field in self.message.fields.fields.iter() {
            if let Field::OrigDate(ref d) = *field {
                return d.clone();
            }
        }
        unreachable!()
    }

    pub fn set_from<F>(&mut self, from: F) -> Result<(), ParseError>
        where From: TryFrom<F, Err=ParseError>
    {
        let value: From = try!(TryFrom::try_from(from));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::From(_) = *field {
                *field = Field::From(value);
                return Ok(());
            }
        }
        unreachable!()
    }
    pub fn get_from(&self) -> From {
        for field in self.message.fields.fields.iter() {
            if let Field::From(ref f) = *field {
                return f.clone()
            }
        }
        unreachable!()
    }

    pub fn set_sender<S>(&mut self, sender: S) -> Result<(), ParseError>
        where Sender: TryFrom<S, Err=ParseError>
    {
        let value: Sender = try!(TryFrom::try_from(sender));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::Sender(_) = *field {
                *field = Field::Sender(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::Sender(value));
        Ok(())
    }
    pub fn get_sender(&self) -> Option<Sender> {
        for field in self.message.fields.fields.iter() {
            if let Field::Sender(ref s) = *field {
                return Some(s.clone());
            }
        }
        None
    }

    pub fn set_reply_to<R>(&mut self, reply_to: R) -> Result<(), ParseError>
        where ReplyTo: TryFrom<R, Err=ParseError>
    {
        let value: ReplyTo = try!(TryFrom::try_from(reply_to));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::ReplyTo(_) = *field {
                *field = Field::ReplyTo(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::ReplyTo(value));
        Ok(())
    }
    pub fn get_reply_to(&self) -> Option<ReplyTo> {
        for field in self.message.fields.fields.iter() {
            if let Field::ReplyTo(ref rt) = *field {
                return Some(rt.clone())
            }
        }
        None
    }

    pub fn set_to<T>(&mut self, to: T) -> Result<(), ParseError>
        where To: TryFrom<T, Err=ParseError>
    {
        let value: To = try!(TryFrom::try_from(to));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::To(_) = *field {
                *field = Field::To(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::To(value));
        Ok(())
    }
    pub fn get_to(&self) -> Option<To> {
        for field in self.message.fields.fields.iter() {
            if let Field::To(ref t) = *field {
                return Some(t.clone())
            }
        }
        None
    }

    pub fn set_cc<C>(&mut self, cc: C) -> Result<(), ParseError>
        where Cc: TryFrom<C, Err=ParseError>
    {
        let value: Cc = try!(TryFrom::try_from(cc));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::Cc(_) = *field {
                *field = Field::Cc(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::Cc(value));
        Ok(())
    }
    pub fn get_cc(&self) -> Option<Cc> {
        for field in self.message.fields.fields.iter() {
            if let Field::Cc(ref cc) = *field {
                return Some(cc.clone())
            }
        }
        None
    }

    pub fn set_bcc<B>(&mut self, bcc: B) -> Result<(), ParseError>
        where Bcc: TryFrom<B, Err=ParseError>
    {
        let value: Bcc = try!(TryFrom::try_from(bcc));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::Bcc(_) = *field {
                *field = Field::Bcc(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::Bcc(value));
        Ok(())
    }
    pub fn get_bcc(&self) -> Option<Bcc> {
        for field in self.message.fields.fields.iter() {
            if let Field::Bcc(ref b) = *field {
                return Some(b.clone())
            }
        }
        None
    }

    pub fn set_message_id<M>(&mut self, message_id: M) -> Result<(), ParseError>
        where MessageId: TryFrom<M, Err=ParseError>
    {
        let value: MessageId = try!(TryFrom::try_from(message_id));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::MessageId(_) = *field {
                *field = Field::MessageId(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::MessageId(value));
        Ok(())
    }
    pub fn get_message_id(&self) -> Option<MessageId> {
        for field in self.message.fields.fields.iter() {
            if let Field::MessageId(ref m) = *field {
                return Some(m.clone())
            }
        }
        None
    }

    pub fn set_in_reply_to<I>(&mut self, in_reply_to: I) -> Result<(), ParseError>
        where InReplyTo: TryFrom<I, Err=ParseError>
    {
        let value: InReplyTo = try!(TryFrom::try_from(in_reply_to));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::InReplyTo(_) = *field {
                *field = Field::InReplyTo(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::InReplyTo(value));
        Ok(())
    }
    pub fn get_in_reply_to(&self) -> Option<InReplyTo> {
        for field in self.message.fields.fields.iter() {
            if let Field::InReplyTo(ref x) = *field {
                return Some(x.clone())
            }
        }
        None
    }

    pub fn set_references<R>(&mut self, references: R) -> Result<(), ParseError>
        where References: TryFrom<R, Err=ParseError>
    {
        let value: References = try!(TryFrom::try_from(references));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::References(_) = *field {
                *field = Field::References(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::References(value));
        Ok(())
    }
    pub fn get_references(&self) -> Option<References> {
        for field in self.message.fields.fields.iter() {
            if let Field::References(ref x) = *field {
                return Some(x.clone())
            }
        }
        None
    }

    pub fn set_subject<S>(&mut self, subject: S) -> Result<(), ParseError>
        where Subject: TryFrom<S, Err=ParseError>
    {
        let value: Subject = try!(TryFrom::try_from(subject));
        for field in self.message.fields.fields.iter_mut() {
            if let Field::Subject(_) = *field {
                *field = Field::Subject(value);
                return Ok(());
            }
        }
        self.message.fields.fields.push(Field::Subject(value));
        Ok(())
    }
    pub fn get_subject(&self) -> Option<Subject> {
        for field in self.message.fields.fields.iter() {
            if let Field::Subject(ref x) = *field {
                return Some(x.clone())
            }
        }
        None
    }

    pub fn add_comments<C>(&mut self, comments: C) -> Result<(), ParseError>
        where Comments: TryFrom<C, Err=ParseError>
    {
        let value: Comments = try!(TryFrom::try_from(comments));
        self.message.fields.fields.push(Field::Comments(value));
        Ok(())
    }
    pub fn get_comments(&self) -> Vec<Comments> {
        let mut output: Vec<Comments> = Vec::new();
        for field in self.message.fields.fields.iter() {
            if let Field::Comments(ref x) = *field {
                output.push(x.clone());
            }
        }
        output
    }

    pub fn add_keywords<K>(&mut self, keywords: K) -> Result<(), ParseError>
        where Keywords: TryFrom<K, Err=ParseError>
    {
        let value: Keywords = try!(TryFrom::try_from(keywords));
        self.message.fields.fields.push(Field::Keywords(value));
        Ok(())
    }
    pub fn get_keywords(&self) -> Vec<Keywords> {
        let mut output: Vec<Keywords> = Vec::new();
        for field in self.message.fields.fields.iter() {
            if let Field::Keywords(ref x) = *field {
                output.push(x.clone());
            }
        }
        output
    }

    pub fn add_optional_field<O>(&mut self, optional_field: O) -> Result<(), ParseError>
        where OptionalField: TryFrom<O, Err=ParseError>
    {
        let value: OptionalField = try!(TryFrom::try_from(optional_field));
        self.message.fields.fields.push(Field::OptionalField(value));
        Ok(())
    }
    pub fn get_optional_fields(&self) -> Vec<OptionalField> {
        let mut output: Vec<OptionalField> = Vec::new();
        for field in self.message.fields.fields.iter() {
            if let Field::OptionalField(ref x) = *field {
                output.push(x.clone());
            }
        }
        output
    }

    // TBD: trace
    // TBD: resent-date
    // TBD: resent-from
    // TBD: resent-sender
    // TBD: resent-to
    // TBD: resent-cc
    // TBD: resent-bcc
    // TBD: resent-msg-id

    pub fn set_body<B>(&mut self, body: B) -> Result<(), ParseError>
        where Body: TryFrom<B, Err=ParseError>
    {
        let value: Body = try!(TryFrom::try_from(body));
        self.message.body = Some(value);
        Ok(())
    }
    pub fn get_body(&self) -> Option<Body> {
        self.message.body.clone()
    }
}

impl Parsable for Email {
    fn parse(input: &[u8]) -> Result<(Self, &[u8]), ParseError> {
        let mut rem = input;
        if let Ok(message) = Message::parse(rem).map(|(value, r)| { rem = r; value }) {
            Ok((Email {
                message: message
            }, rem))
        } else {
            Err(ParseError::NotFound)
        }
    }
}

impl Streamable for Email {
    fn stream<W: Write>(&self, w: &mut W) -> Result<usize, IoError> {
        self.message.stream(w)
    }
}

impl fmt::Display for Email {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let mut output: Vec<u8> = Vec::new();
        if let Err(_) = self.stream(&mut output) {
            return Err(fmt::Error);
        }
        unsafe {
            // rfc5322 formatted emails fall within utf8
            write!(f, "{}", ::std::str::from_utf8_unchecked(&*output))
        }
    }
}
<|endoftext|>