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

//! Parsing interface for parsing a token stream into a syntax tree node.
//!
//! Parsing in Syn is built on parser functions that take in a [`Cursor`] and
//! produce a [`PResult<T>`] where `T` is some syntax tree node. `Cursor` is a
//! cheaply copyable cursor over a range of tokens in a token stream, and
//! `PResult` is a result that packages together a parsed syntax tree node `T`
//! with a stream of remaining unparsed tokens after `T` represented as another
//! `Cursor`, or an [`Error`] if parsing failed.
//!
//! [`Cursor`]: ../buffer/index.html
//! [`PResult<T>`]: type.PResult.html
//! [`Error`]: struct.Error.html
//!
//! This `Cursor`- and `PResult`-based interface is convenient for parser
//! combinators and parser implementations, but not necessarily when you just
//! have some tokens that you want to parse. For that we expose the following
//! two entry points.
//!
//! ## The `syn::parse*` functions
//!
//! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve
//! as an entry point for parsing syntax tree nodes that can be parsed in an
//! obvious default way. These functions can return any syntax tree node that
//! implements the [`Synom`] trait, which includes most types in Syn.
//!
//! [`syn::parse`]: ../fn.parse.html
//! [`syn::parse2`]: ../fn.parse2.html
//! [`syn::parse_str`]: ../fn.parse_str.html
//! [`Synom`]: trait.Synom.html
//!
//! ```
//! use syn::Type;
//!
//! # fn run_parser() -> Result<(), syn::synom::Error> {
//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?;
//! #     Ok(())
//! # }
//! #
//! # fn main() {
//! #     run_parser().unwrap();
//! # }
//! ```
//!
//! The [`parse_quote!`] macro also uses this approach.
//!
//! [`parse_quote!`]: ../macro.parse_quote.html
//!
//! ## The `Parser` trait
//!
//! Some types can be parsed in several ways depending on context. For example
//! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like
//! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`]
//! may or may not allow trailing punctuation, and parsing it the wrong way
//! would either reject valid input or accept invalid input.
//!
//! [`Attribute`]: ../struct.Attribute.html
//! [`Punctuated`]: ../punctuated/index.html
//!
//! The `Synom` trait is not implemented in these cases because there is no good
//! behavior to consider the default.
//!
//! ```ignore
//! // Can't parse `Punctuated` without knowing whether trailing punctuation
//! // should be allowed in this context.
//! let path: Punctuated<PathSegment, Token![::]> = syn::parse(tokens)?;
//! ```
//!
//! In these cases the types provide a choice of parser functions rather than a
//! single `Synom` implementation, and those parser functions can be invoked
//! through the [`Parser`] trait.
//!
//! [`Parser`]: trait.Parser.html
//!
//! ```
//! # #[macro_use]
//! # extern crate syn;
//! #
//! # extern crate proc_macro2;
//! # use proc_macro2::TokenStream;
//! #
//! use syn::synom::Parser;
//! use syn::punctuated::Punctuated;
//! use syn::{PathSegment, Expr, Attribute};
//!
//! # fn run_parsers() -> Result<(), syn::synom::Error> {
//! #     let tokens = TokenStream::new().into();
//! // Parse a nonempty sequence of path segments separated by `::` punctuation
//! // with no trailing punctuation.
//! let parser = Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty;
//! let path = parser.parse(tokens)?;
//!
//! #     let tokens = TokenStream::new().into();
//! // Parse a possibly empty sequence of expressions terminated by commas with
//! // an optional trailing punctuation.
//! let parser = Punctuated::<Expr, Token![,]>::parse_terminated;
//! let args = parser.parse(tokens)?;
//!
//! #     let tokens = TokenStream::new().into();
//! // Parse zero or more outer attributes but not inner attributes.
//! named!(outer_attrs -> Vec<Attribute>, many0!(Attribute::old_parse_outer));
//! let attrs = outer_attrs.parse(tokens)?;
//! #
//! #     Ok(())
//! # }
//! #
//! # fn main() {}
//! ```
//!
//! # Implementing a parser function
//!
//! Parser functions are usually implemented using the [`nom`]-style parser
//! combinator macros provided by Syn, but may also be implemented without
//! macros be using the low-level [`Cursor`] API directly.
//!
//! [`nom`]: https://github.com/Geal/nom
//!
//! The following parser combinator macros are available and a `Synom` parsing
//! example is provided for each one.
//!
//! - [`alt!`](../macro.alt.html)
//! - [`braces!`](../macro.braces.html)
//! - [`brackets!`](../macro.brackets.html)
//! - [`call!`](../macro.call.html)
//! - [`cond!`](../macro.cond.html)
//! - [`cond_reduce!`](../macro.cond_reduce.html)
//! - [`custom_keyword!`](../macro.custom_keyword.html)
//! - [`do_parse!`](../macro.do_parse.html)
//! - [`epsilon!`](../macro.epsilon.html)
//! - [`input_end!`](../macro.input_end.html)
//! - [`keyword!`](../macro.keyword.html)
//! - [`many0!`](../macro.many0.html)
//! - [`map!`](../macro.map.html)
//! - [`not!`](../macro.not.html)
//! - [`option!`](../macro.option.html)
//! - [`parens!`](../macro.parens.html)
//! - [`punct!`](../macro.punct.html)
//! - [`reject!`](../macro.reject.html)
//! - [`switch!`](../macro.switch.html)
//! - [`syn!`](../macro.syn.html)
//! - [`tuple!`](../macro.tuple.html)
//! - [`value!`](../macro.value.html)
//!
//! *This module is available if Syn is built with the `"parsing"` feature.*

use std::cell::Cell;
use std::rc::Rc;
use std::str::FromStr;

#[cfg(all(
    not(all(target_arch = "wasm32", target_os = "unknown")),
    feature = "proc-macro"
))]
use proc_macro;
use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};

pub use error::{Error, PResult};

use buffer::{Cursor, TokenBuffer};
use parse::{Parse, ParseBuffer, ParseStream, Result};

/// Parsing interface implemented by all types that can be parsed in a default
/// way from a token stream.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This trait is available if Syn is built with the `"parsing"` feature.*
pub trait Synom: Sized {
    fn parse(input: Cursor) -> PResult<Self>;

    /// A short name of the type being parsed.
    ///
    /// The description should only be used for a simple name.  It should not
    /// contain newlines or sentence-ending punctuation, to facilitate embedding in
    /// larger user-facing strings.  Syn will use this description when building
    /// error messages about parse failures.
    ///
    /// # Examples
    ///
    /// ```
    /// # use syn::buffer::Cursor;
    /// # use syn::synom::{Synom, PResult};
    /// #
    /// struct ExprMacro {
    ///     // ...
    /// }
    ///
    /// impl Synom for ExprMacro {
    /// #   fn parse(input: Cursor) -> PResult<Self> { unimplemented!() }
    ///     // fn parse(...) -> ... { ... }
    ///
    ///     fn description() -> Option<&'static str> {
    ///         // Will result in messages like
    ///         //
    ///         //     "failed to parse macro invocation expression: $reason"
    ///         Some("macro invocation expression")
    ///     }
    /// }
    /// ```
    fn description() -> Option<&'static str> {
        None
    }
}

impl<T: Parse> Synom for T {
    fn parse(input: Cursor) -> PResult<Self> {
        let unexpected = Rc::new(Cell::new(None));
        let state = ParseBuffer::new(Span::call_site(), input, unexpected);
        let node = <T as Parse>::parse(&state)?;
        state.check_unexpected()?;
        Ok((node, state.cursor()))
    }
}

impl Parse for TokenStream {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| Ok((cursor.token_stream(), Cursor::empty())))
    }
}

impl Parse for TokenTree {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.token_tree() {
            Some((tt, rest)) => Ok((tt, rest)),
            None => Err(cursor.error("expected token tree")),
        })
    }
}

impl Parse for Group {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| {
            for delim in &[Delimiter::Parenthesis, Delimiter::Brace, Delimiter::Bracket] {
                if let Some((inside, span, rest)) = cursor.group(*delim) {
                    let mut group = Group::new(*delim, inside.token_stream());
                    group.set_span(span);
                    return Ok((group, rest));
                }
            }
            Err(cursor.error("expected group token"))
        })
    }
}

impl Parse for Punct {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.punct() {
            Some((punct, rest)) => Ok((punct, rest)),
            None => Err(cursor.error("expected punctuation token")),
        })
    }
}

impl Parse for Literal {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.literal() {
            Some((literal, rest)) => Ok((literal, rest)),
            None => Err(cursor.error("expected literal token")),
        })
    }
}

/// Parser that can parse Rust tokens into a particular syntax tree node.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This trait is available if Syn is built with the `"parsing"` feature.*
pub trait Parser: Sized {
    type Output;

    /// Parse a proc-macro2 token stream into the chosen syntax tree node.
    fn parse2(self, tokens: TokenStream) -> Result<Self::Output>;

    /// Parse tokens of source code into the chosen syntax tree node.
    ///
    /// *This method is available if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", target_os = "unknown")),
        feature = "proc-macro"
    ))]
    fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output> {
        self.parse2(proc_macro2::TokenStream::from(tokens))
    }

    /// Parse a string of Rust code into the chosen syntax tree node.
    ///
    /// # Hygiene
    ///
    /// Every span in the resulting syntax tree will be set to resolve at the
    /// macro call site.
    fn parse_str(self, s: &str) -> Result<Self::Output> {
        self.parse2(proc_macro2::TokenStream::from_str(s)?)
    }
}

impl<F, T> Parser for F
where
    F: FnOnce(ParseStream) -> Result<T>,
{
    type Output = T;

    fn parse2(self, tokens: TokenStream) -> Result<T> {
        let buf = TokenBuffer::new2(tokens);
        let unexpected = Rc::new(Cell::new(None));
        let state = ParseBuffer::new(Span::call_site(), buf.begin(), unexpected);
        let node = self(&state)?;
        state.check_unexpected()?;
        if state.is_empty() {
            Ok(node)
        } else {
            Err(state.error("unexpected token"))
        }
    }
}

/// Extension traits that are made available within the `call!` parser.
///
/// *This module is available if Syn is built with the `"parsing"` feature.*
pub mod ext {
    use proc_macro2::Ident;

    use parse::{ParseStream, Result};

    /// Additional parsing methods for `Ident`.
    ///
    /// This trait is sealed and cannot be implemented for types outside of Syn.
    ///
    /// *This trait is available if Syn is built with the `"parsing"` feature.*
    pub trait IdentExt: Sized + private::Sealed {
        /// Parses any identifier including keywords.
        ///
        /// This is useful when parsing a DSL which allows Rust keywords as
        /// identifiers.
        ///
        /// ```rust
        /// #[macro_use]
        /// extern crate syn;
        ///
        /// use syn::Ident;
        ///
        /// // Parses input that looks like `name = NAME` where `NAME` can be
        /// // any identifier.
        /// //
        /// // Examples:
        /// //
        /// //     name = anything
        /// //     name = impl
        /// named!(parse_dsl -> Ident, do_parse!(
        ///     custom_keyword!(name) >>
        ///     punct!(=) >>
        ///     name: call!(Ident::parse_any) >>
        ///     (name)
        /// ));
        /// #
        /// # fn main() {}
        /// ```
        fn parse_any(input: ParseStream) -> Result<Self>;
    }

    impl IdentExt for Ident {
        fn parse_any(input: ParseStream) -> Result<Self> {
            input.step_cursor(|cursor| match cursor.ident() {
                Some((ident, rest)) => Ok((ident, rest)),
                None => Err(cursor.error("expected ident")),
            })
        }
    }

    mod private {
        use proc_macro2::Ident;

        pub trait Sealed {}

        impl Sealed for Ident {}
    }
}
<commit_msg>Remove Synom trait<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Parsing interface for parsing a token stream into a syntax tree node.
//!
//! Parsing in Syn is built on parser functions that take in a [`Cursor`] and
//! produce a [`PResult<T>`] where `T` is some syntax tree node. `Cursor` is a
//! cheaply copyable cursor over a range of tokens in a token stream, and
//! `PResult` is a result that packages together a parsed syntax tree node `T`
//! with a stream of remaining unparsed tokens after `T` represented as another
//! `Cursor`, or an [`Error`] if parsing failed.
//!
//! [`Cursor`]: ../buffer/index.html
//! [`PResult<T>`]: type.PResult.html
//! [`Error`]: struct.Error.html
//!
//! This `Cursor`- and `PResult`-based interface is convenient for parser
//! combinators and parser implementations, but not necessarily when you just
//! have some tokens that you want to parse. For that we expose the following
//! two entry points.
//!
//! ## The `syn::parse*` functions
//!
//! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve
//! as an entry point for parsing syntax tree nodes that can be parsed in an
//! obvious default way. These functions can return any syntax tree node that
//! implements the [`Synom`] trait, which includes most types in Syn.
//!
//! [`syn::parse`]: ../fn.parse.html
//! [`syn::parse2`]: ../fn.parse2.html
//! [`syn::parse_str`]: ../fn.parse_str.html
//! [`Synom`]: trait.Synom.html
//!
//! ```
//! use syn::Type;
//!
//! # fn run_parser() -> Result<(), syn::synom::Error> {
//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?;
//! #     Ok(())
//! # }
//! #
//! # fn main() {
//! #     run_parser().unwrap();
//! # }
//! ```
//!
//! The [`parse_quote!`] macro also uses this approach.
//!
//! [`parse_quote!`]: ../macro.parse_quote.html
//!
//! ## The `Parser` trait
//!
//! Some types can be parsed in several ways depending on context. For example
//! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like
//! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`]
//! may or may not allow trailing punctuation, and parsing it the wrong way
//! would either reject valid input or accept invalid input.
//!
//! [`Attribute`]: ../struct.Attribute.html
//! [`Punctuated`]: ../punctuated/index.html
//!
//! The `Synom` trait is not implemented in these cases because there is no good
//! behavior to consider the default.
//!
//! ```ignore
//! // Can't parse `Punctuated` without knowing whether trailing punctuation
//! // should be allowed in this context.
//! let path: Punctuated<PathSegment, Token![::]> = syn::parse(tokens)?;
//! ```
//!
//! In these cases the types provide a choice of parser functions rather than a
//! single `Synom` implementation, and those parser functions can be invoked
//! through the [`Parser`] trait.
//!
//! [`Parser`]: trait.Parser.html
//!
//! ```
//! # #[macro_use]
//! # extern crate syn;
//! #
//! # extern crate proc_macro2;
//! # use proc_macro2::TokenStream;
//! #
//! use syn::synom::Parser;
//! use syn::punctuated::Punctuated;
//! use syn::{PathSegment, Expr, Attribute};
//!
//! # fn run_parsers() -> Result<(), syn::synom::Error> {
//! #     let tokens = TokenStream::new().into();
//! // Parse a nonempty sequence of path segments separated by `::` punctuation
//! // with no trailing punctuation.
//! let parser = Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty;
//! let path = parser.parse(tokens)?;
//!
//! #     let tokens = TokenStream::new().into();
//! // Parse a possibly empty sequence of expressions terminated by commas with
//! // an optional trailing punctuation.
//! let parser = Punctuated::<Expr, Token![,]>::parse_terminated;
//! let args = parser.parse(tokens)?;
//!
//! #     let tokens = TokenStream::new().into();
//! // Parse zero or more outer attributes but not inner attributes.
//! named!(outer_attrs -> Vec<Attribute>, many0!(Attribute::old_parse_outer));
//! let attrs = outer_attrs.parse(tokens)?;
//! #
//! #     Ok(())
//! # }
//! #
//! # fn main() {}
//! ```
//!
//! # Implementing a parser function
//!
//! Parser functions are usually implemented using the [`nom`]-style parser
//! combinator macros provided by Syn, but may also be implemented without
//! macros be using the low-level [`Cursor`] API directly.
//!
//! [`nom`]: https://github.com/Geal/nom
//!
//! The following parser combinator macros are available and a `Synom` parsing
//! example is provided for each one.
//!
//! - [`alt!`](../macro.alt.html)
//! - [`braces!`](../macro.braces.html)
//! - [`brackets!`](../macro.brackets.html)
//! - [`call!`](../macro.call.html)
//! - [`cond!`](../macro.cond.html)
//! - [`cond_reduce!`](../macro.cond_reduce.html)
//! - [`custom_keyword!`](../macro.custom_keyword.html)
//! - [`do_parse!`](../macro.do_parse.html)
//! - [`epsilon!`](../macro.epsilon.html)
//! - [`input_end!`](../macro.input_end.html)
//! - [`keyword!`](../macro.keyword.html)
//! - [`many0!`](../macro.many0.html)
//! - [`map!`](../macro.map.html)
//! - [`not!`](../macro.not.html)
//! - [`option!`](../macro.option.html)
//! - [`parens!`](../macro.parens.html)
//! - [`punct!`](../macro.punct.html)
//! - [`reject!`](../macro.reject.html)
//! - [`switch!`](../macro.switch.html)
//! - [`syn!`](../macro.syn.html)
//! - [`tuple!`](../macro.tuple.html)
//! - [`value!`](../macro.value.html)
//!
//! *This module is available if Syn is built with the `"parsing"` feature.*

use std::cell::Cell;
use std::rc::Rc;
use std::str::FromStr;

#[cfg(all(
    not(all(target_arch = "wasm32", target_os = "unknown")),
    feature = "proc-macro"
))]
use proc_macro;
use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};

pub use error::{Error, PResult};

use buffer::{Cursor, TokenBuffer};
use parse::{Parse, ParseBuffer, ParseStream, Result};

impl Parse for TokenStream {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| Ok((cursor.token_stream(), Cursor::empty())))
    }
}

impl Parse for TokenTree {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.token_tree() {
            Some((tt, rest)) => Ok((tt, rest)),
            None => Err(cursor.error("expected token tree")),
        })
    }
}

impl Parse for Group {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| {
            for delim in &[Delimiter::Parenthesis, Delimiter::Brace, Delimiter::Bracket] {
                if let Some((inside, span, rest)) = cursor.group(*delim) {
                    let mut group = Group::new(*delim, inside.token_stream());
                    group.set_span(span);
                    return Ok((group, rest));
                }
            }
            Err(cursor.error("expected group token"))
        })
    }
}

impl Parse for Punct {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.punct() {
            Some((punct, rest)) => Ok((punct, rest)),
            None => Err(cursor.error("expected punctuation token")),
        })
    }
}

impl Parse for Literal {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.literal() {
            Some((literal, rest)) => Ok((literal, rest)),
            None => Err(cursor.error("expected literal token")),
        })
    }
}

/// Parser that can parse Rust tokens into a particular syntax tree node.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This trait is available if Syn is built with the `"parsing"` feature.*
pub trait Parser: Sized {
    type Output;

    /// Parse a proc-macro2 token stream into the chosen syntax tree node.
    fn parse2(self, tokens: TokenStream) -> Result<Self::Output>;

    /// Parse tokens of source code into the chosen syntax tree node.
    ///
    /// *This method is available if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", target_os = "unknown")),
        feature = "proc-macro"
    ))]
    fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output> {
        self.parse2(proc_macro2::TokenStream::from(tokens))
    }

    /// Parse a string of Rust code into the chosen syntax tree node.
    ///
    /// # Hygiene
    ///
    /// Every span in the resulting syntax tree will be set to resolve at the
    /// macro call site.
    fn parse_str(self, s: &str) -> Result<Self::Output> {
        self.parse2(proc_macro2::TokenStream::from_str(s)?)
    }
}

impl<F, T> Parser for F
where
    F: FnOnce(ParseStream) -> Result<T>,
{
    type Output = T;

    fn parse2(self, tokens: TokenStream) -> Result<T> {
        let buf = TokenBuffer::new2(tokens);
        let unexpected = Rc::new(Cell::new(None));
        let state = ParseBuffer::new(Span::call_site(), buf.begin(), unexpected);
        let node = self(&state)?;
        state.check_unexpected()?;
        if state.is_empty() {
            Ok(node)
        } else {
            Err(state.error("unexpected token"))
        }
    }
}

/// Extension traits that are made available within the `call!` parser.
///
/// *This module is available if Syn is built with the `"parsing"` feature.*
pub mod ext {
    use proc_macro2::Ident;

    use parse::{ParseStream, Result};

    /// Additional parsing methods for `Ident`.
    ///
    /// This trait is sealed and cannot be implemented for types outside of Syn.
    ///
    /// *This trait is available if Syn is built with the `"parsing"` feature.*
    pub trait IdentExt: Sized + private::Sealed {
        /// Parses any identifier including keywords.
        ///
        /// This is useful when parsing a DSL which allows Rust keywords as
        /// identifiers.
        ///
        /// ```rust
        /// #[macro_use]
        /// extern crate syn;
        ///
        /// use syn::Ident;
        ///
        /// // Parses input that looks like `name = NAME` where `NAME` can be
        /// // any identifier.
        /// //
        /// // Examples:
        /// //
        /// //     name = anything
        /// //     name = impl
        /// named!(parse_dsl -> Ident, do_parse!(
        ///     custom_keyword!(name) >>
        ///     punct!(=) >>
        ///     name: call!(Ident::parse_any) >>
        ///     (name)
        /// ));
        /// #
        /// # fn main() {}
        /// ```
        fn parse_any(input: ParseStream) -> Result<Self>;
    }

    impl IdentExt for Ident {
        fn parse_any(input: ParseStream) -> Result<Self> {
            input.step_cursor(|cursor| match cursor.ident() {
                Some((ident, rest)) => Ok((ident, rest)),
                None => Err(cursor.error("expected ident")),
            })
        }
    }

    mod private {
        use proc_macro2::Ident;

        pub trait Sealed {}

        impl Sealed for Ident {}
    }
}
<|endoftext|>


<commit_before>
#[cfg(test)]
mod tests {

    #[test]
    fn it_works() {

    }

}

<commit_msg>Add ugliest tests ever.<commit_after>
#![cfg(test)]

mod tests {

    use crypto::sha3::Sha3;

    use MerkleTree;
    use MerkleDigest;
    use Hashable;

    #[test]
    fn test_from_vec3() {
        let mut digest = Sha3::sha3_256();

        let values = vec![1, 2, 3];
        let hashes = vec![digest.hash_bytes(&1.to_bytes()), digest.hash_bytes(&2.to_bytes()), digest.hash_bytes(&3.to_bytes())];

        let tree   = MerkleTree::from_vec(digest, values);

        let root_hash = Sha3::sha3_256().combine_hashes(
            &Sha3::sha3_256().combine_hashes(&hashes[0], &hashes[1]),
            &Sha3::sha3_256().hash_bytes(&hashes[2])
        );

        assert_eq!(tree.count, 3);
        assert_eq!(tree.height, 2);
        assert_eq!(tree.root_hash().as_slice(), root_hash.as_slice());
    }

    #[test]
    fn test_from_vec9() {
        let mut digest = Sha3::sha3_256();

        let values = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let hashes = values.clone().iter().map(|v| digest.hash_bytes(&v.to_bytes())).collect::<Vec<_>>();
        let count  = values.len();

        let tree   = MerkleTree::from_vec(digest, values);

        let root_hash = Sha3::sha3_256().combine_hashes(
            &Sha3::sha3_256().combine_hashes(
                &Sha3::sha3_256().combine_hashes(
                    &Sha3::sha3_256().combine_hashes(&hashes[0], &hashes[1]),
                    &Sha3::sha3_256().combine_hashes(&hashes[2], &hashes[3])
                ),
                &Sha3::sha3_256().combine_hashes(
                    &Sha3::sha3_256().combine_hashes(&hashes[4], &hashes[5]),
                    &Sha3::sha3_256().combine_hashes(&hashes[6], &hashes[7])
                )
            ),
            &Sha3::sha3_256().hash_bytes(&hashes[8])
        );

        assert_eq!(tree.count, count);
        assert_eq!(tree.height, 4);
        assert_eq!(tree.root_hash().as_slice(), root_hash.as_slice());
    }

}

<|endoftext|>


<commit_before>use std::io::fs::{mod, PathExtensions};
use std::io::USER_DIR;
use std::rt::unwind;
use std::path::Path;

use core::{mod, EnvBuilder, DbFlags, EnvNoMemInit, EnvNoMetaSync};

fn test_db_in_path(path: &Path, f: ||) {
    // Delete dir to be sure nothing existed before test
    if path.exists() {
        let _ = fs::rmdir_recursive(path);
    };

    let _ = unsafe { unwind::try(f) };

    let _ = fs::rmdir_recursive(path);
}

#[test]
fn test_environment() {
    let path = Path::new("test-lmdb");
    test_db_in_path(&path, || {
        // It looks pretty tree like, because it is the simplest test and
        // it expected to produce easy traceable results
        let env = EnvBuilder::new()
            .max_readers(33)
            .open(&path, USER_DIR);

        match env {
            Ok(mut env) => {
                match env.sync(true) {
                    Ok(..) => (),
                    Err(err) => panic!("Failed to sync: {}", err)
                };

                let test_flags = EnvNoMemInit | EnvNoMetaSync;

                match env.set_flags(test_flags, true) {
                    Ok(_) => {
                        match env.get_flags() {
                            Ok(new_flags) => assert!((new_flags & test_flags) == test_flags, "Get flags != set flags"),
                            Err(err) => panic!("Failed to get flags: {}", err)
                        }
                    },
                    Err(err) => panic!("Failed to set flags: {}", err)
                };

                match env.get_default_db(DbFlags::empty()) {
                    Ok(db) => {
                        let key = "hello".to_string();
                        let value = "world".to_string();

                        match env.new_transaction() {
                            Ok(txn) => {
                                match db.set(&txn, &key, &value) {
                                    Ok(_) => {
                                        match db.get::<String>(&txn, &key) {
                                            Ok(v) => assert!(v.as_slice() == value.as_slice(), "Written {} and read {}", value.as_slice(), v.as_slice()),
                                            Err(err) => panic!("Failed to read value: {}", err)
                                        }
                                    },
                                    Err(err) => panic!("Failed to write value: {}", err)
                                }
                            },
                            Err(err) => panic!("Failed to create transaction: {}", err)
                        }
                    },
                    Err(err) => panic!("Failed to get default database: {}", err)
                }
            },
            Err(err) => panic!("Failed to open path {}: {}", path.display(), err)
        };
    });
}

#[test]
fn test_single_values() {
    let path = Path::new("single-values");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(DbFlags::empty()).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();
        let test_data1 = "value1".to_string();
        let test_data2 = "value2".to_string();

        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key shouldn't exist yet");

        assert!(db.set(&txn, &test_key1, &test_data1).is_ok());
        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data1.as_slice(), "Data written differs from data read");

        assert!(db.set(&txn, &test_key1, &test_data2).is_ok());
        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data2.as_slice(), "Data written differs from data read");

        assert!(db.del(&txn, &test_key1).is_ok());
        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key should be deleted");
    });
}

#[test]
fn test_multiple_values() {
    let path = Path::new("multiple-values");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(core::DbAllowDups).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();
        let test_data1 = "value1".to_string();
        let test_data2 = "value2".to_string();

        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key shouldn't exist yet");

        assert!(db.set(&txn, &test_key1, &test_data1).is_ok());
        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data1.as_slice(), "Data written differs from data read");

        assert!(db.set(&txn, &test_key1, &test_data2).is_ok());
        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data1.as_slice(), "It should still return first value");

        assert!(db.del_item(&txn, &test_key1, &test_data1).is_ok());

        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data2.as_slice(), "It should return second value");
        assert!(db.del(&txn, &test_key1).is_ok());

        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key shouldn't exist anymore!");
    });
}

#[test]
fn test_cursors() {
    let path = Path::new("cursors");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(core::DbAllowDups).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();
        let test_key2 = "key2".to_string();
        let test_values: Vec<String> = vec!("value1".to_string(), "value2".to_string(), "value3".to_string(), "value4".to_string());

        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key shouldn't exist yet");

        for t in test_values.iter() {
            let _ = db.set(&txn, &test_key1, t);
            let _ = db.set(&txn, &test_key2, t);
        }

        let mut cursor = db.new_cursor(&txn).unwrap();
        assert!(cursor.to_first().is_ok());

        assert!(cursor.to_key(&test_key1).is_ok());
        assert!(cursor.item_count().unwrap() == 4);

        assert!(cursor.del_item().is_ok());
        assert!(cursor.item_count().unwrap() == 3);

        assert!(cursor.to_key(&test_key1).is_ok());
        let new_value = "testme".to_string();

        assert!(cursor.replace(&new_value).is_ok());
        let (_, v): ((), String) = cursor.get().unwrap();
        // NOTE: this asserting will work once new_value is
        // of the same length as it is inplace change
        assert!(v.as_slice() == new_value.as_slice());

        assert!(cursor.del_all().is_ok());
        assert!(cursor.to_key(&test_key1).is_err());

        assert!(cursor.to_key(&test_key2).is_ok());
    });
}

#[test]
fn test_cursor_item_manip() {
    let path = Path::new("cursors-items");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(core::DbAllowDups | core::DbAllowIntDups).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();

        assert!(db.set(&txn, &test_key1, &3u64).is_ok());
        let mut cursor = db.new_cursor(&txn).unwrap();
        assert!(cursor.to_key(&test_key1).is_ok());

        let values: Vec<u64> = db.item_iter(&txn, &test_key1).unwrap()
            .map(|cv| cv.get_value())
            .collect();
        assert_eq!(values, vec![3u64]);

        assert!(cursor.add_item(&4u64).is_ok());
        assert!(cursor.add_item(&5u64).is_ok());

        let values: Vec<u64> = db.item_iter(&txn, &test_key1).unwrap()
            .map(|cv| cv.get_value())
            .collect();
        assert_eq!(values, vec![3u64, 4, 5]);

        assert!(cursor.replace(&6u64).is_ok());
        let values: Vec<u64> = db.item_iter(&txn, &test_key1).unwrap()
            .map(|cv| cv.get_value())
            .collect();

        assert_eq!(values, vec![3u64, 4, 6]);
    });
}

#[test]
fn test_item_iter() {
    let path = Path::new("item_iter");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(core::DbAllowDups).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();
        let test_data1 = "value1".to_string();
        let test_data2 = "value2".to_string();
        let test_key2 = "key2".to_string();
        let test_key3 = "key3".to_string();

        assert!(db.set(&txn, &test_key1, &test_data1).is_ok());
        assert!(db.set(&txn, &test_key1, &test_data2).is_ok());
        assert!(db.set(&txn, &test_key2, &test_data1).is_ok());

        let iter = db.item_iter(&txn, &test_key1).unwrap();
        let values: Vec<String> = iter.map(|cv| cv.get_value()).collect();
        assert_eq!(values.as_slice(), vec![test_data1.clone(), test_data2.clone()].as_slice());

        let iter = db.item_iter(&txn, &test_key2).unwrap();
        let values: Vec<String> = iter.map(|cv| cv.get_value()).collect();
        assert_eq!(values.as_slice(), vec![test_data1.clone()].as_slice());

        let iter = db.item_iter(&txn, &test_key3).unwrap();
        let values: Vec<String> = iter.map(|cv| cv.get_value()).collect();
        assert_eq!(values.len(), 0);
    });
}

#[test]
fn test_db_creation() {
    let path = Path::new("dbs");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();
        assert!(env.get_or_create_db("test-db", DbFlags::empty()).is_ok());
    });
}

/*
#[test]
fn test_env_clone() {
let path = Path::new("clone");
test_db_in_path(&path, || {
let mut env = Environment::new().unwrap();
assert!(env.set_maxdbs(5).is_ok());
assert!(env.open(&path, EnvFlags::empty(), 0o755).is_ok());

let env2 = env;

env.set_maxdbs(4);
        });
    }
     */

    /*

    #[test]
    fn test_compilation_of_moved_items() {
        let path = Path::new("dbcom");
        test_db_in_path(&path, || {
            let mut env = Environment::new().unwrap();
            assert!(env.set_maxdbs(5).is_ok());
            assert!(env.open(&path, 0, 0o755).is_ok());

            let db = env.get_default_db(0).unwrap();
            let mut txn = env.new_transaction().unwrap();

            txn.commit();

            let test_key1 = "key1";
            let test_data1 = "value1";

            assert!(txn.get::<()>(&db, &test_key1).is_err(), "Key shouldn't exist yet");
        })
    }
     */
<commit_msg>Simplified environment test case<commit_after>use std::io::fs::{mod, PathExtensions};
use std::io::USER_DIR;
use std::rt::unwind;
use std::path::Path;

use core::{mod, EnvBuilder, DbFlags, EnvNoMemInit, EnvNoMetaSync};

fn test_db_in_path(path: &Path, f: ||) {
    // Delete dir to be sure nothing existed before test
    if path.exists() {
        let _ = fs::rmdir_recursive(path);
    };

    let _ = unsafe { unwind::try(f) };

    let _ = fs::rmdir_recursive(path);
}

#[test]
fn test_environment() {
    let path = Path::new("test-lmdb");
    test_db_in_path(&path, || {
        let mut env = EnvBuilder::new()
            .max_readers(33)
            .open(&path, USER_DIR).unwrap();

        env.sync(true).unwrap();

        let test_flags = EnvNoMemInit | EnvNoMetaSync;

        env.set_flags(test_flags, true).unwrap();
        let new_flags = env.get_flags().unwrap();
        assert!((new_flags & test_flags) == test_flags, "Get flags != set flags");

        let db = env.get_default_db(DbFlags::empty()).unwrap();
        let key = "hello".to_string();
        let value = "world".to_string();

        let txn = env.new_transaction().unwrap();
        db.set(&txn, &key, &value).unwrap();

        let v = db.get::<String>(&txn, &key).unwrap();
        assert!(v.as_slice() == value.as_slice(), "Written {} and read {}", value.as_slice(), v.as_slice());
    });
}

#[test]
fn test_single_values() {
    let path = Path::new("single-values");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(DbFlags::empty()).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();
        let test_data1 = "value1".to_string();
        let test_data2 = "value2".to_string();

        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key shouldn't exist yet");

        assert!(db.set(&txn, &test_key1, &test_data1).is_ok());
        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data1.as_slice(), "Data written differs from data read");

        assert!(db.set(&txn, &test_key1, &test_data2).is_ok());
        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data2.as_slice(), "Data written differs from data read");

        assert!(db.del(&txn, &test_key1).is_ok());
        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key should be deleted");
    });
}

#[test]
fn test_multiple_values() {
    let path = Path::new("multiple-values");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(core::DbAllowDups).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();
        let test_data1 = "value1".to_string();
        let test_data2 = "value2".to_string();

        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key shouldn't exist yet");

        assert!(db.set(&txn, &test_key1, &test_data1).is_ok());
        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data1.as_slice(), "Data written differs from data read");

        assert!(db.set(&txn, &test_key1, &test_data2).is_ok());
        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data1.as_slice(), "It should still return first value");

        assert!(db.del_item(&txn, &test_key1, &test_data1).is_ok());

        let v: String = db.get(&txn, &test_key1).unwrap();
        assert!(v.as_slice() == test_data2.as_slice(), "It should return second value");
        assert!(db.del(&txn, &test_key1).is_ok());

        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key shouldn't exist anymore!");
    });
}

#[test]
fn test_cursors() {
    let path = Path::new("cursors");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(core::DbAllowDups).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();
        let test_key2 = "key2".to_string();
        let test_values: Vec<String> = vec!("value1".to_string(), "value2".to_string(), "value3".to_string(), "value4".to_string());

        assert!(db.get::<()>(&txn, &test_key1).is_err(), "Key shouldn't exist yet");

        for t in test_values.iter() {
            let _ = db.set(&txn, &test_key1, t);
            let _ = db.set(&txn, &test_key2, t);
        }

        let mut cursor = db.new_cursor(&txn).unwrap();
        assert!(cursor.to_first().is_ok());

        assert!(cursor.to_key(&test_key1).is_ok());
        assert!(cursor.item_count().unwrap() == 4);

        assert!(cursor.del_item().is_ok());
        assert!(cursor.item_count().unwrap() == 3);

        assert!(cursor.to_key(&test_key1).is_ok());
        let new_value = "testme".to_string();

        assert!(cursor.replace(&new_value).is_ok());
        let (_, v): ((), String) = cursor.get().unwrap();
        // NOTE: this asserting will work once new_value is
        // of the same length as it is inplace change
        assert!(v.as_slice() == new_value.as_slice());

        assert!(cursor.del_all().is_ok());
        assert!(cursor.to_key(&test_key1).is_err());

        assert!(cursor.to_key(&test_key2).is_ok());
    });
}

#[test]
fn test_cursor_item_manip() {
    let path = Path::new("cursors-items");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(core::DbAllowDups | core::DbAllowIntDups).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();

        assert!(db.set(&txn, &test_key1, &3u64).is_ok());
        let mut cursor = db.new_cursor(&txn).unwrap();
        assert!(cursor.to_key(&test_key1).is_ok());

        let values: Vec<u64> = db.item_iter(&txn, &test_key1).unwrap()
            .map(|cv| cv.get_value())
            .collect();
        assert_eq!(values, vec![3u64]);

        assert!(cursor.add_item(&4u64).is_ok());
        assert!(cursor.add_item(&5u64).is_ok());

        let values: Vec<u64> = db.item_iter(&txn, &test_key1).unwrap()
            .map(|cv| cv.get_value())
            .collect();
        assert_eq!(values, vec![3u64, 4, 5]);

        assert!(cursor.replace(&6u64).is_ok());
        let values: Vec<u64> = db.item_iter(&txn, &test_key1).unwrap()
            .map(|cv| cv.get_value())
            .collect();

        assert_eq!(values, vec![3u64, 4, 6]);
    });
}

#[test]
fn test_item_iter() {
    let path = Path::new("item_iter");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();

        let db = env.get_default_db(core::DbAllowDups).unwrap();
        let txn = env.new_transaction().unwrap();

        let test_key1 = "key1".to_string();
        let test_data1 = "value1".to_string();
        let test_data2 = "value2".to_string();
        let test_key2 = "key2".to_string();
        let test_key3 = "key3".to_string();

        assert!(db.set(&txn, &test_key1, &test_data1).is_ok());
        assert!(db.set(&txn, &test_key1, &test_data2).is_ok());
        assert!(db.set(&txn, &test_key2, &test_data1).is_ok());

        let iter = db.item_iter(&txn, &test_key1).unwrap();
        let values: Vec<String> = iter.map(|cv| cv.get_value()).collect();
        assert_eq!(values.as_slice(), vec![test_data1.clone(), test_data2.clone()].as_slice());

        let iter = db.item_iter(&txn, &test_key2).unwrap();
        let values: Vec<String> = iter.map(|cv| cv.get_value()).collect();
        assert_eq!(values.as_slice(), vec![test_data1.clone()].as_slice());

        let iter = db.item_iter(&txn, &test_key3).unwrap();
        let values: Vec<String> = iter.map(|cv| cv.get_value()).collect();
        assert_eq!(values.len(), 0);
    });
}

#[test]
fn test_db_creation() {
    let path = Path::new("dbs");
    test_db_in_path(&path, || {
        let env = EnvBuilder::new()
            .max_dbs(5)
            .open(&path, USER_DIR)
            .unwrap();
        assert!(env.get_or_create_db("test-db", DbFlags::empty()).is_ok());
    });
}

/*
#[test]
fn test_env_clone() {
let path = Path::new("clone");
test_db_in_path(&path, || {
let mut env = Environment::new().unwrap();
assert!(env.set_maxdbs(5).is_ok());
assert!(env.open(&path, EnvFlags::empty(), 0o755).is_ok());

let env2 = env;

env.set_maxdbs(4);
        });
    }
     */

    /*

    #[test]
    fn test_compilation_of_moved_items() {
        let path = Path::new("dbcom");
        test_db_in_path(&path, || {
            let mut env = Environment::new().unwrap();
            assert!(env.set_maxdbs(5).is_ok());
            assert!(env.open(&path, 0, 0o755).is_ok());

            let db = env.get_default_db(0).unwrap();
            let mut txn = env.new_transaction().unwrap();

            txn.commit();

            let test_key1 = "key1";
            let test_data1 = "value1";

            assert!(txn.get::<()>(&db, &test_key1).is_err(), "Key shouldn't exist yet");
        })
    }
     */
<|endoftext|>


<commit_before>use traits::{AtEof, Compare, CompareResult, InputLength, InputIter, InputTake, Slice, FindSubstring, FindToken, ParseTo};
use util::Offset;

use std::str::{self, FromStr, Chars, CharIndices};
use std::ops::{Range, RangeTo, RangeFrom, RangeFull};
use std::iter::{Enumerate, Map};
use std::slice::Iter;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item = char;
  type RawItem = char;
  type Iter = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize) -> Option<Self> {
    self.0.take(count).map(|s| CompleteStr(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self, Self)> {
    self.0.take_split(count).map(|(s1, s2)| {
      (CompleteStr(s1), CompleteStr(s2))
    })
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteStr<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteStr<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteStr<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second: &CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item = u8;
  type RawItem = u8;
  type Iter = Enumerate<Self::IterElem>;
  type IterElem = Map<Iter<'a, Self::Item>, fn(&u8) -> u8>; //Iter<'a, Self::RawItem>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize) -> Option<Self> {
    self.0.take(count).map(|s| CompleteByteSlice(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self, Self)> {
    self.0.take_split(count).map(|(s1, s2)| {
      (CompleteByteSlice(s1), CompleteByteSlice(s2))
    })
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteByteSlice<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteByteSlice<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteByteSlice<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second: &CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}
<commit_msg>implement Hash on CompleteStr and CompleteByteSlice<commit_after>use traits::{AtEof, Compare, CompareResult, InputLength, InputIter, InputTake, Slice, FindSubstring, FindToken, ParseTo};
use util::Offset;

use std::str::{self, FromStr, Chars, CharIndices};
use std::ops::{Range, RangeTo, RangeFrom, RangeFull};
use std::iter::{Enumerate, Map};
use std::slice::Iter;

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item = char;
  type RawItem = char;
  type Iter = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize) -> Option<Self> {
    self.0.take(count).map(|s| CompleteStr(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self, Self)> {
    self.0.take_split(count).map(|(s1, s2)| {
      (CompleteStr(s1), CompleteStr(s2))
    })
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteStr<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteStr<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteStr<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second: &CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item = u8;
  type RawItem = u8;
  type Iter = Enumerate<Self::IterElem>;
  type IterElem = Map<Iter<'a, Self::Item>, fn(&u8) -> u8>; //Iter<'a, Self::RawItem>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize) -> Option<Self> {
    self.0.take(count).map(|s| CompleteByteSlice(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self, Self)> {
    self.0.take_split(count).map(|(s1, s2)| {
      (CompleteByteSlice(s1), CompleteByteSlice(s2))
    })
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteByteSlice<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteByteSlice<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteByteSlice<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second: &CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}
<|endoftext|>


<commit_before>use traits::{AtEof,Compare,CompareResult,InputLength,InputIter,InputTake,Slice,FindSubstring,FindToken,ParseTo};
use util::Offset;

use std::str::{self,FromStr,Chars,CharIndices};
use std::ops::{Range,RangeTo,RangeFrom,RangeFull};
use std::iter::Enumerate;
use std::slice::Iter;

#[derive(Clone,Copy,Debug,PartialEq)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool { true }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range:Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range:RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range:RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range:RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item     = char;
  type RawItem  = char;
  type Iter     = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self)  -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize> where P: Fn(Self::RawItem) -> bool {
    self.0.position(predicate)
  }
  fn slice_index(&self, count:usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize)  -> Option<Self> {
    self.0.take(count).map(|s| CompleteStr(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self,Self)> {
    self.0.take_split(count).map(|(s1, s2)| (CompleteStr(s1), CompleteStr(s2)))
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a,'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a,'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<CompleteStr<'a>> for u8 {
  fn find_token(&self, input: CompleteStr<'a>) -> bool {
    self.find_token(input.0)
  }
}

impl<'a, R:FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second:&CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

#[derive(Clone,Copy,Debug,PartialEq)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool { true }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range:Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range:RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range:RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range:RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item     = &'a u8;
  type RawItem  = u8;
  type Iter     = Enumerate<Iter<'a, Self::RawItem>>;
  type IterElem = Iter<'a, Self::RawItem>;

  fn iter_indices(&self)  -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize> where P: Fn(Self::RawItem) -> bool {
    self.0.position(predicate)
  }
  fn slice_index(&self, count:usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize)  -> Option<Self> {
    self.0.take(count).map(|s| CompleteByteSlice(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self,Self)> {
    self.0.take_split(count).map(|(s1, s2)| (CompleteByteSlice(s1), CompleteByteSlice(s2)))
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a,'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a,'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a,'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a,'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<CompleteByteSlice<'a>> for u8 {
  fn find_token(&self, input: CompleteByteSlice<'a>) -> bool {
    self.find_token(input.0)
  }
}

impl<'a, R:FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second:&CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}
<commit_msg>impl FindToken<Complete{Str,ByteSlice}> for &u8<commit_after>use traits::{AtEof,Compare,CompareResult,InputLength,InputIter,InputTake,Slice,FindSubstring,FindToken,ParseTo};
use util::Offset;

use std::str::{self,FromStr,Chars,CharIndices};
use std::ops::{Range,RangeTo,RangeFrom,RangeFull};
use std::iter::Enumerate;
use std::slice::Iter;

#[derive(Clone,Copy,Debug,PartialEq)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool { true }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range:Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range:RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range:RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range:RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item     = char;
  type RawItem  = char;
  type Iter     = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self)  -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize> where P: Fn(Self::RawItem) -> bool {
    self.0.position(predicate)
  }
  fn slice_index(&self, count:usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize)  -> Option<Self> {
    self.0.take(count).map(|s| CompleteStr(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self,Self)> {
    self.0.take_split(count).map(|(s1, s2)| (CompleteStr(s1), CompleteStr(s2)))
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a,'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a,'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<CompleteStr<'a>> for u8 {
  fn find_token(&self, input: CompleteStr<'a>) -> bool {
    self.find_token(input.0)
  }
}

impl<'a, 'b> FindToken<CompleteStr<'a>> for &'b u8 {
  fn find_token(&self, input: CompleteStr<'a>) -> bool {
    self.find_token(input.0)
  }
}

impl<'a, R:FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second:&CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

#[derive(Clone,Copy,Debug,PartialEq)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool { true }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range:Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range:RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range:RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range:RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item     = &'a u8;
  type RawItem  = u8;
  type Iter     = Enumerate<Iter<'a, Self::RawItem>>;
  type IterElem = Iter<'a, Self::RawItem>;

  fn iter_indices(&self)  -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize> where P: Fn(Self::RawItem) -> bool {
    self.0.position(predicate)
  }
  fn slice_index(&self, count:usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize)  -> Option<Self> {
    self.0.take(count).map(|s| CompleteByteSlice(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self,Self)> {
    self.0.take_split(count).map(|(s1, s2)| (CompleteByteSlice(s1), CompleteByteSlice(s2)))
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a,'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a,'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a,'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a,'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<CompleteByteSlice<'a>> for u8 {
  fn find_token(&self, input: CompleteByteSlice<'a>) -> bool {
    self.find_token(input.0)
  }
}

impl<'a, 'b> FindToken<CompleteByteSlice<'a>> for &'b u8 {
  fn find_token(&self, input: CompleteByteSlice<'a>) -> bool {
    self.find_token(input.0)
  }
}

impl<'a, R:FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second:&CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_variables)]

// Useful square-sets
const EMPTY_SET: u64 = 0;
const UNIVERSAL_SET: u64 = 0xffffffffffffffff;

// Color
const WHITE: usize = 0;
const BLACK: usize = 1;

// PieceType
const KING: usize = 0;
const QUEEN: usize = 1;
const ROOK: usize = 2;
const BISHOP: usize = 3;
const KNIGHT: usize = 4;
const PAWN: usize = 5;

pub type Color = usize;
pub type Square = u8;
pub type PieceType = usize;
pub type Bitboard = [[u64; 6]; 2];
pub type CastlingRights = [(bool, bool); 2];  // (King-side, Queen-side)

fn square(file: u8, rank: u8) -> Square {
    assert!(file < 8);
    assert!(rank < 8);
    rank * 8 + file
}

pub struct Board {
    bitboard: Bitboard,
    to_move: Color,
    castling_rights: CastlingRights,
    en_passant_square: Option<Square>,
    halfmove_clock: u32,
    fullmove_number: u32,
}

pub struct ParseError;

extern crate std;
pub type Result<T> = std::result::Result<T, ParseError>;

impl Board {
    pub fn from_fen(fen: &str) -> Result<Board> {
        let parts: Vec<_> = fen.split_whitespace().collect();

        if parts.len() == 6 {
            Ok(Board {
                bitboard: try!(Board::parse_fen_piece_placement(parts[0])),
                to_move: try!(Board::parse_fen_active_color(parts[1])),
                castling_rights: try!(Board::parse_fen_castling_rights(parts[2])),
                en_passant_square: try!(Board::parse_fen_enpassant_square(parts[3])),
                halfmove_clock: try!(parts[4].parse::<u32>().map_err(|e| ParseError)),
                fullmove_number: try!(parts[5].parse::<u32>().map_err(|e| ParseError)),
            })
        } else {
            Err(ParseError)
        }
    }

    // Parses a square in algebraic notation.
    fn parse_square_notation(s: &str) -> Result<Square> {
        use regex::Regex;
        let re = Regex::new(r"^[a-h][1-8]$").unwrap();  // TODO: Do this at compile time!

        if re.is_match(s) {
            let mut chars = s.chars();
            let file = chars.next().unwrap().to_digit(18).unwrap() - 10;
            let rank = chars.next().unwrap().to_digit(9).unwrap() - 1;
            Ok(square(file as u8, rank as u8))
        } else {
            Err(ParseError)
        }
    }

    // Parse FEN piece placement field.
    fn parse_fen_piece_placement(s: &str) -> Result<Bitboard> {

        // We start with an empty bitboard. FEN describes the board
        // starting at A8 and going toward H1.
        let mut bitboard = [[0u64; 6]; 2];
        let mut file = 0u8;
        let mut rank = 7u8;

        // These are the possible productions in the grammar.
        enum Token {
            Piece(Color, PieceType),
            EmptySquares(u8),
            Separator,
        }

        for c in s.chars() {

            // Parse the next character.
            let token = match c {
                'K' => Token::Piece(WHITE, KING),
                'Q' => Token::Piece(WHITE, QUEEN),
                'R' => Token::Piece(WHITE, ROOK),
                'B' => Token::Piece(WHITE, BISHOP),
                'N' => Token::Piece(WHITE, KNIGHT),
                'P' => Token::Piece(WHITE, PAWN),
                'k' => Token::Piece(BLACK, KING),
                'q' => Token::Piece(BLACK, QUEEN),
                'r' => Token::Piece(BLACK, ROOK),
                'b' => Token::Piece(BLACK, BISHOP),
                'n' => Token::Piece(BLACK, KNIGHT),
                'p' => Token::Piece(BLACK, PAWN),
                n @ '1'...'8' => Token::EmptySquares(n.to_digit(9).unwrap() as u8),
                '/' => Token::Separator,
                _ => return Err(ParseError),
            };

            // Update the bitboard accordting to the token.
            match token {
                Token::Piece(color, piece_type) => {
                    if file > 7 {
                        return Err(ParseError);
                    }
                    bitboard[color][piece_type] |= 1 << square(file, rank);
                    file += 1;
                }
                Token::EmptySquares(n) => {
                    file += n;
                    if file > 8 {
                        return Err(ParseError);
                    }
                }
                Token::Separator => {
                    if file == 8 && rank > 0 {
                        file = 0;
                        rank -= 1;
                    } else {
                        return Err(ParseError);
                    }
                }
            }
        }

        // Ensure the piece placement field had the right length.
        if file == 8 && rank == 0 {
            Ok(bitboard)
        } else {
            Err(ParseError)
        }
    }

    // Parse FEN active color field.
    fn parse_fen_active_color(s: &str) -> Result<Color> {
        match s {
            "w" => Ok(WHITE),
            "b" => Ok(BLACK),
            _ => Err(ParseError),
        }
    }

    // Parses FEN castling rights field.
    fn parse_fen_castling_rights(s: &str) -> Result<CastlingRights> {

        // We start with no caltling allowed.
        let mut castling_rights = [(false, false); 2];

        // Then we parse the content and update the castling rights.
        if s != "-" {
            for c in s.chars() {
                match c {
                    'K' => {
                        if !castling_rights[WHITE].0 {
                            castling_rights[WHITE].0 = true;
                        } else {
                            return Err(ParseError);
                        }
                    }
                    'Q' => {
                        if !castling_rights[WHITE].1 {
                            castling_rights[WHITE].1 = true;
                        } else {
                            return Err(ParseError);
                        }
                    }
                    'k' => {
                        if !castling_rights[BLACK].0 {
                            castling_rights[BLACK].0 = true;
                        } else {
                            return Err(ParseError);
                        }
                    }
                    'q' => {
                        if !castling_rights[BLACK].1 {
                            castling_rights[BLACK].1 = true;
                        } else {
                            return Err(ParseError);
                        }
                    }
                    _ => {
                        return Err(ParseError);
                    }
                };
            }
        }

        // Successfully parsed.
        Ok(castling_rights)
    }

    // Parse FEN en-passant square field.
    fn parse_fen_enpassant_square(s: &str) -> Result<Option<Square>> {
        match s {
            "-" => Ok(None),
            _ => Ok(Some(try!(Board::parse_square_notation(s).map_err(|e| ParseError)))),
        }
    }

}

pub type AttackArray = [[u64; 64]; 5];  // for example
                                   // attack_set[Pieces::Queen][0]
                                   // gives the attack set for a queen
                                   // at A1.

#[allow(dead_code)]
pub fn generate_attack_and_blockers_arrays() -> (AttackArray, AttackArray) {

    fn square2grid_index(i: usize) -> usize {
        ((i / 8) * 10 + (i % 8) + 21)
    }

    // Generate a 10x12 grid -- 0xff is the "out of board" marker.
    let mut grid = [0xffu8; 120];
    for i in 0..64 {
        grid[square2grid_index(i)] = i as Square;
    }

    // 0: King, 1: Queen, 2: Rook, 3: Bishop, 4: Knight.
    static PIECE_LONGRANGE: [bool; 5] = [false, true, true, true, false];
    static PIECE_DELTAS: [[i8; 8]; 5] = [[-11, -10, -9, -1, 1, 9, 10, 11],
                                         [-11, -10, -9, -1, 1, 9, 10, 11],
                                         [0, -10, 0, -1, 1, 0, 10, 0],
                                         [-11, 0, -9, 0, 0, 9, 0, 11],
                                         [-21, -19, -12, -8, 8, 12, 19, 21]];

    // At the end those arrays will hold the attack bitsets, and the
    // "blockers and beyond" bitsets for each piece on each possible
    // square.
    let mut attack_array = [[0u64; 64]; 5];
    let mut blockers_array = [[0u64; 64]; 5];

    for piece_type in 0..5 {
        for square in 0..64 {
            let mut attack = 0u64;
            let mut blockers = 0u64;
            for move_direction in 0..8 {
                let delta = PIECE_DELTAS[piece_type][move_direction];
                if delta != 0 {
                    let mut last_mask = 0u64;
                    let mut curr_grid_index = square2grid_index(square);
                    loop {
                        curr_grid_index = (curr_grid_index as i8 + delta) as usize;
                        let curr_square = grid[curr_grid_index];
                        if curr_square != 0xff {
                            last_mask = 1 << curr_square;
                            attack |= last_mask;
                            blockers |= last_mask;
                            if PIECE_LONGRANGE[piece_type] {
                                continue;
                            }
                        }
                        blockers &= !last_mask;
                        break;
                    }
                }
            }
            attack_array[piece_type][square] = attack;
            blockers_array[piece_type][square] = blockers;
        }
    }

    (attack_array, blockers_array)
}

// Forsyth–Edwards Notation
<commit_msg>Refactoring.<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]

pub type Color = usize;
pub type File = usize;
pub type Rank = usize;
pub type Square = usize;
pub type PieceType = usize;
pub type Bitboard = [[u64; 6]; 2];
pub type CastlingRights = [(bool, bool); 2];  // (King-side, Queen-side)

// Useful square-sets
const EMPTY_SET: u64 = 0;
const UNIVERSAL_SET: u64 = 0xffffffffffffffff;

// Color
const WHITE: Color = 0;
const BLACK: Color = 1;

// Piece types
const KING: PieceType = 0;
const QUEEN: PieceType = 1;
const ROOK: PieceType = 2;
const BISHOP: PieceType = 3;
const KNIGHT: PieceType = 4;
const PAWN: PieceType = 5;

fn square(file: File, rank: Rank) -> Square {
    assert!(file < 8);
    assert!(rank < 8);
    rank * 8 + file
}

pub struct Board {
    bitboard: Bitboard,
    to_move: Color,
    castling_rights: CastlingRights,
    en_passant_square: Option<Square>,
    halfmove_clock: u32,
    fullmove_number: u32,
}

pub struct ParseError;

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

impl Board {
    pub fn from_fen(fen: &str) -> Result<Board> {
        let parts: Vec<_> = fen.split_whitespace().collect();

        if parts.len() == 6 {
            Ok(Board {
                bitboard: try!(Board::parse_fen_piece_placement(parts[0])),
                to_move: try!(Board::parse_fen_active_color(parts[1])),
                castling_rights: try!(Board::parse_fen_castling_rights(parts[2])),
                en_passant_square: try!(Board::parse_fen_enpassant_square(parts[3])),
                halfmove_clock: try!(parts[4].parse::<u32>().map_err(|e| ParseError)),
                fullmove_number: try!(parts[5].parse::<u32>().map_err(|e| ParseError)),
            })
        } else {
            Err(ParseError)
        }
    }

    // Parses a square in algebraic notation.
    fn parse_square_notation(s: &str) -> Result<Square> {
        use regex::Regex;
        let re = Regex::new(r"^[a-h][1-8]$").unwrap();  // TODO: Do this at compile time!

        if re.is_match(s) {
            let mut chars = s.chars();
            let file = (chars.next().unwrap().to_digit(18).unwrap() - 10) as File;
            let rank = (chars.next().unwrap().to_digit(9).unwrap() - 1) as Rank;
            Ok(square(file, rank))
        } else {
            Err(ParseError)
        }
    }

    // Parse FEN piece placement field.
    fn parse_fen_piece_placement(s: &str) -> Result<Bitboard> {

        // We start with an empty bitboard. FEN describes the board
        // starting at A8 and going toward H1.
        let mut bitboard = [[0u64; 6]; 2];
        let mut file = 0;
        let mut rank = 7;

        // These are the possible productions in the grammar.
        enum Token {
            Piece(Color, PieceType),
            EmptySquares(u32),
            Separator,
        }

        for c in s.chars() {

            // Parse the next character.
            let token = match c {
                'K' => Token::Piece(WHITE, KING),
                'Q' => Token::Piece(WHITE, QUEEN),
                'R' => Token::Piece(WHITE, ROOK),
                'B' => Token::Piece(WHITE, BISHOP),
                'N' => Token::Piece(WHITE, KNIGHT),
                'P' => Token::Piece(WHITE, PAWN),
                'k' => Token::Piece(BLACK, KING),
                'q' => Token::Piece(BLACK, QUEEN),
                'r' => Token::Piece(BLACK, ROOK),
                'b' => Token::Piece(BLACK, BISHOP),
                'n' => Token::Piece(BLACK, KNIGHT),
                'p' => Token::Piece(BLACK, PAWN),
                n @ '1'...'8' => Token::EmptySquares(n.to_digit(9).unwrap()),
                '/' => Token::Separator,
                _ => return Err(ParseError),
            };

            // Update the bitboard accordting to the token.
            match token {
                Token::Piece(color, piece_type) => {
                    if file > 7 {
                        return Err(ParseError);
                    }
                    bitboard[color][piece_type] |= 1 << square(file, rank);
                    file += 1;
                }
                Token::EmptySquares(n) => {
                    file += n as File;
                    if file > 8 {
                        return Err(ParseError);
                    }
                }
                Token::Separator => {
                    if file == 8 && rank > 0 {
                        file = 0;
                        rank -= 1;
                    } else {
                        return Err(ParseError);
                    }
                }
            }
        }

        // Ensure the piece placement field had the right length.
        if file == 8 && rank == 0 {
            Ok(bitboard)
        } else {
            Err(ParseError)
        }
    }

    // Parse FEN active color field.
    fn parse_fen_active_color(s: &str) -> Result<Color> {
        match s {
            "w" => Ok(WHITE),
            "b" => Ok(BLACK),
            _ => Err(ParseError),
        }
    }

    // Parses FEN castling rights field.
    fn parse_fen_castling_rights(s: &str) -> Result<CastlingRights> {

        // We start with no caltling allowed.
        let mut castling_rights = [(false, false); 2];

        // Then we parse the content and update the castling rights.
        if s != "-" {
            for c in s.chars() {
                match c {
                    'K' => {
                        if !castling_rights[WHITE].0 {
                            castling_rights[WHITE].0 = true;
                        } else {
                            return Err(ParseError);
                        }
                    }
                    'Q' => {
                        if !castling_rights[WHITE].1 {
                            castling_rights[WHITE].1 = true;
                        } else {
                            return Err(ParseError);
                        }
                    }
                    'k' => {
                        if !castling_rights[BLACK].0 {
                            castling_rights[BLACK].0 = true;
                        } else {
                            return Err(ParseError);
                        }
                    }
                    'q' => {
                        if !castling_rights[BLACK].1 {
                            castling_rights[BLACK].1 = true;
                        } else {
                            return Err(ParseError);
                        }
                    }
                    _ => {
                        return Err(ParseError);
                    }
                };
            }
        }

        // Successfully parsed.
        Ok(castling_rights)
    }

    // Parse FEN en-passant square field.
    fn parse_fen_enpassant_square(s: &str) -> Result<Option<Square>> {
        match s {
            "-" => Ok(None),
            _ => Ok(Some(try!(Board::parse_square_notation(s).map_err(|e| ParseError)))),
        }
    }

}

pub type AttackArray = [[u64; 64]; 5];  // for example
                                   // attack_set[Pieces::Queen][0]
                                   // gives the attack set for a queen
                                   // at A1.

pub fn generate_attack_and_blockers_arrays() -> (AttackArray, AttackArray) {

    fn square2grid_index(i: Square) -> usize {
        ((i / 8) * 10 + (i % 8) + 21)
    }

    // Generate a 10x12 grid -- 0xff is the "out of board" marker.
    let mut grid = [0xffu8; 120];
    for i in 0..64 {
        grid[square2grid_index(i)] = i as u8;
    }

    // 0: King, 1: Queen, 2: Rook, 3: Bishop, 4: Knight.
    static PIECE_LONGRANGE: [bool; 5] = [false, true, true, true, false];
    static PIECE_DELTAS: [[i8; 8]; 5] = [[-11, -10, -9, -1, 1, 9, 10, 11],
                                         [-11, -10, -9, -1, 1, 9, 10, 11],
                                         [0, -10, 0, -1, 1, 0, 10, 0],
                                         [-11, 0, -9, 0, 0, 9, 0, 11],
                                         [-21, -19, -12, -8, 8, 12, 19, 21]];

    // At the end those arrays will hold the attack bitsets, and the
    // "blockers and beyond" bitsets for each piece on each possible
    // square.
    let mut attack_array = [[0u64; 64]; 5];
    let mut blockers_array = [[0u64; 64]; 5];

    for piece_type in 0..5 {
        for square in 0..64 {
            let mut attack = 0u64;
            let mut blockers = 0u64;
            for move_direction in 0..8 {
                let delta = PIECE_DELTAS[piece_type][move_direction];
                if delta != 0 {
                    let mut last_mask = 0u64;
                    let mut curr_grid_index = square2grid_index(square);
                    loop {
                        curr_grid_index = (curr_grid_index as i8 + delta) as usize;
                        let curr_square = grid[curr_grid_index];
                        if curr_square != 0xff {
                            last_mask = 1 << curr_square;
                            attack |= last_mask;
                            blockers |= last_mask;
                            if PIECE_LONGRANGE[piece_type] {
                                continue;
                            }
                        }
                        blockers &= !last_mask;
                        break;
                    }
                }
            }
            attack_array[piece_type][square] = attack;
            blockers_array[piece_type][square] = blockers;
        }
    }

    (attack_array, blockers_array)
}

// Forsyth–Edwards Notation
<|endoftext|>


<commit_before>use std::convert::From;
use std::borrow::Cow;

// Variant for a configuration Value
#[derive(Clone)]
pub enum Value {
    String(String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
}

impl Value {
    /// Gets the underyling value as a string, performing a conversion only if neccessary.
    #[allow(needless_lifetimes)]
    pub fn as_str<'a>(&'a self) -> Option<Cow<'a, str>> {
        if let Value::String(ref value) = *self {
            Some(Cow::Borrowed(value))
        } else if let Value::Integer(value) = *self {
            Some(Cow::Owned(value.to_string()))
        } else if let Value::Float(value) = *self {
            Some(Cow::Owned(value.to_string()))
        } else if let Value::Boolean(value) = *self {
            Some(Cow::Owned(value.to_string()))
        } else {
            None
        }
    }

    /// Gets the underlying type as a boolean, performing a conversion only if neccessary.
    pub fn as_bool(&self) -> Option<bool> {
        if let Value::Boolean(value) = *self {
            Some(value)
        } else if let Value::String(ref value) = *self {
            Some(match value.to_lowercase().as_ref() {
                "1" | "true" | "on" | "yes" => true,
                _ => false,
            })
        } else if let Value::Integer(value) = *self {
            Some(value != 0)
        } else if let Value::Float(value) = *self {
            Some(value != 0.0)
        } else {
            None
        }
    }

    /// Gets the underlying type as an integer, performing a conversion only if neccessary.
    pub fn as_int(&self) -> Option<i64> {
        if let Value::Integer(value) = *self {
            Some(value)
        } else if let Value::String(ref value) = *self {
            value.parse().ok()
        } else if let Value::Boolean(value) = *self {
            Some(if value { 1 } else { 0 })
        } else if let Value::Float(value) = *self {
            Some(value.round() as i64)
        } else {
            None
        }
    }

    /// Gets the underlying type as a floating-point, performing a conversion only if neccessary.
    pub fn as_float(&self) -> Option<f64> {
        if let Value::Float(value) = *self {
            Some(value)
        } else if let Value::String(ref value) = *self {
            value.parse().ok()
        } else if let Value::Integer(value) = *self {
            Some(value as f64)
        } else if let Value::Boolean(value) = *self {
            Some(if value { 1.0 } else { 0.0 })
        } else {
            None
        }
    }
}

// Generalized construction from type into variant is needed
// for setting configuration values

impl From<String> for Value {
    fn from(value: String) -> Value {
        Value::String(value)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(value: &'a str) -> Value {
        Value::String(value.into())
    }
}

impl From<i64> for Value {
    fn from(value: i64) -> Value {
        Value::Integer(value)
    }
}

impl From<f64> for Value {
    fn from(value: f64) -> Value {
        Value::Float(value)
    }
}

impl From<bool> for Value {
    fn from(value: bool) -> Value {
        Value::Boolean(value)
    }
}
<commit_msg>:memo:<commit_after>use std::convert::From;
use std::borrow::Cow;

/// A configuration value.
///
/// Has an underlying or native type that comes from the configuration source
/// but will be coerced into the requested type.
#[derive(Clone)]
pub enum Value {
    String(String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
}

impl Value {
    /// Gets the underyling value as a string, performing a conversion only if neccessary.
    #[allow(needless_lifetimes)]
    pub fn as_str<'a>(&'a self) -> Option<Cow<'a, str>> {
        if let Value::String(ref value) = *self {
            Some(Cow::Borrowed(value))
        } else if let Value::Integer(value) = *self {
            Some(Cow::Owned(value.to_string()))
        } else if let Value::Float(value) = *self {
            Some(Cow::Owned(value.to_string()))
        } else if let Value::Boolean(value) = *self {
            Some(Cow::Owned(value.to_string()))
        } else {
            None
        }
    }

    /// Gets the underlying type as a boolean, performing a conversion only if neccessary.
    pub fn as_bool(&self) -> Option<bool> {
        if let Value::Boolean(value) = *self {
            Some(value)
        } else if let Value::String(ref value) = *self {
            Some(match value.to_lowercase().as_ref() {
                "1" | "true" | "on" | "yes" => true,
                _ => false,
            })
        } else if let Value::Integer(value) = *self {
            Some(value != 0)
        } else if let Value::Float(value) = *self {
            Some(value != 0.0)
        } else {
            None
        }
    }

    /// Gets the underlying type as an integer, performing a conversion only if neccessary.
    pub fn as_int(&self) -> Option<i64> {
        if let Value::Integer(value) = *self {
            Some(value)
        } else if let Value::String(ref value) = *self {
            value.parse().ok()
        } else if let Value::Boolean(value) = *self {
            Some(if value { 1 } else { 0 })
        } else if let Value::Float(value) = *self {
            Some(value.round() as i64)
        } else {
            None
        }
    }

    /// Gets the underlying type as a floating-point, performing a conversion only if neccessary.
    pub fn as_float(&self) -> Option<f64> {
        if let Value::Float(value) = *self {
            Some(value)
        } else if let Value::String(ref value) = *self {
            value.parse().ok()
        } else if let Value::Integer(value) = *self {
            Some(value as f64)
        } else if let Value::Boolean(value) = *self {
            Some(if value { 1.0 } else { 0.0 })
        } else {
            None
        }
    }
}

// Generalized construction from type into variant is needed
// for setting configuration values

impl From<String> for Value {
    fn from(value: String) -> Value {
        Value::String(value)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(value: &'a str) -> Value {
        Value::String(value.into())
    }
}

impl From<i64> for Value {
    fn from(value: i64) -> Value {
        Value::Integer(value)
    }
}

impl From<f64> for Value {
    fn from(value: f64) -> Value {
        Value::Float(value)
    }
}

impl From<bool> for Value {
    fn from(value: bool) -> Value {
        Value::Boolean(value)
    }
}
<|endoftext|>