<commit_before>#[macro_use]
extern crate pest;
extern crate regex;

use pest::prelude::*;
use std::io::{self, Write};

pub use error::ParseError;
pub use name::Name;
pub use path::Path;
pub use template::Template;

pub mod ruby;
mod error;
mod name;
mod path;
mod template;

/// Defines the source code output behavior for compiler backends. The main
/// compiler driver treats the result of each backend identically.
pub trait Compile {
    /// Writes the final translated source code to an output buffer.
    fn emit(&self, buf: &mut Write) -> io::Result<()>;
}

#[derive(Debug, PartialEq)]
pub struct Block {
    statements: Vec<Statement>,
}

#[derive(Debug, PartialEq)]
pub enum Statement {
    Program(Block),
    Section(Path, Block),
    Inverted(Path, Block),
    Variable(Path),
    Html(Path),
    Partial(String),
    Content(String),
}

impl Statement {
    pub fn partials<'a>(&'a self) -> Vec<&'a String> {
        match *self {
            Statement::Program(ref block) => {
                block.statements.iter().flat_map(|stmt| stmt.partials()).collect()
            }
            Statement::Section(_, ref block) => {
                block.statements.iter().flat_map(|stmt| stmt.partials()).collect()
            }
            Statement::Inverted(_, ref block) => {
                block.statements.iter().flat_map(|stmt| stmt.partials()).collect()
            }
            Statement::Partial(ref name) => vec![name],
            _ => Vec::new(),
        }
    }
}

impl_rdp! {
    grammar! {
        program     = { block ~ eoi }
        block       = { statement* }
        statement   = { content | variable | html | section | inverted | partial }
        content     = @{ (!open ~ any)+ }
        variable    = { open ~ path ~ close }
        html        = { ["{{{"] ~ path ~ ["}}}"] }
        section     = { ["{{#"] ~ path ~ close ~ block ~ ["{{/"] ~ path ~ close }
        inverted    = { ["{{^"] ~ path ~ close ~ block ~ ["{{/"] ~ path ~ close }
        comment     = _{ ["{{!"] ~ (!close ~ any)* ~ close }
        partial     = { ["{{>"] ~ partial_id ~ close }
        partial_id  = { (['a'..'z'] | ['A'..'Z'] | ['0'..'9'] | ["-"] | ["_"] | ["/"])+ }
        open        = _{ ["{{"] }
        close       = _{ ["}}"] }
        path        = @{ identifier ~ (["."] ~ identifier)* }
        identifier  = { (['a'..'z'] | ['A'..'Z'] | ['0'..'9'] | ["-"] | ["_"])+ }
        whitespace  = _{ [" "] | ["\t"] | ["\r"] | ["\n"]}
    }

    process! {
        tree(&self) -> Result<Statement, ParseError> {
            (_: program, block: _block()) => {
                Ok(Statement::Program(block?))
            }
        }

        _block(&self) -> Result<Block, ParseError> {
            (_: block, list: _statements()) => {
                Ok(Block { statements: list? })
            }
        }

        _statements(&self) -> Result<Vec<Statement>, ParseError> {
            (_: statement, head: _statement(), tail: _statements()) => {
                match tail {
                    Ok(mut tail) => {
                        tail.insert(0, head?);
                        Ok(tail)
                    }
                    Err(e) => Err(e),
                }
            },
            () => {
                Ok(Vec::new())
            }
        }

        _statement(&self) -> Result<Statement, ParseError> {
            (&text: content) => {
                Ok(Statement::Content(String::from(text)))
            },
            (_: variable, path: _path()) => {
                Ok(Statement::Variable(path))
            },
            (_: html, path: _path()) => {
                Ok(Statement::Html(path))
            },
            (_: partial, &name: partial_id) => {
                Ok(Statement::Partial(String::from(name)))
            },
            (_: section, open: _path(), block: _block(), close: _path()) => {
                if open != close {
                    return Err(ParseError::InvalidSection(open, close));
                }
                Ok(Statement::Section(open, block?))
            },
            (_: inverted, open: _path(), block: _block(), close: _path()) => {
                if open != close {
                    return Err(ParseError::InvalidSection(open, close));
                }
                Ok(Statement::Inverted(open, block?))
            }
        }

        _path(&self) -> Path {
            (_: path, list: _identifier()) => {
                Path::new(list)
            }
        }

        _identifier(&self) -> Vec<String> {
            (&head: identifier, mut tail: _identifier()) => {
                tail.insert(0, String::from(head));
                tail
            },
            () => {
                Vec::new()
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use pest::prelude::*;
    use super::{Block, Path, ParseError, Rdp, Rule, Statement};

    #[test]
    fn identifier() {
        let mut parser = Rdp::new(StringInput::new("abc"));
        assert!(parser.identifier());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::identifier, 0, 3)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn path() {
        let mut parser = Rdp::new(StringInput::new("a.b.c"));
        assert!(parser.path());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::path, 0, 5),
                            Token::new(Rule::identifier, 0, 1),
                            Token::new(Rule::identifier, 2, 3),
                            Token::new(Rule::identifier, 4, 5)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn partial_id() {
        let mut parser = Rdp::new(StringInput::new("a/b/c"));
        assert!(parser.partial_id());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::partial_id, 0, 5)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn partial() {
        let mut parser = Rdp::new(StringInput::new("{{> a/b}}"));
        assert!(parser.partial());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::partial, 0, 9), Token::new(Rule::partial_id, 4, 7)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn comment() {
        let mut parser = Rdp::new(StringInput::new("{{! a b c}}"));
        assert!(parser.comment());
        assert!(parser.end());
        assert!(parser.queue().is_empty());
    }

    #[test]
    fn inverted() {
        let mut parser = Rdp::new(StringInput::new("{{^ a}}{{/ a}}"));
        assert!(parser.inverted());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::inverted, 0, 14),
                            Token::new(Rule::path, 4, 5),
                            Token::new(Rule::identifier, 4, 5),
                            Token::new(Rule::path, 11, 12),
                            Token::new(Rule::identifier, 11, 12)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn section() {
        let mut parser = Rdp::new(StringInput::new("{{# a}}{{/ a}}"));
        assert!(parser.section());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::section, 0, 14),
                            Token::new(Rule::path, 4, 5),
                            Token::new(Rule::identifier, 4, 5),
                            Token::new(Rule::path, 11, 12),
                            Token::new(Rule::identifier, 11, 12)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn variable() {
        let mut parser = Rdp::new(StringInput::new("{{ a }}"));
        assert!(parser.variable());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::variable, 0, 7),
                            Token::new(Rule::path, 3, 4),
                            Token::new(Rule::identifier, 3, 4)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn html() {
        let mut parser = Rdp::new(StringInput::new("{{{ a }}}"));
        assert!(parser.html());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::html, 0, 9),
                            Token::new(Rule::path, 4, 5),
                            Token::new(Rule::identifier, 4, 5)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn program() {
        let mut parser = Rdp::new(StringInput::new("
            {{> includes/header }}

                {{# robots}}

{{ name.first }}

                {{/ robots}}
                {{^ robots}}
                    {{! else clause }}
                    No robots
                {{/ robots}}

            {{> includes/footer }}
            {{{ unescaped.html }}}
        "));
        assert!(parser.program());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::program, 0, 380),
                            Token::new(Rule::block, 0, 371),
                            Token::new(Rule::statement, 0, 13),
                            Token::new(Rule::content, 0, 13),
                            Token::new(Rule::statement, 13, 35),
                            Token::new(Rule::partial, 13, 35),
                            Token::new(Rule::partial_id, 17, 32),
                            Token::new(Rule::statement, 48, 69),
                            Token::new(Rule::content, 48, 69),
                            Token::new(Rule::statement, 69, 156),
                            Token::new(Rule::section, 69, 156),
                            Token::new(Rule::path, 73, 79),
                            Token::new(Rule::identifier, 73, 79),
                            Token::new(Rule::block, 102, 144),
                            Token::new(Rule::statement, 102, 106),
                            Token::new(Rule::content, 102, 106),
                            Token::new(Rule::statement, 106, 122),
                            Token::new(Rule::variable, 106, 122),
                            Token::new(Rule::path, 109, 119),
                            Token::new(Rule::identifier, 109, 113),
                            Token::new(Rule::identifier, 114, 119),
                            Token::new(Rule::statement, 122, 144),
                            Token::new(Rule::content, 122, 144),
                            Token::new(Rule::path, 148, 154),
                            Token::new(Rule::identifier, 148, 154),
                            Token::new(Rule::statement, 173, 283),
                            Token::new(Rule::inverted, 173, 283),
                            Token::new(Rule::path, 177, 183),
                            Token::new(Rule::identifier, 177, 183),
                            Token::new(Rule::block, 245, 271),
                            Token::new(Rule::statement, 245, 271),
                            Token::new(Rule::content, 245, 271),
                            Token::new(Rule::path, 275, 281),
                            Token::new(Rule::identifier, 275, 281),
                            Token::new(Rule::statement, 296, 314),
                            Token::new(Rule::content, 296, 314),
                            Token::new(Rule::statement, 314, 336),
                            Token::new(Rule::partial, 314, 336),
                            Token::new(Rule::partial_id, 318, 333),
                            Token::new(Rule::statement, 349, 371),
                            Token::new(Rule::html, 349, 371),
                            Token::new(Rule::path, 353, 367),
                            Token::new(Rule::identifier, 353, 362),
                            Token::new(Rule::identifier, 363, 367)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn invalid_section() {
        let mut parser = Rdp::new(StringInput::new("{{#one}}test{{/two}}"));
        assert!(parser.program());
        assert!(parser.end());
        match parser.tree() {
            Err(ParseError::InvalidSection(..)) => (),
            _ => panic!("Must enforce matching section paths"),
        }
    }

    #[test]
    fn tree() {
        let mut parser = Rdp::new(StringInput::new("
            {{> includes/header }}

                {{# robots}}

{{ name.first }}

                {{/ robots}}
                {{^ robots}}
                    {{! else clause }}
                    No robots
                {{/ robots}}

            {{> includes/footer }}
            {{{ unescaped.html }}}
        "));

        assert!(parser.program());
        assert!(parser.end());

        let list = vec![Statement::Content(String::from("
")),
                        Statement::Variable(Path::new(vec![String::from("name"),
                                                           String::from("first")])),
                        Statement::Content(String::from("
\n                "))];

        let section = Statement::Section(Path::new(vec![String::from("robots")]),
                                         Block { statements: list });

        let invblock = vec![Statement::Content(String::from("No robots\n                "))];
        let inverted = Statement::Inverted(Path::new(vec![String::from("robots")]),
                                           Block { statements: invblock });

        let program = vec![Statement::Content(String::from("\n            ")),
                           Statement::Partial(String::from("includes/header")),
                           Statement::Content(String::from("
\n                ")),
                           section,
                           inverted,
                           Statement::Content(String::from("
\n            ")),
                           Statement::Partial(String::from("includes/footer")),
                           Statement::Html(Path::new(vec![String::from("unescaped"),
                                                          String::from("html")]))];
        let expected = Statement::Program(Block { statements: program });

        match parser.tree() {
            Ok(tree) => assert_eq!(expected, tree),
            Err(e) => panic!("{}", e),
        }
    }
}
<commit_msg>Support ampersand syntax to disable html escaping<commit_after>#[macro_use]
extern crate pest;
extern crate regex;

use pest::prelude::*;
use std::io::{self, Write};

pub use error::ParseError;
pub use name::Name;
pub use path::Path;
pub use template::Template;

pub mod ruby;
mod error;
mod name;
mod path;
mod template;

/// Defines the source code output behavior for compiler backends. The main
/// compiler driver treats the result of each backend identically.
pub trait Compile {
    /// Writes the final translated source code to an output buffer.
    fn emit(&self, buf: &mut Write) -> io::Result<()>;
}

#[derive(Debug, PartialEq)]
pub struct Block {
    statements: Vec<Statement>,
}

#[derive(Debug, PartialEq)]
pub enum Statement {
    Program(Block),
    Section(Path, Block),
    Inverted(Path, Block),
    Variable(Path),
    Html(Path),
    Partial(String),
    Content(String),
}

impl Statement {
    pub fn partials<'a>(&'a self) -> Vec<&'a String> {
        match *self {
            Statement::Program(ref block) => {
                block.statements.iter().flat_map(|stmt| stmt.partials()).collect()
            }
            Statement::Section(_, ref block) => {
                block.statements.iter().flat_map(|stmt| stmt.partials()).collect()
            }
            Statement::Inverted(_, ref block) => {
                block.statements.iter().flat_map(|stmt| stmt.partials()).collect()
            }
            Statement::Partial(ref name) => vec![name],
            _ => Vec::new(),
        }
    }
}

impl_rdp! {
    grammar! {
        program     = { block ~ eoi }
        block       = { statement* }
        statement   = { content | variable | html | section | inverted | partial }
        content     = @{ (!open ~ any)+ }
        variable    = { open ~ path ~ close }
        html        = { (["{{{"] ~ path ~ ["}}}"]) | (["{{&"] ~ path ~ ["}}"]) }
        section     = { ["{{#"] ~ path ~ close ~ block ~ ["{{/"] ~ path ~ close }
        inverted    = { ["{{^"] ~ path ~ close ~ block ~ ["{{/"] ~ path ~ close }
        comment     = _{ ["{{!"] ~ (!close ~ any)* ~ close }
        partial     = { ["{{>"] ~ partial_id ~ close }
        partial_id  = { (['a'..'z'] | ['A'..'Z'] | ['0'..'9'] | ["-"] | ["_"] | ["/"])+ }
        open        = _{ ["{{"] }
        close       = _{ ["}}"] }
        path        = @{ identifier ~ (["."] ~ identifier)* }
        identifier  = { (['a'..'z'] | ['A'..'Z'] | ['0'..'9'] | ["-"] | ["_"])+ }
        whitespace  = _{ [" "] | ["\t"] | ["\r"] | ["\n"]}
    }

    process! {
        tree(&self) -> Result<Statement, ParseError> {
            (_: program, block: _block()) => {
                Ok(Statement::Program(block?))
            }
        }

        _block(&self) -> Result<Block, ParseError> {
            (_: block, list: _statements()) => {
                Ok(Block { statements: list? })
            }
        }

        _statements(&self) -> Result<Vec<Statement>, ParseError> {
            (_: statement, head: _statement(), tail: _statements()) => {
                match tail {
                    Ok(mut tail) => {
                        tail.insert(0, head?);
                        Ok(tail)
                    }
                    Err(e) => Err(e),
                }
            },
            () => {
                Ok(Vec::new())
            }
        }

        _statement(&self) -> Result<Statement, ParseError> {
            (&text: content) => {
                Ok(Statement::Content(String::from(text)))
            },
            (_: variable, path: _path()) => {
                Ok(Statement::Variable(path))
            },
            (_: html, path: _path()) => {
                Ok(Statement::Html(path))
            },
            (_: partial, &name: partial_id) => {
                Ok(Statement::Partial(String::from(name)))
            },
            (_: section, open: _path(), block: _block(), close: _path()) => {
                if open != close {
                    return Err(ParseError::InvalidSection(open, close));
                }
                Ok(Statement::Section(open, block?))
            },
            (_: inverted, open: _path(), block: _block(), close: _path()) => {
                if open != close {
                    return Err(ParseError::InvalidSection(open, close));
                }
                Ok(Statement::Inverted(open, block?))
            }
        }

        _path(&self) -> Path {
            (_: path, list: _identifier()) => {
                Path::new(list)
            }
        }

        _identifier(&self) -> Vec<String> {
            (&head: identifier, mut tail: _identifier()) => {
                tail.insert(0, String::from(head));
                tail
            },
            () => {
                Vec::new()
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use pest::prelude::*;
    use super::{Block, Path, ParseError, Rdp, Rule, Statement};

    #[test]
    fn identifier() {
        let mut parser = Rdp::new(StringInput::new("abc"));
        assert!(parser.identifier());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::identifier, 0, 3)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn path() {
        let mut parser = Rdp::new(StringInput::new("a.b.c"));
        assert!(parser.path());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::path, 0, 5),
                            Token::new(Rule::identifier, 0, 1),
                            Token::new(Rule::identifier, 2, 3),
                            Token::new(Rule::identifier, 4, 5)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn partial_id() {
        let mut parser = Rdp::new(StringInput::new("a/b/c"));
        assert!(parser.partial_id());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::partial_id, 0, 5)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn partial() {
        let mut parser = Rdp::new(StringInput::new("{{> a/b}}"));
        assert!(parser.partial());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::partial, 0, 9), Token::new(Rule::partial_id, 4, 7)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn comment() {
        let mut parser = Rdp::new(StringInput::new("{{! a b c}}"));
        assert!(parser.comment());
        assert!(parser.end());
        assert!(parser.queue().is_empty());
    }

    #[test]
    fn inverted() {
        let mut parser = Rdp::new(StringInput::new("{{^ a}}{{/ a}}"));
        assert!(parser.inverted());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::inverted, 0, 14),
                            Token::new(Rule::path, 4, 5),
                            Token::new(Rule::identifier, 4, 5),
                            Token::new(Rule::path, 11, 12),
                            Token::new(Rule::identifier, 11, 12)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn section() {
        let mut parser = Rdp::new(StringInput::new("{{# a}}{{/ a}}"));
        assert!(parser.section());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::section, 0, 14),
                            Token::new(Rule::path, 4, 5),
                            Token::new(Rule::identifier, 4, 5),
                            Token::new(Rule::path, 11, 12),
                            Token::new(Rule::identifier, 11, 12)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn variable() {
        let mut parser = Rdp::new(StringInput::new("{{ a }}"));
        assert!(parser.variable());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::variable, 0, 7),
                            Token::new(Rule::path, 3, 4),
                            Token::new(Rule::identifier, 3, 4)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn html() {
        let mut parser = Rdp::new(StringInput::new("{{{ a }}}"));
        assert!(parser.html());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::html, 0, 9),
                            Token::new(Rule::path, 4, 5),
                            Token::new(Rule::identifier, 4, 5)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn html_ampersand() {
        let mut parser = Rdp::new(StringInput::new("{{& a }}"));
        assert!(parser.html());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::html, 0, 8),
                            Token::new(Rule::path, 4, 5),
                            Token::new(Rule::identifier, 4, 5)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn program() {
        let mut parser = Rdp::new(StringInput::new("
            {{> includes/header }}

                {{# robots}}

{{ name.first }}

                {{/ robots}}
                {{^ robots}}
                    {{! else clause }}
                    No robots
                {{/ robots}}

            {{> includes/footer }}
            {{{ unescaped.html }}}
        "));
        assert!(parser.program());
        assert!(parser.end());

        let expected = vec![Token::new(Rule::program, 0, 380),
                            Token::new(Rule::block, 0, 371),
                            Token::new(Rule::statement, 0, 13),
                            Token::new(Rule::content, 0, 13),
                            Token::new(Rule::statement, 13, 35),
                            Token::new(Rule::partial, 13, 35),
                            Token::new(Rule::partial_id, 17, 32),
                            Token::new(Rule::statement, 48, 69),
                            Token::new(Rule::content, 48, 69),
                            Token::new(Rule::statement, 69, 156),
                            Token::new(Rule::section, 69, 156),
                            Token::new(Rule::path, 73, 79),
                            Token::new(Rule::identifier, 73, 79),
                            Token::new(Rule::block, 102, 144),
                            Token::new(Rule::statement, 102, 106),
                            Token::new(Rule::content, 102, 106),
                            Token::new(Rule::statement, 106, 122),
                            Token::new(Rule::variable, 106, 122),
                            Token::new(Rule::path, 109, 119),
                            Token::new(Rule::identifier, 109, 113),
                            Token::new(Rule::identifier, 114, 119),
                            Token::new(Rule::statement, 122, 144),
                            Token::new(Rule::content, 122, 144),
                            Token::new(Rule::path, 148, 154),
                            Token::new(Rule::identifier, 148, 154),
                            Token::new(Rule::statement, 173, 283),
                            Token::new(Rule::inverted, 173, 283),
                            Token::new(Rule::path, 177, 183),
                            Token::new(Rule::identifier, 177, 183),
                            Token::new(Rule::block, 245, 271),
                            Token::new(Rule::statement, 245, 271),
                            Token::new(Rule::content, 245, 271),
                            Token::new(Rule::path, 275, 281),
                            Token::new(Rule::identifier, 275, 281),
                            Token::new(Rule::statement, 296, 314),
                            Token::new(Rule::content, 296, 314),
                            Token::new(Rule::statement, 314, 336),
                            Token::new(Rule::partial, 314, 336),
                            Token::new(Rule::partial_id, 318, 333),
                            Token::new(Rule::statement, 349, 371),
                            Token::new(Rule::html, 349, 371),
                            Token::new(Rule::path, 353, 367),
                            Token::new(Rule::identifier, 353, 362),
                            Token::new(Rule::identifier, 363, 367)];
        assert_eq!(&expected, parser.queue());
    }

    #[test]
    fn invalid_section() {
        let mut parser = Rdp::new(StringInput::new("{{#one}}test{{/two}}"));
        assert!(parser.program());
        assert!(parser.end());
        match parser.tree() {
            Err(ParseError::InvalidSection(..)) => (),
            _ => panic!("Must enforce matching section paths"),
        }
    }

    #[test]
    fn tree() {
        let mut parser = Rdp::new(StringInput::new("
            {{> includes/header }}

                {{# robots}}

{{ name.first }}

                {{/ robots}}
                {{^ robots}}
                    {{! else clause }}
                    No robots
                {{/ robots}}

            {{> includes/footer }}
            {{{ unescaped.html }}}
        "));

        assert!(parser.program());
        assert!(parser.end());

        let list = vec![Statement::Content(String::from("
")),
                        Statement::Variable(Path::new(vec![String::from("name"),
                                                           String::from("first")])),
                        Statement::Content(String::from("
\n                "))];

        let section = Statement::Section(Path::new(vec![String::from("robots")]),
                                         Block { statements: list });

        let invblock = vec![Statement::Content(String::from("No robots\n                "))];
        let inverted = Statement::Inverted(Path::new(vec![String::from("robots")]),
                                           Block { statements: invblock });

        let program = vec![Statement::Content(String::from("\n            ")),
                           Statement::Partial(String::from("includes/header")),
                           Statement::Content(String::from("
\n                ")),
                           section,
                           inverted,
                           Statement::Content(String::from("
\n            ")),
                           Statement::Partial(String::from("includes/footer")),
                           Statement::Html(Path::new(vec![String::from("unescaped"),
                                                          String::from("html")]))];
        let expected = Statement::Program(Block { statements: program });

        match parser.tree() {
            Ok(tree) => assert_eq!(expected, tree),
            Err(e) => panic!("{}", e),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(trace_macros)]
// For pest parser generation
#![recursion_limit = "1024"]

extern crate ansi_term;
extern crate dtoa;
#[macro_use]
extern crate error_chain;
extern crate glob;
extern crate itoa;
#[macro_use]
extern crate log;
extern crate ordered_float;
#[macro_use]
extern crate pest;
extern crate protobuf;
extern crate rmp;
extern crate serde;
extern crate serde_avro;
extern crate serde_cbor;
extern crate serde_hjson;
extern crate serde_json;
extern crate serde_protobuf;
extern crate serde_yaml;
extern crate v8;
extern crate xdg_basedir;
extern crate toml;
extern crate yaml_rust;

pub mod config;
pub mod error;
pub mod proto_index;
pub mod query;
pub mod value;

include!(concat!(env!("OUT_DIR"), "/build_info.rs"));

pub const GIT_VERSION: &'static str = rq_git_version!();

pub fn run_query<I, O>(query: &query::Query, source: I, mut sink: O) -> error::Result<()>
    where I: value::Source,
          O: value::Sink
{
    let query_context = query::Context::new();

    let mut results = try!(query.evaluate(&query_context, source));

    while let Some(result) = try!(value::Source::read(&mut results)) {
        try!(sink.write(result));
    }

    Ok(())
}
<commit_msg>Disable trace_macros feature<commit_after>// For pest parser generation
#![recursion_limit = "1024"]

extern crate ansi_term;
extern crate dtoa;
#[macro_use]
extern crate error_chain;
extern crate glob;
extern crate itoa;
#[macro_use]
extern crate log;
extern crate ordered_float;
#[macro_use]
extern crate pest;
extern crate protobuf;
extern crate rmp;
extern crate serde;
extern crate serde_avro;
extern crate serde_cbor;
extern crate serde_hjson;
extern crate serde_json;
extern crate serde_protobuf;
extern crate serde_yaml;
extern crate v8;
extern crate xdg_basedir;
extern crate toml;
extern crate yaml_rust;

pub mod config;
pub mod error;
pub mod proto_index;
pub mod query;
pub mod value;

include!(concat!(env!("OUT_DIR"), "/build_info.rs"));

pub const GIT_VERSION: &'static str = rq_git_version!();

pub fn run_query<I, O>(query: &query::Query, source: I, mut sink: O) -> error::Result<()>
    where I: value::Source,
          O: value::Sink
{
    let query_context = query::Context::new();

    let mut results = try!(query.evaluate(&query_context, source));

    while let Some(result) = try!(value::Source::read(&mut results)) {
        try!(sink.write(result));
    }

    Ok(())
}
<|endoftext|>


<commit_before>
//! `petgraph` is a graph data structure library.
//!
//! Graphs are collections of nodes, and edges between nodes. `petgraph`
//! provides several [graph types](index.html#graph-types) (each differing in the
//! tradeoffs taken in their internal representation),
//! [algorithms](./algo/index.html#functions) on those graphs, and functionality to
//! [output graphs](./doc/petgraph/dot/struct.Dot.html) in
//! [`graphviz`](https://www.graphviz.org/) format. Both nodes and edges
//! can have arbitrary associated data, and edges may be either directed or undirected.
//!
//! # Example
//!
//! ```rust
//! use petgraph::graphmap::UnGraphMap;
//! use petgraph::algo::{dijkstra, min_spanning_tree};
//! use petgraph::data::FromElements;
//! use petgraph::dot::{Dot, Config};
//!
//! // Create an undirected graph where nodes are &str, and edges have no weight.
//! let g = UnGraphMap::<&str, ()>::from_edges(&[
//!     ("a", "b"), ("b", "c"), ("c", "d"),
//!     ("a", "d")]);
//!
//! // Find the shortest path from "a" to "d" using 1 as the cost for every edge.
//! let node_map = dijkstra(&g, "a", Some("d"), |_| 1);
//! assert_eq!(&1, node_map.get("d").unwrap());
//!
//! // Get the minimum spanning tree of the graph as a new graph, and check that
//! // one edge was trimmed.
//! let mst = UnGraphMap::from_elements(min_spanning_tree(&g));
//! assert_eq!(g.all_edges().count() - 1, mst.all_edges().count());
//!
//! // Output the tree to graphviz DOT format
//! println!("{:?}", Dot::with_config(&mst, &[Config::EdgeNoLabel]));
//! // graph {
//! //     0 [label="\"a\""]
//! //     1 [label="\"b\""]
//! //     2 [label="\"c\""]
//! //     3 [label="\"d\""]
//! //     0 -- 1
//! //     2 -- 3
//! //     1 -- 2
//! // }
//! ```
//!
//! # Graph types
//!
//! * [`Graph`](./graph/struct.Graph.html) -
//!   An adjacency list graph with arbitrary associated data.
//! * [`StableGraph`](./stable_graph/struct.StableGraph.html) -
//!   Similar to `Graph`, but it keeps indices stable across removals.
//! * [`GraphMap`](./graphmap/struct.GraphMap.html) -
//!   An adjacency list graph backed by a hash table. The node identifiers are the keys
//!   into the table.
//! * [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html) -
//!   An adjacency matrix graph.
//! * [`CSR`](./csr/struct.Csr.html) -
//!   A sparse adjacency matrix graph with arbitrary associated data.
//!
//! ### Generic parameters
//!
//! Each graph type is generic over a handful of parameters. All graphs share 3 common
//! parameters, `N`, `E`, and `Ty`. This is a broad overview of what those are. Each
//! type's documentation will have finer detail on these parameters.
//!
//! `N` & `E` are called *weights* in this implementation, and are associated with
//! nodes and edges respectively. They can generally be of arbitrary type, and don't have to
//! be what you might conventionally consider weight-like. For example, using `&str` for `N`
//! will work. Many algorithms that require costs let you provide a cost function that
//! translates your `N` and `E` weights into costs appropriate to the algorithm. Some graph
//! types and choices do impose bounds on `N` or `E`.
//! [`min_spanning_tree`](./algo/fn.min_spanning_tree.html) for example requires edge weights that
//! implement [`PartialOrd`](https://doc.rust-lang.org/stable/core/cmp/trait.PartialOrd.html).
//! [`GraphMap`](./graphmap/struct.GraphMap.html) requires node weights that can serve as hash
//! map keys, since that graph type does not create standalone node indices.
//!
//! `Ty` controls whether edges are [`Directed`](./petgraph/enum.Directed.html) or
//! [`Undirected`](./petgraph/enum.Unirected.html).
//!
//! `Ix` appears on graph types that use indices. It is exposed so you can control
//! the size of node and edge indices, and therefore the memory footprint of your graphs.
//! Allowed values are `u8`, `u16`, `u32`, and `usize`, with `u32` being the default.
//!
//! ### Shorthand types
//!
//! Each graph type vends a few shorthand type definitions that name some specific
//! generic choices. For example, [`DiGraph<_, _>`](./graph/type.DiGraph.html) is shorthand
//! for [`Graph<_, _, Undirected>`](graph/struct.Graph.html).
//! [`UnMatrix<_, _>`](./matrix_graph/type.UnMatrix.html) is shorthand for
//! [`MatrixGraph<_, _, Undirected>`](./matrix_graph/struct.MatrixGraph.html). Each graph type's
//! module documentation lists the available shorthand types.
//!
//! # Crate features
//!
//! * **serde-1** -
//!   Defaults off. Enables serialization for ``Graph, StableGraph`` using
//!   [`serde 1.0`](https://crates.io/crates/serde). May require a more recent version
//!   of Rust than petgraph alone.
//! * **graphmap** -
//!   Defaults on. Enables [`GraphMap`](./graphmap/struct.GraphMap.html).
//! * **stable_graph** -
//!   Defaults on. Enables [`StableGraph`](./stable_graph/struct.StableGraph.html).
//! * **matrix_graph** -
//!   Defaults on. Enables [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html).
//!
#![doc(html_root_url = "https://docs.rs/petgraph/0.4/")]

extern crate fixedbitset;
#[cfg(feature = "graphmap")]
extern crate indexmap;

#[cfg(feature = "serde-1")]
extern crate serde;
#[cfg(feature = "serde-1")]
#[macro_use]
extern crate serde_derive;

#[cfg(all(feature = "serde-1", test))]
extern crate itertools;

#[doc(no_inline)]
pub use crate::graph::Graph;

pub use crate::Direction::{Outgoing, Incoming};

#[macro_use]
mod macros;
mod scored;

// these modules define trait-implementing macros
#[macro_use]
pub mod visit;
#[macro_use]
pub mod data;

pub mod algo;
#[cfg(feature = "generate")]
pub mod generate;
#[cfg(feature = "graphmap")]
pub mod graphmap;
#[cfg(feature = "matrix_graph")]
pub mod matrix_graph;
mod graph_impl;
pub mod dot;
pub mod unionfind;
mod dijkstra;
mod astar;
mod simple_paths;
pub mod csr;
mod iter_format;
mod iter_utils;
mod isomorphism;
mod traits_graph;
mod util;
#[cfg(feature = "quickcheck")]
mod quickcheck;
#[cfg(feature = "serde-1")]
mod serde_utils;

pub mod prelude;

/// `Graph<N, E, Ty, Ix>` is a graph datastructure using an adjacency list representation.
pub mod graph {
    pub use crate::graph_impl::{
        Edge,
        EdgeIndex,
        EdgeIndices,
        EdgeReference,
        EdgeReferences,
        EdgeWeightsMut,
        Edges,
        Externals,
        Frozen,
        Graph,
        Neighbors,
        Node,
        NodeIndex,
        NodeIndices,
        NodeWeightsMut,
        NodeReferences,
        WalkNeighbors,
        GraphIndex,
        IndexType,
        edge_index,
        node_index,
        DefaultIx,
        DiGraph,
        UnGraph,
    };
}

#[cfg(feature = "stable_graph")]
pub use crate::graph_impl::stable_graph;

macro_rules! copyclone {
    ($name:ident) => {
        impl Clone for $name {
            #[inline]
            fn clone(&self) -> Self { *self }
        }
    }
}

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction.
#[derive(Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
#[repr(usize)]
pub enum Direction {
    /// An `Outgoing` edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An `Incoming` edge is an inbound edge *to* the current node.
    Incoming = 1
}

copyclone!(Direction);

impl Direction {
    /// Return the opposite `Direction`.
    #[inline]
    pub fn opposite(&self) -> Direction {
        match *self {
            Outgoing => Incoming,
            Incoming => Outgoing,
        }
    }

    /// Return `0` for `Outgoing` and `1` for `Incoming`.
    #[inline]
    pub fn index(&self) -> usize {
        (*self as usize) & 0x1
    }
}

#[doc(hidden)]
pub use crate::Direction as EdgeDirection;

/// Marker type for a directed graph.
#[derive(Copy, Debug)]
pub enum Directed { }
copyclone!(Directed);

/// Marker type for an undirected graph.
#[derive(Copy, Debug)]
pub enum Undirected { }
copyclone!(Undirected);

/// A graph's edge type determines whether it has directed edges or not.
pub trait EdgeType {
    fn is_directed() -> bool;
}

impl EdgeType for Directed {
    #[inline]
    fn is_directed() -> bool { true }
}

impl EdgeType for Undirected {
    #[inline]
    fn is_directed() -> bool { false }
}

/// Convert an element like `(i, j)` or `(i, j, w)` into
/// a triple of source, target, edge weight.
///
/// For `Graph::from_edges` and `GraphMap::from_edges`.
pub trait IntoWeightedEdge<E> {
    type NodeId;
    fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
    where E: Default
{
    type NodeId = Ix;

    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = self;
        (s, t, E::default())
    }
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E)
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &'a E)
    where E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (a, b, c) = self;
        (a, b, c.clone())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix)
    where Ix: Copy, E: Default
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = *self;
        (s, t, E::default())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix, E)
    where Ix: Copy, E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self.clone()
    }
}
<commit_msg>Switch to an example that uses Graph instead of GraphMap<commit_after>
//! `petgraph` is a graph data structure library.
//!
//! Graphs are collections of nodes, and edges between nodes. `petgraph`
//! provides several [graph types](index.html#graph-types) (each differing in the
//! tradeoffs taken in their internal representation),
//! [algorithms](./algo/index.html#functions) on those graphs, and functionality to
//! [output graphs](./doc/petgraph/dot/struct.Dot.html) in
//! [`graphviz`](https://www.graphviz.org/) format. Both nodes and edges
//! can have arbitrary associated data, and edges may be either directed or undirected.
//!
//! # Example
//!
//! ```rust
//! use petgraph::graph::{NodeIndex, UnGraph};
//! use petgraph::algo::{dijkstra, min_spanning_tree};
//! use petgraph::data::FromElements;
//! use petgraph::dot::{Dot, Config};
//!
//! // Create an undirected graph with `i32` nodes and edges with `()` associated data.
//! let g = UnGraph::<i32, ()>::from_edges(&[
//!     (1, 2), (2, 3), (3, 4),
//!     (1, 4)]);
//!
//! // Find the shortest path from `1` to `4` using `1` as the cost for every edge.
//! let node_map = dijkstra(&g, 1.into(), Some(4.into()), |_| 1);
//! assert_eq!(&1i32, node_map.get(&NodeIndex::new(4)).unwrap());
//!
//! // Get the minimum spanning tree of the graph as a new graph, and check that
//! // one edge was trimmed.
//! let mst = UnGraph::<_, _>::from_elements(min_spanning_tree(&g));
//! assert_eq!(g.raw_edges().len() - 1, mst.raw_edges().len());
//!
//! // Output the tree to `graphviz` `DOT` format
//! println!("{:?}", Dot::with_config(&mst, &[Config::EdgeNoLabel]));
//! // graph {
//! //     0 [label="\"0\""]
//! //     1 [label="\"0\""]
//! //     2 [label="\"0\""]
//! //     3 [label="\"0\""]
//! //     1 -- 2
//! //     3 -- 4
//! //     2 -- 3
//! // }
//! ```
//!
//! # Graph types
//!
//! * [`Graph`](./graph/struct.Graph.html) -
//!   An adjacency list graph with arbitrary associated data.
//! * [`StableGraph`](./stable_graph/struct.StableGraph.html) -
//!   Similar to `Graph`, but it keeps indices stable across removals.
//! * [`GraphMap`](./graphmap/struct.GraphMap.html) -
//!   An adjacency list graph backed by a hash table. The node identifiers are the keys
//!   into the table.
//! * [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html) -
//!   An adjacency matrix graph.
//! * [`CSR`](./csr/struct.Csr.html) -
//!   A sparse adjacency matrix graph with arbitrary associated data.
//!
//! ### Generic parameters
//!
//! Each graph type is generic over a handful of parameters. All graphs share 3 common
//! parameters, `N`, `E`, and `Ty`. This is a broad overview of what those are. Each
//! type's documentation will have finer detail on these parameters.
//!
//! `N` & `E` are called *weights* in this implementation, and are associated with
//! nodes and edges respectively. They can generally be of arbitrary type, and don't have to
//! be what you might conventionally consider weight-like. For example, using `&str` for `N`
//! will work. Many algorithms that require costs let you provide a cost function that
//! translates your `N` and `E` weights into costs appropriate to the algorithm. Some graph
//! types and choices do impose bounds on `N` or `E`.
//! [`min_spanning_tree`](./algo/fn.min_spanning_tree.html) for example requires edge weights that
//! implement [`PartialOrd`](https://doc.rust-lang.org/stable/core/cmp/trait.PartialOrd.html).
//! [`GraphMap`](./graphmap/struct.GraphMap.html) requires node weights that can serve as hash
//! map keys, since that graph type does not create standalone node indices.
//!
//! `Ty` controls whether edges are [`Directed`](./petgraph/enum.Directed.html) or
//! [`Undirected`](./petgraph/enum.Unirected.html).
//!
//! `Ix` appears on graph types that use indices. It is exposed so you can control
//! the size of node and edge indices, and therefore the memory footprint of your graphs.
//! Allowed values are `u8`, `u16`, `u32`, and `usize`, with `u32` being the default.
//!
//! ### Shorthand types
//!
//! Each graph type vends a few shorthand type definitions that name some specific
//! generic choices. For example, [`DiGraph<_, _>`](./graph/type.DiGraph.html) is shorthand
//! for [`Graph<_, _, Undirected>`](graph/struct.Graph.html).
//! [`UnMatrix<_, _>`](./matrix_graph/type.UnMatrix.html) is shorthand for
//! [`MatrixGraph<_, _, Undirected>`](./matrix_graph/struct.MatrixGraph.html). Each graph type's
//! module documentation lists the available shorthand types.
//!
//! # Crate features
//!
//! * **serde-1** -
//!   Defaults off. Enables serialization for ``Graph, StableGraph`` using
//!   [`serde 1.0`](https://crates.io/crates/serde). May require a more recent version
//!   of Rust than petgraph alone.
//! * **graphmap** -
//!   Defaults on. Enables [`GraphMap`](./graphmap/struct.GraphMap.html).
//! * **stable_graph** -
//!   Defaults on. Enables [`StableGraph`](./stable_graph/struct.StableGraph.html).
//! * **matrix_graph** -
//!   Defaults on. Enables [`MatrixGraph`](./matrix_graph/struct.MatrixGraph.html).
//!
#![doc(html_root_url = "https://docs.rs/petgraph/0.4/")]

extern crate fixedbitset;
#[cfg(feature = "graphmap")]
extern crate indexmap;

#[cfg(feature = "serde-1")]
extern crate serde;
#[cfg(feature = "serde-1")]
#[macro_use]
extern crate serde_derive;

#[cfg(all(feature = "serde-1", test))]
extern crate itertools;

#[doc(no_inline)]
pub use crate::graph::Graph;

pub use crate::Direction::{Outgoing, Incoming};

#[macro_use]
mod macros;
mod scored;

// these modules define trait-implementing macros
#[macro_use]
pub mod visit;
#[macro_use]
pub mod data;

pub mod algo;
#[cfg(feature = "generate")]
pub mod generate;
#[cfg(feature = "graphmap")]
pub mod graphmap;
#[cfg(feature = "matrix_graph")]
pub mod matrix_graph;
mod graph_impl;
pub mod dot;
pub mod unionfind;
mod dijkstra;
mod astar;
mod simple_paths;
pub mod csr;
mod iter_format;
mod iter_utils;
mod isomorphism;
mod traits_graph;
mod util;
#[cfg(feature = "quickcheck")]
mod quickcheck;
#[cfg(feature = "serde-1")]
mod serde_utils;

pub mod prelude;

/// `Graph<N, E, Ty, Ix>` is a graph datastructure using an adjacency list representation.
pub mod graph {
    pub use crate::graph_impl::{
        Edge,
        EdgeIndex,
        EdgeIndices,
        EdgeReference,
        EdgeReferences,
        EdgeWeightsMut,
        Edges,
        Externals,
        Frozen,
        Graph,
        Neighbors,
        Node,
        NodeIndex,
        NodeIndices,
        NodeWeightsMut,
        NodeReferences,
        WalkNeighbors,
        GraphIndex,
        IndexType,
        edge_index,
        node_index,
        DefaultIx,
        DiGraph,
        UnGraph,
    };
}

#[cfg(feature = "stable_graph")]
pub use crate::graph_impl::stable_graph;

macro_rules! copyclone {
    ($name:ident) => {
        impl Clone for $name {
            #[inline]
            fn clone(&self) -> Self { *self }
        }
    }
}

// Index into the NodeIndex and EdgeIndex arrays
/// Edge direction.
#[derive(Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
#[repr(usize)]
pub enum Direction {
    /// An `Outgoing` edge is an outward edge *from* the current node.
    Outgoing = 0,
    /// An `Incoming` edge is an inbound edge *to* the current node.
    Incoming = 1
}

copyclone!(Direction);

impl Direction {
    /// Return the opposite `Direction`.
    #[inline]
    pub fn opposite(&self) -> Direction {
        match *self {
            Outgoing => Incoming,
            Incoming => Outgoing,
        }
    }

    /// Return `0` for `Outgoing` and `1` for `Incoming`.
    #[inline]
    pub fn index(&self) -> usize {
        (*self as usize) & 0x1
    }
}

#[doc(hidden)]
pub use crate::Direction as EdgeDirection;

/// Marker type for a directed graph.
#[derive(Copy, Debug)]
pub enum Directed { }
copyclone!(Directed);

/// Marker type for an undirected graph.
#[derive(Copy, Debug)]
pub enum Undirected { }
copyclone!(Undirected);

/// A graph's edge type determines whether it has directed edges or not.
pub trait EdgeType {
    fn is_directed() -> bool;
}

impl EdgeType for Directed {
    #[inline]
    fn is_directed() -> bool { true }
}

impl EdgeType for Undirected {
    #[inline]
    fn is_directed() -> bool { false }
}

/// Convert an element like `(i, j)` or `(i, j, w)` into
/// a triple of source, target, edge weight.
///
/// For `Graph::from_edges` and `GraphMap::from_edges`.
pub trait IntoWeightedEdge<E> {
    type NodeId;
    fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
    where E: Default
{
    type NodeId = Ix;

    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = self;
        (s, t, E::default())
    }
}

impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E)
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &'a E)
    where E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (a, b, c) = self;
        (a, b, c.clone())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix)
    where Ix: Copy, E: Default
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        let (s, t) = *self;
        (s, t, E::default())
    }
}

impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix, E)
    where Ix: Copy, E: Clone
{
    type NodeId = Ix;
    fn into_weighted_edge(self) -> (Ix, Ix, E) {
        self.clone()
    }
}
<|endoftext|>


<commit_before>//! Algorithmia client library
//!
//! # Examples
//!
//! ```no_run
//! use algorithmia::Service;
//! use algorithmia::algorithm::AlgorithmOutput;
//!
//! // Initialize with an API key
//! let algo_service = Service::new("111112222233333444445555566");
//! let mut factor = algo_service.algorithm("kenny", "Factor");
//!
//! // Run the algorithm using a type safe decoding of the output to Vec<int>
//! //   since this algorithm outputs results as a JSON array of integers
//! let input = "19635".to_string();
//! let output: AlgorithmOutput<Vec<i64>> = factor.exec(&input).unwrap();
//! println!("Completed in {} seconds with result: {:?}", output.duration, output.result);
//! ```

extern crate hyper;
extern crate mime;
extern crate "rustc-serialize" as rustc_serialize;

pub mod algorithm;
pub mod collection;

use algorithm::{AlgorithmService,Algorithm,AlgorithmOutput};
use collection::{CollectionService,Collection,CollectionCreated};

use hyper::{Client, Url};
use hyper::client::RequestBuilder;
use hyper::header::{Accept, Authorization, ContentType, qitem};
use hyper::net::HttpConnector;
use mime::{Mime, TopLevel, SubLevel};
use rustc_serialize::{json, Decodable};
use self::AlgorithmiaError::*;
use std::io;

pub static API_BASE_URL: &'static str = "https://api.algorithmia.com";

/// The top-level struct for instantiating Algorithmia service endpoints
pub struct Service{
    pub api_key: String,
}

/// Internal ApiClient - generally instantiated by `Service::api_client`
pub struct ApiClient<'c>{
    api_key: String,
    client: Client<HttpConnector<'c>>,
}

/// Errors that may be returned by this library
#[derive(Debug)]
pub enum AlgorithmiaError {
    /// Errors returned by the Algorithmia API
    ApiError(String), //TODO: add the optional stacktrace or use ApiErrorResponse directly
    /// HTTP errors encountered by the hyper client
    HttpError(hyper::HttpError),
    /// Errors decoding response json
    DecoderError(json::DecoderError),
    /// Errors decoding response json with additional debugging context
    DecoderErrorWithContext(json::DecoderError, String),
    /// Errors encoding the request
    EncoderError(json::EncoderError),
    /// General IO errors
    IoError(io::Error),
}

/// Struct for decoding Algorithmia API error responses
#[derive(RustcDecodable, Debug)]
pub struct ApiErrorResponse {
    pub error: String,
    pub stacktrace: Option<String>,
}

impl<'a, 'c> Service {
    /// Instantiate a new Service
    pub fn new(api_key: &str) -> Service {
        Service {
            api_key: api_key.to_string(),
        }
    }

    /// Instantiate a new hyper client for each request through this method
    pub fn api_client(&self) -> ApiClient<'c> {
        ApiClient {
            api_key: self.api_key.clone(),
            client: Client::new(),
        }
    }

    /// Instantiate an `AlgorithmService` from this `Service`
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Service;
    /// let service = Service::new("111112222233333444445555566");
    /// let factor = service.algorithm("anowell", "Dijkstra");
    /// ```
    pub fn algorithm(self, user: &'a str, repo: &'a str) -> AlgorithmService<'a> {
        AlgorithmService {
            service: self,
            algorithm: Algorithm { user: user, repo: repo }
        }
    }

    /// Instantiate a `CollectionService` from this `Service`
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Service;
    /// let service = Service::new("111112222233333444445555566");
    /// let factor = service.algorithm("anowell", "rustfoo");
    /// ```
    pub fn collection(self, user: &'a str, name: &'a str) -> CollectionService<'a> {
        CollectionService {
            service: self,
            collection: Collection { user: user, name: name }
        }
    }

    /// Helper to standardize decoding to a specific Algorithmia Result type
    pub fn decode_to_result<T: Decodable>(res_json: String) -> Result<T, AlgorithmiaError> {
        match json::decode::<T>(&*res_json) {
            Ok(result) => Ok(result),
            Err(why) => match json::decode::<ApiErrorResponse>(&*res_json) {
                Ok(api_error) => Err(AlgorithmiaError::ApiError(api_error.error)),
                Err(_) => Err(AlgorithmiaError::DecoderErrorWithContext(why, res_json)),
            }
        }
    }

}

impl<'c> ApiClient<'c> {
    pub fn new(api_key: &str) -> ApiClient {
        ApiClient {
            api_key: api_key.to_string(),
            client: Client::new(),
        }
    }

    /// Helper to make Algorithmia GET requests with the API key
    pub fn get(&mut self, url: Url) -> RequestBuilder<'c, Url, HttpConnector> {
        // let client = self.client ;
        self.client.get(url)
            .header(Authorization(self.api_key.clone()))
    }

    /// Helper to make Algorithmia POST requests with the API key
    pub fn post(&mut self, url: Url) -> RequestBuilder<'c, Url, HttpConnector> {
        // let client = self.client;
        self.client.post(url)
            .header(Authorization(self.api_key.clone()))
    }

    /// Helper to POST JSON to Algorithmia with the correct Mime types
    pub fn post_json(&mut self, url: Url) -> RequestBuilder<'c, Url, HttpConnector> {
        self.post(url)
            .header(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])))
            .header(Accept(vec![qitem(Mime(TopLevel::Application, SubLevel::Json, vec![]))]))
    }
}

/*
* Trait implementations
*/
/// Allowing cloning a service in order to reuse the API key for multiple connections
impl std::clone::Clone for Service {
    fn clone(&self) -> Service {
        Service {
            api_key: self.api_key.clone(),
        }
    }
}

impl std::error::FromError<io::Error> for AlgorithmiaError {
    fn from_error(err: io::Error) -> AlgorithmiaError {
        IoError(err)
    }
}

impl std::error::FromError<hyper::HttpError> for AlgorithmiaError {
    fn from_error(err: hyper::HttpError) -> AlgorithmiaError {
        HttpError(err)
    }
}

impl std::error::FromError<json::DecoderError> for AlgorithmiaError {
    fn from_error(err: json::DecoderError) -> AlgorithmiaError {
        DecoderError(err)
    }
}

impl std::error::FromError<json::EncoderError> for AlgorithmiaError {
    fn from_error(err: json::EncoderError) -> AlgorithmiaError {
        EncoderError(err)
    }
}
<commit_msg>Throw a UserAgent onto requests<commit_after>//! Algorithmia client library
//!
//! # Examples
//!
//! ```no_run
//! use algorithmia::Service;
//! use algorithmia::algorithm::AlgorithmOutput;
//!
//! // Initialize with an API key
//! let algo_service = Service::new("111112222233333444445555566");
//! let mut factor = algo_service.algorithm("kenny", "Factor");
//!
//! // Run the algorithm using a type safe decoding of the output to Vec<int>
//! //   since this algorithm outputs results as a JSON array of integers
//! let input = "19635".to_string();
//! let output: AlgorithmOutput<Vec<i64>> = factor.exec(&input).unwrap();
//! println!("Completed in {} seconds with result: {:?}", output.duration, output.result);
//! ```

#![doc(html_logo_url = "https://algorithmia.com/assets/images/apple-touch-icon.png")]

extern crate hyper;
extern crate mime;
extern crate "rustc-serialize" as rustc_serialize;

pub mod algorithm;
pub mod collection;

use algorithm::{AlgorithmService,Algorithm,AlgorithmOutput};
use collection::{CollectionService,Collection,CollectionCreated};

use hyper::{Client, Url};
use hyper::client::RequestBuilder;
use hyper::header::{Accept, Authorization, ContentType, UserAgent, qitem};
use hyper::net::HttpConnector;
use mime::{Mime, TopLevel, SubLevel};
use rustc_serialize::{json, Decodable};
use self::AlgorithmiaError::*;
use std::io;

pub static API_BASE_URL: &'static str = "https://api.algorithmia.com";

/// The top-level struct for instantiating Algorithmia service endpoints
pub struct Service{
    pub api_key: String,
}

/// Internal ApiClient - generally instantiated by `Service::api_client`
pub struct ApiClient<'c>{
    api_key: String,
    client: Client<HttpConnector<'c>>,
    user_agent: String,
}

/// Errors that may be returned by this library
#[derive(Debug)]
pub enum AlgorithmiaError {
    /// Errors returned by the Algorithmia API
    ApiError(String), //TODO: add the optional stacktrace or use ApiErrorResponse directly
    /// HTTP errors encountered by the hyper client
    HttpError(hyper::HttpError),
    /// Errors decoding response json
    DecoderError(json::DecoderError),
    /// Errors decoding response json with additional debugging context
    DecoderErrorWithContext(json::DecoderError, String),
    /// Errors encoding the request
    EncoderError(json::EncoderError),
    /// General IO errors
    IoError(io::Error),
}

/// Struct for decoding Algorithmia API error responses
#[derive(RustcDecodable, Debug)]
pub struct ApiErrorResponse {
    pub error: String,
    pub stacktrace: Option<String>,
}

impl<'a, 'c> Service {
    /// Instantiate a new Service
    pub fn new(api_key: &str) -> Service {
        Service {
            api_key: api_key.to_string(),
        }
    }

    /// Instantiate a new hyper client for each request through this method
    pub fn api_client(&self) -> ApiClient<'c> {
        ApiClient::new(self.api_key.clone())
    }

    /// Instantiate an `AlgorithmService` from this `Service`
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Service;
    /// let service = Service::new("111112222233333444445555566");
    /// let factor = service.algorithm("anowell", "Dijkstra");
    /// ```
    pub fn algorithm(self, user: &'a str, repo: &'a str) -> AlgorithmService<'a> {
        AlgorithmService {
            service: self,
            algorithm: Algorithm { user: user, repo: repo }
        }
    }

    /// Instantiate a `CollectionService` from this `Service`
    ///
    /// # Examples
    ///
    /// ```
    /// use algorithmia::Service;
    /// let service = Service::new("111112222233333444445555566");
    /// let factor = service.algorithm("anowell", "rustfoo");
    /// ```
    pub fn collection(self, user: &'a str, name: &'a str) -> CollectionService<'a> {
        CollectionService {
            service: self,
            collection: Collection { user: user, name: name }
        }
    }

    /// Helper to standardize decoding to a specific Algorithmia Result type
    pub fn decode_to_result<T: Decodable>(res_json: String) -> Result<T, AlgorithmiaError> {
        match json::decode::<T>(&*res_json) {
            Ok(result) => Ok(result),
            Err(why) => match json::decode::<ApiErrorResponse>(&*res_json) {
                Ok(api_error) => Err(AlgorithmiaError::ApiError(api_error.error)),
                Err(_) => Err(AlgorithmiaError::DecoderErrorWithContext(why, res_json)),
            }
        }
    }

}

impl<'c> ApiClient<'c> {
    pub fn new(api_key: String) -> ApiClient<'c> {
        ApiClient {
            api_key: api_key,
            client: Client::new(),
            user_agent: format!("rust/{} algorithmia.rs/{}", option_env!("CFG_RELEASE").unwrap_or("unknown"), option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")),
        }
    }

    /// Helper to make Algorithmia GET requests with the API key
    pub fn get(&mut self, url: Url) -> RequestBuilder<'c, Url, HttpConnector> {
        self.client.get(url)
            .header(UserAgent(self.user_agent.clone()))
            .header(Authorization(self.api_key.clone()))
    }

    /// Helper to make Algorithmia POST requests with the API key
    pub fn post(&mut self, url: Url) -> RequestBuilder<'c, Url, HttpConnector> {
        self.client.post(url)
            .header(UserAgent(self.user_agent.clone()))
            .header(Authorization(self.api_key.clone()))
    }

    /// Helper to POST JSON to Algorithmia with the correct Mime types
    pub fn post_json(&mut self, url: Url) -> RequestBuilder<'c, Url, HttpConnector> {
        self.post(url)
            .header(ContentType(Mime(TopLevel::Application, SubLevel::Json, vec![])))
            .header(Accept(vec![qitem(Mime(TopLevel::Application, SubLevel::Json, vec![]))]))
    }
}

/*
* Trait implementations
*/
/// Allowing cloning a service in order to reuse the API key for multiple connections
impl std::clone::Clone for Service {
    fn clone(&self) -> Service {
        Service {
            api_key: self.api_key.clone(),
        }
    }
}

impl std::error::FromError<io::Error> for AlgorithmiaError {
    fn from_error(err: io::Error) -> AlgorithmiaError {
        IoError(err)
    }
}

impl std::error::FromError<hyper::HttpError> for AlgorithmiaError {
    fn from_error(err: hyper::HttpError) -> AlgorithmiaError {
        HttpError(err)
    }
}

impl std::error::FromError<json::DecoderError> for AlgorithmiaError {
    fn from_error(err: json::DecoderError) -> AlgorithmiaError {
        DecoderError(err)
    }
}

impl std::error::FromError<json::EncoderError> for AlgorithmiaError {
    fn from_error(err: json::EncoderError) -> AlgorithmiaError {
        EncoderError(err)
    }
}
<|endoftext|>


<commit_before>//! Securely create and manage temporary files. Temporary files created by this create are
//! automatically deleted.
//!
//! This crate provides two temporary file variants: a `tempfile()` function that returns standard
//! `File` objects and `NamedTempFile`. When choosing between the variants, prefer `tempfile()`
//! unless you either need to know the file's path or to be able to persist it.
//!
//! # Differences
//!
//! ## Resource Leaking
//!
//! `tempfile()` will (almost) never fail to cleanup temporary files but `NamedTempFile` will if
//! its destructor doesn't run. This is because `tempfile()` relies on the OS to cleanup the
//! underlying file so the file while `NamedTempFile` relies on its destructor to do so.
//!
//! ## Security
//!
//! In the presence of pathological temporary file cleaner, relying on file paths is unsafe because
//! a temporary file cleaner could delete the temporary file which an attacker could then replace.
//!
//! `tempfile()` doesn't rely on file paths so this isn't an issue. However, `NamedTempFile` does
//! rely on file paths.
//!

extern crate libc;
extern crate rand;

#[cfg(windows)]
extern crate winapi;

#[cfg(windows)]
extern crate kernel32;

const NUM_RETRIES: u32 = 1 << 31;
const NUM_RAND_CHARS: usize = 6;

mod util;
mod imp;
mod named;
mod unnamed;

pub use named::{NamedTempFile, NamedTempFileOptions, PersistError};
pub use unnamed::{tempfile, tempfile_in};
<commit_msg>add simple tempfile example<commit_after>//! Securely create and manage temporary files. Temporary files created by this create are
//! automatically deleted.
//!
//! This crate provides two temporary file variants: a `tempfile()` function that returns standard
//! `File` objects and `NamedTempFile`. When choosing between the variants, prefer `tempfile()`
//! unless you either need to know the file's path or to be able to persist it.
//!
//! # Example
//!
//! ```
//! use tempfile::tempfile;
//! use std::fs::File;
//!
//! let mut file: File = tempfile().expect("failed to create temporary file");
//! ```
//!
//! # Differences
//!
//! ## Resource Leaking
//!
//! `tempfile()` will (almost) never fail to cleanup temporary files but `NamedTempFile` will if
//! its destructor doesn't run. This is because `tempfile()` relies on the OS to cleanup the
//! underlying file so the file while `NamedTempFile` relies on its destructor to do so.
//!
//! ## Security
//!
//! In the presence of pathological temporary file cleaner, relying on file paths is unsafe because
//! a temporary file cleaner could delete the temporary file which an attacker could then replace.
//!
//! `tempfile()` doesn't rely on file paths so this isn't an issue. However, `NamedTempFile` does
//! rely on file paths.
//!

extern crate libc;
extern crate rand;

#[cfg(windows)]
extern crate winapi;

#[cfg(windows)]
extern crate kernel32;

const NUM_RETRIES: u32 = 1 << 31;
const NUM_RAND_CHARS: usize = 6;

mod util;
mod imp;
mod named;
mod unnamed;

pub use named::{NamedTempFile, NamedTempFileOptions, PersistError};
pub use unnamed::{tempfile, tempfile_in};
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

pub mod parser;
pub mod ast;
pub mod error;
<commit_msg>Add ansi_term<commit_after>#[macro_use]
extern crate nom;

extern crate ansi_term;

pub mod parser;
pub mod ast;
pub mod error;
<|endoftext|>


<commit_before>#![deny(warnings)]
//! # Sqlite support for the `r2d2` connection pool.
//!
//! Library crate: [r2d2-sqlite](https://crates.io/crates/r2d2-sqlite/)
//!
//! Integrated with: [r2d2](https://crates.io/crates/r2d2)
//! and [rusqlite](https://crates.io/crates/rusqlite)
//!
//! ## Example
//!
//! ```rust,no_run
//! extern crate r2d2;
//! extern crate r2d2_sqlite;
//! extern crate rusqlite;
//!
//! use std::thread;
//! use r2d2_sqlite::SqliteConnectionManager;
//!
//! fn main() {
//!     let config = r2d2::Config::default();
//!     let manager = SqliteConnectionManager::new("file.db");
//!     let pool = r2d2::Pool::new(config, manager).unwrap();
//!
//!     for i in 0..10i32 {
//!         let pool = pool.clone();
//!         thread::spawn(move || {
//!             let conn = pool.get().unwrap();
//!             conn.execute("INSERT INTO foo (bar) VALUES (?)", &[&i]).unwrap();
//!         });
//!     }
//! }
//! ```
extern crate r2d2;
extern crate rusqlite;

use rusqlite::{Connection, Error as RusqliteError, OpenFlags};
use std::path::{Path,PathBuf};

enum ConnectionConfig {
    File(PathBuf, OpenFlags),
}

/// An `r2d2::ManageConnection` for `rusqlite::Connection`s.
pub struct SqliteConnectionManager {
    config: ConnectionConfig,
}

impl SqliteConnectionManager {
    /// Creates a new `SqliteConnectionManager` from file.
    ///
    /// See `rusqlite::Connection::open`
    pub fn new<P:AsRef<Path>>(path: P) -> Self {
        Self::new_with_flags(path, OpenFlags::default())
    }

    /// Creates a new `SqliteConnectionManager` from file with open flags.
    ///
    /// See `rusqlite::Connection::open_with_flags`
    pub fn new_with_flags<P:AsRef<Path>>(path: P, flags: OpenFlags) -> Self {
        SqliteConnectionManager { config: ConnectionConfig::File(path.as_ref().to_path_buf(), flags) }
    }
}

impl r2d2::ManageConnection for SqliteConnectionManager {
    type Connection = Connection;
    type Error = RusqliteError;

    fn connect(&self) -> Result<Connection, RusqliteError> {
        match self.config {
                ConnectionConfig::File(ref path, flags) => Connection::open_with_flags(path, flags),
            }
            .map_err(Into::into)
    }

    fn is_valid(&self, conn: &mut Connection) -> Result<(), RusqliteError> {
        conn.execute_batch("").map_err(Into::into)
    }

    fn has_broken(&self, _: &mut Connection) -> bool {
        false
    }
}
<commit_msg>No need to rename rustqlite::Error to RusqliteError, just use rusqlite:Error<commit_after>#![deny(warnings)]
//! # Sqlite support for the `r2d2` connection pool.
//!
//! Library crate: [r2d2-sqlite](https://crates.io/crates/r2d2-sqlite/)
//!
//! Integrated with: [r2d2](https://crates.io/crates/r2d2)
//! and [rusqlite](https://crates.io/crates/rusqlite)
//!
//! ## Example
//!
//! ```rust,no_run
//! extern crate r2d2;
//! extern crate r2d2_sqlite;
//! extern crate rusqlite;
//!
//! use std::thread;
//! use r2d2_sqlite::SqliteConnectionManager;
//!
//! fn main() {
//!     let config = r2d2::Config::default();
//!     let manager = SqliteConnectionManager::new("file.db");
//!     let pool = r2d2::Pool::new(config, manager).unwrap();
//!
//!     for i in 0..10i32 {
//!         let pool = pool.clone();
//!         thread::spawn(move || {
//!             let conn = pool.get().unwrap();
//!             conn.execute("INSERT INTO foo (bar) VALUES (?)", &[&i]).unwrap();
//!         });
//!     }
//! }
//! ```
extern crate r2d2;
extern crate rusqlite;

use rusqlite::{Connection, Error, OpenFlags};
use std::path::{Path,PathBuf};

enum ConnectionConfig {
    File(PathBuf, OpenFlags),
}

/// An `r2d2::ManageConnection` for `rusqlite::Connection`s.
pub struct SqliteConnectionManager {
    config: ConnectionConfig,
}

impl SqliteConnectionManager {
    /// Creates a new `SqliteConnectionManager` from file.
    ///
    /// See `rusqlite::Connection::open`
    pub fn new<P:AsRef<Path>>(path: P) -> Self {
        Self::new_with_flags(path, OpenFlags::default())
    }

    /// Creates a new `SqliteConnectionManager` from file with open flags.
    ///
    /// See `rusqlite::Connection::open_with_flags`
    pub fn new_with_flags<P:AsRef<Path>>(path: P, flags: OpenFlags) -> Self {
        SqliteConnectionManager { config: ConnectionConfig::File(path.as_ref().to_path_buf(), flags) }
    }
}

impl r2d2::ManageConnection for SqliteConnectionManager {
    type Connection = Connection;
    type Error = rusqlite::Error;

    fn connect(&self) -> Result<Connection, Error> {
        match self.config {
                ConnectionConfig::File(ref path, flags) => Connection::open_with_flags(path, flags),
            }
            .map_err(Into::into)
    }

    fn is_valid(&self, conn: &mut Connection) -> Result<(), Error> {
        conn.execute_batch("").map_err(Into::into)
    }

    fn has_broken(&self, _: &mut Connection) -> bool {
        false
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use mustache;

use std::error;
use std::result;
use std::fmt;
use std::borrow::Cow;

#[derive(Debug, PartialEq, Clone)]
/// Source of an error file
pub struct Source {
    /// File name of the source
    #[doc(hidden)]
    pub file: Option<String>,

    /// Line number of the source
    #[doc(hidden)]
    pub line: Option<u32>,
}

impl Source {
    /// Create an empty source, with both fields set to None
    pub fn empty() -> Source {
        Source {
            file: None,
            line: None,
        }
    }

    /// Create a new source pointing to file
    pub fn new<S: Into<String>>(s: S) -> Source {
        Source {
            file: Some(s.into()),
            line: None,
        }
    }

    /// Sets line number of a source (with &mut self)
    pub fn set_line(&mut self, line: u32) -> &mut Self {
        self.line = Some(line);
        self
    }

    /// Unsets a line number of a source
    #[doc(hidden)]
    pub fn unset_line(&mut self) -> &mut Self {
        self.line = None;
        self
    }
}

impl fmt::Display for Source {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ref file) = self.file {
            try!(write!(f, "{}", file));
            if let Some(line) = self.line {
                try!(write!(f, ":{}", line));
            }
        } else {
            try!(write!(f, "<UNKNOWN FILE>"));
        }
        Ok(())
    }
}

impl<'a> From<&'a Source> for Source {
    fn from(s: &'a Source) -> Source {
        s.clone()
    }
}
#[derive(Debug, PartialEq)]
/// Crowbook Error type
pub struct Error {
    /// Origin (file, line) of the error, if there is one
    source: Source,
    inner: Inner,
}

impl Error {
    /// Creates a new default error
    pub fn default<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::Default(msg.into()),
        }
    }

    /// Creates a new grammar check error
    ///
    /// Used when there is a problem connecting to languagetool
    pub fn grammar_check<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::GrammarCheck(msg.into()),
        }
    }
    /// Creates a new parser error
    ///
    /// Error when parsing markdown file
    pub fn parser<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::Parser(msg.into()),
        }
    }

    /// Creates a new config parser error
    ///
    /// Error when parsing book file
    pub fn config_parser<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::ConfigParser(msg.into()),
        }
    }

    /// Creates a new file not found error
    ///
    /// * msg: description of why the file was needed
    /// * file: file name
    pub fn file_not_found<S1: Into<Cow<'static, str>>, S2: Into<Cow<'static, str>>, O: Into<Source>>
        (source: O,
         msg: S1,
         file: S2)
         -> Error {
        Error {
            source: source.into(),
            inner: Inner::FileNotFound(msg.into(), file.into()),
        }
    }

    /// Creates a new render error
    ///
    /// Error when rendering
    pub fn render<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::Render(msg.into()),
        }
    }

    /// Creates a new template error
    ///
    /// Error when compiling a mustache template
    pub fn template<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::Template(msg.into()),
        }
    }

    /// Creates a new invalid option error
    ///
    /// Error when trying to set an option
    pub fn invalid_option<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::InvalidOption(msg.into()),
        }
    }

    /// Creates a new zipper error
    ///
    /// Error when moving/copying files to temporary dir, e.g. using `zip` commmand
    pub fn zipper<S: Into<Cow<'static, str>>>(msg: S) -> Error {
        Error {
            source: Source::empty(),
            inner: Inner::Zipper(msg.into()),
        }
    }

    /// Creates a new book option error
    ///
    /// Used when converting an error to invalid type
    pub fn book_option<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::BookOption(msg.into()),
        }
    }

    /// Change the source of an error
    pub fn with_source<O: Into<Source>>(mut self, source: O) -> Error {
        self.source = source.into();
        self
    }

    /// Returns true if self is a default option error, false else
    pub fn is_default(&self) -> bool {
        match self.inner {
            Inner::Default(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a parser error, false else
    pub fn is_parser(&self) -> bool {
        match self.inner {
            Inner::Parser(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a config parser error, false else
    pub fn is_config_parser(&self) -> bool {
        match self.inner {
            Inner::ConfigParser(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a file not found error, false else
    pub fn is_file_not_found(&self) -> bool {
        match self.inner {
            Inner::FileNotFound(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a render error, false else
    pub fn is_render(&self) -> bool {
        match self.inner {
            Inner::Render(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a zipper error, false else
    pub fn is_zipper(&self) -> bool {
        match self.inner {
            Inner::Zipper(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a book option error, false else
    pub fn is_book_option(&self) -> bool {
        match self.inner {
            Inner::BookOption(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is an invalid option error, false else
    pub fn is_invalid_option(&self) -> bool {
        match self.inner {
            Inner::InvalidOption(..) => true,
            _ => false,
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self.inner {
            Inner::Default(ref s) |
            Inner::Parser(ref s) |
            Inner::Zipper(ref s) |
            Inner::BookOption(ref s) |
            Inner::ConfigParser(ref s) |
            Inner::InvalidOption(ref s) |
            Inner::Render(ref s) |
            Inner::Template(ref s) |
            Inner::GrammarCheck(ref s) => s.as_ref(),

            Inner::FileNotFound(..) => "File not found",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let source = &self.source;
        if let Some(ref file) = source.file {
            try!(write!(f, "{}", file));
            if let Some(line) = source.line {
                try!(write!(f, ":{}", line));
            }
            try!(write!(f, ": "));
        }

        try!(match self.inner {
            Inner::Default(ref s) => write!(f, "{}", s),
            Inner::GrammarCheck(ref s) => {
                write!(f,
                       "{}",
                       lformat!("Error connecting to language tool server: {error}",
                                error = s))
            }
            Inner::Parser(ref s) => {
                write!(f,
                       "{}",
                       lformat!("Error parsing markdown: {error}", error = s))
            }
            Inner::ConfigParser(ref s) => {
                try!(f.write_str(&lformat!("Error parsing configuration file: ")));
                f.write_str(s)
            }
            Inner::FileNotFound(ref description, ref file) => {
                write!(f,
                       "{}",
                       lformat!("Could not find file '{file}' for {description}",
                                file = file,
                                description = description))
            }
            Inner::Template(ref s) => {
                write!(f,
                       "{}",
                       lformat!("Error compiling template: {template}", template = s))
            }
            Inner::Render(ref s) => {
                try!(f.write_str(&lformat!("Error during rendering: ")));
                f.write_str(s)
            }
            Inner::Zipper(ref s) => {
                try!(f.write_str(&lformat!("Error during temporary files editing: ")));
                f.write_str(s)
            }
            Inner::BookOption(ref s) => {
                try!(f.write_str(&lformat!("Error converting BookOption: ")));
                f.write_str(s)
            }
            Inner::InvalidOption(ref s) => {
                try!(f.write_str(&lformat!("Error accessing book option: ")));
                f.write_str(s)
            }
        });
        Ok(())
    }
}

/// Crowbook's Result type, used by many methods that can fail
pub type Result<T> = result::Result<T, Error>;

/// Implement our Error from mustache::Error
impl From<mustache::Error> for Error {
    fn from(err: mustache::Error) -> Error {
        Error::template(Source::empty(),
                       format!("{}", err))
    }
}

#[derive(Debug, PartialEq)]
enum Inner {
    /// Default variant
    Default(Cow<'static, str>),
    /// An error in Parsing markdown file
    Parser(Cow<'static, str>),
    /// An error in parsing a book configuration file
    ConfigParser(Cow<'static, str>),
    /// An error when a file is not found
    FileNotFound(Cow<'static, str>, Cow<'static, str>), // description, file
    /// An error in a renderer
    Render(Cow<'static, str>),
    /// An error during "zipping" processus
    Zipper(Cow<'static, str>),
    /// An error relative to BookOption convertion (usually a type error)
    BookOption(Cow<'static, str>),
    /// An invalid option
    InvalidOption(Cow<'static, str>),
    /// Error when compiling template
    Template(Cow<'static, str>),
    /// Error when connecting to LanguageTool
    GrammarCheck(Cow<'static, str>),
}
<commit_msg>Improve docs of error and source<commit_after>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use mustache;

use std::error;
use std::result;
use std::fmt;
use std::borrow::Cow;

#[derive(Debug, PartialEq, Clone)]
/// Source of an error.
///
/// Contains (if it's possible) the file and ideally the line that the user should
/// look at to correct their error.
pub struct Source {
    /// File name of the source
    #[doc(hidden)]
    pub file: Option<String>,

    /// Line number of the source
    #[doc(hidden)]
    pub line: Option<u32>,
}

impl Source {
    /// Create an empty source, with both fields set to None
    pub fn empty() -> Source {
        Source {
            file: None,
            line: None,
        }
    }

    /// Create a new source pointing to file
    pub fn new<S: Into<String>>(s: S) -> Source {
        Source {
            file: Some(s.into()),
            line: None,
        }
    }

    /// Sets line number of a source.
    pub fn set_line(&mut self, line: u32) -> &mut Self {
        self.line = Some(line);
        self
    }

    /// Unsets a line number of a source
    #[doc(hidden)]
    pub fn unset_line(&mut self) -> &mut Self {
        self.line = None;
        self
    }
}

impl fmt::Display for Source {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ref file) = self.file {
            try!(write!(f, "{}", file));
            if let Some(line) = self.line {
                try!(write!(f, ":{}", line));
            }
        } else {
            try!(write!(f, "<UNKNOWN FILE>"));
        }
        Ok(())
    }
}

impl<'a> From<&'a Source> for Source {
    fn from(s: &'a Source) -> Source {
        s.clone()
    }
}
#[derive(Debug, PartialEq)]
/// Crowbook Error type.
///
/// This type tries (when it can) to track where the error came from, to
/// pinpoint the file (at least) and, if possible, the line the user needs
/// to look at.
pub struct Error {
    /// Origin (file, line) of the error, if there is one
    source: Source,
    inner: Inner,
}

impl Error {
    /// Creates a new default error.
    pub fn default<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::Default(msg.into()),
        }
    }

    /// Creates a new grammar check error.
    ///
    /// Used when there is a problem connecting to languagetool
    pub fn grammar_check<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::GrammarCheck(msg.into()),
        }
    }
    /// Creates a new parser error.
    ///
    /// Error when parsing markdown file.
    pub fn parser<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::Parser(msg.into()),
        }
    }

    /// Creates a new config parser error.
    ///
    /// Error when parsing the book configuration file.
    pub fn config_parser<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::ConfigParser(msg.into()),
        }
    }

    /// Creates a new "file not found" error
    ///
    /// # Arguments
    /// * source: the source of the error.
    /// * msg: description of why the file was needed.
    /// * file: file name that wasn't found.
    pub fn file_not_found<S1: Into<Cow<'static, str>>, S2: Into<Cow<'static, str>>, O: Into<Source>>
        (source: O,
         msg: S1,
         file: S2)
         -> Error {
        Error {
            source: source.into(),
            inner: Inner::FileNotFound(msg.into(), file.into()),
        }
    }

    /// Creates a new render error.
    ///
    /// Error when rendering the book to a given format.
    pub fn render<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::Render(msg.into()),
        }
    }

    /// Creates a new template error.
    ///
    /// Error when compiling a mustache template.
    pub fn template<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::Template(msg.into()),
        }
    }

    /// Creates a new invalid option error.
    ///
    /// Error when trying to set an option.
    pub fn invalid_option<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::InvalidOption(msg.into()),
        }
    }

    /// Creates a new zipper error.
    ///
    /// Error when moving/copying files to temporary dir, e.g. using `zip` commmand.
    pub fn zipper<S: Into<Cow<'static, str>>>(msg: S) -> Error {
        Error {
            source: Source::empty(),
            inner: Inner::Zipper(msg.into()),
        }
    }

    /// Creates a new book option error
    ///
    /// Used when converting an error to invalid type.
    pub fn book_option<S: Into<Cow<'static, str>>, O: Into<Source>>(source: O, msg: S) -> Error {
        Error {
            source: source.into(),
            inner: Inner::BookOption(msg.into()),
        }
    }

    /// Change the source of an error.
    pub fn with_source<O: Into<Source>>(mut self, source: O) -> Error {
        self.source = source.into();
        self
    }

    /// Returns true if self is a default option error, false else.
    pub fn is_default(&self) -> bool {
        match self.inner {
            Inner::Default(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a parser error, false else.
    pub fn is_parser(&self) -> bool {
        match self.inner {
            Inner::Parser(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a config parser error, false else.
    pub fn is_config_parser(&self) -> bool {
        match self.inner {
            Inner::ConfigParser(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a file not found error, false else.
    pub fn is_file_not_found(&self) -> bool {
        match self.inner {
            Inner::FileNotFound(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a render error, false else.
    pub fn is_render(&self) -> bool {
        match self.inner {
            Inner::Render(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a zipper error, false else.
    pub fn is_zipper(&self) -> bool {
        match self.inner {
            Inner::Zipper(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is a book option error, false else.
    pub fn is_book_option(&self) -> bool {
        match self.inner {
            Inner::BookOption(..) => true,
            _ => false,
        }
    }

    /// Returns true if self is an invalid option error, false else.
    pub fn is_invalid_option(&self) -> bool {
        match self.inner {
            Inner::InvalidOption(..) => true,
            _ => false,
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self.inner {
            Inner::Default(ref s) |
            Inner::Parser(ref s) |
            Inner::Zipper(ref s) |
            Inner::BookOption(ref s) |
            Inner::ConfigParser(ref s) |
            Inner::InvalidOption(ref s) |
            Inner::Render(ref s) |
            Inner::Template(ref s) |
            Inner::GrammarCheck(ref s) => s.as_ref(),

            Inner::FileNotFound(..) => "File not found",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let source = &self.source;
        if let Some(ref file) = source.file {
            try!(write!(f, "{}", file));
            if let Some(line) = source.line {
                try!(write!(f, ":{}", line));
            }
            try!(write!(f, ": "));
        }

        try!(match self.inner {
            Inner::Default(ref s) => write!(f, "{}", s),
            Inner::GrammarCheck(ref s) => {
                write!(f,
                       "{}",
                       lformat!("Error connecting to language tool server: {error}",
                                error = s))
            }
            Inner::Parser(ref s) => {
                write!(f,
                       "{}",
                       lformat!("Error parsing markdown: {error}", error = s))
            }
            Inner::ConfigParser(ref s) => {
                try!(f.write_str(&lformat!("Error parsing configuration file: ")));
                f.write_str(s)
            }
            Inner::FileNotFound(ref description, ref file) => {
                write!(f,
                       "{}",
                       lformat!("Could not find file '{file}' for {description}",
                                file = file,
                                description = description))
            }
            Inner::Template(ref s) => {
                write!(f,
                       "{}",
                       lformat!("Error compiling template: {template}", template = s))
            }
            Inner::Render(ref s) => {
                try!(f.write_str(&lformat!("Error during rendering: ")));
                f.write_str(s)
            }
            Inner::Zipper(ref s) => {
                try!(f.write_str(&lformat!("Error during temporary files editing: ")));
                f.write_str(s)
            }
            Inner::BookOption(ref s) => {
                try!(f.write_str(&lformat!("Error converting BookOption: ")));
                f.write_str(s)
            }
            Inner::InvalidOption(ref s) => {
                try!(f.write_str(&lformat!("Error accessing book option: ")));
                f.write_str(s)
            }
        });
        Ok(())
    }
}

/// Crowbook's Result type, used by many methods that can fail
pub type Result<T> = result::Result<T, Error>;

/// Implement our Error from mustache::Error
impl From<mustache::Error> for Error {
    fn from(err: mustache::Error) -> Error {
        Error::template(Source::empty(),
                       format!("{}", err))
    }
}

#[derive(Debug, PartialEq)]
enum Inner {
    /// Default variant
    Default(Cow<'static, str>),
    /// An error in Parsing markdown file
    Parser(Cow<'static, str>),
    /// An error in parsing a book configuration file
    ConfigParser(Cow<'static, str>),
    /// An error when a file is not found
    FileNotFound(Cow<'static, str>, Cow<'static, str>), // description, file
    /// An error in a renderer
    Render(Cow<'static, str>),
    /// An error during "zipping" processus
    Zipper(Cow<'static, str>),
    /// An error relative to BookOption convertion (usually a type error)
    BookOption(Cow<'static, str>),
    /// An invalid option
    InvalidOption(Cow<'static, str>),
    /// Error when compiling template
    Template(Cow<'static, str>),
    /// Error when connecting to LanguageTool
    GrammarCheck(Cow<'static, str>),
}
<|endoftext|>


<commit_before><commit_msg>Suppress needless_lifetimes lint in test suite<commit_after><|endoftext|>


<commit_before><commit_msg>Add more information for test failure<commit_after><|endoftext|>