<commit_before>extern crate "parser-combinators" as parser_combinators;

use self::parser_combinators::{try, between, spaces, string, parser, many, many1, digit, any_char, optional, hex_digit, not_followed_by, satisfy, Parser, ParserExt, ParseResult};
use self::parser_combinators::primitives::{State, Stream};

use super::ast::*;
use super::ast::ExprNode::*;

use std::str::FromStr;
use std::num::FromStrRadix;
use std::char;

/// Parser for signed integer constants.
///
/// This parses signed integer constants in decimal and hexadecimal.
///
/// TODO: add support for octal
/// TODO: add support for binary
/// TODO: add support for R6RS exponents
fn sint_const<I>(input: State<I>) -> ParseResult<NumNode, I>
    where I: Stream<Item=char> {

        fn hex_string<I>(input: State<I>) -> ParseResult<isize, I>
            where I: Stream<Item=char> {
                (satisfy(|c| c == '#')
                    .and(satisfy(|c| c == 'x' || c == 'X')))
                    .with(many1::<Vec<_>, _>(hex_digit()))
                    .map(|x| {
                        isize::from_str_radix(
                            x.iter()
                             .fold(
                                String::new(),
                                |mut s: String, i| { s.push(*i); s })
                             .as_slice(),
                        16).unwrap()
                    }).parse_state(input)
        }

        fn dec_string<I>(input: State<I>) -> ParseResult<isize, I>
            where I: Stream<Item=char> {
                optional(satisfy(|c| c == '#')
                    .and(satisfy(|c| c == 'd' || c == 'D')))
                .with(many1::<Vec<_>, _>(digit())
                    .map(|x| isize::from_str(x.iter().fold(
                        String::new(), |mut s: String, i| { s.push(*i); s })
                        .as_slice()
                    ).unwrap()
                    )).parse_state(input)
            }

        optional(satisfy(|c| c == '-'))
            .and(
                try(parser(hex_string))
                .or(parser(dec_string))
                )
            .map(|x| {
                if let Some(sign) = x.0 {
                    let mut s = String::new();
                    s.push(sign);
                    s.push('1');
                    x.1 * isize::from_str(s.as_slice()).unwrap()
                } else {
                    x.1
                }
                })
            .skip(not_followed_by(satisfy(|c|
                c == 'u' || c == 'U' || c == '.' || c == 'f' || c == 'F')
            ))
            .map(|x: isize| NumNode::IntConst(IntNode{value: x}))
            .parse_state(input)
}
/// Parser for unsigned integer constants.
///
/// This parses unssigned integer constants in decimal and hexadecimal.
///
/// TODO: add support for octal
/// TODO: add support for binary
/// TODO: add support for R6RS exponents
fn uint_const<I>(input: State<I>) -> ParseResult<NumNode, I>
    where I: Stream<Item=char> {

        fn hex_string<I>(input: State<I>) -> ParseResult<usize, I>
            where I: Stream<Item=char> {
            (satisfy(|c| c == '#')
                .and(satisfy(|c| c == 'x' || c == 'X')))
                .with(many1::<Vec<_>, _>(hex_digit()))
                .map(|x| usize::from_str_radix(
                        x.iter()
                         .fold(
                            String::new(),
                            |mut s: String, i| { s.push(*i); s })
                         .as_slice(),
                    16).unwrap()
                ).parse_state(input)
        }

        try(parser(hex_string))
        .or( many1::<Vec<_>, _>(digit())
            .map(|x|usize::from_str(x.iter().fold(
                String::new(), |mut s: String, i| { s.push(*i); s })
                .as_slice()
            ).unwrap())
        )
        .skip(satisfy(|c| c == 'u' || c == 'U'))
        .map(|x: usize| NumNode::UIntConst(UIntNode{value: x}))
        .parse_state(input)
}

/// Parser for floating-point constants.
///
/// This parses floating-point constants. Currently, this parser
/// recognizes numbers with decimal points as floating point, followed
/// by an optional `f` or `F`. Numbers with `f`s but no decimal points,
/// i.e. `1F`, are currently not recognized. While this form of number
/// is not specified by R6RS, I'd like to support it anyway as it's
/// a common form for floating-point numbers. Priority: low.
fn float_const<I>(input: State<I>) -> ParseResult<NumNode, I>
    where I: Stream<Item=char> {
        many1::<Vec<_>, _>(digit())
            .and(satisfy(|c| c == '.'))
            .and(many1::<Vec<_>, _>(digit()))
            .map(|x| {
                let mut s = String::new();
                for i in (x.0).0.iter() { s.push(*i); } ;
                s.push((x.0).1);

                for i in x.1.iter() { s.push(*i); };
                NumNode::FloatConst(FloatNode{
                    value: f64::from_str(s.as_slice()).unwrap()
                })
            })
            .skip(optional(satisfy(|c| c == 'f' || c == 'F')))
            .parse_state(input)
}

/// Parses boolean constants.
///
/// Note that this parser recognizes the strings `"true"` and `"false"`
/// as true and false. While this is not specified in R6RS, the use of
/// these tokens is common enough in other programming languages that
/// I've decided that Seax Scheme should support it as well. This may
/// be removed in a future version if it causes unforseen compatibility
/// issues.
///
/// `#t`, `#T`, or `true`  -> `true`
/// `#f`, `#F`, or `false` -> `false`
pub fn bool_const<I>(input: State<I>) -> ParseResult<BoolNode, I>
    where I: Stream<Item=char> {
        let t_const = try(string("#t"))
            .or(try(string("#T")))
            .or(try(string("true")))
            .map(|_| BoolNode{ value: true });
        let f_const = try(string("#f"))
            .or(try(string("#F")))
            .or(try(string("false")))
            .map(|_| BoolNode{ value: false });
        t_const
            .or(f_const)
            .parse_state(input)
    }

/// Parses a floating-point, signed integer, or unsigned integer constant.
pub fn number<I>(input: State<I>) -> ParseResult<NumNode, I>
    where I: Stream<Item=char> {
        try(parser(sint_const))
            .or(try(parser(uint_const)))
            .or(try(parser(float_const)))
            .parse_state(input)
}

/// Parser for valid R6RS identifiers.
///
/// An identifier may begin with an alphabetic character or
/// one of the following special characters `!`, `$`, `&`, `:`, `^`,
/// `<`, `>`, `_`,`~`,`\`, or `?`. Subsequent characters may also include
/// numbers or the special characters `+`, `-`, `.`, and `@`.
///
/// Essentially, this parser recognizes the regular expression
/// `[a-zA-Z!\$%:\^<>_~\\\?][a-zA-Z0-9!\$%:\^<>_~\\\?\+\-\.@]*`.
///
/// For more information, consult the
/// [R6RS](http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-7.html).
pub fn name<I>(input: State<I>) -> ParseResult<NameNode, I>
    where I: Stream<Item=char> {

        fn initial<I>(input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                satisfy(|c|
                    c.is_alphabetic()
                    // R6RS 'special initial' characters
                    || c == '!' || c == '$' || c == '%' || c == ':' || c == '^'
                    || c == '<' || c == '>' || c == '_' || c == '~' || c == '\\'
                    || c == '?'
                ).parse_state(input)
            }

        fn subsequent<I>(input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {

            satisfy(|c|
                c.is_alphanumeric()
                    // R6RS 'special initial' characters
                    || c == '!' || c == '$' || c == '%' || c == ':' || c == '^'
                    || c == '<' || c == '>' || c == '_' || c == '~' || c == '\\'
                    || c == '?'
                    // R6RS 'special subsequent' characters
                    || c == '+' || c == '-' || c == '.' || c == '@'
                ).parse_state(input)
            }

        fn rest<I>(input: State<I>) -> ParseResult<String, I>
            where I: Stream<Item=char> {
                many::<Vec<_>, _>(parser(subsequent))
                    .map(|it|
                        it.iter().fold(
                            String::new(),
                            |mut s: String, i| {
                                s.push(*i);
                                s
                            })
                        )
                    .parse_state(input)
            }

        parser(initial)
            .and(parser(rest))
            .parse_state(input)
            .map(|x| {
                let mut s = String::new();
                s.push((x.0).0);
                s.push_str(&(x.0).1);
                (NameNode{ name: s}, x.1)
            })
}

pub fn character<I> (input: State<I>) -> ParseResult<CharNode, I>
    where I: Stream<Item=char> {

        fn newline<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("newline"))
                    .or(try(string("linefeed")))
                    .map(|_| '\n')
                    .parse_state(input)
            }

        fn tab<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("tab")).map(|_| '\t').parse_state(input)
            }

        fn nul<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("nul"))
                    .map(|_| char::from_u32(0x0000).unwrap())
                    .parse_state(input)
            }

        fn backspace<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("backspace"))
                    .map(|_| char::from_u32(0x0008).unwrap())
                    .parse_state(input)
            }

        fn vtab<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("vtab"))
                    .map(|_| char::from_u32(0x000B).unwrap())
                    .parse_state(input)
            }

        fn page<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("page"))
                    .map(|_| char::from_u32(0x000C).unwrap())
                    .parse_state(input)
            }

        fn retn<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("return"))
                    .map(|_| char::from_u32(0x000D).unwrap())
                    .parse_state(input)
            }

        fn esc<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("esc"))
                    .map(|_| char::from_u32(0x001B).unwrap())
                    .parse_state(input)
            }

        fn delete<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("delete"))
                    .map(|_| char::from_u32(0x007F).unwrap())
                    .parse_state(input)
            }

        fn alarm<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("alarm"))
                    .map(|_| char::from_u32(0x0007).unwrap())
                    .parse_state(input)
            }

        fn space<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                try(string("space"))
                    .map(|_| char::from_u32(0x0020).unwrap())
                    .parse_state(input)
            }

        fn char_name<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                parser(newline)
                    .or(parser(tab))
                    .or(parser(vtab))
                    .or(parser(backspace))
                    .or(parser(nul))
                    .or(parser(page))
                    .or(parser(retn))
                    .or(parser(esc))
                    .or(parser(delete))
                    .or(parser(alarm))
                    .or(parser(space))
                    .parse_state(input)
            }

        fn hex_char<I> (input: State<I>) -> ParseResult<char, I>
            where I: Stream<Item=char> {
                satisfy(|c| c == 'x')
                    .with(many1::<Vec<_>, _>(hex_digit()))
                    .map(|x| {
                        char::from_u32(
                            u32::from_str_radix(
                                x.iter()
                                 .fold(
                                    String::new(),
                                    |mut s: String, i| { s.push(*i); s })
                                 .as_slice(),
                            16).unwrap()
                        ).unwrap()
                    })
                    .parse_state(input)
            }

        string("#\\")
            .with(
                parser(char_name)
                .or(parser(hex_char))
                .or(parser(any_char))
            ).map(|c| CharNode { value: c})
            .parse_state(input)

}

/// Parses Scheme expressions.
#[allow(unconditional_recursion)]
pub fn expr<I>(input: State<I>) -> ParseResult<ExprNode, I>
    where I: Stream<Item=char> {
        let spaces = spaces();

        fn sexpr<I>(input: State<I>) -> ParseResult<ExprNode, I>
            where I: Stream<Item=char> {
                between(
                    satisfy(|c| c == '('),
                    satisfy(|c| c == ')'),
                    parser(name)
                        .and(many(parser(expr)))
                        .map(|x| {
                            SExpr(SExprNode {
                                operator: x.0,
                                operands: x.1
                            })
                        })
                ).parse_state(input)
            }

        fn list<I>(input: State<I>) -> ParseResult<ExprNode, I>
            where I: Stream<Item=char> {
                between(
                    satisfy(|c| c == '('),
                    satisfy(|c| c == ')'),
                    many(parser(expr))
                        .map(|x| {
                            ListConst(ListNode {
                                elements: x
                            })
                        })
                ).parse_state(input)
            }

        spaces.clone().with(
            try(parser(sexpr))
                .or(try(parser(list)))
                .or(try(parser(name).map(Name)))
                .or(try(parser(number).map(NumConst)))
            ).parse_state(input)
}

#[cfg(test)]
mod tests;<commit_msg>Refactor: de-generalize parsers<commit_after>extern crate "parser-combinators" as parser_combinators;

use self::parser_combinators::{try, between, spaces, string, parser, many, many1, digit, any_char, optional, hex_digit, not_followed_by, satisfy, Parser, ParserExt, ParseResult};
use self::parser_combinators::primitives::State;

use super::ast::*;
use super::ast::ExprNode::*;

use std::str::FromStr;
use std::num::FromStrRadix;
use std::char;

/// Parser for signed integer constants.
///
/// This parses signed integer constants in decimal and hexadecimal.
///
/// TODO: add support for octal
/// TODO: add support for binary
/// TODO: add support for R6RS exponents
fn sint_const(input: State<&str>) -> ParseResult<NumNode, &str> {

        fn hex_string(input: State<&str>) -> ParseResult<isize, &str> {
                (satisfy(|c| c == '#')
                    .and(satisfy(|c| c == 'x' || c == 'X')))
                    .with(many1::<Vec<_>, _>(hex_digit()))
                    .map(|x| {
                        isize::from_str_radix(
                            x.iter()
                             .fold(
                                String::new(),
                                |mut s: String, i| { s.push(*i); s })
                             .as_slice(),
                        16).unwrap()
                    }).parse_state(input)
        }

        fn dec_string(input: State<&str>) -> ParseResult<isize, &str> {
                optional(satisfy(|c| c == '#')
                    .and(satisfy(|c| c == 'd' || c == 'D')))
                .with(many1::<Vec<_>, _>(digit())
                    .map(|x| isize::from_str(x.iter().fold(
                        String::new(), |mut s: String, i| { s.push(*i); s })
                        .as_slice()
                    ).unwrap()
                    )).parse_state(input)
            }

        optional(satisfy(|c| c == '-'))
            .and(
                try(parser(hex_string))
                .or(parser(dec_string))
                )
            .map(|x| {
                if let Some(sign) = x.0 {
                    let mut s = String::new();
                    s.push(sign);
                    s.push('1');
                    x.1 * isize::from_str(s.as_slice()).unwrap()
                } else {
                    x.1
                }
                })
            .skip(not_followed_by(satisfy(|c|
                c == 'u' || c == 'U' || c == '.' || c == 'f' || c == 'F')
            ))
            .map(|x: isize| NumNode::IntConst(IntNode{value: x}))
            .parse_state(input)
}
/// Parser for unsigned integer constants.
///
/// This parses unssigned integer constants in decimal and hexadecimal.
///
/// TODO: add support for octal
/// TODO: add support for binary
/// TODO: add support for R6RS exponents
fn uint_const(input: State<&str>) -> ParseResult<NumNode, &str> {

        fn hex_string(input: State<&str>) -> ParseResult<usize, &str> {
            (satisfy(|c| c == '#')
                .and(satisfy(|c| c == 'x' || c == 'X')))
                .with(many1::<Vec<_>, _>(hex_digit()))
                .map(|x| usize::from_str_radix(
                        x.iter()
                         .fold(
                            String::new(),
                            |mut s: String, i| { s.push(*i); s })
                         .as_slice(),
                    16).unwrap()
                ).parse_state(input)
        }

        try(parser(hex_string))
        .or( many1::<Vec<_>, _>(digit())
            .map(|x|usize::from_str(x.iter().fold(
                String::new(), |mut s: String, i| { s.push(*i); s })
                .as_slice()
            ).unwrap())
        )
        .skip(satisfy(|c| c == 'u' || c == 'U'))
        .map(|x: usize| NumNode::UIntConst(UIntNode{value: x}))
        .parse_state(input)
}

/// Parser for floating-point constants.
///
/// This parses floating-point constants. Currently, this parser
/// recognizes numbers with decimal points as floating point, followed
/// by an optional `f` or `F`. Numbers with `f`s but no decimal points,
/// i.e. `1F`, are currently not recognized. While this form of number
/// is not specified by R6RS, I'd like to support it anyway as it's
/// a common form for floating-point numbers. Priority: low.
fn float_const(input: State<&str>) -> ParseResult<NumNode, &str> {
        many1::<Vec<_>, _>(digit())
            .and(satisfy(|c| c == '.'))
            .and(many1::<Vec<_>, _>(digit()))
            .map(|x| {
                let mut s = String::new();
                for i in (x.0).0.iter() { s.push(*i); } ;
                s.push((x.0).1);

                for i in x.1.iter() { s.push(*i); };
                NumNode::FloatConst(FloatNode{
                    value: f64::from_str(s.as_slice()).unwrap()
                })
            })
            .skip(optional(satisfy(|c| c == 'f' || c == 'F')))
            .parse_state(input)
}

/// Parses boolean constants.
///
/// Note that this parser recognizes the strings `"true"` and `"false"`
/// as true and false. While this is not specified in R6RS, the use of
/// these tokens is common enough in other programming languages that
/// I've decided that Seax Scheme should support it as well. This may
/// be removed in a future version if it causes unforseen compatibility
/// issues.
///
/// `#t`, `#T`, or `true`  -> `true`
/// `#f`, `#F`, or `false` -> `false`
pub fn bool_const(input: State<&str>) -> ParseResult<BoolNode, &str> {
        let t_const = try(string("#t"))
            .or(try(string("#T")))
            .or(try(string("true")))
            .map(|_| BoolNode{ value: true });
        let f_const = try(string("#f"))
            .or(try(string("#F")))
            .or(try(string("false")))
            .map(|_| BoolNode{ value: false });
        t_const
            .or(f_const)
            .parse_state(input)
    }

/// Parses a floating-point, signed integer, or unsigned integer constant.
pub fn number(input: State<&str>) -> ParseResult<NumNode, &str> {
        try(parser(sint_const))
            .or(try(parser(uint_const)))
            .or(try(parser(float_const)))
            .parse_state(input)
}

/// Parser for valid R6RS identifiers.
///
/// An identifier may begin with an alphabetic character or
/// one of the following special characters `!`, `$`, `&`, `:`, `^`,
/// `<`, `>`, `_`,`~`,`\`, or `?`. Subsequent characters may also include
/// numbers or the special characters `+`, `-`, `.`, and `@`.
///
/// Essentially, this parser recognizes the regular expression
/// `[a-zA-Z!\$%:\^<>_~\\\?][a-zA-Z0-9!\$%:\^<>_~\\\?\+\-\.@]*`.
///
/// For more information, consult the
/// [R6RS](http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-7.html).
pub fn name(input: State<&str>) -> ParseResult<NameNode, &str> {

        fn initial(input: State<&str>) -> ParseResult<char, &str> {
                satisfy(|c|
                    c.is_alphabetic()
                    // R6RS 'special initial' characters
                    || c == '!' || c == '$' || c == '%' || c == ':' || c == '^'
                    || c == '<' || c == '>' || c == '_' || c == '~' || c == '\\'
                    || c == '?'
                ).parse_state(input)
            }

        fn subsequent(input: State<&str>) -> ParseResult<char, &str> {

            satisfy(|c|
                c.is_alphanumeric()
                    // R6RS 'special initial' characters
                    || c == '!' || c == '$' || c == '%' || c == ':' || c == '^'
                    || c == '<' || c == '>' || c == '_' || c == '~' || c == '\\'
                    || c == '?'
                    // R6RS 'special subsequent' characters
                    || c == '+' || c == '-' || c == '.' || c == '@'
                ).parse_state(input)
            }

        fn rest(input: State<&str>) -> ParseResult<String, &str> {
                many::<Vec<_>, _>(parser(subsequent))
                    .map(|it|
                        it.iter().fold(
                            String::new(),
                            |mut s: String, i| {
                                s.push(*i);
                                s
                            })
                        )
                    .parse_state(input)
            }

        parser(initial)
            .and(parser(rest))
            .parse_state(input)
            .map(|x| {
                let mut s = String::new();
                s.push((x.0).0);
                s.push_str(&(x.0).1);
                (NameNode{ name: s}, x.1)
            })
}

pub fn character(input: State<&str>) -> ParseResult<CharNode, &str> {

        fn newline(input: State<&str>) -> ParseResult<char, &str> {
                try(string("newline"))
                    .or(try(string("linefeed")))
                    .map(|_| '\n')
                    .parse_state(input)
            }

        fn tab(input: State<&str>) -> ParseResult<char, &str> {
                try(string("tab")).map(|_| '\t').parse_state(input)
            }

        fn nul(input: State<&str>) -> ParseResult<char, &str> {
                try(string("nul"))
                    .map(|_| char::from_u32(0x0000).unwrap())
                    .parse_state(input)
            }

        fn backspace(input: State<&str>) -> ParseResult<char, &str> {
                try(string("backspace"))
                    .map(|_| char::from_u32(0x0008).unwrap())
                    .parse_state(input)
            }

        fn vtab(input: State<&str>) -> ParseResult<char, &str> {
                try(string("vtab"))
                    .map(|_| char::from_u32(0x000B).unwrap())
                    .parse_state(input)
            }

        fn page(input: State<&str>) -> ParseResult<char, &str> {
                try(string("page"))
                    .map(|_| char::from_u32(0x000C).unwrap())
                    .parse_state(input)
            }

        fn retn(input: State<&str>) -> ParseResult<char, &str> {
                try(string("return"))
                    .map(|_| char::from_u32(0x000D).unwrap())
                    .parse_state(input)
            }

        fn esc(input: State<&str>) -> ParseResult<char, &str> {
                try(string("esc"))
                    .map(|_| char::from_u32(0x001B).unwrap())
                    .parse_state(input)
            }

        fn delete(input: State<&str>) -> ParseResult<char, &str> {
                try(string("delete"))
                    .map(|_| char::from_u32(0x007F).unwrap())
                    .parse_state(input)
            }

        fn alarm(input: State<&str>) -> ParseResult<char, &str> {
                try(string("alarm"))
                    .map(|_| char::from_u32(0x0007).unwrap())
                    .parse_state(input)
            }

        fn space(input: State<&str>) -> ParseResult<char, &str> {
                try(string("space"))
                    .map(|_| char::from_u32(0x0020).unwrap())
                    .parse_state(input)
            }

        fn char_name(input: State<&str>) -> ParseResult<char, &str> {
                parser(newline)
                    .or(parser(tab))
                    .or(parser(vtab))
                    .or(parser(backspace))
                    .or(parser(nul))
                    .or(parser(page))
                    .or(parser(retn))
                    .or(parser(esc))
                    .or(parser(delete))
                    .or(parser(alarm))
                    .or(parser(space))
                    .parse_state(input)
            }

        fn hex_char(input: State<&str>) -> ParseResult<char, &str> {
                satisfy(|c| c == 'x')
                    .with(many1::<Vec<_>, _>(hex_digit()))
                    .map(|x| {
                        char::from_u32(
                            u32::from_str_radix(
                                x.iter()
                                 .fold(
                                    String::new(),
                                    |mut s: String, i| { s.push(*i); s })
                                 .as_slice(),
                            16).unwrap()
                        ).unwrap()
                    })
                    .parse_state(input)
            }

        string("#\\")
            .with(
                parser(char_name)
                .or(parser(hex_char))
                .or(parser(any_char))
            ).map(|c| CharNode { value: c})
            .parse_state(input)

}

/// Parses Scheme expressions.
#[allow(unconditional_recursion)]
pub fn expr(input: State<&str>) -> ParseResult<ExprNode, &str> {
        let spaces = spaces();

        fn sexpr(input: State<&str>) -> ParseResult<ExprNode, &str> {
                between(
                    satisfy(|c| c == '('),
                    satisfy(|c| c == ')'),
                    parser(name)
                        .and(many(parser(expr)))
                        .map(|x| {
                            SExpr(SExprNode {
                                operator: x.0,
                                operands: x.1
                            })
                        })
                ).parse_state(input)
            }

        fn list(input: State<&str>) -> ParseResult<ExprNode, &str>{
                between(
                    satisfy(|c| c == '('),
                    satisfy(|c| c == ')'),
                    many(parser(expr))
                        .map(|x| {
                            ListConst(ListNode {
                                elements: x
                            })
                        })
                ).parse_state(input)
            }

        spaces.clone().with(
            try(parser(sexpr))
                .or(try(parser(list)))
                .or(try(parser(name).map(Name)))
                .or(try(parser(number).map(NumConst)))
            ).parse_state(input)
}

#[cfg(test)]
mod tests;<|endoftext|>


<commit_before>// xfail-test - this isn't really a test.

 {

// select!
macro_rules! select_if (

    {
        $index:expr,
        $count:expr
    } => {
        fail
    };

    {
        $index:expr,
        $count:expr,
        $port:path => [
            $(type_this $message:path$(($(x $x: ident),+))dont_type_this*
              -> $next:ident => { $e:expr }),+
        ]
        $(, $ports:path => [
            $(type_this $messages:path$(($(x $xs: ident),+))dont_type_this*
              -> $nexts:ident => { $es:expr }),+
        ] )*
    } => {
        if $index == $count {
            match move pipes::try_recv($port) {
              $(Some($message($($(ref $x,)+)* move next)) => {
                let $next = next;
                $e
              })+
              _ => fail
            }
        } else {
            select_if!(
                $index,
                $count + 1
                $(, $ports => [
                    $(type_this $messages$(($(x $xs),+))dont_type_this*
                      -> $nexts => { $es }),+
                ])*
            )
        }
    };
)

macro_rules! select (
    {
        $( $port:path => {
            $($message:path$(($($x: ident),+))dont_type_this*
              -> $next:ident $e:expr),+
        } )+
    } => {
        let index = pipes::selecti([$(($port).header()),+]/_);
        select_if!(index, 0 $(, $port => [
            $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { $e }),+
        ])+)
    }
)

}
<commit_msg>Use move instead of ref in select-macro<commit_after>// xfail-test - this isn't really a test.

 {

// select!
macro_rules! select_if (

    {
        $index:expr,
        $count:expr
    } => {
        fail
    };

    {
        $index:expr,
        $count:expr,
        $port:path => [
            $(type_this $message:path$(($(x $x: ident),+))dont_type_this*
              -> $next:ident => { $e:expr }),+
        ]
        $(, $ports:path => [
            $(type_this $messages:path$(($(x $xs: ident),+))dont_type_this*
              -> $nexts:ident => { $es:expr }),+
        ] )*
    } => {
        if $index == $count {
            match move pipes::try_recv($port) {
              $(Some($message($($(move $x,)+)* move next)) => {
                let $next = next;
                $e
              })+
              _ => fail
            }
        } else {
            select_if!(
                $index,
                $count + 1
                $(, $ports => [
                    $(type_this $messages$(($(x $xs),+))dont_type_this*
                      -> $nexts => { $es }),+
                ])*
            )
        }
    };
)

macro_rules! select (
    {
        $( $port:path => {
            $($message:path$(($($x: ident),+))dont_type_this*
              -> $next:ident $e:expr),+
        } )+
    } => {
        let index = pipes::selecti([$(($port).header()),+]/_);
        select_if!(index, 0 $(, $port => [
            $(type_this $message$(($(x $x),+))dont_type_this* -> $next => { $e }),+
        ])+)
    }
)

}
<|endoftext|>


<commit_before>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], A superset of JSON including some productions from ES5.
//! - [URL], the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//! - [Postcard], a `no_std` and embedded-systems friendly compact binary format.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html
//! [Postcard]: https://github.com/jamesmunns/postcard

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.100")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // not available in our oldest supported compiler
        checked_conversions,
        empty_enum,
        redundant_field_names,
        redundant_static_lifetimes,
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // not practical
        needless_pass_by_value,
        similar_names,
        // preference
        doc_markdown,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", collections_bound))]
    pub use std::collections::Bound;

    #[cfg(core_reverse)]
    pub use self::core::cmp::Reverse;

    #[cfg(ops_bound)]
    pub use self::core::ops::Bound;

    #[cfg(range_inclusive)]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", std_atomic))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", std_atomic64))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<commit_msg>Sort Postcard in the same order as on the website<commit_after>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], A superset of JSON including some productions from ES5.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [URL], the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://github.com/nox/serde_urlencoded
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.100")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // not available in our oldest supported compiler
        checked_conversions,
        empty_enum,
        redundant_field_names,
        redundant_static_lifetimes,
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // not practical
        needless_pass_by_value,
        similar_names,
        // preference
        doc_markdown,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", collections_bound))]
    pub use std::collections::Bound;

    #[cfg(core_reverse)]
    pub use self::core::cmp::Reverse;

    #[cfg(ops_bound)]
    pub use self::core::ops::Bound;

    #[cfg(range_inclusive)]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", std_atomic))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", std_atomic64))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<|endoftext|>


<commit_before>//! HIR (previously known as descriptors) provides a high-level object oriented
//! access to Rust code.
//!
//! The principal difference between HIR and syntax trees is that HIR is bound
//! to a particular crate instance. That is, it has cfg flags and features
//! applied. So, the relation between syntax and HIR is many-to-one.
//!
//! HIR is the public API of the all of the compiler logic above syntax trees.
//! It is written in "OO" style. Each type is self contained (as in, it knows it's
//! parents and full context). It should be "clean code".
//!
//! `ra_hir_*` crates are the implementation of the compiler logic.
//! They are written in "ECS" style, with relatively little abstractions.
//! Many types are not self-contained, and explicitelly use local indexes, arenas, etc.
//!
//! `ra_hir` is what insulates the "we don't know how to actually write an incremental compiler"
//! from the ide with completions, hovers, etc. It is a (soft, internal) boundary:
//! https://www.tedinski.com/2018/02/06/system-boundaries.html.

#![recursion_limit = "512"]

macro_rules! impl_froms {
    ($e:ident: $($v:ident $(($($sv:ident),*))?),*$(,)?) => {
        $(
            impl From<$v> for $e {
                fn from(it: $v) -> $e {
                    $e::$v(it)
                }
            }
            $($(
                impl From<$sv> for $e {
                    fn from(it: $sv) -> $e {
                        $e::$v($v::$sv(it))
                    }
                }
            )*)?
        )*
    }
}

mod semantics;
pub mod db;
mod source_analyzer;

pub mod diagnostics;

mod from_id;
mod code_model;

mod has_source;

pub use crate::{
    code_model::{
        Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, CrateDependency,
        DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, HasAttrs,
        HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct,
        StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef,
    },
    has_source::HasSource,
    semantics::{original_range, PathResolution, Semantics, SemanticsScope},
};

pub use hir_def::{
    adt::StructKind,
    body::scope::ExprScopes,
    builtin_type::BuiltinType,
    docs::Documentation,
    nameres::ModuleSource,
    path::{ModPath, Path, PathKind},
    type_ref::Mutability,
};
pub use hir_expand::{
    name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin,
};
pub use hir_ty::{display::HirDisplay, CallableDef};
<commit_msg>ra_hir: fix typo<commit_after>//! HIR (previously known as descriptors) provides a high-level object oriented
//! access to Rust code.
//!
//! The principal difference between HIR and syntax trees is that HIR is bound
//! to a particular crate instance. That is, it has cfg flags and features
//! applied. So, the relation between syntax and HIR is many-to-one.
//!
//! HIR is the public API of the all of the compiler logic above syntax trees.
//! It is written in "OO" style. Each type is self contained (as in, it knows it's
//! parents and full context). It should be "clean code".
//!
//! `ra_hir_*` crates are the implementation of the compiler logic.
//! They are written in "ECS" style, with relatively little abstractions.
//! Many types are not self-contained, and explicitly use local indexes, arenas, etc.
//!
//! `ra_hir` is what insulates the "we don't know how to actually write an incremental compiler"
//! from the ide with completions, hovers, etc. It is a (soft, internal) boundary:
//! https://www.tedinski.com/2018/02/06/system-boundaries.html.

#![recursion_limit = "512"]

macro_rules! impl_froms {
    ($e:ident: $($v:ident $(($($sv:ident),*))?),*$(,)?) => {
        $(
            impl From<$v> for $e {
                fn from(it: $v) -> $e {
                    $e::$v(it)
                }
            }
            $($(
                impl From<$sv> for $e {
                    fn from(it: $sv) -> $e {
                        $e::$v($v::$sv(it))
                    }
                }
            )*)?
        )*
    }
}

mod semantics;
pub mod db;
mod source_analyzer;

pub mod diagnostics;

mod from_id;
mod code_model;

mod has_source;

pub use crate::{
    code_model::{
        Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Const, Crate, CrateDependency,
        DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, HasAttrs,
        HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct,
        StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef,
    },
    has_source::HasSource,
    semantics::{original_range, PathResolution, Semantics, SemanticsScope},
};

pub use hir_def::{
    adt::StructKind,
    body::scope::ExprScopes,
    builtin_type::BuiltinType,
    docs::Documentation,
    nameres::ModuleSource,
    path::{ModPath, Path, PathKind},
    type_ref::Mutability,
};
pub use hir_expand::{
    name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin,
};
pub use hir_ty::{display::HirDisplay, CallableDef};
<|endoftext|>


<commit_before>//! `mbe` (short for Macro By Example) crate contains code for handling
//! `macro_rules` macros. It uses `TokenTree` (from `ra_tt` package) as the
//! interface, although it contains some code to bridge `SyntaxNode`s and
//! `TokenTree`s as well!

mod parser;
mod mbe_expander;
mod syntax_bridge;
mod tt_iter;
mod subtree_source;

pub use tt::{Delimiter, Punct};

use crate::{
    parser::{parse_pattern, Op},
    tt_iter::TtIter,
};

#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
    Expected(String),
}

#[derive(Debug, PartialEq, Eq)]
pub enum ExpandError {
    NoMatchingRule,
    UnexpectedToken,
    BindingError(String),
    ConversionError,
    InvalidRepeat,
}

pub use crate::syntax_bridge::{
    ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_items,
    token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty,
};

/// This struct contains AST for a single `macro_rules` definition. What might
/// be very confusing is that AST has almost exactly the same shape as
/// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
/// and `$()*` have special meaning (see `Var` and `Repeat` data structures)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MacroRules {
    pub(crate) rules: Vec<Rule>,
    /// Highest id of the token we have in TokenMap
    pub(crate) shift: Option<u32>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct Rule {
    pub(crate) lhs: tt::Subtree,
    pub(crate) rhs: tt::Subtree,
}

/// Find the "shift" (the highest id of the TokenId) inside a subtree
fn find_subtree_shift(tt: &tt::Subtree, mut cur: Option<u32>) -> Option<u32> {
    use std::cmp::max;

    for t in &tt.token_trees {
        cur = match t {
            tt::TokenTree::Leaf(leaf) => match leaf {
                tt::Leaf::Ident(ident) if ident.id != tt::TokenId::unspecified() => {
                    Some(max(cur.unwrap_or(0), ident.id.0))
                }
                _ => cur,
            },
            tt::TokenTree::Subtree(tt) => find_subtree_shift(tt, cur),
        }
    }

    cur
}

/// Shift given TokenTree token id
fn shift_subtree(tt: &mut tt::Subtree, shift: u32) {
    for t in tt.token_trees.iter_mut() {
        match t {
            tt::TokenTree::Leaf(leaf) => match leaf {
                tt::Leaf::Ident(ident) if ident.id != tt::TokenId::unspecified() => {
                    // Note that TokenId is started from zero,
                    // We have to add 1 to prevent duplication.
                    ident.id.0 += shift + 1;
                }
                _ => (),
            },
            tt::TokenTree::Subtree(tt) => shift_subtree(tt, shift),
        }
    }
}

impl MacroRules {
    pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
        // Note: this parsing can be implemented using mbe machinery itself, by
        // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
        // manually seems easier.
        let mut src = TtIter::new(tt);
        let mut rules = Vec::new();
        while src.len() > 0 {
            let rule = Rule::parse(&mut src)?;
            rules.push(rule);
            if let Err(()) = src.expect_char(';') {
                if src.len() > 0 {
                    return Err(ParseError::Expected("expected `:`".to_string()));
                }
                break;
            }
        }

        for rule in rules.iter() {
            validate(&rule.lhs)?;
        }

        Ok(MacroRules { rules, shift: find_subtree_shift(tt, None) })
    }

    pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> {
        // apply shift
        let mut tt = tt.clone();
        if let Some(shift) = self.shift {
            shift_subtree(&mut tt, shift)
        }

        mbe_expander::expand(self, &tt)
    }
}

impl Rule {
    fn parse(src: &mut TtIter) -> Result<Rule, ParseError> {
        let mut lhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
            .clone();
        lhs.delimiter = tt::Delimiter::None;
        src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?;
        src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?;
        let mut rhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
            .clone();
        rhs.delimiter = tt::Delimiter::None;
        Ok(crate::Rule { lhs, rhs })
    }
}

fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
    for op in parse_pattern(pattern) {
        let op = match op {
            Ok(it) => it,
            Err(e) => {
                let msg = match e {
                    ExpandError::InvalidRepeat => "invalid repeat".to_string(),
                    _ => "invalid macro definition".to_string(),
                };
                return Err(ParseError::Expected(msg));
            }
        };
        match op {
            Op::TokenTree(tt::TokenTree::Subtree(subtree)) | Op::Repeat { subtree, .. } => {
                validate(subtree)?
            }
            _ => (),
        }
    }
    Ok(())
}

#[cfg(test)]
mod tests;
<commit_msg>Change Option<u32> to u32 for shift value<commit_after>//! `mbe` (short for Macro By Example) crate contains code for handling
//! `macro_rules` macros. It uses `TokenTree` (from `ra_tt` package) as the
//! interface, although it contains some code to bridge `SyntaxNode`s and
//! `TokenTree`s as well!

mod parser;
mod mbe_expander;
mod syntax_bridge;
mod tt_iter;
mod subtree_source;

pub use tt::{Delimiter, Punct};

use crate::{
    parser::{parse_pattern, Op},
    tt_iter::TtIter,
};

#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
    Expected(String),
}

#[derive(Debug, PartialEq, Eq)]
pub enum ExpandError {
    NoMatchingRule,
    UnexpectedToken,
    BindingError(String),
    ConversionError,
    InvalidRepeat,
}

pub use crate::syntax_bridge::{
    ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_items,
    token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty,
};

/// This struct contains AST for a single `macro_rules` definition. What might
/// be very confusing is that AST has almost exactly the same shape as
/// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
/// and `$()*` have special meaning (see `Var` and `Repeat` data structures)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MacroRules {
    pub(crate) rules: Vec<Rule>,
    /// Highest id of the token we have in TokenMap
    pub(crate) shift: u32,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct Rule {
    pub(crate) lhs: tt::Subtree,
    pub(crate) rhs: tt::Subtree,
}

/// Find the "shift" (the highest id of the TokenId) inside a subtree
fn find_subtree_shift(tt: &tt::Subtree, mut cur: u32) -> u32 {
    use std::cmp::max;

    for t in &tt.token_trees {
        cur = match t {
            tt::TokenTree::Leaf(leaf) => match leaf {
                tt::Leaf::Ident(ident) if ident.id != tt::TokenId::unspecified() => {
                    max(cur, ident.id.0)
                }
                _ => cur,
            },
            tt::TokenTree::Subtree(tt) => find_subtree_shift(tt, cur),
        }
    }

    cur
}

/// Shift given TokenTree token id
fn shift_subtree(tt: &mut tt::Subtree, shift: u32) {
    for t in tt.token_trees.iter_mut() {
        match t {
            tt::TokenTree::Leaf(leaf) => match leaf {
                tt::Leaf::Ident(ident) if ident.id != tt::TokenId::unspecified() => {
                    // Note that TokenId is started from zero,
                    // We have to add 1 to prevent duplication.
                    ident.id.0 += shift + 1;
                }
                _ => (),
            },
            tt::TokenTree::Subtree(tt) => shift_subtree(tt, shift),
        }
    }
}

impl MacroRules {
    pub fn parse(tt: &tt::Subtree) -> Result<MacroRules, ParseError> {
        // Note: this parsing can be implemented using mbe machinery itself, by
        // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
        // manually seems easier.
        let mut src = TtIter::new(tt);
        let mut rules = Vec::new();
        while src.len() > 0 {
            let rule = Rule::parse(&mut src)?;
            rules.push(rule);
            if let Err(()) = src.expect_char(';') {
                if src.len() > 0 {
                    return Err(ParseError::Expected("expected `:`".to_string()));
                }
                break;
            }
        }

        for rule in rules.iter() {
            validate(&rule.lhs)?;
        }

        Ok(MacroRules { rules, shift: find_subtree_shift(tt, 0) })
    }

    pub fn expand(&self, tt: &tt::Subtree) -> Result<tt::Subtree, ExpandError> {
        // apply shift
        let mut tt = tt.clone();
        shift_subtree(&mut tt, self.shift);
        mbe_expander::expand(self, &tt)
    }
}

impl Rule {
    fn parse(src: &mut TtIter) -> Result<Rule, ParseError> {
        let mut lhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
            .clone();
        lhs.delimiter = tt::Delimiter::None;
        src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?;
        src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?;
        let mut rhs = src
            .expect_subtree()
            .map_err(|()| ParseError::Expected("expected subtree".to_string()))?
            .clone();
        rhs.delimiter = tt::Delimiter::None;
        Ok(crate::Rule { lhs, rhs })
    }
}

fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
    for op in parse_pattern(pattern) {
        let op = match op {
            Ok(it) => it,
            Err(e) => {
                let msg = match e {
                    ExpandError::InvalidRepeat => "invalid repeat".to_string(),
                    _ => "invalid macro definition".to_string(),
                };
                return Err(ParseError::Expected(msg));
            }
        };
        match op {
            Op::TokenTree(tt::TokenTree::Subtree(subtree)) | Op::Repeat { subtree, .. } => {
                validate(subtree)?
            }
            _ => (),
        }
    }
    Ok(())
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>use iron::prelude::*;
use iron::Handler;
use iron::status::{self, Status};

use hyper::header::ContentType;
use hyper::mime;

use controller::Reservation;

// Re-export Logger and Router so you can use redstart::Router instead of redstart::router::Router.
pub use self::logger::Logger;
pub use self::urlparser::{URLParser, URL};
pub use self::cookieparser::CookieParser;
pub use self::configreader::ConfigReader;
pub use self::authentication::Authentication as Auth;
pub use self::session::{Session, Store, SessionStore};
//pub use self::authentication::Authentication::API as AuthAPI;

mod logger;
mod urlparser;
mod cookieparser;
mod permission;
mod configreader;
mod authentication;
mod session;
// End Re-export

pub struct RedStart;

#[allow(unused_variables)]
impl Handler for RedStart
{
    fn handle(&self, req: &mut Request) -> IronResult<Response>
    {
        let controller_string: String;
        let model_string: String;
        {
            let ext_url: &mut [String] = req.extensions.get_mut::<URL>().unwrap(); // If this panics, URLParser has a bug! :D
            controller_string = ext_url[0].clone();
            model_string = ext_url[1].clone();
        }
        let controller: &str = controller_string.as_slice();
        let model: &str = model_string.as_slice();

        let session_key: Option<String>;
        if req.extensions.contains::<Session>()
        {
            let ext_session: &mut String = req.extensions.get_mut::<Session>().unwrap();
            session_key = Some(ext_session.clone());
        }
        else
        {
            session_key = None;
        }

        let reservation = Reservation::new();

        let status: Status;
        let body: Box<Reader + Send>;
        let (status, body) = match controller
        {
            "reservation" => { reservation.call(model, req) },
            _ =>
            {
                (status::NotFound, "".to_string())
            },
        };

        let mime: mime::Mime = "application/json".parse().unwrap();
        let mut res = Response::new();
        res.headers.set(ContentType(mime));
        Ok(res.set(status).set(body))
    }
}

<commit_msg>Removed Configreader mod and use statements in redstart/mod.rs<commit_after>use iron::prelude::*;
use iron::Handler;
use iron::status::{self, Status};

use hyper::header::ContentType;
use hyper::mime;

use controller::Reservation;

// Re-export Logger and Router so you can use redstart::Router instead of redstart::router::Router.
pub use self::logger::Logger;
pub use self::urlparser::{URLParser, URL};
pub use self::cookieparser::CookieParser;
pub use self::authentication::Authentication as Auth;
pub use self::session::{Session, Store, SessionStore};
//pub use self::authentication::Authentication::API as AuthAPI;

mod logger;
mod urlparser;
mod cookieparser;
mod permission;
mod authentication;
mod session;
// End Re-export

pub struct RedStart;

#[allow(unused_variables)]
impl Handler for RedStart
{
    fn handle(&self, req: &mut Request) -> IronResult<Response>
    {
        let controller_string: String;
        let model_string: String;
        {
            let ext_url: &mut [String] = req.extensions.get_mut::<URL>().unwrap(); // If this panics, URLParser has a bug! :D
            controller_string = ext_url[0].clone();
            model_string = ext_url[1].clone();
        }
        let controller: &str = controller_string.as_slice();
        let model: &str = model_string.as_slice();

        let session_key: Option<String>;
        if req.extensions.contains::<Session>()
        {
            let ext_session: &mut String = req.extensions.get_mut::<Session>().unwrap();
            session_key = Some(ext_session.clone());
        }
        else
        {
            session_key = None;
        }

        let reservation = Reservation::new();

        let status: Status;
        let body: Box<Reader + Send>;
        let (status, body) = match controller
        {
            "reservation" => { reservation.call(model, req) },
            _ =>
            {
                (status::NotFound, "".to_string())
            },
        };

        let mime: mime::Mime = "application/json".parse().unwrap();
        let mut res = Response::new();
        res.headers.set(ContentType(mime));
        Ok(res.set(status).set(body))
    }
}

<|endoftext|>


<commit_before>#[macro_use]
mod macros;

use internal::IResult;
use error::ParseError;

pub fn pair<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, (O1, O2), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    second(input).map(|(i, o2)| (i, (o1, o2)))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn pairc<I, O1, O2, E: ParseError<I>, F, G>(input: I, first: F, second: G) -> IResult<I, (O1, O2), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  pair(first, second)(input)
}

pub fn preceded<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  move |input: I| {
    let (input, _) = first(input)?;
    second(input)
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn precededc<I, O1, O2, E: ParseError<I>, F, G>(input: I, first: F, second: G) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  preceded(first, second)(input)
}

pub fn terminated<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O1, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    second(input).map(|(i, _)| (i, o1))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn terminatedc<I, O1, O2, E: ParseError<I>, F, G>(input: I, first: F, second: G) -> IResult<I, O1, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  terminated(first, second)(input)
}

pub fn separated_pair<I, O1, O2, O3, E: ParseError<I>, F, G, H>(first: F, sep: G, second: H) -> impl Fn(I) -> IResult<I, (O1, O3), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    let (input, _) = sep(input)?;
    second(input).map(|(i, o2)| (i, (o1, o2)))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn separated_pairc<I, O1, O2, O3, E: ParseError<I>, F, G, H>(input: I, first: F, sep: G, second: H) -> IResult<I, (O1, O3), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  separated_pair(first, sep, second)(input)
}

pub fn delimited<I, O1, O2, O3, E: ParseError<I>, F, G, H>(first: F, sep: G, second: H) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  move |input: I| {
    let (input, _) = first(input)?;
    let (input, o2) = sep(input)?;
    second(input).map(|(i, _)| (i, o2))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn delimitedc<I, O1, O2, O3, E: ParseError<I>, F, G, H>(input: I, first: F, sep: G, second: H) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  delimited(first, sep, second)(input)
}

pub trait Tuple<I,O,E> {
  fn parse(&self, input: I) -> IResult<I,O,E>;
}

macro_rules! tuple_parser(
  ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
    tuple_parser!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
    tuple_impl!($($name $ty),+);
    tuple_parser!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
    tuple_impl!($($name $ty),+);
    tuple_impl!($($name $ty),+, $name1 $ty1);
  );
);

macro_rules! tuple_impl(
  ($($name:ident $ty: ident),+) => (
    impl<
      Input: Clone, $($ty),+ , Error: ParseError<Input>,
      $($name: Fn(Input) -> IResult<Input, $ty, Error>),+
    > Tuple<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {

      fn parse(&self, input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
        tuple_inner!(0, self, input, (), $($name)+)

      }
    }
  );
);

macro_rules! tuple_inner(
  ($it:tt, $self:expr, $input:expr, (), $head:ident $($id:ident)+) => ({
    let (i, o) = acc!($it, $self)($input.clone())?;

    succ!($it, tuple_inner!($self, i, ( o ), $($id)+))
  });
  ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident $($id:ident)+) => ({
    let (i, o) = acc!($it, $self)($input.clone())?;

    succ!($it, tuple_inner!($self, i, ($($parsed)* , o), $($id)+))
  });
  ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident) => ({
    let (i, o) = acc!($it, $self)($input.clone())?;

    Ok((i, ($($parsed)* , o)))
  });
);

tuple_parser!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L,
  FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);

pub fn tuple<I: Clone, O, E: ParseError<I>, List: Tuple<I,O,E>>(l: List)  -> impl Fn(I) -> IResult<I, O, E> {
  move |i: I| {
    l.parse(i)
  }
}
<commit_msg>avoid macro name collisions<commit_after>#[macro_use]
mod macros;

use internal::IResult;
use error::ParseError;

pub fn pair<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, (O1, O2), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    second(input).map(|(i, o2)| (i, (o1, o2)))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn pairc<I, O1, O2, E: ParseError<I>, F, G>(input: I, first: F, second: G) -> IResult<I, (O1, O2), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  pair(first, second)(input)
}

pub fn preceded<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  move |input: I| {
    let (input, _) = first(input)?;
    second(input)
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn precededc<I, O1, O2, E: ParseError<I>, F, G>(input: I, first: F, second: G) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  preceded(first, second)(input)
}

pub fn terminated<I, O1, O2, E: ParseError<I>, F, G>(first: F, second: G) -> impl Fn(I) -> IResult<I, O1, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    second(input).map(|(i, _)| (i, o1))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn terminatedc<I, O1, O2, E: ParseError<I>, F, G>(input: I, first: F, second: G) -> IResult<I, O1, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
{
  terminated(first, second)(input)
}

pub fn separated_pair<I, O1, O2, O3, E: ParseError<I>, F, G, H>(first: F, sep: G, second: H) -> impl Fn(I) -> IResult<I, (O1, O3), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  move |input: I| {
    let (input, o1) = first(input)?;
    let (input, _) = sep(input)?;
    second(input).map(|(i, o2)| (i, (o1, o2)))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn separated_pairc<I, O1, O2, O3, E: ParseError<I>, F, G, H>(input: I, first: F, sep: G, second: H) -> IResult<I, (O1, O3), E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  separated_pair(first, sep, second)(input)
}

pub fn delimited<I, O1, O2, O3, E: ParseError<I>, F, G, H>(first: F, sep: G, second: H) -> impl Fn(I) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  move |input: I| {
    let (input, _) = first(input)?;
    let (input, o2) = sep(input)?;
    second(input).map(|(i, _)| (i, o2))
  }
}

// this implementation is used for type inference issues in macros
#[doc(hidden)]
pub fn delimitedc<I, O1, O2, O3, E: ParseError<I>, F, G, H>(input: I, first: F, sep: G, second: H) -> IResult<I, O2, E>
where
  F: Fn(I) -> IResult<I, O1, E>,
  G: Fn(I) -> IResult<I, O2, E>,
  H: Fn(I) -> IResult<I, O3, E>,
{
  delimited(first, sep, second)(input)
}

pub trait Tuple<I,O,E> {
  fn parse(&self, input: I) -> IResult<I,O,E>;
}

macro_rules! tuple_trait(
  ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
    tuple_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
    tuple_trait_impl!($($name $ty),+);
    tuple_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
  );
  (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
    tuple_trait_impl!($($name $ty),+);
    tuple_trait_impl!($($name $ty),+, $name1 $ty1);
  );
);

macro_rules! tuple_trait_impl(
  ($($name:ident $ty: ident),+) => (
    impl<
      Input: Clone, $($ty),+ , Error: ParseError<Input>,
      $($name: Fn(Input) -> IResult<Input, $ty, Error>),+
    > Tuple<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {

      fn parse(&self, input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
        tuple_trait_inner!(0, self, input, (), $($name)+)

      }
    }
  );
);

macro_rules! tuple_trait_inner(
  ($it:tt, $self:expr, $input:expr, (), $head:ident $($id:ident)+) => ({
    let (i, o) = acc!($it, $self)($input.clone())?;

    succ!($it, tuple_trait_inner!($self, i, ( o ), $($id)+))
  });
  ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident $($id:ident)+) => ({
    let (i, o) = acc!($it, $self)($input.clone())?;

    succ!($it, tuple_trait_inner!($self, i, ($($parsed)* , o), $($id)+))
  });
  ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident) => ({
    let (i, o) = acc!($it, $self)($input.clone())?;

    Ok((i, ($($parsed)* , o)))
  });
);

tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L,
  FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);

pub fn tuple<I: Clone, O, E: ParseError<I>, List: Tuple<I,O,E>>(l: List)  -> impl Fn(I) -> IResult<I, O, E> {
  move |i: I| {
    l.parse(i)
  }
}
<|endoftext|>


<commit_before>use std::str::FromStr;

/// A hashing algorithm.
///
/// # Examples
///
/// ```
/// # use std::str::FromStr;
/// assert_eq!(checksums::Algorithm::from_str("SHA1"), Ok(checksums::Algorithm::SHA1));
/// assert_eq!(checksums::Algorithm::from_str("SHA-1"), Ok(checksums::Algorithm::SHA1));
///
/// assert_eq!(checksums::Algorithm::from_str("SHA2"), Ok(checksums::Algorithm::SHA2512));
/// assert_eq!(checksums::Algorithm::from_str("SHA-2"), Ok(checksums::Algorithm::SHA2512));
///
/// assert_eq!(checksums::Algorithm::from_str("BLAKE"), Ok(checksums::Algorithm::BLAKE));
/// assert_eq!(checksums::Algorithm::from_str("BLAKE2"), Ok(checksums::Algorithm::BLAKE2));
///
/// assert_eq!(checksums::Algorithm::from_str("MD5"), Ok(checksums::Algorithm::MD5));
/// ```
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Algorithm {
    SHA1,
    /// SHA2-256
    SHA2256,
    /// SHA2-512
    SHA2512,
    /// SHA3-256
    SHA3256,
    /// SHA3-512
    SHA3512,
    BLAKE,
    BLAKE2,
    CRC64,
    CRC32,
    CRC16,
    CRC8,
    MD5,
    /// MD6-128
    MD6128,
    /// MD6-256
    MD6256,
    /// MD6-512
    MD6512,
    XOR8,
}

impl Algorithm {
    /// Length, in bytes, of the algorithm's output hex string
    pub fn hexlen(&self) -> usize {
        match *self {
            Algorithm::XOR8 | Algorithm::CRC8 => 2,
            Algorithm::CRC16 => 4,
            Algorithm::CRC32 => 8,
            Algorithm::CRC64 => 16,
            Algorithm::MD5 |
            Algorithm::MD6128 => 32,
            Algorithm::SHA1 => 40,
            Algorithm::SHA2256 |
            Algorithm::SHA3256 |
            Algorithm::MD6256 => 64,
            Algorithm::SHA2512 |
            Algorithm::SHA3512 |
            Algorithm::BLAKE |
            Algorithm::BLAKE2 |
            Algorithm::MD6512 => 128,
        }
    }
}

impl FromStr for Algorithm {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "SHA1" | "SHA-1" | "sha1" => Ok(Algorithm::SHA1),
            "SHA2256" | "SHA2-256" | "SHA-2-256" | "SHA2_256" | "SHA-2_256" | "SHA_2-256" | "SHA_2_256" | "sha2256" | "sha2-256" | "sha2_256" => {
                Ok(Algorithm::SHA2256)
            }
            "SHA2" | "SHA-2" | "sha2" | "SHA2512" | "SHA2-512" | "SHA-2-512" | "SHA2_512" | "SHA-2_512" | "SHA_2-512" | "SHA_2_512" | "sha2512" |
            "sha2-512" | "sha2_512" => Ok(Algorithm::SHA2512),
            "SHA3256" | "SHA3-256" | "SHA-3-256" | "SHA3_256" | "SHA-3_256" | "SHA_3-256" | "SHA_3_256" | "sha3256" | "sha3-256" | "sha3_256" => {
                Ok(Algorithm::SHA3256)
            }
            "SHA3" | "SHA-3" | "sha3" | "SHA3512" | "SHA3-512" | "SHA-3-512" | "SHA3_512" | "SHA-3_512" | "SHA_3-512" | "SHA_3_512" | "sha3512" |
            "sha3-512" | "sha3_512" => Ok(Algorithm::SHA3512),
            "BLAKE" | "blake" => Ok(Algorithm::BLAKE),
            "BLAKE2" | "blake2" => Ok(Algorithm::BLAKE2),
            "CRC64" | "crc64" => Ok(Algorithm::CRC64),
            "CRC32" | "crc32" => Ok(Algorithm::CRC32),
            "CRC16" | "crc16" => Ok(Algorithm::CRC16),
            "CRC8" | "crc8" => Ok(Algorithm::CRC8),
            "MD5" | "md5" => Ok(Algorithm::MD5),
            "MD6128" | "MD6-128" | "MD6_128" | "md6128" | "md6-128" | "md6_128" => Ok(Algorithm::MD6128),
            "MD6256" | "MD6-256" | "MD6_256" | "md6256" | "md6-256" | "md6_256" => Ok(Algorithm::MD6256),
            "MD6512" | "MD6-512" | "MD6_512" | "md6512" | "md6-512" | "md6_512" => Ok(Algorithm::MD6512),
            "XOR8" | "xor8" => Ok(Algorithm::XOR8),
            _ => Err(format!("\"{}\" is not a recognised compression algorithm", s)),
        }
    }
}
<commit_msg>Simplify Algorithm::from_str()<commit_after>use std::str::FromStr;

/// A hashing algorithm.
///
/// # Examples
///
/// ```
/// # use std::str::FromStr;
/// assert_eq!(checksums::Algorithm::from_str("SHA1"), Ok(checksums::Algorithm::SHA1));
/// assert_eq!(checksums::Algorithm::from_str("SHA-1"), Ok(checksums::Algorithm::SHA1));
///
/// assert_eq!(checksums::Algorithm::from_str("SHA2"), Ok(checksums::Algorithm::SHA2512));
/// assert_eq!(checksums::Algorithm::from_str("SHA-2"), Ok(checksums::Algorithm::SHA2512));
///
/// assert_eq!(checksums::Algorithm::from_str("BLAKE"), Ok(checksums::Algorithm::BLAKE));
/// assert_eq!(checksums::Algorithm::from_str("BLAKE2"), Ok(checksums::Algorithm::BLAKE2));
///
/// assert_eq!(checksums::Algorithm::from_str("MD5"), Ok(checksums::Algorithm::MD5));
/// ```
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Algorithm {
    SHA1,
    /// SHA2-256
    SHA2256,
    /// SHA2-512
    SHA2512,
    /// SHA3-256
    SHA3256,
    /// SHA3-512
    SHA3512,
    BLAKE,
    BLAKE2,
    CRC64,
    CRC32,
    CRC16,
    CRC8,
    MD5,
    /// MD6-128
    MD6128,
    /// MD6-256
    MD6256,
    /// MD6-512
    MD6512,
    XOR8,
}

impl Algorithm {
    /// Length, in bytes, of the algorithm's output hex string
    pub fn hexlen(&self) -> usize {
        match *self {
            Algorithm::XOR8 | Algorithm::CRC8 => 2,
            Algorithm::CRC16 => 4,
            Algorithm::CRC32 => 8,
            Algorithm::CRC64 => 16,
            Algorithm::MD5 |
            Algorithm::MD6128 => 32,
            Algorithm::SHA1 => 40,
            Algorithm::SHA2256 |
            Algorithm::SHA3256 |
            Algorithm::MD6256 => 64,
            Algorithm::SHA2512 |
            Algorithm::SHA3512 |
            Algorithm::BLAKE |
            Algorithm::BLAKE2 |
            Algorithm::MD6512 => 128,
        }
    }
}

impl FromStr for Algorithm {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match &s.replace("_", "-").to_lowercase()[..] {
            "sha-1" | "sha1" => Ok(Algorithm::SHA1),
            "sha2256" | "sha2-256" | "sha-2-256" => Ok(Algorithm::SHA2256),
            "sha2" | "sha-2" | "sha2512" | "sha2-512" | "sha-2-512" => Ok(Algorithm::SHA2512),
            "sha3256" | "sha3-256" | "sha-3-256" => Ok(Algorithm::SHA3256),
            "sha3" | "sha-3" | "sha3512" | "sha3-512" | "sha-3-512" => Ok(Algorithm::SHA3512),
            "blake" => Ok(Algorithm::BLAKE),
            "blake2" => Ok(Algorithm::BLAKE2),
            "crc64" => Ok(Algorithm::CRC64),
            "crc32" => Ok(Algorithm::CRC32),
            "crc16" => Ok(Algorithm::CRC16),
            "crc8" => Ok(Algorithm::CRC8),
            "md5" => Ok(Algorithm::MD5),
            "md6128" | "md6-128" => Ok(Algorithm::MD6128),
            "md6256" | "md6-256" => Ok(Algorithm::MD6256),
            "md6512" | "md6-512" => Ok(Algorithm::MD6512),
            "xor8" => Ok(Algorithm::XOR8),
            _ => Err(format!("\"{}\" is not a recognised compression algorithm", s)),
        }
    }
}
<|endoftext|>