<commit_before>//! This crate contains parser combinators, roughly based on the Haskell library [parsec](http://hackage.haskell.org/package/parsec).
//!
//! A parser in this library can be described as a function which takes some input and if it
//! is succesful, returns a value together with the remaining input.
//! A parser combinator is a function which takes one or more parsers and returns a new parser.
//! For instance the `many` parser can be used to convert a parser for single digits into one that
//! parses multiple digits.
//!
//!# Overview
//!
//! This library is currently split into three modules.
//!
//! * `primitives` contains the `Parser` trait as well as various structs dealing with input
//! streams and errors.
//!
//! * `combinator` contains the before mentioned parser combinators and thus contains the main
//! building blocks for creating any sort of more complex parsers. It consists of free functions as
//! well as a the `ParserExt` trait which provides a few functions which are more naturally used
//! through method calls.
//!
//! * `char` is the last module. It provides parsers specifically working with streams of
//! characters. As a few examples it has parsers for accepting digits, letters or whitespace.
//!
//!
//!# Examples
//!
//!```
//! extern crate parser_combinators;
//! use parser_combinators::{spaces, many1, sep_by, digit, char, Parser, ParserExt, ParseError};
//!
//! fn main() {
//!     let input = "1234, 45,78";
//!     let spaces = spaces();
//!     let integer = spaces.clone()//Parse spaces first and use the with method to only keep the result of the next parser
//!         .with(many1(digit()).map(|string: String| string.parse::<i32>().unwrap()));//parse a string of digits into an i32
//!     //Parse integers separated by commas, skipping whitespace
//!     let mut integer_list = sep_by(integer, spaces.skip(char(',')));
//!
//!     //Call parse with the input to execute the parser
//!     let result: Result<(Vec<i32>, &str), ParseError> = integer_list.parse(input);
//!     match result {
//!         Ok((value, _remaining_input)) => println!("{:?}", value),
//!         Err(err) => println!("{}", err)
//!     }
//! }
//!```
//!
//! If we need a parser that is mutually recursive we can define a free function which internally
//! can in turn be used as a parser (Note that we need to explicitly cast the function, this should
//! not be necessary once changes in rustc to make orphan checking less restrictive gets implemented)
//!
//! `expr` is written fully general here which may not be necessary in a specific implementation
//! The `Stream` trait is predefined to work with array slices, string slices and iterators
//! meaning that in this case it could be defined as
//! `fn expr(input: State<&str>) -> ParseResult<Expr, &str>`
//!
//!```
//! extern crate parser_combinators;
//! use parser_combinators::{between, char, letter, spaces, many1, parser, sep_by, Parser, ParserExt,
//! ParseResult};
//! use parser_combinators::primitives::{State, Stream};
//!
//! #[derive(Debug, PartialEq)]
//! enum Expr {
//!     Id(String),
//!     Array(Vec<Expr>),
//!     Pair(Box<Expr>, Box<Expr>)
//! }
//!
//! fn expr<I>(input: State<I>) -> ParseResult<Expr, I>
//!     where I: Stream<Item=char> {
//!     let word = many1(letter());
//!     //Creates a parser which parses a char and skips any trailing whitespace
//!     let lex_char = |c| char(c).skip(spaces());
//!     let comma_list = sep_by(parser(expr::<I>), lex_char(','));
//!     let array = between(lex_char('['), lex_char(']'), comma_list);
//!     //We can use tuples to run several parsers in sequence
//!     //The resulting type is a tuple containing each parsers output
//!     let pair = (lex_char('('), parser(expr::<I>), lex_char(','), parser(expr::<I>), lex_char(')'))
//!         .map(|t| Expr::Pair(Box::new(t.1), Box::new(t.3)));
//!     word.map(Expr::Id)
//!         .or(array.map(Expr::Array))
//!         .or(pair)
//!         .skip(spaces())
//!         .parse_state(input)
//! }
//!
//! fn main() {
//!     let result = parser(expr)
//!         .parse("[[], (hello, world), [rust]]");
//!     let expr = Expr::Array(vec![
//!           Expr::Array(Vec::new())
//!         , Expr::Pair(Box::new(Expr::Id("hello".to_string())),
//!                      Box::new(Expr::Id("world".to_string())))
//!         , Expr::Array(vec![Expr::Id("rust".to_string())])
//!     ]);
//!     assert_eq!(result, Ok((expr, "")));
//! }
//!```

#[doc(inline)]
pub use primitives::{Parser, ParseResult, ParseError, from_iter};
#[doc(inline)]
pub use char::{
    any_char,
    char,
    digit,
    space,
    spaces,
    newline,
    crlf,
    tab,
    upper,
    lower,
    letter,
    alpha_num,
    hex_digit,
    oct_digit,
    string,
    satisfy,
};
#[doc(inline)]
pub use combinator::{
    between,
    chainl1,
    choice,
    many,
    many1,
    optional,
    parser,
    sep_by,
    skip_many,
    skip_many1,
    try,
    value,
    unexpected,
    not_followed_by,

    ParserExt
};

macro_rules! static_fn {
    (($($arg: pat, $arg_ty: ty),*) -> $ret: ty { $body: expr }) => { {
        fn temp($($arg: $arg_ty),*) -> $ret { $body }
        let temp: fn (_) -> _ = temp;
        temp
    } }
}

///Module containing the primitive types which is used to create and compose more advanced parsers
pub mod primitives;
///Module containing all specific parsers
pub mod combinator;
///Module containg parsers specialized on character streams
pub mod char;

#[cfg(test)]
mod tests {
    use super::*;
    use super::primitives::{SourcePosition, State, Stream, Error, Consumed};

    fn integer<'a, I>(input: State<I>) -> ParseResult<i64, I>
        where I: Stream<Item=char> {
        let (s, input) = try!(many1::<String, _>(digit())
            .expected("integer")
            .parse_state(input));
        let mut n = 0;
        for c in s.chars() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        Ok((n, input))
    }

    #[test]
    fn test_integer() {
        let result = parser(integer).parse("123");
        assert_eq!(result, Ok((123i64, "")));
    }
    #[test]
    fn list() {
        let mut p = sep_by(parser(integer), char(','));
        let result = p.parse("123,4,56");
        assert_eq!(result, Ok((vec![123i64, 4, 56], "")));
    }
    #[test]
    fn iterator() {
        let result = parser(integer).parse(from_iter("123".chars()))
            .map(|(i, input)| (i, input.uncons().err()));
        assert_eq!(result, Ok((123i64, Some(()))));
    }
    #[test]
    fn field() {
        let word = || many(alpha_num());
        let spaces = spaces();
        let c_decl = (word(), spaces.clone(), char(':'), spaces, word())
            .map(|t| (t.0, t.4))
            .parse("x: int");
        assert_eq!(c_decl, Ok((("x".to_string(), "int".to_string()), "")));
    }
    #[test]
    fn source_position() {
        let source =
r"
123
";
        let result = (spaces(), parser(integer), spaces())
            .map(|t| t.1)
            .parse_state(State::new(source));
        let state = Consumed::Consumed(State {
            position: SourcePosition { line: 3, column: 1 },
            input: ""
        });
        assert_eq!(result, Ok((123i64, state)));
    }

    #[derive(Debug, PartialEq)]
    enum Expr {
        Id(String),
        Int(i64),
        Array(Vec<Expr>),
        Plus(Box<Expr>, Box<Expr>),
        Times(Box<Expr>, Box<Expr>),
    }

    #[allow(unconditional_recursion)]
    fn expr(input: State<&str>) -> ParseResult<Expr, &str> {
        let word = many1(letter())
            .expected("identifier");
        let integer = parser(integer);
        let array = between(char('['), char(']'), sep_by(parser(expr), char(',')))
            .expected("[");
        let paren_expr = between(char('('), char(')'), parser(term))
            .expected("(");
        let spaces = spaces();
        spaces.clone().with(
                word.map(Expr::Id)
                .or(integer.map(Expr::Int))
                .or(array.map(Expr::Array))
                .or(paren_expr)
            ).skip(spaces)
            .parse_state(input)
    }

    #[test]
    fn expression() {
        let result = sep_by(parser(expr), char(','))
            .parse("int, 100, [[], 123]");
        let exprs = vec![
              Expr::Id("int".to_string())
            , Expr::Int(100)
            , Expr::Array(vec![Expr::Array(vec![]), Expr::Int(123)])
        ];
        assert_eq!(result, Ok((exprs, "")));
    }

    #[test]
    fn expression_error() {
        let input =
r"
,123
";
        let result = parser(expr)
            .parse(input);
        let err = ParseError {
            position: SourcePosition { line: 2, column: 1 },
                errors: vec![
                    Error::Unexpected(','),
                    Error::Expected("identifier".into()),
                    Error::Expected("integer".into()),
                    Error::Expected("[".into()),
                    Error::Expected("(".into()),
                ]
        };
        assert_eq!(result, Err(err));
    }

    #[test]
    fn expression_error_message() {
        let input =
r"
,123
";
        let result = parser(expr)
            .parse(input);
        let m = format!("{}", result.unwrap_err());
let expected =
r"Parse error at line: 2, column: 1
Unexpected character ','
Expected 'identifier', 'integer', '[' or '('
";
        assert_eq!(m, expected);
    }

    fn term(input: State<&str>) -> ParseResult<Expr, &str> {

        let mul = char('*')
            .map(|_| |l, r| Expr::Times(Box::new(l), Box::new(r)));
        let add = char('+')
            .map(|_| |l, r| Expr::Plus(Box::new(l), Box::new(r)));
        let factor = chainl1(parser(expr), mul);
        chainl1(factor, add)
            .parse_state(input)
    }

    #[test]
    fn operators() {
        let input =
r"
1 * 2 + 3 * test
";
        let (result, _) = parser(term)
            .parse(input)
            .unwrap();

        let e1 = Expr::Times(Box::new(Expr::Int(1)), Box::new(Expr::Int(2)));
        let e2 = Expr::Times(Box::new(Expr::Int(3)), Box::new(Expr::Id("test".to_string())));
        assert_eq!(result, Expr::Plus(Box::new(e1), Box::new(e2)));
    }

    fn follow(input: State<&str>) -> ParseResult<(), &str> {
        match input.clone().uncons_char() {
            Ok((c, _)) => {
                if c.is_alphanumeric() {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                }
                else {
                    Ok(((), Consumed::Empty(input)))
                }
            }
            Err(_) => Ok(((), Consumed::Empty(input)))
        }
    }
    #[test]
    fn error_position() {
        let mut p = string("let").skip(parser(follow)).map(|x| x.to_string())
            .or(many1(digit()));
        match p.parse("le123") {
            Ok(_) => assert!(false),
            Err(err) => assert_eq!(err.position, SourcePosition { line: 1, column: 1 })
        }
    }

    #[test]
    fn sep_by_error_consume() {
        let mut p = sep_by::<Vec<_>, _, _>(string("abc"), char(','));
        let err = p.parse("ab,abc")
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(err.position, SourcePosition { line: 1, column: 1});
    }

    #[test]
    fn optional_error_consume() {
        let mut p = optional(string("abc"));
        let err = p.parse("ab")
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(err.position, SourcePosition { line: 1, column: 1});
    }
    #[test]
    fn chainl1_error_consume() {
        let mut p = chainl1(string("abc"), char(',').map(|_| |l, _| l));
        assert!(p.parse("abc,ab").is_err());
    }

    #[test]
    fn inner_error_consume() {
        let mut p = many::<Vec<_>, _>(between(char('['), char(']'), digit()));
        let result = p.parse("[1][2][]");
        assert!(result.is_err(), format!("{:?}", result));
        let error = result
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(error.position, SourcePosition { line: 1, column: 8 });
    }

    #[test]
    fn infinite_recursion_in_box_parser() {
        let _: Result<(Vec<_>, _), _> = (many(Box::new(digit())))
            .parse("1");
    }

    #[test]
    fn unsized_parser() {
        let mut parser: Box<Parser<Input=&str, Output=char>> = Box::new(digit());
        let borrow_parser = &mut *parser;
        assert_eq!(borrow_parser.parse("1"), Ok(('1', "")));
    }

    #[test]
    fn choice_strings() {
        let mut fruits = [
            try(string("Apple")),
            try(string("Banana")),
            try(string("Cherry")),
            try(string("Date")),
            try(string("Fig")),
            try(string("Grape")),
        ];
        let mut parser = choice(&mut fruits);
        assert_eq!(parser.parse("Apple"), Ok(("Apple", "")));
        assert_eq!(parser.parse("Banana"), Ok(("Banana", "")));
        assert_eq!(parser.parse("Cherry"), Ok(("Cherry", "")));
        assert_eq!(parser.parse("DateABC"), Ok(("Date", "ABC")));
        assert_eq!(parser.parse("Fig123"), Ok(("Fig", "123")));
        assert_eq!(parser.parse("GrapeApple"), Ok(("Grape", "Apple")));
    }
}
<commit_msg>Revert accidental removal of the fix for returning closures<commit_after>//! This crate contains parser combinators, roughly based on the Haskell library [parsec](http://hackage.haskell.org/package/parsec).
//!
//! A parser in this library can be described as a function which takes some input and if it
//! is succesful, returns a value together with the remaining input.
//! A parser combinator is a function which takes one or more parsers and returns a new parser.
//! For instance the `many` parser can be used to convert a parser for single digits into one that
//! parses multiple digits.
//!
//!# Overview
//!
//! This library is currently split into three modules.
//!
//! * `primitives` contains the `Parser` trait as well as various structs dealing with input
//! streams and errors.
//!
//! * `combinator` contains the before mentioned parser combinators and thus contains the main
//! building blocks for creating any sort of more complex parsers. It consists of free functions as
//! well as a the `ParserExt` trait which provides a few functions which are more naturally used
//! through method calls.
//!
//! * `char` is the last module. It provides parsers specifically working with streams of
//! characters. As a few examples it has parsers for accepting digits, letters or whitespace.
//!
//!
//!# Examples
//!
//!```
//! extern crate parser_combinators;
//! use parser_combinators::{spaces, many1, sep_by, digit, char, Parser, ParserExt, ParseError};
//!
//! fn main() {
//!     let input = "1234, 45,78";
//!     let spaces = spaces();
//!     let integer = spaces.clone()//Parse spaces first and use the with method to only keep the result of the next parser
//!         .with(many1(digit()).map(|string: String| string.parse::<i32>().unwrap()));//parse a string of digits into an i32
//!     //Parse integers separated by commas, skipping whitespace
//!     let mut integer_list = sep_by(integer, spaces.skip(char(',')));
//!
//!     //Call parse with the input to execute the parser
//!     let result: Result<(Vec<i32>, &str), ParseError> = integer_list.parse(input);
//!     match result {
//!         Ok((value, _remaining_input)) => println!("{:?}", value),
//!         Err(err) => println!("{}", err)
//!     }
//! }
//!```
//!
//! If we need a parser that is mutually recursive we can define a free function which internally
//! can in turn be used as a parser (Note that we need to explicitly cast the function, this should
//! not be necessary once changes in rustc to make orphan checking less restrictive gets implemented)
//!
//! `expr` is written fully general here which may not be necessary in a specific implementation
//! The `Stream` trait is predefined to work with array slices, string slices and iterators
//! meaning that in this case it could be defined as
//! `fn expr(input: State<&str>) -> ParseResult<Expr, &str>`
//!
//!```
//! extern crate parser_combinators;
//! use parser_combinators::{between, char, letter, spaces, many1, parser, sep_by, Parser, ParserExt,
//! ParseResult};
//! use parser_combinators::primitives::{State, Stream};
//!
//! #[derive(Debug, PartialEq)]
//! enum Expr {
//!     Id(String),
//!     Array(Vec<Expr>),
//!     Pair(Box<Expr>, Box<Expr>)
//! }
//!
//! fn expr<I>(input: State<I>) -> ParseResult<Expr, I>
//!     where I: Stream<Item=char> {
//!     let word = many1(letter());
//!     //Creates a parser which parses a char and skips any trailing whitespace
//!     let lex_char = |c| char(c).skip(spaces());
//!     let comma_list = sep_by(parser(expr::<I>), lex_char(','));
//!     let array = between(lex_char('['), lex_char(']'), comma_list);
//!     //We can use tuples to run several parsers in sequence
//!     //The resulting type is a tuple containing each parsers output
//!     let pair = (lex_char('('), parser(expr::<I>), lex_char(','), parser(expr::<I>), lex_char(')'))
//!         .map(|t| Expr::Pair(Box::new(t.1), Box::new(t.3)));
//!     word.map(Expr::Id)
//!         .or(array.map(Expr::Array))
//!         .or(pair)
//!         .skip(spaces())
//!         .parse_state(input)
//! }
//!
//! fn main() {
//!     let result = parser(expr)
//!         .parse("[[], (hello, world), [rust]]");
//!     let expr = Expr::Array(vec![
//!           Expr::Array(Vec::new())
//!         , Expr::Pair(Box::new(Expr::Id("hello".to_string())),
//!                      Box::new(Expr::Id("world".to_string())))
//!         , Expr::Array(vec![Expr::Id("rust".to_string())])
//!     ]);
//!     assert_eq!(result, Ok((expr, "")));
//! }
//!```

#[doc(inline)]
pub use primitives::{Parser, ParseResult, ParseError, from_iter};
#[doc(inline)]
pub use char::{
    any_char,
    char,
    digit,
    space,
    spaces,
    newline,
    crlf,
    tab,
    upper,
    lower,
    letter,
    alpha_num,
    hex_digit,
    oct_digit,
    string,
    satisfy,
};
#[doc(inline)]
pub use combinator::{
    between,
    chainl1,
    choice,
    many,
    many1,
    optional,
    parser,
    sep_by,
    skip_many,
    skip_many1,
    try,
    value,
    unexpected,
    not_followed_by,

    ParserExt
};

macro_rules! static_fn {
    (($($arg: pat, $arg_ty: ty),*) -> $ret: ty { $body: expr }) => { {
        fn temp($($arg: $arg_ty),*) -> $ret { $body }
        let temp: fn (_) -> _ = temp;
        temp
    } }
}

///Module containing the primitive types which is used to create and compose more advanced parsers
pub mod primitives;
///Module containing all specific parsers
pub mod combinator;
///Module containg parsers specialized on character streams
pub mod char;

#[cfg(test)]
mod tests {
    use super::*;
    use super::primitives::{SourcePosition, State, Stream, Error, Consumed};

    fn integer<'a, I>(input: State<I>) -> ParseResult<i64, I>
        where I: Stream<Item=char> {
        let (s, input) = try!(many1::<String, _>(digit())
            .expected("integer")
            .parse_state(input));
        let mut n = 0;
        for c in s.chars() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        Ok((n, input))
    }

    #[test]
    fn test_integer() {
        let result = parser(integer).parse("123");
        assert_eq!(result, Ok((123i64, "")));
    }
    #[test]
    fn list() {
        let mut p = sep_by(parser(integer), char(','));
        let result = p.parse("123,4,56");
        assert_eq!(result, Ok((vec![123i64, 4, 56], "")));
    }
    #[test]
    fn iterator() {
        let result = parser(integer).parse(from_iter("123".chars()))
            .map(|(i, input)| (i, input.uncons().err()));
        assert_eq!(result, Ok((123i64, Some(()))));
    }
    #[test]
    fn field() {
        let word = || many(alpha_num());
        let spaces = spaces();
        let c_decl = (word(), spaces.clone(), char(':'), spaces, word())
            .map(|t| (t.0, t.4))
            .parse("x: int");
        assert_eq!(c_decl, Ok((("x".to_string(), "int".to_string()), "")));
    }
    #[test]
    fn source_position() {
        let source =
r"
123
";
        let result = (spaces(), parser(integer), spaces())
            .map(|t| t.1)
            .parse_state(State::new(source));
        let state = Consumed::Consumed(State {
            position: SourcePosition { line: 3, column: 1 },
            input: ""
        });
        assert_eq!(result, Ok((123i64, state)));
    }

    #[derive(Debug, PartialEq)]
    enum Expr {
        Id(String),
        Int(i64),
        Array(Vec<Expr>),
        Plus(Box<Expr>, Box<Expr>),
        Times(Box<Expr>, Box<Expr>),
    }

    #[allow(unconditional_recursion)]
    fn expr(input: State<&str>) -> ParseResult<Expr, &str> {
        let word = many1(letter())
            .expected("identifier");
        let integer = parser(integer);
        let array = between(char('['), char(']'), sep_by(parser(expr), char(',')))
            .expected("[");
        let paren_expr = between(char('('), char(')'), parser(term))
            .expected("(");
        let spaces = spaces();
        spaces.clone().with(
                word.map(Expr::Id)
                .or(integer.map(Expr::Int))
                .or(array.map(Expr::Array))
                .or(paren_expr)
            ).skip(spaces)
            .parse_state(input)
    }

    #[test]
    fn expression() {
        let result = sep_by(parser(expr), char(','))
            .parse("int, 100, [[], 123]");
        let exprs = vec![
              Expr::Id("int".to_string())
            , Expr::Int(100)
            , Expr::Array(vec![Expr::Array(vec![]), Expr::Int(123)])
        ];
        assert_eq!(result, Ok((exprs, "")));
    }

    #[test]
    fn expression_error() {
        let input =
r"
,123
";
        let result = parser(expr)
            .parse(input);
        let err = ParseError {
            position: SourcePosition { line: 2, column: 1 },
                errors: vec![
                    Error::Unexpected(','),
                    Error::Expected("identifier".into()),
                    Error::Expected("integer".into()),
                    Error::Expected("[".into()),
                    Error::Expected("(".into()),
                ]
        };
        assert_eq!(result, Err(err));
    }

    #[test]
    fn expression_error_message() {
        let input =
r"
,123
";
        let result = parser(expr)
            .parse(input);
        let m = format!("{}", result.unwrap_err());
let expected =
r"Parse error at line: 2, column: 1
Unexpected character ','
Expected 'identifier', 'integer', '[' or '('
";
        assert_eq!(m, expected);
    }

    fn term(input: State<&str>) -> ParseResult<Expr, &str> {
        fn times(l: Expr, r: Expr) -> Expr { Expr::Times(Box::new(l), Box::new(r)) }
        fn plus(l: Expr, r: Expr) -> Expr { Expr::Plus(Box::new(l), Box::new(r)) }
        let mul = char('*')
            .map(|_| times);
        let add = char('+')
            .map(|_| plus);
        let factor = chainl1(parser(expr), mul);
        chainl1(factor, add)
            .parse_state(input)
    }

    #[test]
    fn operators() {
        let input =
r"
1 * 2 + 3 * test
";
        let (result, _) = parser(term)
            .parse(input)
            .unwrap();

        let e1 = Expr::Times(Box::new(Expr::Int(1)), Box::new(Expr::Int(2)));
        let e2 = Expr::Times(Box::new(Expr::Int(3)), Box::new(Expr::Id("test".to_string())));
        assert_eq!(result, Expr::Plus(Box::new(e1), Box::new(e2)));
    }

    fn follow(input: State<&str>) -> ParseResult<(), &str> {
        match input.clone().uncons_char() {
            Ok((c, _)) => {
                if c.is_alphanumeric() {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                }
                else {
                    Ok(((), Consumed::Empty(input)))
                }
            }
            Err(_) => Ok(((), Consumed::Empty(input)))
        }
    }
    #[test]
    fn error_position() {
        let mut p = string("let").skip(parser(follow)).map(|x| x.to_string())
            .or(many1(digit()));
        match p.parse("le123") {
            Ok(_) => assert!(false),
            Err(err) => assert_eq!(err.position, SourcePosition { line: 1, column: 1 })
        }
    }

    #[test]
    fn sep_by_error_consume() {
        let mut p = sep_by::<Vec<_>, _, _>(string("abc"), char(','));
        let err = p.parse("ab,abc")
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(err.position, SourcePosition { line: 1, column: 1});
    }

    #[test]
    fn optional_error_consume() {
        let mut p = optional(string("abc"));
        let err = p.parse("ab")
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(err.position, SourcePosition { line: 1, column: 1});
    }
    #[test]
    fn chainl1_error_consume() {
        fn first<T, U>(t: T, _: U) -> T { t }
        let mut p = chainl1(string("abc"), char(',').map(|_| first));
        assert!(p.parse("abc,ab").is_err());
    }

    #[test]
    fn inner_error_consume() {
        let mut p = many::<Vec<_>, _>(between(char('['), char(']'), digit()));
        let result = p.parse("[1][2][]");
        assert!(result.is_err(), format!("{:?}", result));
        let error = result
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(error.position, SourcePosition { line: 1, column: 8 });
    }

    #[test]
    fn infinite_recursion_in_box_parser() {
        let _: Result<(Vec<_>, _), _> = (many(Box::new(digit())))
            .parse("1");
    }

    #[test]
    fn unsized_parser() {
        let mut parser: Box<Parser<Input=&str, Output=char>> = Box::new(digit());
        let borrow_parser = &mut *parser;
        assert_eq!(borrow_parser.parse("1"), Ok(('1', "")));
    }

    #[test]
    fn choice_strings() {
        let mut fruits = [
            try(string("Apple")),
            try(string("Banana")),
            try(string("Cherry")),
            try(string("Date")),
            try(string("Fig")),
            try(string("Grape")),
        ];
        let mut parser = choice(&mut fruits);
        assert_eq!(parser.parse("Apple"), Ok(("Apple", "")));
        assert_eq!(parser.parse("Banana"), Ok(("Banana", "")));
        assert_eq!(parser.parse("Cherry"), Ok(("Cherry", "")));
        assert_eq!(parser.parse("DateABC"), Ok(("Date", "ABC")));
        assert_eq!(parser.parse("Fig123"), Ok(("Fig", "123")));
        assert_eq!(parser.parse("GrapeApple"), Ok(("Grape", "Apple")));
    }
}
<|endoftext|>


<commit_before>//! A memory-safer wrapper around system dynamic library primitives.
//!
//! With this library you can load [dynamic libraries](struct.Library.html) and retrieve
//! [symbols](struct.Symbol.html) from the loaded libraries.
//!
//! Less safe platform specific bindings are available in the [`os::platform`](os/index.html)
//! modules.
use std::ffi::OsStr;
use std::marker;

#[macro_use]
extern crate lazy_static;

#[cfg(any(target_os="linux",
          target_os="macos",
          target_os="freebsd",
          target_os="dragonfly",
          target_os="bitrig",
          target_os="netbsd",
          target_os="openbsd"))]
use self::os::unix as imp;
#[cfg(target_os="windows")]
use self::os::windows as imp;

pub mod os;
mod util;

pub type Result<T> = ::std::io::Result<T>;

/// A dynamically loaded library.
pub struct Library(imp::Library);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// // on Unix
    /// let lib = Library::new("libm.so.6").unwrap();
    /// // on OS X
    /// let lib = Library::new("libm.dylib").unwrap();
    /// // on Windows
    /// let lib = Library::new("msvcrt.dll").unwrap();
    /// ```
    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library> {
        imp::Library::new(filename).map(Library)
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    ///
    /// # Examples
    ///
    /// Simple function:
    ///
    /// ```ignore
    /// let sin: Symbol<extern fn(f64) -> f64> = unsafe {
    ///     lib.get(b"sin\0").unwrap()
    /// };
    /// ```
    ///
    /// A static or TLS variable:
    ///
    /// ```ignore
    /// let errno: Symbol<*mut u32> = unsafe {
    ///     lib.get(b"errno\0").unwrap()
    /// };
    /// ```
    pub unsafe fn get<'lib, T>(&'lib self, symbol: &[u8]) -> Result<Symbol<'lib, T>> {
        self.0.get(symbol).map(|from| {
            Symbol {
                inner: from,
                pd: marker::PhantomData
            }
        })
    }
}

/// Symbol from a library.
///
/// This type is a safeguard against using dynamically loaded symbols after a `Library` is
/// unloaded. Primary method to create an instance of a `Symbol` is via `Library::get`.
///
/// Due to implementation of the `Deref` trait, an instance of `Symbol` may be used as if it was a
/// function or variable directly, without taking care to “extract” function or variable manually
/// most of the time.
///
/// # Examples
///
/// ```ignore
/// let sin: Symbol<extern fn(f64) -> f64> = unsafe {
///     lib.get(b"sin\0").unwrap()
/// };
/// let sine0 = sin(0);
/// assert!(sine0 < 0.1E-10);
/// ```
pub struct Symbol<'lib, T: 'lib> {
    inner: imp::Symbol<T>,
    pd: marker::PhantomData<&'lib T>
}

impl<'lib, T> ::std::ops::Deref for Symbol<'lib, T> {
    type Target = T;
    fn deref(&self) -> &T {
        ::std::ops::Deref::deref(&self.inner)
    }
}

#[cfg(not(any(target_os="windows", target_os="macos")))]
#[test]
fn libm() {
    let lib = Library::new("libm.so.6").unwrap();
    let sin: Symbol<extern fn(f64) -> f64> = unsafe {
        lib.get(b"sin").unwrap()
    };
    assert!(sin(::std::f64::INFINITY).is_nan());
    let errno: Symbol<*mut u32> = unsafe {
        lib.get(b"errno").unwrap()
    };
    assert!(unsafe { **errno } != 0);
    unsafe { **errno = 0; }
}
<commit_msg>Only extern crate lazy_static conditionally<commit_after>//! A memory-safer wrapper around system dynamic library primitives.
//!
//! With this library you can load [dynamic libraries](struct.Library.html) and retrieve
//! [symbols](struct.Symbol.html) from the loaded libraries.
//!
//! Less safe platform specific bindings are available in the [`os::platform`](os/index.html)
//! modules.
use std::ffi::OsStr;
use std::marker;

#[cfg(any(target_os="linux",
          target_os="macos",
          target_os="freebsd",
          target_os="dragonfly",
          target_os="bitrig",
          target_os="netbsd",
          target_os="openbsd"))]
#[macro_use]
extern crate lazy_static;

#[cfg(any(target_os="linux",
          target_os="macos",
          target_os="freebsd",
          target_os="dragonfly",
          target_os="bitrig",
          target_os="netbsd",
          target_os="openbsd"))]
use self::os::unix as imp;
#[cfg(target_os="windows")]
use self::os::windows as imp;

pub mod os;
mod util;

pub type Result<T> = ::std::io::Result<T>;

/// A dynamically loaded library.
pub struct Library(imp::Library);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// // on Unix
    /// let lib = Library::new("libm.so.6").unwrap();
    /// // on OS X
    /// let lib = Library::new("libm.dylib").unwrap();
    /// // on Windows
    /// let lib = Library::new("msvcrt.dll").unwrap();
    /// ```
    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library> {
        imp::Library::new(filename).map(Library)
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    ///
    /// # Examples
    ///
    /// Simple function:
    ///
    /// ```ignore
    /// let sin: Symbol<extern fn(f64) -> f64> = unsafe {
    ///     lib.get(b"sin\0").unwrap()
    /// };
    /// ```
    ///
    /// A static or TLS variable:
    ///
    /// ```ignore
    /// let errno: Symbol<*mut u32> = unsafe {
    ///     lib.get(b"errno\0").unwrap()
    /// };
    /// ```
    pub unsafe fn get<'lib, T>(&'lib self, symbol: &[u8]) -> Result<Symbol<'lib, T>> {
        self.0.get(symbol).map(|from| {
            Symbol {
                inner: from,
                pd: marker::PhantomData
            }
        })
    }
}

/// Symbol from a library.
///
/// This type is a safeguard against using dynamically loaded symbols after a `Library` is
/// unloaded. Primary method to create an instance of a `Symbol` is via `Library::get`.
///
/// Due to implementation of the `Deref` trait, an instance of `Symbol` may be used as if it was a
/// function or variable directly, without taking care to “extract” function or variable manually
/// most of the time.
///
/// # Examples
///
/// ```ignore
/// let sin: Symbol<extern fn(f64) -> f64> = unsafe {
///     lib.get(b"sin\0").unwrap()
/// };
/// let sine0 = sin(0);
/// assert!(sine0 < 0.1E-10);
/// ```
pub struct Symbol<'lib, T: 'lib> {
    inner: imp::Symbol<T>,
    pd: marker::PhantomData<&'lib T>
}

impl<'lib, T> ::std::ops::Deref for Symbol<'lib, T> {
    type Target = T;
    fn deref(&self) -> &T {
        ::std::ops::Deref::deref(&self.inner)
    }
}

#[cfg(not(any(target_os="windows", target_os="macos")))]
#[test]
fn libm() {
    let lib = Library::new("libm.so.6").unwrap();
    let sin: Symbol<extern fn(f64) -> f64> = unsafe {
        lib.get(b"sin").unwrap()
    };
    assert!(sin(::std::f64::INFINITY).is_nan());
    let errno: Symbol<*mut u32> = unsafe {
        lib.get(b"errno").unwrap()
    };
    assert!(unsafe { **errno } != 0);
    unsafe { **errno = 0; }
}
<|endoftext|>


<commit_before>#![feature(unboxed_closures, phase)]
#![unstable]

//! # Handlebars
//! Handlebars is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for server-side page generation. It's a general-purpose library so you use it for any kind of text generation.
//!
//! ## Handlebars spec
//!
//! ### Base
//!
//! You can go to [Handlebars.js](http://handlebarsjs.com/) website for its syntax. This implementation should be compatible with most parts of the spec, except:
//!
//! * raw helper syntax `{{{raw-helper}}}...{{{/raw-helper}}}` is implemented as block helper raw.
//! * configurable logging (hard-coded to rust native logging, with fixed level `INFO`)
//!
//! ### Extensions
//!
//! We have template reuse facilities supported via built-in helpers `>`, `partial` and `block`.
//!
//! There are two ways to reuse a template:
//!
//! * include (using `>`)
//! * inheritance (using `>` together with `block` and `partial`)
//!
//! Consult [Handlebar.java document about template inheritance](http://jknack.github.io/handlebars.java/reuse.html).
//!
//! ## Usage
//!
//! ### Template Creation and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template created");
//! }
//! ```
//!
//! ### Rendering Something
//!
//! I should say that rendering is a little tricky. Since handlebars is originally a JavaScript templating framework. It supports dynamic features like duck-typing, truthy/falsy values. But for a static language like Rust, this is a little difficult. As a solution, I'm using the `serialize::json::Json` internally for data rendering, which seems good by far.
//!
//! That means, if you want to render something, you have to ensure that it implements the `serialize::json::ToJson` trait. Luckily, most built-in types already have trait. However, if you want to render your custom struct, you need to implement this trait manually. (Rust has a deriving facility, but it's just for selected types. Maybe I will add some syntax extensions or macros to simplify this process.)
//!
//! ```
//! extern crate "rustc-serialize" as serialize;
//! extern crate handlebars;
//!
//! use serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! impl ToJson for Person {
//!   fn to_json(&self) -> Json {
//!     let mut m = BTreeMap::new();
//!     m.insert("name".to_string(), self.name.to_json());
//!     m.insert("age".to_string(), self.age.to_json());
//!     Json::Object(m)
//!   }
//! }
//!
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template creation failed");
//!
//!   let mut data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   let result = handlebars.render("helloworld", &data);
//! }
//! ```
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context};
//!
//! // implement by a structure impls HelperDef
//! #[deriving(Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My helper dumps: {} ", value))
//!   }
//! }
//!
//! // create an instance
//! static MY_HELPER: SimpleHelper = SimpleHelper;
//!
//! // implement via bare function
//! fn another_simple_helper (c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My second helper dumps: {} ", value))
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", box MY_HELPER);
//!   handlebars.register_helper("another-simple-helper", box another_simple_helper);
//!
//!   //...
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of String as params in helper, like `{{#somehelper param1 param2 param3}}`.
//! * `hash()` is a map of String key and Json value, defined in helper as `{{@somehelper a=1 b="2" c=true}}`.
//! * `template()` gives you the nested template of block helper.
//! * `inverse()` gives you the inversed template of it, inversed template is the template behind `{{else}}`.
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{#partial ...}} ... {{/partial}}` template reuse, used to replace block with same name
//! * `{{#block ...}} ... {{/block}}` template reuse, used to be replaced by partial with same name, with default content if partial not found.
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!

extern crate "rustc-serialize" as serialize;
extern crate regex;
#[phase(plugin)]
extern crate regex_macros;

#[phase(plugin, link)]
extern crate log;

pub use self::template::{Template, Helper};
pub use self::registry::Registry as Handlebars;
pub use self::render::{Renderable, RenderError, RenderContext};
pub use self::helpers::{HelperDef};
pub use self::context::{Context, JsonRender, JsonTruthy};

mod template;
mod registry;
mod render;
mod helpers;
mod context;
<commit_msg>rustup<commit_after>#![feature(unboxed_closures, phase, plugin)]
#![unstable]

//! # Handlebars
//! Handlebars is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for server-side page generation. It's a general-purpose library so you use it for any kind of text generation.
//!
//! ## Handlebars spec
//!
//! ### Base
//!
//! You can go to [Handlebars.js](http://handlebarsjs.com/) website for its syntax. This implementation should be compatible with most parts of the spec, except:
//!
//! * raw helper syntax `{{{raw-helper}}}...{{{/raw-helper}}}` is implemented as block helper raw.
//! * configurable logging (hard-coded to rust native logging, with fixed level `INFO`)
//!
//! ### Extensions
//!
//! We have template reuse facilities supported via built-in helpers `>`, `partial` and `block`.
//!
//! There are two ways to reuse a template:
//!
//! * include (using `>`)
//! * inheritance (using `>` together with `block` and `partial`)
//!
//! Consult [Handlebar.java document about template inheritance](http://jknack.github.io/handlebars.java/reuse.html).
//!
//! ## Usage
//!
//! ### Template Creation and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template created");
//! }
//! ```
//!
//! ### Rendering Something
//!
//! I should say that rendering is a little tricky. Since handlebars is originally a JavaScript templating framework. It supports dynamic features like duck-typing, truthy/falsy values. But for a static language like Rust, this is a little difficult. As a solution, I'm using the `serialize::json::Json` internally for data rendering, which seems good by far.
//!
//! That means, if you want to render something, you have to ensure that it implements the `serialize::json::ToJson` trait. Luckily, most built-in types already have trait. However, if you want to render your custom struct, you need to implement this trait manually. (Rust has a deriving facility, but it's just for selected types. Maybe I will add some syntax extensions or macros to simplify this process.)
//!
//! ```
//! extern crate "rustc-serialize" as serialize;
//! extern crate handlebars;
//!
//! use serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! impl ToJson for Person {
//!   fn to_json(&self) -> Json {
//!     let mut m = BTreeMap::new();
//!     m.insert("name".to_string(), self.name.to_json());
//!     m.insert("age".to_string(), self.age.to_json());
//!     Json::Object(m)
//!   }
//! }
//!
//!
//! fn main() {
//!   let source = "hello {{world}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().expect("template creation failed");
//!
//!   let mut data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   let result = handlebars.render("helloworld", &data);
//! }
//! ```
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//! extern crate handlebars;
//!
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context};
//!
//! // implement by a structure impls HelperDef
//! #[deriving(Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My helper dumps: {} ", value))
//!   }
//! }
//!
//! // create an instance
//! static MY_HELPER: SimpleHelper = SimpleHelper;
//!
//! // implement via bare function
//! fn another_simple_helper (c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<String, RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     Ok(format!("My second helper dumps: {} ", value))
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", box MY_HELPER);
//!   handlebars.register_helper("another-simple-helper", box another_simple_helper);
//!
//!   //...
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of String as params in helper, like `{{#somehelper param1 param2 param3}}`.
//! * `hash()` is a map of String key and Json value, defined in helper as `{{@somehelper a=1 b="2" c=true}}`.
//! * `template()` gives you the nested template of block helper.
//! * `inverse()` gives you the inversed template of it, inversed template is the template behind `{{else}}`.
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{#partial ...}} ... {{/partial}}` template reuse, used to replace block with same name
//! * `{{#block ...}} ... {{/block}}` template reuse, used to be replaced by partial with same name, with default content if partial not found.
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!

extern crate "rustc-serialize" as serialize;
extern crate regex;
#[plugin]
extern crate regex_macros;

#[plugin]
#[macro_use]
extern crate log;

pub use self::template::{Template, Helper};
pub use self::registry::Registry as Handlebars;
pub use self::render::{Renderable, RenderError, RenderContext};
pub use self::helpers::{HelperDef};
pub use self::context::{Context, JsonRender, JsonTruthy};

mod template;
mod registry;
mod render;
mod helpers;
mod context;
<|endoftext|>


<commit_before>#![deny(/*missing_docs,*/unsafe_code,
    unstable_features,
    unused_import_braces, unused_qualifications)]

#[macro_use]
extern crate log;

#[macro_use]
mod rparser;
pub mod probe;
pub use rparser::*;

mod variant;
pub use variant::*;

pub mod prologue;

pub mod dhcp;
pub mod dns_tcp;
pub mod dns_udp;
pub mod http;
pub mod ipsec;
pub mod ipsec_natt;
pub mod kerberos_tcp;
pub mod kerberos_udp;
pub mod ntp;
pub mod openvpn;
pub mod openvpn_udp;
pub mod radius;
pub mod snmp;
pub mod snmpv3;
pub mod ssh;
pub mod tls;
<commit_msg>Forbid unsafe code<commit_after>#![deny(/*missing_docs,*/
    unstable_features,
    unused_import_braces, unused_qualifications)]
#![forbid(unsafe_code)]

#[macro_use]
extern crate log;

#[macro_use]
mod rparser;
pub mod probe;
pub use rparser::*;

mod variant;
pub use variant::*;

pub mod prologue;

pub mod dhcp;
pub mod dns_tcp;
pub mod dns_udp;
pub mod http;
pub mod ipsec;
pub mod ipsec_natt;
pub mod kerberos_tcp;
pub mod kerberos_udp;
pub mod ntp;
pub mod openvpn;
pub mod openvpn_udp;
pub mod radius;
pub mod snmp;
pub mod snmpv3;
pub mod ssh;
pub mod tls;
<|endoftext|>


<commit_before>// Copyright 2015 Dawid Ciężarkiewicz
// See LICENSE-MPL
//
//! Non-thread-shareable, simple and efficient Circular Buffer
//! implementation that can store N elements when full (typical circular
//! buffer implementations store N-1) without using separate flags.
//!
//! Uses only `core` so can be used in `#[no_std]` projects by using
//! `no_std` feature.
//!
#![cfg_attr(feature = "no_std", feature(no_std))]

#![cfg_attr(test, feature(test))]

#![feature(core)]

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

#[cfg(test)]
extern crate test as test;

#[macro_use]
extern crate core;

use core::option::Option::{self, Some, None};
use core::marker::PhantomData;
#[cfg(feature = "no_std")]
use core::marker::Copy;
#[cfg(feature = "no_std")]
use core::slice::SliceExt;
const CBUF_DATA_BIT : usize = 1 << 63;

pub trait CopyOrClone {
    fn clone(&self) -> Self;
}

#[cfg(feature = "no_std")]
impl<T : Copy> CopyOrClone for T {
    fn clone(&self) -> T {
        *self
    }
}

#[cfg(not(feature = "no_std"))]
impl<T : Clone> CopyOrClone for T {
    fn clone(&self) -> T {
        self.clone()
    }
}

/// Circular Buffer
///
/// Turns `Vec` into a Circular buffer with head and tail indexes.
#[cfg(not(feature = "no_std"))]
#[derive(Debug)]
pub struct CBuf<T> {
    buf : Vec<T>,
    ctrl: CBufControl<T>,
}

/// Circular Buffer Control
///
/// Implements the actual logic of Circular Buffer, but requires passing &[T]
/// to `get` and `put`.
///
/// Useful for operating on a raw slice, without allocating new `Vec`.
#[derive(Debug)]
pub struct CBufControl<T> {
    head : usize,
    tail : usize,
    phantom : PhantomData<T>
}

#[cfg(not(feature = "no_std"))]
impl<T : CopyOrClone> CBuf<T>
where T : Clone {

    /// Create new CBuf
    ///
    /// Length (not capacity) will be used to store elements
    /// in the circular buffer.
    pub fn new(buf : Vec<T>) -> CBuf<T> {
        debug_assert!(buf.len() < CBUF_DATA_BIT);

        CBuf {
            buf: buf,
            ctrl: CBufControl::new(),
        }
    }

    /// Is buffer full?
    #[inline]
    pub fn is_full(&self) -> bool {
        let CBuf {
            ref ctrl,
            ..
        } = *self;

        ctrl.is_full()
    }

    /// Is buffer empty?
    #[inline]
    pub fn is_empty(&self) -> bool {
        let CBuf {
            ref ctrl,
            ..
        } = *self;

        ctrl.is_empty()
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn peek(&mut self) -> Option<T> {
        let CBuf {
            ref mut ctrl,
            ref buf,
        } = *self;

        ctrl.get(buf)
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn peek_unchecked(&mut self) -> T {
        let CBuf {
            ref mut ctrl,
            ref buf,
        } = *self;

        ctrl.peek_unchecked(buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn get(&mut self) -> Option<T> {
        let CBuf {
            ref mut ctrl,
            ref buf,
        } = *self;

        ctrl.get(buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn get_unchecked(&mut self) -> T {
        let CBuf {
            ref mut ctrl,
            ref buf,
        } = *self;

        ctrl.get_unchecked(buf)
    }

    /// Add element the buffer
    ///
    /// Ignores the write if buffer is full.
    #[inline]
    pub fn put(&mut self, val : T) {
        let CBuf {
            ref mut ctrl,
            ref mut buf,
        } = *self;

        ctrl.put(buf, val)
    }

    /// Add element the buffer
    ///
    /// Makes the buffer misbehave if it's full.
    #[inline]
    pub fn put_unchecked(&mut self, val : T) {
        let CBuf {
            ref mut ctrl,
            ref mut buf,
        } = *self;

        ctrl.put_unchecked(buf, val)
    }
}

impl<T : CopyOrClone> CBufControl<T> {

    pub fn new() -> CBufControl<T> {
        CBufControl {
            tail: 0,
            head: 0,
            phantom: PhantomData,
        }
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_full(&self) -> bool {
        (self.head ^ self.tail) == CBUF_DATA_BIT
    }

    /// See corresponding method of CBuf
    pub fn get(&mut self, buf : &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.get_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn get_unchecked(&mut self, buf : &[T]) -> T {
        let val = buf[self.tail & !CBUF_DATA_BIT].clone();

        self.tail += 1;

        if (self.tail & !CBUF_DATA_BIT) >= buf.len() {
            self.tail = (self.tail - buf.len()) ^ CBUF_DATA_BIT;
        }

        val
    }

    /// See corresponding method of CBuf
    pub fn peek(&mut self, buf : &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.peek_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn peek_unchecked(&mut self, buf : &[T]) -> T {
        buf[self.tail & !CBUF_DATA_BIT].clone()
    }

    /// See corresponding method of CBuf
    pub fn put(&mut self, buf : &mut [T], val : T) {
        if self.is_full() {
            return;
        }
        self.put_unchecked(buf, val)
    }

    /// See corresponding method of CBuf
    pub fn put_unchecked(&mut self, buf : &mut [T], val : T) {
        buf[self.head & !CBUF_DATA_BIT] = val;

        self.head += 1;

        if (self.head & !CBUF_DATA_BIT) >= buf.len() {
            self.head = (self.head - buf.len()) ^ CBUF_DATA_BIT;
        }
    }
}

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

    #[test]
    fn basic_ctl() {
        let mut buf = [0u8, 2];
        let mut cbuf = CBufControl::<u8>::new();

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(&mut buf, 0);
        cbuf.put(&mut buf, 0);
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        cbuf.get(&buf);
        cbuf.get(&buf);
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());
    }

    #[test]
    fn basic_cbuf() {
        let mut buf = Vec::new();
        buf.push(0u8);
        buf.push(0u8);
        let mut cbuf = CBuf::new(buf);

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(0);
        cbuf.put(0);
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        cbuf.get();
        cbuf.get();
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());
    }

    #[test]
    fn patterns() {
        let mut buf = [0u8, 7];
        let mut cbuf = CBufControl::<u8>::new();

        let mut cur_len = 0;
        let mut put_val = 0;
        let mut get_val = 0;

        for pattern in 0..256 {
            if cur_len == 0 {
                assert!(cbuf.is_empty());
            }
            if cur_len == buf.len() {
                assert!(cbuf.is_full());
            }

            for bit_i in 0..8 {
                match pattern & (1 << bit_i) == 0 {
                    true => if cbuf.is_empty() {
                        assert!(cbuf.peek(&buf).is_none());
                        assert!(cbuf.get(&buf).is_none());
                    } else {
                        assert!(cbuf.peek(&buf).unwrap() == get_val);
                        let val = cbuf.get(&buf).unwrap();
                        assert!(val == get_val);
                        get_val = get_val.wrapping_add(1);
                        cur_len -= 1;
                    },
                    false => if cbuf.is_full() {
                        cbuf.put(&mut buf, put_val);
                        assert!(cbuf.is_full());
                    } else {
                        cbuf.put(&mut buf, put_val);
                        put_val = put_val.wrapping_add(1);
                        cur_len += 1;
                    },
                }
            }
        }
    }

    #[bench]
    pub fn put_and_get(b : &mut Bencher) {
        let mut buf = Vec::new();
        for _ in 0..256 {
            buf.push(0u8);
        }
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put(0u8);
            cbuf.get();
        });

        test::black_box(cbuf.get());
    }
    #[bench]
    pub fn put_unchecked_and_get(b : &mut Bencher) {
        let mut buf = Vec::new();
        for _ in 0..256 {
            buf.push(0u8);
        }
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put_unchecked(0u8);
            cbuf.get_unchecked();
        });

        test::black_box(cbuf.get());
    }

}
<commit_msg>use slice instead<commit_after>// Copyright 2015 Dawid Ciężarkiewicz
// See LICENSE-MPL
//
//! Non-thread-shareable, simple and efficient Circular Buffer
//! implementation that can store N elements when full (typical circular
//! buffer implementations store N-1) without using separate flags.
//!
//! Uses only `core` so can be used in `#[no_std]` projects by using
//! `no_std` feature.
//!
#![no_std]
#![feature(const_fn)]
#![feature(test)]

use core::option::Option::{self, Some, None};
use core::marker::PhantomData;

extern crate test as test;

const CBUF_DATA_BIT: usize = !((usize::max_value() << 1) >> 1);

pub trait CopyOrClone {
    fn clone(&self) -> Self;
}

#[cfg(feature = "no_std")]
impl<T : Copy> CopyOrClone for T {
    fn clone(&self) -> T {
        *self
    }
}

#[cfg(not(feature = "no_std"))]
impl<T : Clone> CopyOrClone for T {
    fn clone(&self) -> T {
        self.clone()
    }
}

/// Circular Buffer
///
/// Turns a slice into a Circular buffer with head and tail indexes.
#[derive(Debug)]
pub struct CBuf<'a, T: 'a> {
    buf: &'a mut [T],
    ctrl: CBufControl<T>,
}

/// Circular Buffer Control
///
/// Implements the actual logic of Circular Buffer, but requires passing &[T]
/// to `get` and `put`.
#[derive(Debug)]
pub struct CBufControl<T> {
    head : usize,
    tail : usize,
    phantom : PhantomData<T>
}

#[cfg(not(feature = "no_std"))]
impl<'a, T: CopyOrClone> CBuf<'a, T>
        where T: Clone {

    /// Create new CBuf
    ///
    /// Length (not capacity) will be used to store elements
    /// in the circular buffer.
    pub fn new(buf: &'a mut [T]) -> CBuf<T> {
        debug_assert!(buf.len() < CBUF_DATA_BIT);

        CBuf {
            buf: buf,
            ctrl: CBufControl::new(),
        }
    }

    /// Is buffer full?
    #[inline]
    pub fn is_full(&self) -> bool {
        let CBuf {
            ref ctrl,
            ..
        } = *self;

        ctrl.is_full()
    }

    /// Is buffer empty?
    #[inline]
    pub fn is_empty(&self) -> bool {
        let CBuf {
            ref ctrl,
            ..
        } = *self;

        ctrl.is_empty()
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn peek(&mut self) -> Option<T> {
        let CBuf {
            ref mut ctrl,
            ref buf,
        } = *self;

        ctrl.get(buf)
    }

    /// Peek next element from the CBuf without removing it
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn peek_unchecked(&mut self) -> T {
        let CBuf {
            ref mut ctrl,
            ref buf,
        } = *self;

        ctrl.peek_unchecked(buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Returns `None` if buffer is empty.
    #[inline]
    pub fn get(&mut self) -> Option<T> {
        let CBuf {
            ref mut ctrl,
            ref buf,
        } = *self;

        ctrl.get(buf)
    }

    /// Remove one element from the CBuf
    ///
    /// Makes the buffer misbehave if it's empty.
    #[inline]
    pub fn get_unchecked(&mut self) -> T {
        let CBuf {
            ref mut ctrl,
            ref buf,
        } = *self;

        ctrl.get_unchecked(buf)
    }

    /// Add element the buffer
    ///
    /// Ignores the write if buffer is full.
    #[inline]
    pub fn put(&mut self, val : T) {
        let CBuf {
            ref mut ctrl,
            ref mut buf,
        } = *self;

        ctrl.put(buf, val)
    }

    /// Add element the buffer
    ///
    /// Makes the buffer misbehave if it's full.
    #[inline]
    pub fn put_unchecked(&mut self, val : T) {
        let CBuf {
            ref mut ctrl,
            ref mut buf,
        } = *self;

        ctrl.put_unchecked(buf, val)
    }
}

impl<T : CopyOrClone> CBufControl<T> {

    pub fn new() -> CBufControl<T> {
        CBufControl {
            tail: 0,
            head: 0,
            phantom: PhantomData,
        }
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.head == self.tail
    }

    /// See corresponding method of CBuf
    #[inline]
    pub fn is_full(&self) -> bool {
        (self.head ^ self.tail) == CBUF_DATA_BIT
    }

    /// See corresponding method of CBuf
    pub fn get(&mut self, buf : &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.get_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn get_unchecked(&mut self, buf : &[T]) -> T {
        let val = buf[self.tail & !CBUF_DATA_BIT].clone();

        self.tail += 1;

        if (self.tail & !CBUF_DATA_BIT) >= buf.len() {
            self.tail = (self.tail - buf.len()) ^ CBUF_DATA_BIT;
        }

        val
    }

    /// See corresponding method of CBuf
    pub fn peek(&mut self, buf : &[T]) -> Option<T> {
        if self.is_empty() {
            return None;
        }
        Some(self.peek_unchecked(buf))
    }

    /// See corresponding method of CBuf
    pub fn peek_unchecked(&mut self, buf : &[T]) -> T {
        buf[self.tail & !CBUF_DATA_BIT].clone()
    }

    /// See corresponding method of CBuf
    pub fn put(&mut self, buf : &mut [T], val : T) {
        if self.is_full() {
            return;
        }
        self.put_unchecked(buf, val)
    }

    /// See corresponding method of CBuf
    pub fn put_unchecked(&mut self, buf : &mut [T], val : T) {
        buf[self.head & !CBUF_DATA_BIT] = val;

        self.head += 1;

        if (self.head & !CBUF_DATA_BIT) >= buf.len() {
            self.head = (self.head - buf.len()) ^ CBUF_DATA_BIT;
        }
    }
}

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

    #[test]
    fn basic_ctl() {
        let mut buf = [0u8, 2];
        let mut cbuf = CBufControl::<u8>::new();

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(&mut buf, 0);
        cbuf.put(&mut buf, 0);
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        cbuf.get(&buf);
        cbuf.get(&buf);
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());
    }

    #[test]
    fn basic_cbuf() {
        let mut buf = &mut [0u8, 0u8];
        let mut cbuf = CBuf::new(buf);

        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());

        cbuf.put(0);
        cbuf.put(0);
        assert!(!cbuf.is_empty());
        assert!(cbuf.is_full());

        cbuf.get();
        cbuf.get();
        assert!(cbuf.is_empty());
        assert!(!cbuf.is_full());
    }

    #[test]
    fn patterns() {
        let mut buf = [0u8, 7];
        let mut cbuf = CBufControl::<u8>::new();

        let mut cur_len = 0;
        let mut put_val = 0;
        let mut get_val = 0;

        for pattern in 0..256 {
            if cur_len == 0 {
                assert!(cbuf.is_empty());
            }
            if cur_len == buf.len() {
                assert!(cbuf.is_full());
            }

            for bit_i in 0..8 {
                match pattern & (1 << bit_i) == 0 {
                    true => if cbuf.is_empty() {
                        assert!(cbuf.peek(&buf).is_none());
                        assert!(cbuf.get(&buf).is_none());
                    } else {
                        assert!(cbuf.peek(&buf).unwrap() == get_val);
                        let val = cbuf.get(&buf).unwrap();
                        assert!(val == get_val);
                        get_val = get_val.wrapping_add(1);
                        cur_len -= 1;
                    },
                    false => if cbuf.is_full() {
                        cbuf.put(&mut buf, put_val);
                        assert!(cbuf.is_full());
                    } else {
                        cbuf.put(&mut buf, put_val);
                        put_val = put_val.wrapping_add(1);
                        cur_len += 1;
                    },
                }
            }
        }
    }

    #[bench]
    pub fn put_and_get(b : &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put(0u8);
            cbuf.get();
        });

        test::black_box(cbuf.get());
    }

    #[bench]
    pub fn put_unchecked_and_get(b : &mut Bencher) {
        let buf = &mut [0u8; 256];
        let mut cbuf = CBuf::new(buf);

        b.iter(|| {
            cbuf.put_unchecked(0u8);
            cbuf.get_unchecked();
        });

        test::black_box(cbuf.get());
    }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Num-rs Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[crate_type = "lib"];
#[crate_id = "github.com/bjz/num-rs#num:0.1"];
#[comment = "Fundamental algebraic structures."];

//! Fundamental algebraic structures
//!
//! # Definitions
//!
//! Throughout this module, we use the following definitions:
//!
//! ## Semigroup
//!
//! A set `S` with a binary operation `•` that satisfies:
//!
//! * Closure: For all `a, b ∈ S`, `a • b ∈ S`
//! * Associativity: For all `a, b, c ∈ S`, `(a • b) • c = a • (b • c)`
//!
//! ## Monoid
//!
//! A semigroup `S` that satisfies:
//!
//! * Identity element: For each `a ∈ S` there exists an element `e ∈ S`, such
//!   that `e • a = a • e = a`
//!
//! ## Group
//!
//! A monoid `G` that satisfies:
//!
//! * Inverse element: For each `a ∈ S` there exists an element `b ∈ G`, such
//!   that `a • b = b • a = e`, where `e` is the identity element.
//!
//! ## Abelian Group (Commutative Group)
//!
//! A group `A` that satisfies:
//!
//! * Commutativity: For all `a, b ∈ S`, `a • b = b • a`
//!
//! # Inspirations
//!
//! * [Numeric Prelude](http://www.haskell.org/haskellwiki/Numeric_Prelude) (Haskell)
//! * [Agda's Algebra module](http://www.cse.chalmers.se/~nad/listings/lib-0.7/Algebra.html) (Agda)
//! * [non/spire](https://github.com/non/spire) (Scala)
//!

/// A semigroup whose binary operation is identified with addition.
pub trait AdditiveSemiGroup
    : Add<Self, Self> {
}

impl AdditiveSemiGroup for u8   {}
impl AdditiveSemiGroup for u16  {}
impl AdditiveSemiGroup for u32  {}
impl AdditiveSemiGroup for u64  {}
impl AdditiveSemiGroup for uint {}
impl AdditiveSemiGroup for i8   {}
impl AdditiveSemiGroup for i16  {}
impl AdditiveSemiGroup for i32  {}
impl AdditiveSemiGroup for i64  {}
impl AdditiveSemiGroup for int  {}
impl AdditiveSemiGroup for f32  {}
impl AdditiveSemiGroup for f64  {}

/// An additive semigroup with an identity element, `0`.
pub trait AdditiveMonoid
    : AdditiveSemiGroup {
    /// The additive identity, `0`.
    fn zero() -> Self;
}

/// The additive identity, `0`.
#[inline]
pub fn zero<T: AdditiveMonoid>() -> T {
    AdditiveMonoid::zero()
}

impl AdditiveMonoid for u8   { #[inline] fn zero() -> u8   { 0   } }
impl AdditiveMonoid for u16  { #[inline] fn zero() -> u16  { 0   } }
impl AdditiveMonoid for u32  { #[inline] fn zero() -> u32  { 0   } }
impl AdditiveMonoid for u64  { #[inline] fn zero() -> u64  { 0   } }
impl AdditiveMonoid for uint { #[inline] fn zero() -> uint { 0   } }
impl AdditiveMonoid for i8   { #[inline] fn zero() -> i8   { 0   } }
impl AdditiveMonoid for i16  { #[inline] fn zero() -> i16  { 0   } }
impl AdditiveMonoid for i32  { #[inline] fn zero() -> i32  { 0   } }
impl AdditiveMonoid for i64  { #[inline] fn zero() -> i64  { 0   } }
impl AdditiveMonoid for int  { #[inline] fn zero() -> int  { 0   } }
impl AdditiveMonoid for f32  { #[inline] fn zero() -> f32  { 0.0 } }
impl AdditiveMonoid for f64  { #[inline] fn zero() -> f64  { 0.0 } }

/// An additive monoid with an inverse element.
pub trait AdditiveGroup
    : AdditiveMonoid
    + Sub<Self, Self>
    + Neg<Self> {
}

impl AdditiveGroup for u8   {}
impl AdditiveGroup for u16  {}
impl AdditiveGroup for u32  {}
impl AdditiveGroup for u64  {}
impl AdditiveGroup for uint {}
impl AdditiveGroup for i8   {}
impl AdditiveGroup for i16  {}
impl AdditiveGroup for i32  {}
impl AdditiveGroup for i64  {}
impl AdditiveGroup for int  {}
impl AdditiveGroup for f32  {}
impl AdditiveGroup for f64  {}

/// An additive group whose addition operation is commutative.
pub trait AdditiveAbelianGroup
    : AdditiveGroup {
}

impl AdditiveAbelianGroup for u8   {}
impl AdditiveAbelianGroup for u16  {}
impl AdditiveAbelianGroup for u32  {}
impl AdditiveAbelianGroup for u64  {}
impl AdditiveAbelianGroup for uint {}
impl AdditiveAbelianGroup for i8   {}
impl AdditiveAbelianGroup for i16  {}
impl AdditiveAbelianGroup for i32  {}
impl AdditiveAbelianGroup for i64  {}
impl AdditiveAbelianGroup for int  {}
impl AdditiveAbelianGroup for f32  {}
impl AdditiveAbelianGroup for f64  {}

/// A semigroup whose binary operation is identified with multiplication.
pub trait MultiplicativeSemiGroup
    : Mul<Self, Self> {
}

impl MultiplicativeSemiGroup for u8   {}
impl MultiplicativeSemiGroup for u16  {}
impl MultiplicativeSemiGroup for u32  {}
impl MultiplicativeSemiGroup for u64  {}
impl MultiplicativeSemiGroup for uint {}
impl MultiplicativeSemiGroup for i8   {}
impl MultiplicativeSemiGroup for i16  {}
impl MultiplicativeSemiGroup for i32  {}
impl MultiplicativeSemiGroup for i64  {}
impl MultiplicativeSemiGroup for int  {}
impl MultiplicativeSemiGroup for f32  {}
impl MultiplicativeSemiGroup for f64  {}

/// A multiplicative semigroup with an identity element, `1`.
pub trait MultiplicativeMonoid
    : MultiplicativeSemiGroup {
    fn one() -> Self;
}

/// The multiplicative identity, `1`.
#[inline]
pub fn one<T: MultiplicativeMonoid>() -> T {
    MultiplicativeMonoid::one()
}

impl MultiplicativeMonoid for u8   { #[inline] fn one() -> u8   { 1   } }
impl MultiplicativeMonoid for u16  { #[inline] fn one() -> u16  { 1   } }
impl MultiplicativeMonoid for u32  { #[inline] fn one() -> u32  { 1   } }
impl MultiplicativeMonoid for u64  { #[inline] fn one() -> u64  { 1   } }
impl MultiplicativeMonoid for uint { #[inline] fn one() -> uint { 1   } }
impl MultiplicativeMonoid for i8   { #[inline] fn one() -> i8   { 1   } }
impl MultiplicativeMonoid for i16  { #[inline] fn one() -> i16  { 1   } }
impl MultiplicativeMonoid for i32  { #[inline] fn one() -> i32  { 1   } }
impl MultiplicativeMonoid for i64  { #[inline] fn one() -> i64  { 1   } }
impl MultiplicativeMonoid for int  { #[inline] fn one() -> int  { 1   } }
impl MultiplicativeMonoid for f32  { #[inline] fn one() -> f32  { 1.0 } }
impl MultiplicativeMonoid for f64  { #[inline] fn one() -> f64  { 1.0 } }

/// A multiplicative monoid with an division and a reciprocal.
pub trait MultiplicativeGroup
    : MultiplicativeMonoid
    + Div<Self, Self> {
    #[inline]
    fn recip(&self) -> Self { one::<Self>() / *self }
}

impl MultiplicativeGroup for f32  {}
impl MultiplicativeGroup for f64  {}

/// A multiplicative group whose multiplication operation is commutative.
pub trait MultiplicativeAbelianGroup
    : MultiplicativeGroup {
}

impl MultiplicativeAbelianGroup for f32  {}
impl MultiplicativeAbelianGroup for f64  {}

/// An algebraic structure that:
///
/// * is a commutative group under addition
/// * is a monoid under multiplication
/// * distributes over addition, ie. `a * (b + c) = a * b + a * c`
///
/// # Examples
///
/// Integers, matrices, quaternions.
///
pub trait Ring
    : AdditiveAbelianGroup
    + MultiplicativeMonoid {
}

impl Ring for u8   {}
impl Ring for u16  {}
impl Ring for u32  {}
impl Ring for u64  {}
impl Ring for uint {}
impl Ring for i8   {}
impl Ring for i16  {}
impl Ring for i32  {}
impl Ring for i64  {}
impl Ring for int  {}
impl Ring for f32  {}
impl Ring for f64  {}

/// A ring whose multiplication operation is commutative.
///
/// # Examples
///
/// Complex numbers, reals, rationals, integers.
///
pub trait CommutativeRing
    : Ring {
}

impl CommutativeRing for u8   {}
impl CommutativeRing for u16  {}
impl CommutativeRing for u32  {}
impl CommutativeRing for u64  {}
impl CommutativeRing for uint {}
impl CommutativeRing for i8   {}
impl CommutativeRing for i16  {}
impl CommutativeRing for i32  {}
impl CommutativeRing for i64  {}
impl CommutativeRing for int  {}
impl CommutativeRing for f32  {}
impl CommutativeRing for f64  {}

/// A commutative ring that also has a multiplicative inverse operation for
/// every non-zero element.
///
/// # Examples
///
/// Complex numbers, rationals, reals.
///
pub trait Field
    : CommutativeRing
    + MultiplicativeAbelianGroup
    + Rem<Self, Self> {
}

impl Field for f32 {}
impl Field for f64 {}

trait Real
    : Ord
    + Field {
}

impl Real for f32  {}
impl Real for f64  {}
<commit_msg>Add Semigroup, Monoid, Group and AbelianGroup, and improve documentation<commit_after>// Copyright 2013 The Num-rs Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[crate_type = "lib"];
#[crate_id = "github.com/bjz/num-rs#num:0.1"];
#[comment = "Fundamental algebraic structures."];

//! Fundamental algebraic structures
//!
//! # Inspirations
//!
//! * [Numeric Prelude](http://www.haskell.org/haskellwiki/Numeric_Prelude) (Haskell)
//! * [Agda's Algebra module](http://www.cse.chalmers.se/~nad/listings/lib-0.7/Algebra.html) (Agda)
//! * [Idris' Algebra module](https://github.com/idris-lang/Idris-dev/blob/master/libs/prelude/Prelude/Algebra.idr) (Idris)
//! * [non/spire](https://github.com/non/spire) (Scala)
//!

/// Sets equipped with an associative binary operation `•`.
///
/// # Laws
///
/// ~~~
/// Associativity of •:
///     forall a b c,              (a • b) • c = a • (b • c)
/// ~~~
pub trait Semigroup {
    /// The binary operation `•`.
    fn op(a: &Self, b: &Self) -> Self;
}

/// A semigroup's binary operation.
#[inline]
pub fn op<T: Semigroup>(a: &T, b: &T) -> T {
    Semigroup::op(a, b)
}

/// Sets equipped with an associative binary operation and a corresponding
/// identity element.
///
/// # Laws
///
/// ~~~
/// Associativity of •:
///     forall a b c,               (a • b) • c = a • (b • c)
/// Identity for •:
///     forall a,                   a • identity = a
///     forall a,                   identity • a = a
/// ~~~
pub trait Monoid
    : Semigroup {
    /// The identity element for `•`.
    fn identity() -> Self;
}

/// The identity element of a monoid's binary operation.
#[inline]
pub fn identity<T: Monoid>() -> T {
    Monoid::identity()
}

/// Sets equipped with an associative binary operation, a corresponding
/// identity element, and an inverse.
///
/// # Laws
///
/// ~~~
/// Associativity of •:
///     forall a b c,               (a • b) • c = a • (b • c)
/// Identity for •:
///     forall a,                   a • identity = a
///     forall a,                   identity • a = a
/// Inverse for •:
///     forall a,                   a • inverse(a) = identity
///     forall a,                   inverse(a) • a = identity
/// ~~~
pub trait Group
    : Monoid {
    fn inverse(&self) -> Self;
}

/// Sets equipped with an associative and commutative binary operation, a
/// corresponding identity element, and an inverse.
///
/// # Laws
///
/// ~~~
/// Associativity of •:
///     forall a b c,               (a • b) • c = a • (b • c)
/// Commutativity of •:
///     forall a b,                 a • b = b • a
/// Identity for •:
///     forall a,                   a • identity = a
///     forall a,                   identity • a = a
/// Inverse for •:
///     forall a,                   a • inverse(a) = identity
///     forall a,                   inverse(a) • a = identity
/// ~~~
pub trait AbelianGroup
    : Group {
}

/// Sets that are a semigroup under addition.
pub trait AdditiveSemiGroup
    : Add<Self, Self> {
}

impl AdditiveSemiGroup for u8   {}
impl AdditiveSemiGroup for u16  {}
impl AdditiveSemiGroup for u32  {}
impl AdditiveSemiGroup for u64  {}
impl AdditiveSemiGroup for uint {}
impl AdditiveSemiGroup for i8   {}
impl AdditiveSemiGroup for i16  {}
impl AdditiveSemiGroup for i32  {}
impl AdditiveSemiGroup for i64  {}
impl AdditiveSemiGroup for int  {}
impl AdditiveSemiGroup for f32  {}
impl AdditiveSemiGroup for f64  {}

/// Sets that are a monoid under addition.
pub trait AdditiveMonoid
    : AdditiveSemiGroup {
    /// The additive identity, `0`.
    fn zero() -> Self;
}

/// The additive identity, `0`.
#[inline]
pub fn zero<T: AdditiveMonoid>() -> T {
    AdditiveMonoid::zero()
}

impl AdditiveMonoid for u8   { #[inline] fn zero() -> u8   { 0   } }
impl AdditiveMonoid for u16  { #[inline] fn zero() -> u16  { 0   } }
impl AdditiveMonoid for u32  { #[inline] fn zero() -> u32  { 0   } }
impl AdditiveMonoid for u64  { #[inline] fn zero() -> u64  { 0   } }
impl AdditiveMonoid for uint { #[inline] fn zero() -> uint { 0   } }
impl AdditiveMonoid for i8   { #[inline] fn zero() -> i8   { 0   } }
impl AdditiveMonoid for i16  { #[inline] fn zero() -> i16  { 0   } }
impl AdditiveMonoid for i32  { #[inline] fn zero() -> i32  { 0   } }
impl AdditiveMonoid for i64  { #[inline] fn zero() -> i64  { 0   } }
impl AdditiveMonoid for int  { #[inline] fn zero() -> int  { 0   } }
impl AdditiveMonoid for f32  { #[inline] fn zero() -> f32  { 0.0 } }
impl AdditiveMonoid for f64  { #[inline] fn zero() -> f64  { 0.0 } }

/// Sets that are a group under addition.
pub trait AdditiveGroup
    : AdditiveMonoid
    + Sub<Self, Self>
    + Neg<Self> {
}

impl AdditiveGroup for u8   {}
impl AdditiveGroup for u16  {}
impl AdditiveGroup for u32  {}
impl AdditiveGroup for u64  {}
impl AdditiveGroup for uint {}
impl AdditiveGroup for i8   {}
impl AdditiveGroup for i16  {}
impl AdditiveGroup for i32  {}
impl AdditiveGroup for i64  {}
impl AdditiveGroup for int  {}
impl AdditiveGroup for f32  {}
impl AdditiveGroup for f64  {}

/// Sets that are an abelian group under addition.
pub trait AdditiveAbelianGroup
    : AdditiveGroup {
}

impl AdditiveAbelianGroup for u8   {}
impl AdditiveAbelianGroup for u16  {}
impl AdditiveAbelianGroup for u32  {}
impl AdditiveAbelianGroup for u64  {}
impl AdditiveAbelianGroup for uint {}
impl AdditiveAbelianGroup for i8   {}
impl AdditiveAbelianGroup for i16  {}
impl AdditiveAbelianGroup for i32  {}
impl AdditiveAbelianGroup for i64  {}
impl AdditiveAbelianGroup for int  {}
impl AdditiveAbelianGroup for f32  {}
impl AdditiveAbelianGroup for f64  {}

/// A/// Sets that are a semigroup under addition.
pub trait MultiplicativeSemiGroup
    : Mul<Self, Self> {
}

impl MultiplicativeSemiGroup for u8   {}
impl MultiplicativeSemiGroup for u16  {}
impl MultiplicativeSemiGroup for u32  {}
impl MultiplicativeSemiGroup for u64  {}
impl MultiplicativeSemiGroup for uint {}
impl MultiplicativeSemiGroup for i8   {}
impl MultiplicativeSemiGroup for i16  {}
impl MultiplicativeSemiGroup for i32  {}
impl MultiplicativeSemiGroup for i64  {}
impl MultiplicativeSemiGroup for int  {}
impl MultiplicativeSemiGroup for f32  {}
impl MultiplicativeSemiGroup for f64  {}

/// Sets that are a monoid under addition.
pub trait MultiplicativeMonoid
    : MultiplicativeSemiGroup {
    fn one() -> Self;
}

/// The multiplicative identity, `1`.
#[inline]
pub fn one<T: MultiplicativeMonoid>() -> T {
    MultiplicativeMonoid::one()
}

impl MultiplicativeMonoid for u8   { #[inline] fn one() -> u8   { 1   } }
impl MultiplicativeMonoid for u16  { #[inline] fn one() -> u16  { 1   } }
impl MultiplicativeMonoid for u32  { #[inline] fn one() -> u32  { 1   } }
impl MultiplicativeMonoid for u64  { #[inline] fn one() -> u64  { 1   } }
impl MultiplicativeMonoid for uint { #[inline] fn one() -> uint { 1   } }
impl MultiplicativeMonoid for i8   { #[inline] fn one() -> i8   { 1   } }
impl MultiplicativeMonoid for i16  { #[inline] fn one() -> i16  { 1   } }
impl MultiplicativeMonoid for i32  { #[inline] fn one() -> i32  { 1   } }
impl MultiplicativeMonoid for i64  { #[inline] fn one() -> i64  { 1   } }
impl MultiplicativeMonoid for int  { #[inline] fn one() -> int  { 1   } }
impl MultiplicativeMonoid for f32  { #[inline] fn one() -> f32  { 1.0 } }
impl MultiplicativeMonoid for f64  { #[inline] fn one() -> f64  { 1.0 } }

/// Sets that are a group under addition.
pub trait MultiplicativeGroup
    : MultiplicativeMonoid
    + Div<Self, Self> {
    #[inline]
    fn recip(&self) -> Self { one::<Self>() / *self }
}

impl MultiplicativeGroup for f32  {}
impl MultiplicativeGroup for f64  {}

/// Sets that are an abelian group under addition.
pub trait MultiplicativeAbelianGroup
    : MultiplicativeGroup {
}

impl MultiplicativeAbelianGroup for f32  {}
impl MultiplicativeAbelianGroup for f64  {}

/// Sets that are an abelian group under addition, a monoid under
/// multiplication, and where multiplication distributes over addition.
///
/// # Laws
///
/// ~~~
/// Associativity of +:
///     forall a b c,               (a + b) + c = a + (b + c)
/// Commutativity of +:
///     forall a b,                 a + b = b + a
/// Identity for +:
///     forall a,                   a + 0 = a
///     forall a,                   0 + a = a
/// Inverse for +:
///     forall a,                   a + -a = 0
///     forall a,                   -a + a = 0
/// Associativity of *:
///     forall a b c,               (a * b) * c = a * (b * c)
/// Identity for *:
///     forall a,                   a * 1 = a
///     forall a,                   1 * a = a
/// Distributivity of * and +:
///     forall a b c,               a * (b + c) = (a * b) + (a * c)
///     forall a b c,               (a + b) * c = (a * c) + (b * c)
/// ~~~
///
/// # Examples
///
/// Integers, matrices, quaternions.
///
pub trait Ring
    : AdditiveAbelianGroup
    + MultiplicativeMonoid {
}

impl Ring for u8   {}
impl Ring for u16  {}
impl Ring for u32  {}
impl Ring for u64  {}
impl Ring for uint {}
impl Ring for i8   {}
impl Ring for i16  {}
impl Ring for i32  {}
impl Ring for i64  {}
impl Ring for int  {}
impl Ring for f32  {}
impl Ring for f64  {}

/// A ring whose multiplication operation is also commutative.
///
/// # Laws
///
/// ~~~
/// Associativity of +:
///     forall a b c,               (a + b) + c = a + (b + c)
/// Commutativity of +:
///     forall a b,                 a + b = b + a
/// Identity for +:
///     forall a,                   a + 0 = a
///     forall a,                   0 + a = a
/// Inverse for +:
///     forall a,                   a + -a = 0
///     forall a,                   -a + a = 0
/// Associativity of *:
///     forall a b c,               (a * b) * c = a * (b * c)
/// Commutativity of *:
///     forall a b,                 a * b = b * a
/// Identity for *:
///     forall a,                   a * 1 = a
///     forall a,                   1 * a = a
/// Distributivity of * and +:
///     forall a b c,               a * (b + c) = (a * b) + (a * c)
///     forall a b c,               (a + b) * c = (a * c) + (b * c)
/// ~~~
///
/// # Examples
///
/// Complex numbers, reals, rationals, integers.
///
pub trait CommutativeRing
    : Ring {
}

impl CommutativeRing for u8   {}
impl CommutativeRing for u16  {}
impl CommutativeRing for u32  {}
impl CommutativeRing for u64  {}
impl CommutativeRing for uint {}
impl CommutativeRing for i8   {}
impl CommutativeRing for i16  {}
impl CommutativeRing for i32  {}
impl CommutativeRing for i64  {}
impl CommutativeRing for int  {}
impl CommutativeRing for f32  {}
impl CommutativeRing for f64  {}

/// A commutative ring that also has a multiplicative inverse operation for
/// every non-zero element.
///
/// # Laws
///
/// ~~~
/// Associativity of +:
///     forall a b c,               (a + b) + c = a + (b + c)
/// Commutativity of +:
///     forall a b,                 a + b = b + a
/// Identity for +:
///     forall a,                   a + 0 = a
///     forall a,                   0 + a = a
/// Inverse for +:
///     forall a,                   a + -a = 0
///     forall a,                   -a + a = 0
/// Associativity of *:
///     forall a b c,               (a * b) * c = a * (b * c)
/// Commutativity of *:
///     forall a b,                 a * b = b * a
/// Identity for *:
///     forall a,                   a * 1 = a
///     forall a,                   1 * a = a
/// Inverse for *:
///     forall a,                   a * a⁻¹ = 1
///     forall a,                   a⁻¹ * a = 1
/// Distributivity of * and +:
///     forall a b c,               a * (b + c) = (a * b) + (a * c)
///     forall a b c,               (a + b) * c = (a * c) + (b * c)
/// ~~~
///
/// # Examples
///
/// Complex numbers, rationals, reals.
///
pub trait Field
    : CommutativeRing
    + MultiplicativeAbelianGroup
    + Rem<Self, Self> {
}

impl Field for f32 {}
impl Field for f64 {}

trait Real
    : Ord
    + Field {
}

impl Real for f32  {}
impl Real for f64  {}

trait Integral
    : Ord
    + CommutativeRing {}

impl Integral for u8   {}
impl Integral for u16  {}
impl Integral for u32  {}
impl Integral for u64  {}
impl Integral for uint {}
impl Integral for i8   {}
impl Integral for i16  {}
impl Integral for i32  {}
impl Integral for i64  {}
impl Integral for int  {}
<|endoftext|>


<commit_before>#![allow(let_unit_value, new_without_default, non_snake_case, transmute_ptr_to_ref, type_complexity, unused_imports)]

#[macro_use]
extern crate glib;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys;
extern crate gtk;
extern crate libc;

extern crate webkit2gtk_webextension_sys as ffi;

pub use glib::Error;

macro_rules! assert_initialized_main_thread {
    () => (
        if !::gtk::is_initialized_main_thread() {
            if ::gtk::is_initialized() {
                panic!("GTK may only be used from the main thread.");
            }
            else {
                panic!("GTK has not been initialized. Call `gtk::init` first.");
            }
        }
    )
}

macro_rules! skip_assert_initialized {
    () => ()
}

macro_rules! callback_guard {
    () => (
        let _guard = ::glib::CallbackGuard::new();
    )
}

#[macro_export]
macro_rules! web_extension_init {
    () => {
        extern crate glib;
        extern crate glib_sys;
        extern crate webkit2gtk_webextension_sys;

        #[no_mangle]
        pub unsafe fn webkit_web_extension_initialize_with_user_data(extension: *mut ::webkit2gtk_webextension_sys::WebKitWebExtension, user_data: *mut ::glib_sys::GVariant) {
            web_extension_initialize(::glib::translate::FromGlibPtr::from_glib_none(extension), ::glib::translate::FromGlibPtr::from_glib_none(user_data));
        }
    };
}

mod auto;
mod dom_dom_selection;
mod dom_dom_window;
mod dom_html_field_set_element;

pub use auto::*;
pub use dom_dom_selection::*;
pub use dom_dom_window::*;
pub use dom_html_field_set_element::*;

unsafe impl Send for WebExtension {}
<commit_msg>Fix web_extension_init macro<commit_after>#![allow(let_unit_value, new_without_default, non_snake_case, transmute_ptr_to_ref, type_complexity, unused_imports)]

#[macro_use]
extern crate glib;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys;
extern crate gtk;
extern crate libc;

extern crate webkit2gtk_webextension_sys as ffi;

pub use glib::Error;

macro_rules! assert_initialized_main_thread {
    () => (
        if !::gtk::is_initialized_main_thread() {
            if ::gtk::is_initialized() {
                panic!("GTK may only be used from the main thread.");
            }
            else {
                panic!("GTK has not been initialized. Call `gtk::init` first.");
            }
        }
    )
}

macro_rules! skip_assert_initialized {
    () => ()
}

macro_rules! callback_guard {
    () => (
        let _guard = ::glib::CallbackGuard::new();
    )
}

#[macro_export]
macro_rules! web_extension_init {
    () => {
        extern crate glib;
        extern crate glib_sys;
        extern crate webkit2gtk_webextension_sys;

        #[no_mangle]
        pub unsafe fn webkit_web_extension_initialize_with_user_data(extension: *mut ::webkit2gtk_webextension_sys::WebKitWebExtension, user_data: *mut ::glib_sys::GVariant) {
            web_extension_initialize(::glib::translate::FromGlibPtrNone::from_glib_none(extension), ::glib::translate::FromGlibPtr::from_glib_none(user_data));
        }
    };
}

mod auto;
mod dom_dom_selection;
mod dom_dom_window;
mod dom_html_field_set_element;

pub use auto::*;
pub use dom_dom_selection::*;
pub use dom_dom_window::*;
pub use dom_html_field_set_element::*;

unsafe impl Send for WebExtension {}
<|endoftext|>