<commit_before>use std::collections::VecDeque;
use std::iter::Peekable;
use lexer::Lexer;
use token::{Token, TokenType};

#[derive(Clone, PartialEq, Eq, Debug)]
enum MessageType {
    PGPMessage,
    PGPPublicKeyBlock,
    PGPPrivateKeyBlock,
    PGPSignature,
    PGPMessagePartXofY(usize, usize),
    PGPMessagePartX(usize),
}

#[derive(Clone, PartialEq, Eq, Debug)]
enum ParseError {
    CorruptHeader,
    EndOfFile,
    ParseError,
}

type ParseResult<T> = Result<T, ParseError>;

impl ParseError {
    fn eof<T>() -> ParseResult<T> {
        Err(ParseError::EndOfFile)
    }

    fn parse_error<T>() -> ParseResult<T> {
        Err(ParseError::ParseError)
    }

    fn corrupt_header<T>() -> ParseResult<T> {
        Err(ParseError::CorruptHeader)
    }
}

pub struct Parser<S> where S: Iterator<Item=char> {
    input:  Peekable<Lexer<S>>,
    lookahead: VecDeque<Token>,
    offset: usize
}

impl<S> Parser<S> where S: Iterator<Item=char> {
    pub fn new(mut input: Lexer<S>) -> Parser<S> {
        Parser {
            input:     input.peekable(),
            lookahead: VecDeque::with_capacity(20),
            offset:    0
        }
    }

    fn peek_token(&mut self) -> Option<Token> {
        if self.lookahead.is_empty() {
            self.offset = 0;
            let next_token = self.input.next();
            if next_token.is_some() {
                self.lookahead.push_back(next_token.clone().unwrap());
                Some(next_token.unwrap())
            } else {
                None
            }
        } else {
            self.sync();
            Some(self.lookahead[self.offset].clone())
        }
    }

    fn read_token(&mut self) -> Option<Token> {
        match self.peek_token() {
            Some(token) => {
                self.offset += 1;
                Some(token)
            }
            None => None
        }
    }

    fn sync(&mut self) {
        if self.offset > self.lookahead.len()-1 {
            let n = self.offset - (self.lookahead.len()-1);
            self.fill(n);
        }
    }

    fn fill(&mut self, amount: usize) {
        for _ in 0..amount {
            match self.input.next() {
                Some(token) => {
                    self.lookahead.push_back(token);
                }
                None => break
            }
        }
    }

    fn reset_offset(&mut self) {
        self.offset = 0;
    }

    fn consume(&mut self) {
        for _ in 0..self.offset {
            self.lookahead.pop_front();
        }
        self.reset_offset();
    }

    fn consume_char(&mut self) {
        if self.lookahead.is_empty() {
            self.reset_offset();
        } else {
            self.lookahead.pop_front();
            if self.offset > 0 {
                self.offset -= 1;
            }
        }
    }

    fn backtrack(&mut self, amount: usize) {
        if amount > self.offset {
            self.reset_offset();
        } else {
            self.offset -= amount;
        }
    }

    fn parse_number(&mut self) -> ParseResult<usize> {
        let mut result = String::new();
        loop {
            match self.peek_token() {
                Some(token) => {
                    match token.token_type() {
                        TokenType::Digit => {
                            result.push_str(token.as_str());
                            self.read_token();
                        }
                        _ => break
                    }
                }
                None => break
            }
        }

        if !result.is_empty() {
            let parse_result = result.parse::<usize>().unwrap();
            Ok(parse_result)
        } else if self.peek_token().is_none() {
            Err(ParseError::EndOfFile)
        } else {
            Err(ParseError::ParseError)
        }
    }

    fn read_or_else(&mut self, tt: TokenType, err: ParseError) -> ParseResult<Token> {
        match self.peek_token() {
            Some(token) => {
                if !token.has_token_type(tt) {
                    return Err(err);
                }
            } None => {
                return Err(ParseError::EndOfFile);
            }
        }

        Ok(self.read_token().unwrap())
    }

    fn parse_x_div_y(&mut self) -> ParseResult<(usize, usize)> {
        let num_x = self.parse_number();
        match num_x {
            Ok(_) => {}
            Err(e) => return Err(e)
        }

        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::ForwardSlash => {}
                    TokenType::FiveDashes => {}
                    _ => {
                        return Err(ParseError::CorruptHeader);
                    }
                }
            }
            None => return Err(ParseError::CorruptHeader)
        }

        let num_y = self.parse_number();
        match num_y {
            Ok(_) => {}
            Err(e) => return Err(e)
        }

        Ok((num_x.unwrap(), num_y.unwrap()))
    }

    fn parse_pgp_message_part(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPMessagePart => {
                        match self.parse_x_div_y() {
                            Ok((x,y)) => {
                                self.consume();
                                return Ok(MessageType::PGPMessagePartXofY(x,y))
                            }
                            Err(_)    => {}
                        }
                        match self.parse_number() {
                            Ok(x)  => {
                                self.consume();
                                return Ok(MessageType::PGPMessagePartX(x))
                            }
                            Err(e) => Err(ParseError::CorruptHeader)
                        }
                    }
                    _ => return Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn parse_pgp_message(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPMessage => {
                        self.consume();
                        Ok(MessageType::PGPMessage)
                    }
                    _ => Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn parse_pgp_publickey_block(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPPublicKeyBlock => {
                        self.consume();
                        Ok(MessageType::PGPPublicKeyBlock)
                    }
                    _ => Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn parse_pgp_privatekey_block(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPPrivateKeyBlock => {
                        self.consume();
                        Ok(MessageType::PGPPrivateKeyBlock)
                    }
                    _ => Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn parse_pgp_signature(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPSignature => {
                        self.consume();
                        Ok(MessageType::PGPSignature)
                    }
                    _ => Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn __parse_header_tail_line(&mut self, tt: TokenType) -> ParseResult<MessageType> {
        match self.read_or_else(TokenType::FiveDashes, ParseError::CorruptHeader) {
            Ok(_)  => {}
            Err(e) => return Err(e)
        }
        match self.read_or_else(tt, ParseError::CorruptHeader) {
            Ok(_) => {}
            Err(e) => return Err(e)
        }

        let message_type = match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPMessagePart     => self.parse_pgp_message_part(),
                    TokenType::PGPMessage         => self.parse_pgp_message(),
                    TokenType::PGPPublicKeyBlock  => self.parse_pgp_publickey_block(),
                    TokenType::PGPPrivateKeyBlock => self.parse_pgp_privatekey_block(),
                    TokenType::PGPSignature       => self.parse_pgp_signature(),
                    _ => return Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        };

        match message_type {
            Ok(_) => {}
            Err(e) => return Err(e)
        }

        match self.read_or_else(TokenType::FiveDashes, ParseError::CorruptHeader) {
            Ok(_)  => {}
            Err(e) => return Err(e)
        }

        self.consume();
        Ok(message_type.unwrap())
    }

    fn parse_header_line(&mut self) -> ParseResult<MessageType> {
        self.__parse_header_tail_line(TokenType::Begin)
    }

    fn parse_tail_line(&mut self) -> ParseResult<MessageType> {
        self.__parse_header_tail_line(TokenType::End)
    }
}

#[cfg(test)]
mod tests {

}
<commit_msg>Implement header parser.<commit_after>use std::collections::VecDeque;
use std::iter::Peekable;
use lexer::Lexer;
use token::{Token, TokenType};

#[derive(Clone, PartialEq, Eq, Debug)]
enum MessageType {
    PGPMessage,
    PGPPublicKeyBlock,
    PGPPrivateKeyBlock,
    PGPSignature,
    PGPMessagePartXofY(usize, usize),
    PGPMessagePartX(usize)
}

#[derive(Clone, PartialEq, Eq, Debug)]
enum HeaderType {
    Version,
    Comment,
    MessageID,
    Hash,
    Charset,
    OtherHeader(String)
}

fn token_type_to_header_type(token_type: TokenType) -> HeaderType {
    match token_type {
        TokenType::Version   => HeaderType::Version,
        TokenType::Comment   => HeaderType::Comment,
        TokenType::MessageID => HeaderType::MessageID,
        TokenType::Hash      => HeaderType::Hash,
        TokenType::Charset   => HeaderType::Charset,
        _                    => HeaderType::OtherHeader(String::new())
    }
}

struct Header {
    header_type: MessageType,
    header_block: Vec<(HeaderType, String)>
}

#[derive(Clone, PartialEq, Eq, Debug)]
enum ParseError {
    CorruptHeader,
    InvalidHeaderLine,
    EndOfFile,
    ParseError,
}

type ParseResult<T> = Result<T, ParseError>;

impl ParseError {
    fn eof<T>() -> ParseResult<T> {
        Err(ParseError::EndOfFile)
    }

    fn parse_error<T>() -> ParseResult<T> {
        Err(ParseError::ParseError)
    }

    fn corrupt_header<T>() -> ParseResult<T> {
        Err(ParseError::CorruptHeader)
    }
}

pub struct Parser<S> where S: Iterator<Item=char> {
    input:  Peekable<Lexer<S>>,
    lookahead: VecDeque<Token>,
    offset: usize
}

impl<S> Parser<S> where S: Iterator<Item=char> {
    pub fn new(mut input: Lexer<S>) -> Parser<S> {
        Parser {
            input:     input.peekable(),
            lookahead: VecDeque::with_capacity(20),
            offset:    0
        }
    }

    fn peek_token(&mut self) -> Option<Token> {
        if self.lookahead.is_empty() {
            self.offset = 0;
            let next_token = self.input.next();
            if next_token.is_some() {
                self.lookahead.push_back(next_token.clone().unwrap());
                Some(next_token.unwrap())
            } else {
                None
            }
        } else {
            self.sync();
            Some(self.lookahead[self.offset].clone())
        }
    }

    fn read_token(&mut self) -> Option<Token> {
        match self.peek_token() {
            Some(token) => {
                self.offset += 1;
                Some(token)
            }
            None => None
        }
    }

    fn sync(&mut self) {
        if self.offset > self.lookahead.len()-1 {
            let n = self.offset - (self.lookahead.len()-1);
            self.fill(n);
        }
    }

    fn fill(&mut self, amount: usize) {
        for _ in 0..amount {
            match self.input.next() {
                Some(token) => {
                    self.lookahead.push_back(token);
                }
                None => break
            }
        }
    }

    fn reset_offset(&mut self) {
        self.offset = 0;
    }

    fn consume(&mut self) {
        for _ in 0..self.offset {
            self.lookahead.pop_front();
        }
        self.reset_offset();
    }

    fn consume_char(&mut self) {
        if self.lookahead.is_empty() {
            self.reset_offset();
        } else {
            self.lookahead.pop_front();
            if self.offset > 0 {
                self.offset -= 1;
            }
        }
    }

    fn backtrack(&mut self, amount: usize) {
        if amount > self.offset {
            self.reset_offset();
        } else {
            self.offset -= amount;
        }
    }

    fn parse_number(&mut self) -> ParseResult<usize> {
        let mut result = String::new();
        loop {
            match self.peek_token() {
                Some(token) => {
                    match token.token_type() {
                        TokenType::Digit => {
                            result.push_str(token.as_str());
                            self.read_token();
                        }
                        _ => break
                    }
                }
                None => break
            }
        }

        if !result.is_empty() {
            let parse_result = result.parse::<usize>().unwrap();
            Ok(parse_result)
        } else if self.peek_token().is_none() {
            Err(ParseError::EndOfFile)
        } else {
            Err(ParseError::ParseError)
        }
    }

    fn read_or_else(&mut self, tt: TokenType, err: ParseError) -> ParseResult<Token> {
        match self.peek_token() {
            Some(token) => {
                if !token.has_token_type(tt) {
                    return Err(err);
                }
            } None => {
                return Err(ParseError::EndOfFile);
            }
        }

        Ok(self.read_token().unwrap())
    }

    fn parse_x_div_y(&mut self) -> ParseResult<(usize, usize)> {
        let num_x = self.parse_number();
        match num_x {
            Ok(_) => {}
            Err(e) => return Err(e)
        }

        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::ForwardSlash => {}
                    TokenType::FiveDashes => {}
                    _ => {
                        return Err(ParseError::CorruptHeader);
                    }
                }
            }
            None => return Err(ParseError::CorruptHeader)
        }

        let num_y = self.parse_number();
        match num_y {
            Ok(_) => {}
            Err(e) => return Err(e)
        }

        Ok((num_x.unwrap(), num_y.unwrap()))
    }

    fn parse_pgp_message_part(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPMessagePart => {
                        match self.parse_x_div_y() {
                            Ok((x,y)) => {
                                self.consume();
                                return Ok(MessageType::PGPMessagePartXofY(x,y))
                            }
                            Err(_)    => {}
                        }
                        match self.parse_number() {
                            Ok(x)  => {
                                self.consume();
                                return Ok(MessageType::PGPMessagePartX(x))
                            }
                            Err(e) => Err(ParseError::CorruptHeader)
                        }
                    }
                    _ => return Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn parse_pgp_message(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPMessage => {
                        self.consume();
                        Ok(MessageType::PGPMessage)
                    }
                    _ => Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn parse_pgp_publickey_block(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPPublicKeyBlock => {
                        self.consume();
                        Ok(MessageType::PGPPublicKeyBlock)
                    }
                    _ => Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn parse_pgp_privatekey_block(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPPrivateKeyBlock => {
                        self.consume();
                        Ok(MessageType::PGPPrivateKeyBlock)
                    }
                    _ => Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn parse_pgp_signature(&mut self) -> ParseResult<MessageType> {
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPSignature => {
                        self.consume();
                        Ok(MessageType::PGPSignature)
                    }
                    _ => Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        }
    }

    fn parse_header_tail_line(&mut self, tt: TokenType) -> ParseResult<MessageType> {
        match self.read_or_else(TokenType::FiveDashes, ParseError::CorruptHeader) {
            Ok(_)  => {}
            Err(e) => return Err(e)
        }
        match self.read_or_else(tt, ParseError::CorruptHeader) {
            Ok(_) => {}
            Err(e) => return Err(e)
        }

        let message_type = match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::PGPMessagePart     => self.parse_pgp_message_part(),
                    TokenType::PGPMessage         => self.parse_pgp_message(),
                    TokenType::PGPPublicKeyBlock  => self.parse_pgp_publickey_block(),
                    TokenType::PGPPrivateKeyBlock => self.parse_pgp_privatekey_block(),
                    TokenType::PGPSignature       => self.parse_pgp_signature(),
                    _ => return Err(ParseError::CorruptHeader)
                }
            }
            None => return Err(ParseError::EndOfFile)
        };

        match message_type {
            Ok(_) => {}
            Err(e) => return Err(e)
        }

        match self.read_or_else(TokenType::FiveDashes, ParseError::CorruptHeader) {
            Ok(_)  => {}
            Err(e) => return Err(e)
        }

        self.consume();
        Ok(message_type.unwrap())
    }

    fn parse_header_line(&mut self) -> ParseResult<MessageType> {
        self.parse_header_tail_line(TokenType::Begin)
    }

    fn parse_tail_line(&mut self) -> ParseResult<MessageType> {
        self.parse_header_tail_line(TokenType::End)
    }

    fn parse_header_text(&mut self) -> ParseResult<String> {
        let mut result = String::new();
        loop {
            match self.peek_token() {
                Some(token) => {
                    match token.token_type() {
                        TokenType::Version
                            | TokenType::Comment
                            | TokenType::MessageID
                            | TokenType::Hash
                            | TokenType::Charset => break,
                        TokenType::BlankLine => break,
                        _ => {
                            result.push_str(token.as_str());
                            self.read_token();
                        }
                    }
                }
                None => {
                    return Err(ParseError::EndOfFile)
                }
            }
        }

        Ok(result)
    }

    fn skip_whitespace(&mut self) -> ParseResult<()> {
        loop {
            match self.peek_token() {
                Some(token) => {
                    match token.token_type() {
                        TokenType::WhiteSpace => {
                            self.read_token();
                        }
                        _ => break
                    }
                }
                None => return Err(ParseError::EndOfFile)
            }
        }

        Ok(())
    }

    fn parse_headerkv(&mut self) -> ParseResult<(HeaderType, String)> {
        let header_type = match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    tt @ TokenType::Version
                        | tt @ TokenType::Comment
                        | tt @ TokenType::MessageID
                        | tt @ TokenType::Hash
                        | tt @ TokenType::Charset => {
                           Ok(token_type_to_header_type(tt))
                    }
                    _ => return Err(ParseError::InvalidHeaderLine)
                }
            }
            None => {
                return Err(ParseError::EndOfFile)
            }
        };
        match header_type {
            Ok(_) => {
                self.read_token();
                self.skip_whitespace();
            }
            Err(e) => return Err(e)
        }
        match self.peek_token() {
            Some(token) => {
                match token.token_type() {
                    TokenType::ColonSpace => {
                        self.read_token();
                        self.skip_whitespace();
                    }
                    _ => return Err(ParseError::InvalidHeaderLine)
                }
            }
            None => {
                return Err(ParseError::EndOfFile)
            }
        }
        let header_text = match self.peek_token() {
            Some(token) => {
                self.parse_header_text()
            }
            None => {
                return Err(ParseError::EndOfFile)
            }
        };
        match header_text {
            Ok(_) => {}
            Err(e) => return Err(e)
        }

        self.consume();
        Ok((header_type.unwrap(), header_text.unwrap()))
    }

    fn parse_header_block(&mut self) -> ParseResult<Vec<(HeaderType, String)>> {
        let mut result = Vec::new();
        loop {
            match self.peek_token() {
                Some(token) => {
                    match token.token_type() {
                        TokenType::Version
                           | TokenType::Comment
                           | TokenType::MessageID
                           | TokenType::Hash
                           | TokenType::Charset => {

                            let kv = self.parse_headerkv();
                            match kv {
                                Ok((key, val)) => {
                                    result.push((key, val));
                                }
                                Err(e) => return Err(e)
                            }
                        }
                        TokenType::BlankLine => {
                            self.read_token();
                            break;
                        }
                        _ => {
                            return Err(ParseError::CorruptHeader)
                        }
                    }
                }
                None => {
                    return Err(ParseError::EndOfFile)
                }
            }
        }

        self.consume();
        Ok(result)
    }

    fn parse_header(&mut self) -> ParseResult<Header> {
        let header_type: ParseResult<MessageType> = match self.parse_header_line() {
            Ok(val) => Ok(val),
            Err(e) => return Err(e)
        };

        self.skip_whitespace();

        let header_block: ParseResult<Vec<(HeaderType, String)>> = match self.parse_header_block() {
            Ok(block) => Ok(block),
            Err(e) => return Err(e)
        };

        let header = Header {
            header_type: header_type.unwrap(),
            header_block: header_block.unwrap()
        };

        Ok(header)
    }
}

#[cfg(test)]
mod tests {

}
<|endoftext|>


<commit_before>use syntax::ast;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::ptr::P;

use block::{Block, Describe, It, Bench};

pub fn parse(parser: &mut Parser) -> Describe {
    parse_describe("sup", parser)
}

fn parse_describe(name: &str, parser: &mut Parser) -> Describe {
    let brace = token::CloseDelim(token::Brace);

    let mut before = vec![];
    let mut after = vec![];
    let mut blocks = vec![];

    loop {
        if parser.token == brace || parser.token == token::Eof {
            break
        }

        let span = parser.span;
        let ident = parser.parse_ident().unwrap();

        match ident.as_str() {
            "describe" | "context" => {
                let (name, _) = parser.parse_str().unwrap();
                parser.expect(&token::OpenDelim(token::Brace)).unwrap();
                let block = Block::Describe(parse_describe(&name, parser));
                parser.expect(&token::CloseDelim(token::Brace)).unwrap();
                blocks.push(block);
            },

            "it" | "test" => {
                let (name, _) = parser.parse_str().unwrap();
                let block = parse_block(parser);

                blocks.push(Block::It(It {
                    name: name.to_string(),
                    block: block
                }))
            },

            "bench" => {
                let (name, _) = parser.parse_str().unwrap();
                parser.expect(&token::BinOp(token::Or)).unwrap();
                let ident = parser.parse_ident().unwrap();
                parser.expect(&token::BinOp(token::Or)).unwrap();
                let block = parse_block(parser);

                blocks.push(Block::Bench(Bench {
                    name: name.to_string(),
                    ident: ident,
                    block: block
                }))
            },

            "before" => {
                before.push(parse_block(parser));
            },

            "after" => {
                after.push(parse_block(parser));
            },

            otherwise => {
                let message = format!("Expected `describe`, `context`, \
`before`, `after`, `it`, `test`, or `bench`, found `{}`", otherwise);
                panic!("{}", parser.span_fatal(span, &message))
            }
        }
    }

    Describe {
        name: name.to_string(),
        before: before,
        after: after,
        blocks: blocks
    }
}

fn parse_block(parser: &mut Parser) -> P<ast::Block> {
    let span = parser.span;
    let block = parser.parse_block().unwrap();
    if block.expr.is_some() {
        panic!("{}", parser.span_fatal(
            span,
            "last expression in this block must be terminated by `;`"))
    }
    block
}
<commit_msg>Fix for `rustc 1.3.0-nightly (8d432fbf1 2015-07-29)`.<commit_after>use syntax::ast;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::ptr::P;

use block::{Block, Describe, It, Bench};

pub fn parse(parser: &mut Parser) -> Describe {
    parse_describe("sup", parser)
}

fn parse_describe(name: &str, parser: &mut Parser) -> Describe {
    let brace = token::CloseDelim(token::Brace);

    let mut before = vec![];
    let mut after = vec![];
    let mut blocks = vec![];

    loop {
        if parser.token == brace || parser.token == token::Eof {
            break
        }

        let span = parser.span;
        let ident = parser.parse_ident().unwrap();

        match &*ident.name.as_str() {
            "describe" | "context" => {
                let (name, _) = parser.parse_str().unwrap();
                parser.expect(&token::OpenDelim(token::Brace)).unwrap();
                let block = Block::Describe(parse_describe(&name, parser));
                parser.expect(&token::CloseDelim(token::Brace)).unwrap();
                blocks.push(block);
            },

            "it" | "test" => {
                let (name, _) = parser.parse_str().unwrap();
                let block = parse_block(parser);

                blocks.push(Block::It(It {
                    name: name.to_string(),
                    block: block
                }))
            },

            "bench" => {
                let (name, _) = parser.parse_str().unwrap();
                parser.expect(&token::BinOp(token::Or)).unwrap();
                let ident = parser.parse_ident().unwrap();
                parser.expect(&token::BinOp(token::Or)).unwrap();
                let block = parse_block(parser);

                blocks.push(Block::Bench(Bench {
                    name: name.to_string(),
                    ident: ident,
                    block: block
                }))
            },

            "before" => {
                before.push(parse_block(parser));
            },

            "after" => {
                after.push(parse_block(parser));
            },

            otherwise => {
                let message = format!("Expected `describe`, `context`, \
`before`, `after`, `it`, `test`, or `bench`, found `{}`", otherwise);
                panic!("{}", parser.span_fatal(span, &message))
            }
        }
    }

    Describe {
        name: name.to_string(),
        before: before,
        after: after,
        blocks: blocks
    }
}

fn parse_block(parser: &mut Parser) -> P<ast::Block> {
    let span = parser.span;
    let block = parser.parse_block().unwrap();
    if block.expr.is_some() {
        panic!("{}", parser.span_fatal(
            span,
            "last expression in this block must be terminated by `;`"))
    }
    block
}
<|endoftext|>


<commit_before>#![cfg(feature = "use_std")]

use std::collections::HashMap;
use std::hash::Hash;
use std::iter::Iterator;

/// A wrapper to allow for an easy [`into_grouping_map_by`](../trait.Itertools.html#method.into_grouping_map_by)
pub struct MapForGrouping<I, F>(I, F);

impl<I, F> MapForGrouping<I, F> {
    pub(crate) fn new(iter: I, key_mapper: F) -> Self {
        Self(iter, key_mapper)
    }
}

impl<K, V, I, F> Iterator for MapForGrouping<I, F>
    where I: Iterator<Item = V>,
          K: Hash + Eq,
          F: FnMut(&V) -> K,
{
    type Item = (K, V);
    fn next(&mut self) -> Option<Self::Item> {
        let val = self.0.next()?;
        Some(((self.1)(&val), val))
    }
}

/// Creates a new `GroupingMap` from `iter`
pub fn new<I, K, V>(iter: I) -> GroupingMap<I>
    where I: Iterator<Item = (K, V)>,
          K: Hash + Eq,
{
    GroupingMap { iter }
}

/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations.
/// It groups elements by their key and at the same time fold each group
/// using some aggregating operation.
///
/// No method on this struct performs temporary allocations.
#[must_use = "GroupingMap is lazy and do nothing unless consumed"]
pub struct GroupingMap<I> {
    iter: I,
}

impl<I, K, V> GroupingMap<I>
    where I: Iterator<Item = (K, V)>,
          K: Hash + Eq,
{
    /// This is the generic way to perform any operations on a `GroupingMap`.
    /// It's suggested to use this method only to implement custom operations
    /// when the already provided ones are not enough.
    ///
    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in an `HashMap`.
    ///
    /// The `operation` function is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group if there is currently one;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being aggregated;
    /// If `operation` returns `Some(element)` then the accumulator is updated with `element`,
    /// otherwise the previous accumulation is discarded.
    ///
    /// Return a `HashMap` associating the key of each group with the result of aggregation of the group elements.
    /// If there's no result then there won't be an entry associated to that key.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let data = vec![2, 8, 5, 7, 9, 0, 4, 10];
    /// let lookup = data.into_iter()
    ///     .into_grouping_map_by(|&n| n % 4)
    ///     .aggregate(|acc, _, val| {
    ///         if val == 0 || val == 10 {
    ///             None
    ///         } else {
    ///             Some(acc.unwrap_or(0) + val)
    ///         }
    ///     });
    ///
    /// assert_eq!(lookup[&0], 4);        // 0 resets the accumulator so only 4 is summed
    /// assert_eq!(lookup[&1], 14);       // 5 + 9
    /// assert_eq!(lookup.get(&2), None); // 10 resets the accumulator and nothing is summed afterward
    /// assert_eq!(lookup[&3], 7);        // 7
    /// assert_eq!(lookup.len(), 3);      // The final keys are only 0, 1 and 2
    /// ```
    pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R>
        where FO: FnMut(Option<R>, &K, V) -> Option<R>,
    {
        let mut destination_map = HashMap::new();

        for (key, val) in self.iter {
            let acc = destination_map.remove(&key);
            if let Some(op_res) = operation(acc, &key, val) {
                destination_map.insert(key, op_res);
            }
        }

        destination_map
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// `init` is the value from which will be cloned the initial value of each accumulator.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = (1..=7)
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .fold(0, |acc, _, val| acc + val);
    ///
    /// assert_eq!(lookup[&0], 9);   // 3 + 6
    /// assert_eq!(lookup[&1], 12);  // 1 + 4 + 7
    /// assert_eq!(lookup[&2], 7);   // 2 + 5
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn fold<FO, R>(self, init: R, mut operation: FO) -> HashMap<K, R>
        where R: Clone,
              FO: FnMut(R, &K, V) -> R,
    {
        self.aggregate(|acc, key, val| {
            let acc = acc.unwrap_or_else(|| init.clone());
            Some(operation(acc, key, val))
        })
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// This is similar to [`fold`] but the initial value of the accumulator is the first element of the group.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// [`fold`]: #tymethod.fold
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = (1..=7)
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .fold_first(|acc, _, val| acc + val);
    ///
    /// assert_eq!(lookup[&0], 9);   // 3 + 6
    /// assert_eq!(lookup[&1], 12);  // 1 + 4 + 7
    /// assert_eq!(lookup[&2], 7);   // 2 + 5
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn fold_first<FO>(self, mut operation: FO) -> HashMap<K, V>
        where FO: FnMut(V, &K, V) -> V,
    {
        self.aggregate(|acc, key, val| {
            Some(match acc {
                Some(acc) => operation(acc, key, val),
                None => val,
            })
        })
    }

    /// Groups elements from the `GroupingMap` source by key and collects the elements of each group in
    /// an instance of `C`. The iteration order is preserved when inserting elements.
    ///
    /// Return a `HashMap` associating the key of each group with the collection containing the elements of that group.
    ///
    /// ```
    /// use itertools::Itertools;
    /// use std::collections::HashSet;
    ///
    /// let lookup = vec![0, 1, 2, 3, 4, 5, 6, 2, 3, 6].into_iter()
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .collect::<HashSet<_>>();
    ///
    /// assert_eq!(lookup[&0], vec![0, 3, 6].into_iter().collect());
    /// assert_eq!(lookup[&1], vec![1, 4].into_iter().collect());
    /// assert_eq!(lookup[&2], vec![2, 5].into_iter().collect());
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn collect<C>(self) -> HashMap<K, C>
        where C: Default + Extend<V>,
    {
        self.aggregate(|acc, _, v| {
            let mut acc = acc.unwrap_or_else(C::default);
            acc.extend(Some(v));
            Some(acc)
        })
    }

    /// Groups elements from the `GroupingMap` source by key and counts them.
    ///
    /// Return a `HashMap` associating the key of each group with the number of elements in that group.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = "This is a string".chars()
    ///     .into_grouping_map_by(|&c| c)
    ///     .count();
    ///
    /// assert_eq!(lookup[&'T'], 1);
    /// assert_eq!(lookup[&'h'], 1);
    /// assert_eq!(lookup[&'i'], 3);
    /// assert_eq!(lookup[&'s'], 3);
    /// assert_eq!(lookup[&' '], 3);
    /// assert_eq!(lookup[&'a'], 1);
    /// assert_eq!(lookup[&'t'], 1);
    /// assert_eq!(lookup[&'r'], 1);
    /// assert_eq!(lookup[&'n'], 1);
    /// assert_eq!(lookup[&'g'], 1);
    /// assert_eq!(lookup.len(), 10);
    /// ```
    pub fn count(self) -> HashMap<K, usize> {
        self.fold(0, |acc, _, _| acc + 1)
    }
}
<commit_msg>Added GroupingMap::{max, max_by, max_by_key, min, min_by, min_by_key}<commit_after>#![cfg(feature = "use_std")]

use std::collections::HashMap;
use std::cmp::Ordering;
use std::hash::Hash;
use std::iter::Iterator;

/// A wrapper to allow for an easy [`into_grouping_map_by`](../trait.Itertools.html#method.into_grouping_map_by)
pub struct MapForGrouping<I, F>(I, F);

impl<I, F> MapForGrouping<I, F> {
    pub(crate) fn new(iter: I, key_mapper: F) -> Self {
        Self(iter, key_mapper)
    }
}

impl<K, V, I, F> Iterator for MapForGrouping<I, F>
    where I: Iterator<Item = V>,
          K: Hash + Eq,
          F: FnMut(&V) -> K,
{
    type Item = (K, V);
    fn next(&mut self) -> Option<Self::Item> {
        let val = self.0.next()?;
        Some(((self.1)(&val), val))
    }
}

/// Creates a new `GroupingMap` from `iter`
pub fn new<I, K, V>(iter: I) -> GroupingMap<I>
    where I: Iterator<Item = (K, V)>,
          K: Hash + Eq,
{
    GroupingMap { iter }
}

/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations.
/// It groups elements by their key and at the same time fold each group
/// using some aggregating operation.
///
/// No method on this struct performs temporary allocations.
#[must_use = "GroupingMap is lazy and do nothing unless consumed"]
pub struct GroupingMap<I> {
    iter: I,
}

impl<I, K, V> GroupingMap<I>
    where I: Iterator<Item = (K, V)>,
          K: Hash + Eq,
{
    /// This is the generic way to perform any operations on a `GroupingMap`.
    /// It's suggested to use this method only to implement custom operations
    /// when the already provided ones are not enough.
    ///
    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in an `HashMap`.
    ///
    /// The `operation` function is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group if there is currently one;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being aggregated;
    /// If `operation` returns `Some(element)` then the accumulator is updated with `element`,
    /// otherwise the previous accumulation is discarded.
    ///
    /// Return a `HashMap` associating the key of each group with the result of aggregation of the group elements.
    /// If there's no result then there won't be an entry associated to that key.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let data = vec![2, 8, 5, 7, 9, 0, 4, 10];
    /// let lookup = data.into_iter()
    ///     .into_grouping_map_by(|&n| n % 4)
    ///     .aggregate(|acc, _, val| {
    ///         if val == 0 || val == 10 {
    ///             None
    ///         } else {
    ///             Some(acc.unwrap_or(0) + val)
    ///         }
    ///     });
    ///
    /// assert_eq!(lookup[&0], 4);        // 0 resets the accumulator so only 4 is summed
    /// assert_eq!(lookup[&1], 14);       // 5 + 9
    /// assert_eq!(lookup.get(&2), None); // 10 resets the accumulator and nothing is summed afterward
    /// assert_eq!(lookup[&3], 7);        // 7
    /// assert_eq!(lookup.len(), 3);      // The final keys are only 0, 1 and 2
    /// ```
    pub fn aggregate<FO, R>(self, mut operation: FO) -> HashMap<K, R>
        where FO: FnMut(Option<R>, &K, V) -> Option<R>,
    {
        let mut destination_map = HashMap::new();

        for (key, val) in self.iter {
            let acc = destination_map.remove(&key);
            if let Some(op_res) = operation(acc, &key, val) {
                destination_map.insert(key, op_res);
            }
        }

        destination_map
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// `init` is the value from which will be cloned the initial value of each accumulator.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = (1..=7)
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .fold(0, |acc, _, val| acc + val);
    ///
    /// assert_eq!(lookup[&0], 9);   // 3 + 6
    /// assert_eq!(lookup[&1], 12);  // 1 + 4 + 7
    /// assert_eq!(lookup[&2], 7);   // 2 + 5
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn fold<FO, R>(self, init: R, mut operation: FO) -> HashMap<K, R>
        where R: Clone,
              FO: FnMut(R, &K, V) -> R,
    {
        self.aggregate(|acc, key, val| {
            let acc = acc.unwrap_or_else(|| init.clone());
            Some(operation(acc, key, val))
        })
    }

    /// Groups elements from the `GroupingMap` source by key and applies `operation` to the elements
    /// of each group sequentially, passing the previously accumulated value, a reference to the key
    /// and the current element as arguments, and stores the results in a new map.
    ///
    /// This is similar to [`fold`] but the initial value of the accumulator is the first element of the group.
    ///
    /// `operation` is a function that is invoked on each element with the following parameters:
    ///  - the current value of the accumulator of the group;
    ///  - a reference to the key of the group this element belongs to;
    ///  - the element from the source being accumulated.
    ///
    /// Return a `HashMap` associating the key of each group with the result of folding the group elements.
    ///
    /// [`fold`]: #tymethod.fold
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = (1..=7)
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .fold_first(|acc, _, val| acc + val);
    ///
    /// assert_eq!(lookup[&0], 9);   // 3 + 6
    /// assert_eq!(lookup[&1], 12);  // 1 + 4 + 7
    /// assert_eq!(lookup[&2], 7);   // 2 + 5
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn fold_first<FO>(self, mut operation: FO) -> HashMap<K, V>
        where FO: FnMut(V, &K, V) -> V,
    {
        self.aggregate(|acc, key, val| {
            Some(match acc {
                Some(acc) => operation(acc, key, val),
                None => val,
            })
        })
    }

    /// Groups elements from the `GroupingMap` source by key and collects the elements of each group in
    /// an instance of `C`. The iteration order is preserved when inserting elements.
    ///
    /// Return a `HashMap` associating the key of each group with the collection containing the elements of that group.
    ///
    /// ```
    /// use itertools::Itertools;
    /// use std::collections::HashSet;
    ///
    /// let lookup = vec![0, 1, 2, 3, 4, 5, 6, 2, 3, 6].into_iter()
    ///     .into_grouping_map_by(|&n| n % 3)
    ///     .collect::<HashSet<_>>();
    ///
    /// assert_eq!(lookup[&0], vec![0, 3, 6].into_iter().collect());
    /// assert_eq!(lookup[&1], vec![1, 4].into_iter().collect());
    /// assert_eq!(lookup[&2], vec![2, 5].into_iter().collect());
    /// assert_eq!(lookup.len(), 3);
    /// ```
    pub fn collect<C>(self) -> HashMap<K, C>
        where C: Default + Extend<V>,
    {
        self.aggregate(|acc, _, v| {
            let mut acc = acc.unwrap_or_else(C::default);
            acc.extend(Some(v));
            Some(acc)
        })
    }

    /// Groups elements from the `GroupingMap` source by key and counts them.
    ///
    /// Return a `HashMap` associating the key of each group with the number of elements in that group.
    ///
    /// ```
    /// use itertools::Itertools;
    ///
    /// let lookup = "This is a string".chars()
    ///     .into_grouping_map_by(|&c| c)
    ///     .count();
    ///
    /// assert_eq!(lookup[&'T'], 1);
    /// assert_eq!(lookup[&'h'], 1);
    /// assert_eq!(lookup[&'i'], 3);
    /// assert_eq!(lookup[&'s'], 3);
    /// assert_eq!(lookup[&' '], 3);
    /// assert_eq!(lookup[&'a'], 1);
    /// assert_eq!(lookup[&'t'], 1);
    /// assert_eq!(lookup[&'r'], 1);
    /// assert_eq!(lookup[&'n'], 1);
    /// assert_eq!(lookup[&'g'], 1);
    /// assert_eq!(lookup.len(), 10);
    /// ```
    pub fn count(self) -> HashMap<K, usize> {
        self.fold(0, |acc, _, _| acc + 1)
    }

    pub fn max(self) -> HashMap<K, V>
        where V: Ord,
    {
        self.fold_first(|acc, _, val| std::cmp::max(acc, val))
    }

    pub fn max_by<F>(self, mut compare: F) -> HashMap<K, V>
        where F: FnMut(&V, &V) -> Ordering,
    {
        self.fold_first(|acc, _, val| match compare(&acc, &val) {
            Ordering::Less | Ordering::Equal => val,
            Ordering::Greater => acc
        })
    }

    pub fn max_by_key<F, CK>(self, mut f: F) -> HashMap<K, V>
        where F: FnMut(&V) -> CK,
              CK: Ord,
    {
        self.max_by(|v1, v2| f(&v1).cmp(&f(&v2)))
    }

    pub fn min(self) -> HashMap<K, V>
        where V: Ord,
    {
        self.fold_first(|acc, _, val| std::cmp::min(acc, val))
    }

    pub fn min_by<F>(self, mut compare: F) -> HashMap<K, V>
        where F: FnMut(&V, &V) -> Ordering,
    {
        self.fold_first(|acc, _, val| match compare(&acc, &val) {
            Ordering::Less | Ordering::Equal => acc,
            Ordering::Greater => val
        })
    }

    pub fn min_by_key<F, CK>(self, mut f: F) -> HashMap<K, V>
        where F: FnMut(&V) -> CK,
              CK: Ord,
    {
        self.min_by(|v1, v2| f(&v1).cmp(&f(&v2)))
    }
}
<|endoftext|>


<commit_before>//! Image Processing Functions
use std::cmp;

use image:: {
    SubImage,
    GenericImage,
};

use buffer::Pixel;

pub use self::sample::FilterType;

pub use self::sample::FilterType:: {
    Triangle,
    Nearest,
    CatmullRom,
    Gaussian,
    Lanczos3
};

/// Affine transformations
pub use self::affine:: {
    rotate90,
    rotate180,
    rotate270,
    flip_horizontal,
    flip_vertical,
};

/// Image sampling
pub use self::sample:: {
    filter3x3,
    resize,
    blur,
    unsharpen,
};

/// Color operations
pub use self::colorops:: {
    grayscale,
    invert,
    contrast,
    brighten,
    huerotate,
    ColorMap,
    BiLevel,
    dither,
    index_colors,
};

mod affine;
/// Public only because of Rust bug:
/// https://github.com/rust-lang/rust/issues/18241
pub mod colorops;
mod sample;

/// Return a mutable view into an image
// TODO: Is a 'static bound on `I` really required? Acn we avoid it?
pub fn crop<I: GenericImage + 'static>(image: &mut I, x: u32, y: u32,
                                       width: u32, height: u32)
                                       -> SubImage<I>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {

    let (iwidth, iheight) = image.dimensions();

    let x = cmp::min(x, iwidth);
    let y = cmp::min(y, iheight);

    let height = cmp::min(height, iheight - y);
    let width  = cmp::min(width, iwidth - x);

    SubImage::new(image, x, y, width, height)
}

/// Overlay an image at a given coordinate (x, y)
pub fn overlay<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y:u32) {
    let (top_width, top_height) = top.dimensions();
    let (bottom_width, bottom_height) = bottom.dimensions();

    // Crop our top image if we're going out of bounds
    let range_width = if x + top_width > bottom_width {
        bottom_width - x
    } else {
        top_width
    };

    let range_height = if y + top_height > bottom_height {
        bottom_height - y
    } else {
        top_height
    };

    for top_y in 0..range_height {
        for top_x in 0..range_width {
            let p = top.get_pixel(top_x, top_y);
            bottom.get_pixel_mut(x + top_x, y + top_y).blend(&p);
        }
    }
}

/// Replace the contents of an image at a given coordinate (x, y)
pub fn replace<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y:u32) {
    let (top_width, top_height) = top.dimensions();
    let (bottom_width, bottom_height) = bottom.dimensions();

    // Crop our top image if we're going out of bounds
    let range_width = if x + top_width > bottom_width {
        bottom_width - x
    } else {
        top_width
    };

    let range_height = if y + top_height > bottom_height {
        bottom_height - y
    } else {
        top_height
    };

    for top_y in 0..range_height {
        for top_x in 0..range_width {
            let p = top.get_pixel(top_x, top_y);
            *bottom.get_pixel_mut(x + top_x, y + top_y)= p;
        }
    }
}

#[cfg(test)]
mod tests {

    use image::GenericImage;
    use buffer::ImageBuffer;
    use color::{Rgb};
    use super::overlay;

    #[test]
    /// Test that images written into other images works
    fn test_image_in_image() {
        let mut target = ImageBuffer::new(32, 32);
        let source = ImageBuffer::from_pixel(16, 16, Rgb([255u8, 0, 0]));
        overlay(&mut target, &source, 0, 0);
        assert!(*target.get_pixel(0, 0) == Rgb([255u8, 0, 0]));
        assert!(*target.get_pixel(15, 0) == Rgb([255u8, 0, 0]));
        assert!(*target.get_pixel(16, 0) == Rgb([0u8, 0, 0]));
        assert!(*target.get_pixel(0, 15) == Rgb([255u8, 0, 0]));
        assert!(*target.get_pixel(0, 16) == Rgb([0u8, 0, 0]));
    }

    #[test]
    /// Test that images written outside of a frame doesn't blow up
    fn test_image_in_image_outside_of_bounds() {
        let mut target = ImageBuffer::new(32, 32);
        let source = ImageBuffer::from_pixel(32, 32, Rgb([255u8, 0, 0]));
        overlay(&mut target, &source, 1, 1);
        assert!(*target.get_pixel(0, 0) == Rgb([0, 0, 0]));
        assert!(*target.get_pixel(1, 1) == Rgb([255u8, 0, 0]));
        assert!(*target.get_pixel(31, 31) == Rgb([255u8, 0, 0]));
    }

}
<commit_msg>Updated overlay() and replace() to stop using deprecated and implemented get_pixel_mut method<commit_after>//! Image Processing Functions
use std::cmp;

use image:: {
    SubImage,
    GenericImage,
};

use buffer::Pixel;

pub use self::sample::FilterType;

pub use self::sample::FilterType:: {
    Triangle,
    Nearest,
    CatmullRom,
    Gaussian,
    Lanczos3
};

/// Affine transformations
pub use self::affine:: {
    rotate90,
    rotate180,
    rotate270,
    flip_horizontal,
    flip_vertical,
};

/// Image sampling
pub use self::sample:: {
    filter3x3,
    resize,
    blur,
    unsharpen,
};

/// Color operations
pub use self::colorops:: {
    grayscale,
    invert,
    contrast,
    brighten,
    huerotate,
    ColorMap,
    BiLevel,
    dither,
    index_colors,
};

mod affine;
/// Public only because of Rust bug:
/// https://github.com/rust-lang/rust/issues/18241
pub mod colorops;
mod sample;

/// Return a mutable view into an image
// TODO: Is a 'static bound on `I` really required? Acn we avoid it?
pub fn crop<I: GenericImage + 'static>(image: &mut I, x: u32, y: u32,
                                       width: u32, height: u32)
                                       -> SubImage<I>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {

    let (iwidth, iheight) = image.dimensions();

    let x = cmp::min(x, iwidth);
    let y = cmp::min(y, iheight);

    let height = cmp::min(height, iheight - y);
    let width  = cmp::min(width, iwidth - x);

    SubImage::new(image, x, y, width, height)
}

/// Overlay an image at a given coordinate (x, y)
pub fn overlay<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y:u32) {
    let (top_width, top_height) = top.dimensions();
    let (bottom_width, bottom_height) = bottom.dimensions();

    // Crop our top image if we're going out of bounds
    let range_width = if x + top_width > bottom_width {
        bottom_width - x
    } else {
        top_width
    };

    let range_height = if y + top_height > bottom_height {
        bottom_height - y
    } else {
        top_height
    };

    for top_y in 0..range_height {
        for top_x in 0..range_width {
            let p = top.get_pixel(top_x, top_y);
            let mut bottom_pixel = bottom.get_pixel(x + top_x, y + top_y);
            bottom_pixel.blend(&p);

            bottom.put_pixel(x + top_x, y + top_y, bottom_pixel);
        }
    }
}

/// Replace the contents of an image at a given coordinate (x, y)
pub fn replace<I: GenericImage>(bottom: &mut I, top: &I, x: u32, y:u32) {
    let (top_width, top_height) = top.dimensions();
    let (bottom_width, bottom_height) = bottom.dimensions();

    // Crop our top image if we're going out of bounds
    let range_width = if x + top_width > bottom_width {
        bottom_width - x
    } else {
        top_width
    };

    let range_height = if y + top_height > bottom_height {
        bottom_height - y
    } else {
        top_height
    };

    for top_y in 0..range_height {
        for top_x in 0..range_width {
            let p = top.get_pixel(top_x, top_y);
            bottom.put_pixel(x + top_x, y + top_y, p);
        }
    }
}

#[cfg(test)]
mod tests {

    use image::GenericImage;
    use buffer::ImageBuffer;
    use color::{Rgb};
    use super::overlay;

    #[test]
    /// Test that images written into other images works
    fn test_image_in_image() {
        let mut target = ImageBuffer::new(32, 32);
        let source = ImageBuffer::from_pixel(16, 16, Rgb([255u8, 0, 0]));
        overlay(&mut target, &source, 0, 0);
        assert!(*target.get_pixel(0, 0) == Rgb([255u8, 0, 0]));
        assert!(*target.get_pixel(15, 0) == Rgb([255u8, 0, 0]));
        assert!(*target.get_pixel(16, 0) == Rgb([0u8, 0, 0]));
        assert!(*target.get_pixel(0, 15) == Rgb([255u8, 0, 0]));
        assert!(*target.get_pixel(0, 16) == Rgb([0u8, 0, 0]));
    }

    #[test]
    /// Test that images written outside of a frame doesn't blow up
    fn test_image_in_image_outside_of_bounds() {
        let mut target = ImageBuffer::new(32, 32);
        let source = ImageBuffer::from_pixel(32, 32, Rgb([255u8, 0, 0]));
        overlay(&mut target, &source, 1, 1);
        assert!(*target.get_pixel(0, 0) == Rgb([0, 0, 0]));
        assert!(*target.get_pixel(1, 1) == Rgb([255u8, 0, 0]));
        assert!(*target.get_pixel(31, 31) == Rgb([255u8, 0, 0]));
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use capnp::{any_pointer};
use capnp::Error;
use capnp::capability::Promise;
use capnp::private::capability::{ClientHook, ParamsHook, PipelineHook, PipelineOp,
                                 ResultsHook, ResultsDoneHook};

use futures::Future;

use std::cell::RefCell;
use std::rc::{Rc};

use {broken, local, ForkedPromise};

struct PipelineInner {
    promise: ForkedPromise<Promise<Box<PipelineHook>, Error>>,

    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<PipelineHook>>,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,
}

pub struct Pipeline {
    inner: Rc<RefCell<PipelineInner>>,
}

impl Pipeline {
    pub fn new(promise_param: Promise<Box<PipelineHook>, Error>) -> Pipeline {
        let promise = ForkedPromise::new(promise_param);
        let branch = promise.clone();
        let inner = Rc::new(RefCell::new(PipelineInner {
            promise: promise,
            redirect: None,
            self_resolution_op: Promise::ok(()),
        }));
        let this = Rc::downgrade(&inner);
        let self_res = ::eagerly_evaluate(branch.then(move |result| {
            let this = this.upgrade().expect("dangling self reference?");
            match result {
                Ok(pipeline_hook) => {
                    this.borrow_mut().redirect = Some(pipeline_hook);
                }
                Err(e) => {
                    this.borrow_mut().redirect = Some(Box::new(broken::Pipeline::new(e)));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_res;
        Pipeline { inner: inner }
    }
}

impl Clone for Pipeline {
    fn clone(&self) -> Pipeline {
        Pipeline { inner: self.inner.clone() }
    }
}

impl PipelineHook for Pipeline {
    fn add_ref(&self) -> Box<PipelineHook> {
        Box::new(self.clone())
    }
    fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<ClientHook> {
        let mut cp = Vec::with_capacity(ops.len());
        for &op in ops {
            cp.push(op);
        }
        self.get_pipelined_cap_move(cp)
    }

    fn get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<ClientHook> {
        match &self.inner.borrow().redirect {
            &Some(ref p) => {
                return p.get_pipelined_cap_move(ops)
            }
            &None => (),
        }
        let client_promise = self.inner.borrow_mut().promise.clone().map(move |pipeline| {
            pipeline.get_pipelined_cap_move(ops)
        });

        Box::new(Client::new(Promise::from_future(client_promise)))
    }
}

type ClientHookPromiseFork = ForkedPromise<Promise<Box<ClientHook>, Error>>;

struct ClientInner {
    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<ClientHook>>,

    // Promise that resolves when we have a new ClientHook to forward to.
    //
    // This fork shall only have three branches:  `selfResolutionOp`, `promiseForCallForwarding`, and
    // `promiseForClientResolution`, in that order.
    _promise: ClientHookPromiseFork,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,

    // When this promise resolves, each queued call will be forwarded to the real client.  This needs
    // to occur *before* any 'whenMoreResolved()' promises resolve, because we want to make sure
    // previously-queued calls are delivered before any new calls made in response to the resolution.
    promise_for_call_forwarding: ClientHookPromiseFork,

    // whenMoreResolved() returns forks of this promise.  These must resolve *after* queued calls
    // have been initiated (so that any calls made in the whenMoreResolved() handler are correctly
    // delivered after calls made earlier), but *before* any queued calls return (because it might
    // confuse the application if a queued call returns before the capability on which it was made
    // resolves).  Luckily, we know that queued calls will involve, at the very least, an
    // eventLoop.evalLater.
    promise_for_client_resolution: ClientHookPromiseFork,
}

pub struct Client {
    inner: Rc<RefCell<ClientInner>>,
}

impl Client {
    pub fn new(promise_param: Promise<Box<ClientHook>, Error>)
           -> Client
    {
        let promise = ForkedPromise::new(promise_param);
        let branch1 = promise.clone();
        let branch2 = promise.clone();
        let branch3 = promise.clone();
        let inner = Rc::new(RefCell::new(ClientInner {
            redirect: None,
            _promise: promise,
            self_resolution_op: Promise::from_future(::futures::future::empty()),
            promise_for_call_forwarding: ForkedPromise::new(Promise::from_future(branch2)),
            promise_for_client_resolution: ForkedPromise::new(Promise::from_future(branch3)),
        }));
        let this = Rc::downgrade(&inner);
        let self_resolution_op = ::eagerly_evaluate(branch1.then(move |result| {
            let state = this.upgrade().expect("dangling reference to QueuedClient");
            match result {
                Ok(clienthook) => {
                    state.borrow_mut().redirect = Some(clienthook);
                }
                Err(e) => {
                    state.borrow_mut().redirect = Some(broken::new_cap(e));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_resolution_op;
        Client {
            inner: inner
        }
    }
}

impl ClientHook for Client {
    fn add_ref(&self) -> Box<ClientHook> {
        Box::new(Client {inner: self.inner.clone()})
    }
    fn new_call(&self, interface_id: u64, method_id: u16,
                size_hint: Option<::capnp::MessageSize>)
                -> ::capnp::capability::Request<any_pointer::Owned, any_pointer::Owned>
    {
        ::capnp::capability::Request::new(
            Box::new(local::Request::new(interface_id, method_id, size_hint, self.add_ref())))
    }

    fn call(&self, interface_id: u64, method_id: u16, params: Box<ParamsHook>, results: Box<ResultsHook>,
            results_done: Promise<Box<ResultsDoneHook>, Error>)
        -> (Promise<(), Error>, Box<PipelineHook>)
    {
        // The main reason this is complicated is that we don't want the call to get cancelled
        // if the caller drops just the returned promise but not the pipeline.
        struct CallResultHolder {
            promise: Option<Promise<(), Error>>,
            pipeline: Option<Box<PipelineHook>>,
        }

        let call_result_promise =
            ForkedPromise::new(Box::new(self.inner.borrow_mut().promise_for_call_forwarding.clone().and_then(move |client| {
                let (promise, pipeline) = client.call(interface_id, method_id, params, results, results_done);
                Ok(Rc::new(RefCell::new(CallResultHolder {
                    promise: Some(promise),
                    pipeline: Some(pipeline),
                })))
            })));

        let pipeline_promise = call_result_promise.clone().and_then(|call_result| {
            Ok(call_result.borrow_mut().pipeline.take().expect("pipeline gone?"))
        });
        let pipeline = Pipeline::new(Promise::from_future(pipeline_promise));

        let completion_promise = call_result_promise.and_then(|call_result| {
            call_result.borrow_mut().promise.take().expect("promise gone?")
        });

        (Promise::from_future(completion_promise), Box::new(pipeline))
    }

    fn get_ptr(&self) -> usize {
        (&*self.inner.borrow()) as * const _ as usize
    }

    fn get_brand(&self) -> usize {
        0
    }

    fn get_resolved(&self) -> Option<Box<ClientHook>> {
        match self.inner.borrow().redirect {
            Some(ref inner) => Some(inner.clone()),
            None => None,
        }
    }

    fn when_more_resolved(&self) -> Option<Promise<Box<ClientHook>, Error>> {
        Some(Promise::from_future(self.inner.borrow_mut().promise_for_client_resolution.clone()))
    }
}
<commit_msg>eliminate some panics<commit_after>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use capnp::{any_pointer};
use capnp::Error;
use capnp::capability::Promise;
use capnp::private::capability::{ClientHook, ParamsHook, PipelineHook, PipelineOp,
                                 ResultsHook, ResultsDoneHook};

use futures::Future;

use std::cell::RefCell;
use std::rc::{Rc};

use {broken, local, ForkedPromise};

struct PipelineInner {
    promise: ForkedPromise<Promise<Box<PipelineHook>, Error>>,

    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<PipelineHook>>,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,
}

pub struct Pipeline {
    inner: Rc<RefCell<PipelineInner>>,
}

impl Pipeline {
    pub fn new(promise_param: Promise<Box<PipelineHook>, Error>) -> Pipeline {
        let promise = ForkedPromise::new(promise_param);
        let branch = promise.clone();
        let inner = Rc::new(RefCell::new(PipelineInner {
            promise: promise,
            redirect: None,
            self_resolution_op: Promise::ok(()),
        }));
        let this = Rc::downgrade(&inner);
        let self_res = ::eagerly_evaluate(branch.then(move |result| {
            let this = match this.upgrade(){
                Some(v) => v,
                None => return Err(Error::failed("dangling self reference in queued::Pipeline".into())),
            };
            match result {
                Ok(pipeline_hook) => {
                    this.borrow_mut().redirect = Some(pipeline_hook);
                }
                Err(e) => {
                    this.borrow_mut().redirect = Some(Box::new(broken::Pipeline::new(e)));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_res;
        Pipeline { inner: inner }
    }
}

impl Clone for Pipeline {
    fn clone(&self) -> Pipeline {
        Pipeline { inner: self.inner.clone() }
    }
}

impl PipelineHook for Pipeline {
    fn add_ref(&self) -> Box<PipelineHook> {
        Box::new(self.clone())
    }
    fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<ClientHook> {
        let mut cp = Vec::with_capacity(ops.len());
        for &op in ops {
            cp.push(op);
        }
        self.get_pipelined_cap_move(cp)
    }

    fn get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<ClientHook> {
        match &self.inner.borrow().redirect {
            &Some(ref p) => {
                return p.get_pipelined_cap_move(ops)
            }
            &None => (),
        }
        let client_promise = self.inner.borrow_mut().promise.clone().map(move |pipeline| {
            pipeline.get_pipelined_cap_move(ops)
        });

        Box::new(Client::new(Promise::from_future(client_promise)))
    }
}

type ClientHookPromiseFork = ForkedPromise<Promise<Box<ClientHook>, Error>>;

struct ClientInner {
    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<ClientHook>>,

    // Promise that resolves when we have a new ClientHook to forward to.
    //
    // This fork shall only have three branches:  `selfResolutionOp`, `promiseForCallForwarding`, and
    // `promiseForClientResolution`, in that order.
    _promise: ClientHookPromiseFork,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,

    // When this promise resolves, each queued call will be forwarded to the real client.  This needs
    // to occur *before* any 'whenMoreResolved()' promises resolve, because we want to make sure
    // previously-queued calls are delivered before any new calls made in response to the resolution.
    promise_for_call_forwarding: ClientHookPromiseFork,

    // whenMoreResolved() returns forks of this promise.  These must resolve *after* queued calls
    // have been initiated (so that any calls made in the whenMoreResolved() handler are correctly
    // delivered after calls made earlier), but *before* any queued calls return (because it might
    // confuse the application if a queued call returns before the capability on which it was made
    // resolves).  Luckily, we know that queued calls will involve, at the very least, an
    // eventLoop.evalLater.
    promise_for_client_resolution: ClientHookPromiseFork,
}

pub struct Client {
    inner: Rc<RefCell<ClientInner>>,
}

impl Client {
    pub fn new(promise_param: Promise<Box<ClientHook>, Error>)
           -> Client
    {
        let promise = ForkedPromise::new(promise_param);
        let branch1 = promise.clone();
        let branch2 = promise.clone();
        let branch3 = promise.clone();
        let inner = Rc::new(RefCell::new(ClientInner {
            redirect: None,
            _promise: promise,
            self_resolution_op: Promise::from_future(::futures::future::empty()),
            promise_for_call_forwarding: ForkedPromise::new(Promise::from_future(branch2)),
            promise_for_client_resolution: ForkedPromise::new(Promise::from_future(branch3)),
        }));
        let this = Rc::downgrade(&inner);
        let self_resolution_op = ::eagerly_evaluate(branch1.then(move |result| {
            let state = match this.upgrade() {
                Some(s) => s,
                None => return Err(Error::failed("dangling reference to QueuedClient".into())),
            };
            match result {
                Ok(clienthook) => {
                    state.borrow_mut().redirect = Some(clienthook);
                }
                Err(e) => {
                    state.borrow_mut().redirect = Some(broken::new_cap(e));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_resolution_op;
        Client {
            inner: inner
        }
    }
}

impl ClientHook for Client {
    fn add_ref(&self) -> Box<ClientHook> {
        Box::new(Client {inner: self.inner.clone()})
    }
    fn new_call(&self, interface_id: u64, method_id: u16,
                size_hint: Option<::capnp::MessageSize>)
                -> ::capnp::capability::Request<any_pointer::Owned, any_pointer::Owned>
    {
        ::capnp::capability::Request::new(
            Box::new(local::Request::new(interface_id, method_id, size_hint, self.add_ref())))
    }

    fn call(&self, interface_id: u64, method_id: u16, params: Box<ParamsHook>, results: Box<ResultsHook>,
            results_done: Promise<Box<ResultsDoneHook>, Error>)
        -> (Promise<(), Error>, Box<PipelineHook>)
    {
        // The main reason this is complicated is that we don't want the call to get cancelled
        // if the caller drops just the returned promise but not the pipeline.
        struct CallResultHolder {
            promise: Option<Promise<(), Error>>,
            pipeline: Option<Box<PipelineHook>>,
        }

        let call_result_promise =
            ForkedPromise::new(Box::new(self.inner.borrow_mut().promise_for_call_forwarding.clone().and_then(move |client| {
                let (promise, pipeline) = client.call(interface_id, method_id, params, results, results_done);
                Ok(Rc::new(RefCell::new(CallResultHolder {
                    promise: Some(promise),
                    pipeline: Some(pipeline),
                })))
            })));

        let pipeline_promise = call_result_promise.clone().and_then(|call_result| {
            Ok(call_result.borrow_mut().pipeline.take().expect("pipeline gone?"))
        });
        let pipeline = Pipeline::new(Promise::from_future(pipeline_promise));

        let completion_promise = call_result_promise.and_then(|call_result| {
            call_result.borrow_mut().promise.take().expect("promise gone?")
        });

        (Promise::from_future(completion_promise), Box::new(pipeline))
    }

    fn get_ptr(&self) -> usize {
        (&*self.inner.borrow()) as * const _ as usize
    }

    fn get_brand(&self) -> usize {
        0
    }

    fn get_resolved(&self) -> Option<Box<ClientHook>> {
        match self.inner.borrow().redirect {
            Some(ref inner) => Some(inner.clone()),
            None => None,
        }
    }

    fn when_more_resolved(&self) -> Option<Promise<Box<ClientHook>, Error>> {
        Some(Promise::from_future(self.inner.borrow_mut().promise_for_client_resolution.clone()))
    }
}
<|endoftext|>


<commit_before>// Copyright 2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use enums::Status;
use std::io;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum BorrowError {
    #[error("BorrowError::Cairo({0})")]
    Cairo(Status),
    #[error("BorrowError::NonExclusive")]
    NonExclusive,
}

impl From<Status> for BorrowError {
    fn from(status: Status) -> Self {
        BorrowError::Cairo(status)
    }
}

#[derive(Error, Debug)]
pub enum IoError {
    #[error("IoError::Cairo({0}")]
    Cairo(Status),
    #[error("IoError::Io({0}")]
    Io(#[from] io::Error),
}

impl From<Status> for IoError {
    fn from(status: Status) -> Self {
        IoError::Cairo(status)
    }
}
<commit_msg>Make errors text more readable<commit_after>// Copyright 2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use enums::Status;
use std::io;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum BorrowError {
    #[error("Failed to borrow with Cairo error:{0}")]
    Cairo(Status),
    #[error("Can't get exclusive access")]
    NonExclusive,
}

impl From<Status> for BorrowError {
    fn from(status: Status) -> Self {
        BorrowError::Cairo(status)
    }
}

#[derive(Error, Debug)]
pub enum IoError {
    #[error("Cairo error: {0}")]
    Cairo(Status),
    #[error("IO error: {0}")]
    Io(#[from] io::Error),
}

impl From<Status> for IoError {
    fn from(status: Status) -> Self {
        IoError::Cairo(status)
    }
}
<|endoftext|>


<commit_before>use std::io;

use regex;

#[derive(Debug)]
pub enum Error {
    Misc(String),
    IO(io::Error),
    Regex(regex::Error),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::IO(err)
    }
}

impl From<regex::Error> for Error {
    fn from(err: regex::Error) -> Self {
        Error::Regex(err)
    }
}

impl Error {
    pub fn from_str(msg: &str) -> Self {
        Error::Misc(msg.to_owned())
    }
}
<commit_msg>more stuff re error handling<commit_after>// use std::error;
use std::fmt;
use std::io;

use regex;

#[derive(Debug)]
pub enum Error {
    Misc(String),
    ParseError(String, usize, String),
    IO(io::Error),
    Regex(regex::Error),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::IO(err)
    }
}

impl From<regex::Error> for Error {
    fn from(err: regex::Error) -> Self {
        Error::Regex(err)
    }
}

impl Error {
    pub fn from_str(msg: &str) -> Self {
        Error::Misc(msg.to_owned())
    }

    pub fn parse_error(filename: &str, lineno: usize, msg: &str) -> Error {
        Error::ParseError(filename.to_owned(), lineno, msg.to_owned())
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Misc(ref err) =>
                write!(f, "Misc error: {}", err),

            Error::ParseError(ref filename, ref lineno, ref err) =>
                write!(f, "{}: {}: parse error: {}", filename, lineno, err),

            Error::IO(ref err) =>
                err.fmt(f),

            Error::Regex(ref err) =>
                err.fmt(f),
        }
    }
}

// impl error::Error for Error {
//     fn description(&self) -> &str {
//         match *self {
//             Error::Io(ref err) =>
//                 err.description(),
//
//             Error::Parse(ref err) =>
//                 err.description(),
//
//             _ => {
//                 format!("some error");
//             }
//         }
//     }
//
//     fn cause(&self) -> Option<&error::Error> {
//         match *self {
//             // N.B. Both of these implicitly cast `err` from their concrete
//             // types (either `&io::Error` or `&num::ParseIntError`)
//             // to a trait object `&Error`. This works because both error types
//             // implement `Error`.
//             Error::Io(ref err) => Some(err),
//             Error::Parse(ref err) => Some(err),
//         }
//     }
// }
<|endoftext|>