<commit_before>use super::Token;

use std::iter::{Iterator, Peekable};
use std::fmt;

#[derive(PartialEq)]
enum LexToken {
	Begin,
	End,
	Colon,
	Questionmark,
	Exclamation,
	Plus,
	Slash,
	Quote,
	Character(char)
}

impl LexToken {
	fn push_to_buf(&self, buf: &mut String) {
		match *self {
			LexToken::Begin => {
				buf.push('[');
				buf.push('[');
			},
			LexToken::End => {
				buf.push(']');
				buf.push(']');
			},
			LexToken::Colon => buf.push(':'),
			LexToken::Questionmark => buf.push('?'),
			LexToken::Exclamation => buf.push('!'),
			LexToken::Plus => buf.push('+'),
			LexToken::Slash => buf.push('/'),
			LexToken::Quote => buf.push('"'),
			LexToken::Character(c) => buf.push(c)
		}
	}
}

impl fmt::Show for LexToken {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			LexToken::Begin => {
				'['.fmt(f).and_then(|_| '['.fmt(f))
			},
			LexToken::End => ']'.fmt(f).and_then(|_| ']'.fmt(f)),
			LexToken::Colon => ':'.fmt(f),
			LexToken::Questionmark => '?'.fmt(f),
			LexToken::Exclamation => '!'.fmt(f),
			LexToken::Plus => '+'.fmt(f),
			LexToken::Slash => '/'.fmt(f),
			LexToken::Quote => '"'.fmt(f),
			LexToken::Character(c) => c.fmt(f)
		}
	}
}

struct Parser<T: Iterator<Item=V>, V> {
    tokens: Peekable<V, T>
}

impl<T: Iterator<Item=V>, V: PartialEq> Parser<T, V> {
	#[inline]
	fn eat(&mut self, expected: V) -> bool {
		let eaten = match self.peek() {
			Some(t) if *t == expected => {
				true
			},
			_ => false
		};

		if eaten {
			self.next();
		}

		eaten
	}

	fn eat_while(&mut self, is_edible: |&V| -> bool) {
		loop {
			let eaten = match self.peek() {
				Some(t) => is_edible(t),
				_ => false
			};

			if eaten {
				self.next();
			} else {
				break;
			}
		}
	}

	#[inline]
	fn peek<'a>(&'a mut self) -> Option<&'a V> {
		self.tokens.peek()
	}
}

impl<T: Iterator<Item=V>, V> Iterator for Parser<T, V> {
	type Item = V;

	#[inline]
	fn next(&mut self) -> Option<V> {
		self.tokens.by_ref().next()
	}
}

pub fn parse<T: Iterator<Item=Result<char, String>>>(chars: &mut T) -> Result<Vec<Token>, String> {
	let tokens = try!(lex(chars));
	parse_block(&mut Parser{
		tokens: tokens.into_iter().by_ref().peekable()
	})
}

fn lex<T: Iterator<Item=Result<char, String>>>(chars: &mut T) -> Result<Vec<LexToken>, String> {
	let mut chars = chars.by_ref().peekable();
	let mut tokens = Vec::new();

	loop {
		match chars.next() {
			Some(Ok(c)) => match c {
				'[' => match chars.peek() {
					Some(&Ok('[')) => {
						tokens.push(LexToken::Begin);
						chars.next();
					},
					_ => tokens.push(LexToken::Character('['))
				},
				']' => match chars.peek() {
					Some(&Ok(']')) => {
						tokens.push(LexToken::End);
						chars.next();
					},
					_ => tokens.push(LexToken::Character(']'))
				},
				':' => tokens.push(LexToken::Colon),
				'?' => tokens.push(LexToken::Questionmark),
				'!' => tokens.push(LexToken::Exclamation),
				'+' => tokens.push(LexToken::Plus),
				'/' => tokens.push(LexToken::Slash),
				'"' => tokens.push(LexToken::Quote),
				'\\' => match chars.next() {
					Some(Ok(c)) => {
						tokens.push(LexToken::Character(c));
					},
					Some(Err(e)) => return Err(e),
					None => break
				},
				c => tokens.push(LexToken::Character(c))
			},
			Some(Err(e)) => return Err(e),
			None => break
		}
	}

	Ok(tokens)
}

fn parse_block<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) -> Result<Vec<Token>, String> {
	let mut result = Vec::new();
	let mut string = String::new();

	loop {
		match tokens.next() {
			Some(LexToken::Begin) => match tokens.next() {
				Some(LexToken::Colon) => {
					if string.len() > 0 {
						result.push(Token::String(string));
						string = String::new();
					}

					result.push(try!(parse_placeholder(tokens)));
				},
				Some(LexToken::Questionmark) => {
					if string.len() > 0 {
						result.push(Token::String(string));
						string = String::new();
					}

					result.push(try!(parse_conditional(tokens)));
				},
				Some(LexToken::Plus) => {
					if string.len() > 0 {
						result.push(Token::String(string));
						string = String::new();
					}

					result.push(try!(parse_generator(tokens)));
				},
				Some(LexToken::Slash) => {
					if string.len() > 0 {
						result.push(Token::String(string));
						string = String::new();
					}

					parse_block_end(tokens);
					break
				},
				Some(t) => {
					return Err(format!("parse error: unknown token type: '{}'", t))
				},
				None => LexToken::Begin.push_to_buf(&mut string)
			},
			Some(t) => t.push_to_buf(&mut string),
			None => break
		}
	}

	if string.len() > 0 {
		result.push(Token::String(string));
	}

	Ok(result)
}

fn parse_placeholder<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) -> Result<Token, String> {
	let mut label = String::new();

	for t in tokens.by_ref().take_while(|t| *t != LexToken::End) {
		t.push_to_buf(&mut label);
	}

	Ok(Token::Placeholder(label))
}

fn parse_conditional<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) -> Result<Token, String> {
	let negative = tokens.eat(LexToken::Exclamation);
	let content_cond = tokens.eat(LexToken::Colon);
	let mut label = String::new();

	for t in tokens.by_ref().take_while(|t| *t != LexToken::End) {
		t.push_to_buf(&mut label);
	}

	let content = try!(parse_block(tokens));

	if content_cond {
		Ok(Token::ContentConditional(label, !negative, content))
	} else {
		Ok(Token::Conditional(label, !negative, content))
	}
}

fn parse_generator<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) -> Result<Token, String> {
	let mut label = String::new();
	let mut args = Vec::new();

	if tokens.eat(LexToken::Quote) {
		for t in tokens.by_ref().take_while(|t| *t != LexToken::Quote) {
			t.push_to_buf(&mut label);
		}
	} else {
		loop {
			match tokens.next() {
				Some(LexToken::End) => return Ok(Token::Generated(label, Vec::new())),
				Some(LexToken::Character(c)) if c.is_whitespace() => break,
				Some(t) => t.push_to_buf(&mut label),
				None => break
			}
		}
	}

	'arg_list: loop {
		let mut new_arg = String::new();

		tokens.eat_while(|t| match *t {LexToken::Character(c) if c.is_whitespace() => true, _ => false});

		if tokens.eat(LexToken::Quote) {
			for t in tokens.by_ref().take_while(|t| *t != LexToken::Quote) {
				t.push_to_buf(&mut new_arg);
			}
		} else {
			'arg: loop {
				match tokens.next() {
					Some(LexToken::End) => if new_arg.len() > 0 {
						args.push(new_arg);
						break 'arg_list;
					},
					Some(LexToken::Character(c)) if c.is_whitespace() => {
						tokens.eat_while(|t| match *t {LexToken::Character(c) if c.is_whitespace() => true, _ => false});
						break 'arg
					},
					Some(t) => t.push_to_buf(&mut new_arg),
					None => break 'arg_list
				}
			}
		}

		args.push(new_arg);
	}

	Ok(Token::Generated(label, args))
}

fn parse_block_end<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) {
	tokens.by_ref().all(|t| t != LexToken::End);
}

<commit_msg>Update for new closure argument syntax<commit_after>use super::Token;

use std::iter::{Iterator, Peekable};
use std::fmt;

#[derive(PartialEq)]
enum LexToken {
	Begin,
	End,
	Colon,
	Questionmark,
	Exclamation,
	Plus,
	Slash,
	Quote,
	Character(char)
}

impl LexToken {
	fn push_to_buf(&self, buf: &mut String) {
		match *self {
			LexToken::Begin => {
				buf.push('[');
				buf.push('[');
			},
			LexToken::End => {
				buf.push(']');
				buf.push(']');
			},
			LexToken::Colon => buf.push(':'),
			LexToken::Questionmark => buf.push('?'),
			LexToken::Exclamation => buf.push('!'),
			LexToken::Plus => buf.push('+'),
			LexToken::Slash => buf.push('/'),
			LexToken::Quote => buf.push('"'),
			LexToken::Character(c) => buf.push(c)
		}
	}
}

impl fmt::Show for LexToken {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			LexToken::Begin => {
				'['.fmt(f).and_then(|_| '['.fmt(f))
			},
			LexToken::End => ']'.fmt(f).and_then(|_| ']'.fmt(f)),
			LexToken::Colon => ':'.fmt(f),
			LexToken::Questionmark => '?'.fmt(f),
			LexToken::Exclamation => '!'.fmt(f),
			LexToken::Plus => '+'.fmt(f),
			LexToken::Slash => '/'.fmt(f),
			LexToken::Quote => '"'.fmt(f),
			LexToken::Character(c) => c.fmt(f)
		}
	}
}

struct Parser<T: Iterator<Item=V>, V> {
    tokens: Peekable<V, T>
}

impl<T: Iterator<Item=V>, V: PartialEq> Parser<T, V> {
	#[inline]
	fn eat(&mut self, expected: V) -> bool {
		let eaten = match self.peek() {
			Some(t) if *t == expected => {
				true
			},
			_ => false
		};

		if eaten {
			self.next();
		}

		eaten
	}

	fn eat_while<F: Fn(&V) -> bool>(&mut self, is_edible: F) {
		loop {
			let eaten = match self.peek() {
				Some(t) => is_edible(t),
				_ => false
			};

			if eaten {
				self.next();
			} else {
				break;
			}
		}
	}

	#[inline]
	fn peek<'a>(&'a mut self) -> Option<&'a V> {
		self.tokens.peek()
	}
}

impl<T: Iterator<Item=V>, V> Iterator for Parser<T, V> {
	type Item = V;

	#[inline]
	fn next(&mut self) -> Option<V> {
		self.tokens.by_ref().next()
	}
}

pub fn parse<T: Iterator<Item=Result<char, String>>>(chars: &mut T) -> Result<Vec<Token>, String> {
	let tokens = try!(lex(chars));
	parse_block(&mut Parser{
		tokens: tokens.into_iter().by_ref().peekable()
	})
}

fn lex<T: Iterator<Item=Result<char, String>>>(chars: &mut T) -> Result<Vec<LexToken>, String> {
	let mut chars = chars.by_ref().peekable();
	let mut tokens = Vec::new();

	loop {
		match chars.next() {
			Some(Ok(c)) => match c {
				'[' => match chars.peek() {
					Some(&Ok('[')) => {
						tokens.push(LexToken::Begin);
						chars.next();
					},
					_ => tokens.push(LexToken::Character('['))
				},
				']' => match chars.peek() {
					Some(&Ok(']')) => {
						tokens.push(LexToken::End);
						chars.next();
					},
					_ => tokens.push(LexToken::Character(']'))
				},
				':' => tokens.push(LexToken::Colon),
				'?' => tokens.push(LexToken::Questionmark),
				'!' => tokens.push(LexToken::Exclamation),
				'+' => tokens.push(LexToken::Plus),
				'/' => tokens.push(LexToken::Slash),
				'"' => tokens.push(LexToken::Quote),
				'\\' => match chars.next() {
					Some(Ok(c)) => {
						tokens.push(LexToken::Character(c));
					},
					Some(Err(e)) => return Err(e),
					None => break
				},
				c => tokens.push(LexToken::Character(c))
			},
			Some(Err(e)) => return Err(e),
			None => break
		}
	}

	Ok(tokens)
}

fn parse_block<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) -> Result<Vec<Token>, String> {
	let mut result = Vec::new();
	let mut string = String::new();

	loop {
		match tokens.next() {
			Some(LexToken::Begin) => match tokens.next() {
				Some(LexToken::Colon) => {
					if string.len() > 0 {
						result.push(Token::String(string));
						string = String::new();
					}

					result.push(try!(parse_placeholder(tokens)));
				},
				Some(LexToken::Questionmark) => {
					if string.len() > 0 {
						result.push(Token::String(string));
						string = String::new();
					}

					result.push(try!(parse_conditional(tokens)));
				},
				Some(LexToken::Plus) => {
					if string.len() > 0 {
						result.push(Token::String(string));
						string = String::new();
					}

					result.push(try!(parse_generator(tokens)));
				},
				Some(LexToken::Slash) => {
					if string.len() > 0 {
						result.push(Token::String(string));
						string = String::new();
					}

					parse_block_end(tokens);
					break
				},
				Some(t) => {
					return Err(format!("parse error: unknown token type: '{}'", t))
				},
				None => LexToken::Begin.push_to_buf(&mut string)
			},
			Some(t) => t.push_to_buf(&mut string),
			None => break
		}
	}

	if string.len() > 0 {
		result.push(Token::String(string));
	}

	Ok(result)
}

fn parse_placeholder<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) -> Result<Token, String> {
	let mut label = String::new();

	for t in tokens.by_ref().take_while(|t| *t != LexToken::End) {
		t.push_to_buf(&mut label);
	}

	Ok(Token::Placeholder(label))
}

fn parse_conditional<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) -> Result<Token, String> {
	let negative = tokens.eat(LexToken::Exclamation);
	let content_cond = tokens.eat(LexToken::Colon);
	let mut label = String::new();

	for t in tokens.by_ref().take_while(|t| *t != LexToken::End) {
		t.push_to_buf(&mut label);
	}

	let content = try!(parse_block(tokens));

	if content_cond {
		Ok(Token::ContentConditional(label, !negative, content))
	} else {
		Ok(Token::Conditional(label, !negative, content))
	}
}

fn parse_generator<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) -> Result<Token, String> {
	let mut label = String::new();
	let mut args = Vec::new();

	if tokens.eat(LexToken::Quote) {
		for t in tokens.by_ref().take_while(|t| *t != LexToken::Quote) {
			t.push_to_buf(&mut label);
		}
	} else {
		loop {
			match tokens.next() {
				Some(LexToken::End) => return Ok(Token::Generated(label, Vec::new())),
				Some(LexToken::Character(c)) if c.is_whitespace() => break,
				Some(t) => t.push_to_buf(&mut label),
				None => break
			}
		}
	}

	'arg_list: loop {
		let mut new_arg = String::new();

		tokens.eat_while(|t| match *t {LexToken::Character(c) if c.is_whitespace() => true, _ => false});

		if tokens.eat(LexToken::Quote) {
			for t in tokens.by_ref().take_while(|t| *t != LexToken::Quote) {
				t.push_to_buf(&mut new_arg);
			}
		} else {
			'arg: loop {
				match tokens.next() {
					Some(LexToken::End) => if new_arg.len() > 0 {
						args.push(new_arg);
						break 'arg_list;
					},
					Some(LexToken::Character(c)) if c.is_whitespace() => {
						tokens.eat_while(|t| match *t {LexToken::Character(c) if c.is_whitespace() => true, _ => false});
						break 'arg
					},
					Some(t) => t.push_to_buf(&mut new_arg),
					None => break 'arg_list
				}
			}
		}

		args.push(new_arg);
	}

	Ok(Token::Generated(label, args))
}

fn parse_block_end<T: Iterator<Item=LexToken>>(tokens: &mut Parser<T, LexToken>) {
	tokens.by_ref().all(|t| t != LexToken::End);
}

<|endoftext|>


<commit_before>use ast::*;
use scanner::{Token, TokenWithContext};
use std::iter::Peekable;

/// This behave exactly as try! but wraps the returned result in a Some.
/// It's useful to remove some boilerplate in the code introduced by
/// the use of Option<Result<T, E>>
macro_rules! try_wrap_err {
    ($e:expr) => (match $e {Ok(e) => e, Err(e) => return Some(Err(e))})
}

#[derive(Debug)]
pub struct ParseError {
    message: String,
}

impl ParseError {
    fn from_message(message: String) -> ParseError {
        ParseError { message: message }
    }
}

pub fn parse(tokens: Vec<TokenWithContext>) -> Result<Expr, Vec<ParseError>> {
    let mut iter = tokens.iter().peekable();
    if let Some(result) = parse_expression(&mut iter) {
        match result {
            Ok(expr) => {
                if let None = iter.next() {
                    Ok(expr)
                } else {
                    Err(vec![ParseError::from_message("Parser didn't consume all the tokens"
                                 .into())])
                }
            }
            Err(error) => {
                {
                    synchronise(&mut iter);
                }
                Err(vec![error])
            }
        }

    } else {
        Err(vec![ParseError::from_message("Parser didn't return anything".into())])
    }
}

fn synchronise<'a, I>(tokens: &mut Peekable<I>)
    where I: Iterator<Item = &'a TokenWithContext>
{
    enum TokenKind{
        StartOfConstruct,
        BodyOfConstruct,
        EndOfConstruct,
    };
    fn classify(token: &Token) -> TokenKind{
        match token {
            &Token::Semicolon => TokenKind::EndOfConstruct,
            &Token::Class => TokenKind::StartOfConstruct,
            &Token::Fun => TokenKind::StartOfConstruct,
            &Token::Var => TokenKind::StartOfConstruct,
            &Token::For => TokenKind::StartOfConstruct,
            &Token::If => TokenKind::StartOfConstruct,
            &Token::While => TokenKind::StartOfConstruct,
            &Token::Print => TokenKind::StartOfConstruct,
            &Token::Return => TokenKind::StartOfConstruct,
            _ => TokenKind::BodyOfConstruct
    }
    }
    while let Some(token_kind) = tokens.peek().map(|t|classify(&t.token)) {
        match token_kind {
            TokenKind::StartOfConstruct => {
                break;
            },
            TokenKind::BodyOfConstruct =>{
                let _ = tokens.next();
            }
            TokenKind::EndOfConstruct => {
                let _ = tokens.next();
                break;
            },
        }
    }
}

fn parse_expression<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    parse_equality(tokens)
}

fn parse_binary<'a, I>(tokens: &mut Peekable<I>,
                       map_operator: &Fn(&Token) -> Option<Operator>,
                       parse_subexpression: &Fn(&mut Peekable<I>)
                                                -> Option<Result<Expr, ParseError>>)
                       -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    let mut expr;
    {
        let result = parse_subexpression(tokens);
        if let Some(Ok(subexpression)) =  result{
            expr = subexpression;
        } else {
            return result;
        }
    };
    while let Some(Some(mapped_operator)) = tokens.peek().map(|pt| map_operator(&pt.token)) {
        let operator; // We know it's right, we read it just for error reporting
        {
            operator = tokens.next().unwrap();
        }
        let right;
        {
            if let Some(result) = parse_subexpression(tokens) {
                right = try_wrap_err!(result);
            } else {
                return Some(Err(ParseError::from_message(format!("Expected subexpression \
                                                                  after {:?} at {:?}",
                                                                 operator.lexeme,
                                                                 operator.position))));
            }
        };
        let binary_expression = BinaryExpr {
            left: expr,
            operator: mapped_operator,
            right: right,
        };
        expr = Expr::Binary(Box::new(binary_expression));
    }
    Some(Ok(expr))
}

fn parse_equality<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::BangEqual => Some(Operator::NotEqual),
            &Token::EqualEqual => Some(Operator::Equal),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_comparison)
}

fn parse_comparison<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Greater => Some(Operator::Greater),
            &Token::GreaterEqual => Some(Operator::GreaterEqual),
            &Token::Less => Some(Operator::Less),
            &Token::LessEqual => Some(Operator::LessEqual),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_term)
}

fn parse_term<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Minus => Some(Operator::Minus),
            &Token::Plus => Some(Operator::Plus),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_factor)
}

fn parse_factor<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Slash => Some(Operator::Slash),
            &Token::Star => Some(Operator::Star),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_unary)
}

fn parse_unary<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Minus => Some(Operator::Minus),
            &Token::Bang => Some(Operator::Bang),
            _ => None,
        }
    }
    if let Some(Some(mapped_operator)) = tokens.peek().cloned().map(|pt| map_operator(&pt.token)) {
        let operator; // For error reporting
        {
            operator = tokens.next().unwrap();
        }
        let right;
        {
            if let Some(result) = parse_unary(tokens) {
                right = try_wrap_err!(result);
            } else {
                return Some(Err(ParseError::from_message(format!("Expected subexpression \
                                                                  after {:?} at {:?}",
                                                                 operator.lexeme,
                                                                 operator.position))));
            }
        };
        let unary_expression = UnaryExpr {
            operator: mapped_operator,
            right: right,
        };
        return Some(Ok(Expr::Unary(Box::new(unary_expression))));
    } else {
        parse_primary(tokens)
    }
}

fn parse_primary<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    let primary_token;
    {
        primary_token = tokens.next();
    };
    if let Some(primary_token) = primary_token {
        let parsed_expression = match primary_token.token {
            Token::False => Expr::Literal(Literal::BoolLiteral(false)),
            Token::True => Expr::Literal(Literal::BoolLiteral(true)),
            Token::Nil => Expr::Literal(Literal::NilLiteral),
            Token::NumberLiteral(n) => Expr::Literal(Literal::NumberLiteral(n)),
            Token::StringLiteral(ref s) => Expr::Literal(Literal::StringLiteral(s.clone())),
            Token::LeftParen => {
                let expr;
                {
                    if let Some(result) = parse_expression(tokens) {
                        expr = try_wrap_err!(result);
                    } else {
                        return Some(Err(ParseError::from_message(format!("Unfinished grouping \
                                                                     expression near {:?} at \
                                                                     {:?}",
                                                                         primary_token.lexeme,
                                                                         primary_token.position))));
                    }
                };
                {
                    if let Some(token) = tokens.next() {
                        if token.token == Token::RightParen {
                            let grouping_expression = Grouping { expr: expr };
                            return Some(Ok(Expr::Grouping(Box::new(grouping_expression))));
                        } else {
                            return Some(Err(ParseError::from_message(format!("Missing ) near \
                                                                              {:?} at {:?}",
                                                                             token.lexeme,
                                                                             token.position))));
                        }

                    }
                    return Some(Err(ParseError::from_message(format!("Missing ) before end of \
                                                                      file"))));
                }
            }
            _ => {
                return Some(Err(ParseError::from_message(format!("Unexpected token {:?} at \
                                                                  {:?}",
                                                                 primary_token.lexeme,
                                                                 primary_token.position))));
            }
        };
        Some(Ok(parsed_expression))
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use scanner::*;
    use parser::*;
    use pretty_printer::PrettyPrint;

    #[test]
    fn literal() {
        let (tokens, _) = scan(&"123".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("123", &expr.pretty_print());
    }

    #[test]
    fn binary() {
        let (tokens, _) = scan(&"123+456".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ 123 456)", &expr.pretty_print());
    }

    #[test]
    fn precedence_add_mul() {
        let (tokens, _) = scan(&"123+456*789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ 123 (* 456 789))", &expr.pretty_print());
    }

    #[test]
    fn precedence_mul_add() {
        let (tokens, _) = scan(&"123*456+789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ (* 123 456) 789)", &expr.pretty_print());
    }

    #[test]
    fn precedence_mul_add_unary() {
        let (tokens, _) = scan(&"-123*456+789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ (* (- 123) 456) 789)", &expr.pretty_print());
    }

    #[test]
    fn unclosed_group() {
        let (tokens, _) = scan(&"(2".into());
        assert!(parse(tokens).is_err());
    }

    #[test]
    fn unopened_group() {
        let (tokens, _) = scan(&"2)".into());
        assert!(parse(tokens).is_err());
    }
}
<commit_msg>Removed another unnecessary clone<commit_after>use ast::*;
use scanner::{Token, TokenWithContext};
use std::iter::Peekable;

/// This behave exactly as try! but wraps the returned result in a Some.
/// It's useful to remove some boilerplate in the code introduced by
/// the use of Option<Result<T, E>>
macro_rules! try_wrap_err {
    ($e:expr) => (match $e {Ok(e) => e, Err(e) => return Some(Err(e))})
}

#[derive(Debug)]
pub struct ParseError {
    message: String,
}

impl ParseError {
    fn from_message(message: String) -> ParseError {
        ParseError { message: message }
    }
}

pub fn parse(tokens: Vec<TokenWithContext>) -> Result<Expr, Vec<ParseError>> {
    let mut iter = tokens.iter().peekable();
    if let Some(result) = parse_expression(&mut iter) {
        match result {
            Ok(expr) => {
                if let None = iter.next() {
                    Ok(expr)
                } else {
                    Err(vec![ParseError::from_message("Parser didn't consume all the tokens"
                                 .into())])
                }
            }
            Err(error) => {
                {
                    synchronise(&mut iter);
                }
                Err(vec![error])
            }
        }

    } else {
        Err(vec![ParseError::from_message("Parser didn't return anything".into())])
    }
}

fn synchronise<'a, I>(tokens: &mut Peekable<I>)
    where I: Iterator<Item = &'a TokenWithContext>
{
    enum TokenKind{
        StartOfConstruct,
        BodyOfConstruct,
        EndOfConstruct,
    };
    fn classify(token: &Token) -> TokenKind{
        match token {
            &Token::Semicolon => TokenKind::EndOfConstruct,
            &Token::Class => TokenKind::StartOfConstruct,
            &Token::Fun => TokenKind::StartOfConstruct,
            &Token::Var => TokenKind::StartOfConstruct,
            &Token::For => TokenKind::StartOfConstruct,
            &Token::If => TokenKind::StartOfConstruct,
            &Token::While => TokenKind::StartOfConstruct,
            &Token::Print => TokenKind::StartOfConstruct,
            &Token::Return => TokenKind::StartOfConstruct,
            _ => TokenKind::BodyOfConstruct
    }
    }
    while let Some(token_kind) = tokens.peek().map(|t|classify(&t.token)) {
        match token_kind {
            TokenKind::StartOfConstruct => {
                break;
            },
            TokenKind::BodyOfConstruct =>{
                let _ = tokens.next();
            }
            TokenKind::EndOfConstruct => {
                let _ = tokens.next();
                break;
            },
        }
    }
}

fn parse_expression<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    parse_equality(tokens)
}

fn parse_binary<'a, I>(tokens: &mut Peekable<I>,
                       map_operator: &Fn(&Token) -> Option<Operator>,
                       parse_subexpression: &Fn(&mut Peekable<I>)
                                                -> Option<Result<Expr, ParseError>>)
                       -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    let mut expr;
    {
        let result = parse_subexpression(tokens);
        if let Some(Ok(subexpression)) =  result{
            expr = subexpression;
        } else {
            return result;
        }
    };
    while let Some(Some(mapped_operator)) = tokens.peek().map(|pt| map_operator(&pt.token)) {
        let operator; // We know it's right, we read it just for error reporting
        {
            operator = tokens.next().unwrap();
        }
        let right;
        {
            if let Some(result) = parse_subexpression(tokens) {
                right = try_wrap_err!(result);
            } else {
                return Some(Err(ParseError::from_message(format!("Expected subexpression \
                                                                  after {:?} at {:?}",
                                                                 operator.lexeme,
                                                                 operator.position))));
            }
        };
        let binary_expression = BinaryExpr {
            left: expr,
            operator: mapped_operator,
            right: right,
        };
        expr = Expr::Binary(Box::new(binary_expression));
    }
    Some(Ok(expr))
}

fn parse_equality<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::BangEqual => Some(Operator::NotEqual),
            &Token::EqualEqual => Some(Operator::Equal),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_comparison)
}

fn parse_comparison<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Greater => Some(Operator::Greater),
            &Token::GreaterEqual => Some(Operator::GreaterEqual),
            &Token::Less => Some(Operator::Less),
            &Token::LessEqual => Some(Operator::LessEqual),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_term)
}

fn parse_term<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Minus => Some(Operator::Minus),
            &Token::Plus => Some(Operator::Plus),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_factor)
}

fn parse_factor<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Slash => Some(Operator::Slash),
            &Token::Star => Some(Operator::Star),
            _ => None,
        }
    }
    parse_binary(tokens, &map_operator, &parse_unary)
}

fn parse_unary<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    fn map_operator(token: &Token) -> Option<Operator> {
        match token {
            &Token::Minus => Some(Operator::Minus),
            &Token::Bang => Some(Operator::Bang),
            _ => None,
        }
    }
    if let Some(Some(mapped_operator)) = tokens.peek().map(|pt| map_operator(&pt.token)) {
        let operator; // For error reporting
        {
            operator = tokens.next().unwrap();
        }
        let right;
        {
            if let Some(result) = parse_unary(tokens) {
                right = try_wrap_err!(result);
            } else {
                return Some(Err(ParseError::from_message(format!("Expected subexpression \
                                                                  after {:?} at {:?}",
                                                                 operator.lexeme,
                                                                 operator.position))));
            }
        };
        let unary_expression = UnaryExpr {
            operator: mapped_operator,
            right: right,
        };
        return Some(Ok(Expr::Unary(Box::new(unary_expression))));
    } else {
        parse_primary(tokens)
    }
}

fn parse_primary<'a, I>(tokens: &mut Peekable<I>) -> Option<Result<Expr, ParseError>>
    where I: Iterator<Item = &'a TokenWithContext>
{
    let primary_token;
    {
        primary_token = tokens.next();
    };
    if let Some(primary_token) = primary_token {
        let parsed_expression = match primary_token.token {
            Token::False => Expr::Literal(Literal::BoolLiteral(false)),
            Token::True => Expr::Literal(Literal::BoolLiteral(true)),
            Token::Nil => Expr::Literal(Literal::NilLiteral),
            Token::NumberLiteral(n) => Expr::Literal(Literal::NumberLiteral(n)),
            Token::StringLiteral(ref s) => Expr::Literal(Literal::StringLiteral(s.clone())),
            Token::LeftParen => {
                let expr;
                {
                    if let Some(result) = parse_expression(tokens) {
                        expr = try_wrap_err!(result);
                    } else {
                        return Some(Err(ParseError::from_message(format!("Unfinished grouping \
                                                                     expression near {:?} at \
                                                                     {:?}",
                                                                         primary_token.lexeme,
                                                                         primary_token.position))));
                    }
                };
                {
                    if let Some(token) = tokens.next() {
                        if token.token == Token::RightParen {
                            let grouping_expression = Grouping { expr: expr };
                            return Some(Ok(Expr::Grouping(Box::new(grouping_expression))));
                        } else {
                            return Some(Err(ParseError::from_message(format!("Missing ) near \
                                                                              {:?} at {:?}",
                                                                             token.lexeme,
                                                                             token.position))));
                        }

                    }
                    return Some(Err(ParseError::from_message(format!("Missing ) before end of \
                                                                      file"))));
                }
            }
            _ => {
                return Some(Err(ParseError::from_message(format!("Unexpected token {:?} at \
                                                                  {:?}",
                                                                 primary_token.lexeme,
                                                                 primary_token.position))));
            }
        };
        Some(Ok(parsed_expression))
    } else {
        None
    }
}

#[cfg(test)]
mod tests {
    use scanner::*;
    use parser::*;
    use pretty_printer::PrettyPrint;

    #[test]
    fn literal() {
        let (tokens, _) = scan(&"123".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("123", &expr.pretty_print());
    }

    #[test]
    fn binary() {
        let (tokens, _) = scan(&"123+456".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ 123 456)", &expr.pretty_print());
    }

    #[test]
    fn precedence_add_mul() {
        let (tokens, _) = scan(&"123+456*789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ 123 (* 456 789))", &expr.pretty_print());
    }

    #[test]
    fn precedence_mul_add() {
        let (tokens, _) = scan(&"123*456+789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ (* 123 456) 789)", &expr.pretty_print());
    }

    #[test]
    fn precedence_mul_add_unary() {
        let (tokens, _) = scan(&"-123*456+789".into());
        let expr = parse(tokens).unwrap();
        assert_eq!("(+ (* (- 123) 456) 789)", &expr.pretty_print());
    }

    #[test]
    fn unclosed_group() {
        let (tokens, _) = scan(&"(2".into());
        assert!(parse(tokens).is_err());
    }

    #[test]
    fn unopened_group() {
        let (tokens, _) = scan(&"2)".into());
        assert!(parse(tokens).is_err());
    }
}
<|endoftext|>


<commit_before>use core::mem::ManuallyDrop;
use core::ptr::{self};
use core::slice::{self};

use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec};

/// Specialization trait used for Vec::from_iter
///
/// ## The delegation graph:
///
/// ```text
/// +-------------+
/// |FromIterator |
/// +-+-----------+
///   |
///   v
/// +-+-------------------------------+  +---------------------+
/// |SpecFromIter                  +---->+SpecFromIterNested   |
/// |where I:                      |  |  |where I:             |
/// |  Iterator (default)----------+  |  |  Iterator (default) |
/// |  vec::IntoIter               |  |  |  TrustedLen         |
/// |  SourceIterMarker---fallback-+  |  |                     |
/// |  slice::Iter                    |  |                     |
/// |  Iterator<Item = &Clone>        |  +---------------------+
/// +---------------------------------+
/// ```
pub(super) trait SpecFromIter<T, I> {
    fn from_iter(iter: I) -> Self;
}

impl<T, I> SpecFromIter<T, I> for Vec<T>
where
    I: Iterator<Item = T>,
{
    default fn from_iter(iterator: I) -> Self {
        SpecFromIterNested::from_iter(iterator)
    }
}

impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
    fn from_iter(iterator: IntoIter<T>) -> Self {
        // A common case is passing a vector into a function which immediately
        // re-collects into a vector. We can short circuit this if the IntoIter
        // has not been advanced at all.
        // When it has been advanced We can also reuse the memory and move the data to the front.
        // But we only do so when the resulting Vec wouldn't have more unused capacity
        // than creating it through the generic FromIterator implementation would. That limitation
        // is not strictly necessary as Vec's allocation behavior is intentionally unspecified.
        // But it is a conservative choice.
        let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr;
        if !has_advanced || iterator.len() >= iterator.cap / 2 {
            unsafe {
                let it = ManuallyDrop::new(iterator);
                if has_advanced {
                    ptr::copy(it.ptr, it.buf.as_ptr(), it.len());
                }
                return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap);
            }
        }

        let mut vec = Vec::new();
        // must delegate to spec_extend() since extend() itself delegates
        // to spec_from for empty Vecs
        vec.spec_extend(iterator);
        vec
    }
}

impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec<T>
where
    I: Iterator<Item = &'a T>,
    T: Clone,
{
    default fn from_iter(iterator: I) -> Self {
        SpecFromIter::from_iter(iterator.cloned())
    }
}

// This utilizes `iterator.as_slice().to_vec()` since spec_extend
// must take more steps to reason about the final capacity + length
// and thus do more work. `to_vec()` directly allocates the correct amount
// and fills it exactly.
impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T> {
    #[cfg(not(test))]
    fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
        iterator.as_slice().to_vec()
    }

    // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
    // required for this method definition, is not available. Instead use the
    // `slice::to_vec`  function which is only available with cfg(test)
    // NB see the slice::hack module in slice.rs for more information
    #[cfg(test)]
    fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
        crate::slice::to_vec(iterator.as_slice(), crate::alloc::Global)
    }
}
<commit_msg>Remove unnecessary SpecFromIter impls<commit_after>use core::mem::ManuallyDrop;
use core::ptr::{self};

use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec};

/// Specialization trait used for Vec::from_iter
///
/// ## The delegation graph:
///
/// ```text
/// +-------------+
/// |FromIterator |
/// +-+-----------+
///   |
///   v
/// +-+-------------------------------+  +---------------------+
/// |SpecFromIter                  +---->+SpecFromIterNested   |
/// |where I:                      |  |  |where I:             |
/// |  Iterator (default)----------+  |  |  Iterator (default) |
/// |  vec::IntoIter               |  |  |  TrustedLen         |
/// |  SourceIterMarker---fallback-+  |  |                     |
/// |  slice::Iter                    |  |                     |
/// |  Iterator<Item = &Clone>        |  +---------------------+
/// +---------------------------------+
/// ```
pub(super) trait SpecFromIter<T, I> {
    fn from_iter(iter: I) -> Self;
}

impl<T, I> SpecFromIter<T, I> for Vec<T>
where
    I: Iterator<Item = T>,
{
    default fn from_iter(iterator: I) -> Self {
        SpecFromIterNested::from_iter(iterator)
    }
}

impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
    fn from_iter(iterator: IntoIter<T>) -> Self {
        // A common case is passing a vector into a function which immediately
        // re-collects into a vector. We can short circuit this if the IntoIter
        // has not been advanced at all.
        // When it has been advanced We can also reuse the memory and move the data to the front.
        // But we only do so when the resulting Vec wouldn't have more unused capacity
        // than creating it through the generic FromIterator implementation would. That limitation
        // is not strictly necessary as Vec's allocation behavior is intentionally unspecified.
        // But it is a conservative choice.
        let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr;
        if !has_advanced || iterator.len() >= iterator.cap / 2 {
            unsafe {
                let it = ManuallyDrop::new(iterator);
                if has_advanced {
                    ptr::copy(it.ptr, it.buf.as_ptr(), it.len());
                }
                return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap);
            }
        }

        let mut vec = Vec::new();
        // must delegate to spec_extend() since extend() itself delegates
        // to spec_from for empty Vecs
        vec.spec_extend(iterator);
        vec
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Location in memory that contains data.
//!
//! A Vulkan buffer is very similar to a buffer that you would use in programming languages in
//! general, in the sense that it is a location in memory that contains data. The difference
//! between a Vulkan buffer and a regular buffer is that the content of a Vulkan buffer is
//! accessible from the GPU.
//!
//! # High-level wrappers
//!
//! The low level implementation of a buffer is `UnsafeBuffer`. However, the vulkano library
//! provides high-level wrappers around that type that are specialized depending on the way you
//! are going to use it:
//!
//! - `CpuAccessBuffer` designates a buffer located in RAM and whose content can be directly
//!   written by your application.
//! - `DeviceLocalBuffer` designates a buffer located in video memory and whose content can't be
//!   written by your application. Accessing this buffer from the GPU is usually faster than the
//!   `CpuAccessBuffer`.
//! - `ImmutableBuffer` designates a buffer in video memory and whose content can only be
//!   written once. Compared to `DeviceLocalBuffer`, this buffer requires less processing on the
//!   CPU because we don't need to keep track of the reads and writes.
//!
//! If you have data that is modified at every single frame, you are encouraged to use a
//! `CpuAccessibleBuffer`. If you have data that is very rarely modified, you are encouraged to
//! use an `ImmutableBuffer` or a `DeviceLocalBuffer` instead.
//!
//! If you just want to get started, you can use the `CpuAccessibleBuffer` everywhere, as it is
//! the most flexible type of buffer.
//!
//! # Buffers usage
//!
//! When you create a buffer object, you have to specify its *usage*. In other words, you have to
//! specify the way it is going to be used. Trying to use a buffer in a way that wasn't specified
//! when you created it will result in an error.
//!
//! You can use buffers for the following purposes:
//!
//! - Can contain arbitrary data that can be transferred from/to other buffers and images.
//! - Can be read and modified from a shader.
//! - Can be used as a source of vertices and indices.
//! - Can be used as a source of list of models for draw indirect commands.
//!
//! Accessing a buffer from a shader can be done in the following ways:
//!
//! - As a uniform buffer. Uniform buffers are read-only.
//! - As a storage buffer. Storage buffers can be read and written.
//! - As a uniform texel buffer. Contrary to a uniform buffer, the data is interpreted by the
//!   GPU and can be for example normalized.
//! - As a storage texel buffer. Additionnally, some data formats can be modified with atomic
//!   operations.
//!
//! Using uniform/storage texel buffers requires creating a *buffer view*. See the `view` module
//! for how to create a buffer view.
//!

pub use self::cpu_access::CpuAccessibleBuffer;
pub use self::cpu_pool::CpuBufferPool;
pub use self::device_local::DeviceLocalBuffer;
pub use self::immutable::ImmutableBuffer;
pub use self::slice::BufferSlice;
pub use self::sys::BufferCreationError;
pub use self::sys::Usage as BufferUsage;
pub use self::traits::BufferAccess;
pub use self::traits::BufferInner;
pub use self::traits::Buffer;
pub use self::traits::TypedBufferAccess;
pub use self::view::BufferView;
pub use self::view::BufferViewRef;

pub mod cpu_access;
pub mod cpu_pool;
pub mod device_local;
pub mod immutable;
pub mod sys;
pub mod view;

mod slice;
mod traits;
<commit_msg>Reexport TypedBuffer in buffer<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Location in memory that contains data.
//!
//! A Vulkan buffer is very similar to a buffer that you would use in programming languages in
//! general, in the sense that it is a location in memory that contains data. The difference
//! between a Vulkan buffer and a regular buffer is that the content of a Vulkan buffer is
//! accessible from the GPU.
//!
//! # High-level wrappers
//!
//! The low level implementation of a buffer is `UnsafeBuffer`. However, the vulkano library
//! provides high-level wrappers around that type that are specialized depending on the way you
//! are going to use it:
//!
//! - `CpuAccessBuffer` designates a buffer located in RAM and whose content can be directly
//!   written by your application.
//! - `DeviceLocalBuffer` designates a buffer located in video memory and whose content can't be
//!   written by your application. Accessing this buffer from the GPU is usually faster than the
//!   `CpuAccessBuffer`.
//! - `ImmutableBuffer` designates a buffer in video memory and whose content can only be
//!   written once. Compared to `DeviceLocalBuffer`, this buffer requires less processing on the
//!   CPU because we don't need to keep track of the reads and writes.
//!
//! If you have data that is modified at every single frame, you are encouraged to use a
//! `CpuAccessibleBuffer`. If you have data that is very rarely modified, you are encouraged to
//! use an `ImmutableBuffer` or a `DeviceLocalBuffer` instead.
//!
//! If you just want to get started, you can use the `CpuAccessibleBuffer` everywhere, as it is
//! the most flexible type of buffer.
//!
//! # Buffers usage
//!
//! When you create a buffer object, you have to specify its *usage*. In other words, you have to
//! specify the way it is going to be used. Trying to use a buffer in a way that wasn't specified
//! when you created it will result in an error.
//!
//! You can use buffers for the following purposes:
//!
//! - Can contain arbitrary data that can be transferred from/to other buffers and images.
//! - Can be read and modified from a shader.
//! - Can be used as a source of vertices and indices.
//! - Can be used as a source of list of models for draw indirect commands.
//!
//! Accessing a buffer from a shader can be done in the following ways:
//!
//! - As a uniform buffer. Uniform buffers are read-only.
//! - As a storage buffer. Storage buffers can be read and written.
//! - As a uniform texel buffer. Contrary to a uniform buffer, the data is interpreted by the
//!   GPU and can be for example normalized.
//! - As a storage texel buffer. Additionnally, some data formats can be modified with atomic
//!   operations.
//!
//! Using uniform/storage texel buffers requires creating a *buffer view*. See the `view` module
//! for how to create a buffer view.
//!

pub use self::cpu_access::CpuAccessibleBuffer;
pub use self::cpu_pool::CpuBufferPool;
pub use self::device_local::DeviceLocalBuffer;
pub use self::immutable::ImmutableBuffer;
pub use self::slice::BufferSlice;
pub use self::sys::BufferCreationError;
pub use self::sys::Usage as BufferUsage;
pub use self::traits::BufferAccess;
pub use self::traits::BufferInner;
pub use self::traits::Buffer;
pub use self::traits::TypedBuffer;
pub use self::traits::TypedBufferAccess;
pub use self::view::BufferView;
pub use self::view::BufferViewRef;

pub mod cpu_access;
pub mod cpu_pool;
pub mod device_local;
pub mod immutable;
pub mod sys;
pub mod view;

mod slice;
mod traits;
<|endoftext|>


<commit_before>// Copyright 2013-2017, 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>

#[cfg(feature = "use_glib")]
use glib::translate::*;
use ffi::enums::RegionOverlap;
use RectangleInt;
use ffi;

use ffi::cairo_region_t;
use ffi::enums::Status;

pub struct Region(*mut cairo_region_t, bool);

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *mut ffi::cairo_region_t> for &'a Region {
    type Storage = &'a Region;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::cairo_region_t, &'a Region> {
        Stash(self.0, *self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut ffi::cairo_region_t {
        unsafe {
            ffi::cairo_region_reference(self.0)
        }
    }
}

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl<'a> ToGlibPtrMut<'a, *mut ffi::cairo_region_t> for Region {
    type Storage = &'a mut Self;

    // FIXME: This is unsafe: regions are reference counted so we could get multiple mutable
    // references here
    #[inline]
    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::cairo_region_t, Self> {
        StashMut(self.0, self)
    }
}

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl FromGlibPtrNone<*mut ffi::cairo_region_t> for Region {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::cairo_region_t) -> Region {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl FromGlibPtrBorrow<*mut ffi::cairo_region_t> for Region {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_region_t) -> Region {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl FromGlibPtrFull<*mut ffi::cairo_region_t> for Region {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::cairo_region_t) -> Region {
        Self::from_raw_full(ptr)
    }
}

#[cfg(feature = "use_glib")]
gvalue_impl!(Region, ffi::cairo_region_t, ffi::gobject::cairo_gobject_region_get_type);

impl AsRef<Region> for Region {
    fn as_ref(&self) -> &Region {
        self
    }
}

impl Clone for Region {
    fn clone(&self) -> Region {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl Drop for Region {
    fn drop(&mut self) {
        if !self.1 {
            unsafe { ffi::cairo_region_destroy(self.0); }
        }
    }
}

impl PartialEq for Region {
    fn eq(&self, other: &Region) -> bool {
        unsafe {
            ffi::cairo_region_equal(self.0, other.0).as_bool()
        }
    }
}

impl Region {
    #[inline]
    unsafe fn from_raw_none(ptr: *mut ffi::cairo_region_t) -> Region {
        assert!(!ptr.is_null());
        ffi::cairo_region_reference(ptr);
        Region(ptr, false)
    }

    #[inline]
    unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_region_t) -> Region {
        assert!(!ptr.is_null());
        Region(ptr, true)
    }

    #[inline]
    unsafe fn from_raw_full(ptr: *mut ffi::cairo_region_t) -> Region {
        assert!(!ptr.is_null());
        Region(ptr, false)
    }

    #[doc(hidden)]
    pub fn to_raw_none(&self) -> *mut ffi::cairo_region_t {
        self.0
    }

    pub fn create() -> Region {
        unsafe {
            Self::from_raw_full(ffi::cairo_region_create())
        }
    }

    pub fn create_rectangle(rectangle: &RectangleInt) -> Region {
        unsafe {
            Self::from_raw_full(ffi::cairo_region_create_rectangle(rectangle.to_raw_none()))
        }
    }

    pub fn create_rectangles(rectangles: &[RectangleInt]) -> Region {
        unsafe {
            Self::from_raw_full(ffi::cairo_region_create_rectangles(rectangles.as_ptr() as *mut ffi::cairo_rectangle_int_t, rectangles.len() as i32))
        }
    }

    pub fn copy(&self) -> Region {
        unsafe {
            Self::from_raw_full(ffi::cairo_region_copy(self.0))
        }
    }

    pub fn status(&self) -> Status {
        unsafe {
            ffi::cairo_region_status(self.0)
        }
    }

    pub fn get_extents(&self, rectangle: &mut RectangleInt) {
        unsafe {
            ffi::cairo_region_get_extents(self.0, rectangle.to_raw_none())
        }
    }

    pub fn num_rectangles(&self) -> i32 {
        unsafe {
            ffi::cairo_region_num_rectangles(self.0)
        }
    }

    pub fn get_rectangle(&self, nth: i32) -> RectangleInt {
        unsafe {
            let rectangle: RectangleInt = ::std::mem::zeroed();
            ffi::cairo_region_get_rectangle(self.0, nth, rectangle.to_raw_none());
            rectangle
        }
    }

    pub fn is_empty(&self) -> bool {
        unsafe {
            ffi::cairo_region_is_empty(self.0).as_bool()
        }
    }

    pub fn contains_point(&self, x: i32, y: i32) -> bool {
        unsafe {
            ffi::cairo_region_contains_point(self.0, x, y).as_bool()
        }
    }

    pub fn contains_rectangle(&self, rectangle: &RectangleInt) -> RegionOverlap {
        unsafe {
            ffi::cairo_region_contains_rectangle(self.0, rectangle.to_raw_none())
        }
    }

    pub fn translate(&self, dx: i32, dy: i32) {
        unsafe {
            ffi::cairo_region_translate(self.0, dx, dy)
        }
    }

    pub fn intersect(&self, other: &Region) -> Status {
        unsafe {
            ffi::cairo_region_intersect(self.0, other.0)
        }
    }

    pub fn intersect_rectangle(&self, rectangle: &RectangleInt) -> Status {
        unsafe {
            ffi::cairo_region_intersect_rectangle(self.0, rectangle.to_raw_none())
        }
    }

    pub fn subtract(&self, other: &Region) -> Status {
        unsafe {
            ffi::cairo_region_subtract(self.0, other.0)
        }
    }

    pub fn subtract_rectangle(&self, rectangle: &RectangleInt) -> Status {
        unsafe {
            ffi::cairo_region_subtract_rectangle(self.0, rectangle.to_raw_none())
        }
    }

    pub fn union(&self, other: &Region) -> Status {
        unsafe {
            ffi::cairo_region_union(self.0, other.0)
        }
    }

    pub fn union_rectangle(&self, rectangle: &RectangleInt) -> Status {
        unsafe {
            ffi::cairo_region_union_rectangle(self.0, rectangle.to_raw_none())
        }
    }

    pub fn xor(&self, other: &Region) -> Status {
        unsafe {
            ffi::cairo_region_xor(self.0, other.0)
        }
    }

    pub fn xor_rectangle(&self, rectangle: &RectangleInt) -> Status {
        unsafe {
            ffi::cairo_region_xor_rectangle(self.0, rectangle.to_raw_none())
        }
    }
}
<commit_msg>Implement Eq for Region<commit_after>// Copyright 2013-2017, 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>

#[cfg(feature = "use_glib")]
use glib::translate::*;
use ffi::enums::RegionOverlap;
use RectangleInt;
use ffi;

use ffi::cairo_region_t;
use ffi::enums::Status;

pub struct Region(*mut cairo_region_t, bool);

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *mut ffi::cairo_region_t> for &'a Region {
    type Storage = &'a Region;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::cairo_region_t, &'a Region> {
        Stash(self.0, *self)
    }

    #[inline]
    fn to_glib_full(&self) -> *mut ffi::cairo_region_t {
        unsafe {
            ffi::cairo_region_reference(self.0)
        }
    }
}

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl<'a> ToGlibPtrMut<'a, *mut ffi::cairo_region_t> for Region {
    type Storage = &'a mut Self;

    // FIXME: This is unsafe: regions are reference counted so we could get multiple mutable
    // references here
    #[inline]
    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut ffi::cairo_region_t, Self> {
        StashMut(self.0, self)
    }
}

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl FromGlibPtrNone<*mut ffi::cairo_region_t> for Region {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::cairo_region_t) -> Region {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl FromGlibPtrBorrow<*mut ffi::cairo_region_t> for Region {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::cairo_region_t) -> Region {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
#[doc(hidden)]
impl FromGlibPtrFull<*mut ffi::cairo_region_t> for Region {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::cairo_region_t) -> Region {
        Self::from_raw_full(ptr)
    }
}

#[cfg(feature = "use_glib")]
gvalue_impl!(Region, ffi::cairo_region_t, ffi::gobject::cairo_gobject_region_get_type);

impl AsRef<Region> for Region {
    fn as_ref(&self) -> &Region {
        self
    }
}

impl Clone for Region {
    fn clone(&self) -> Region {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl Drop for Region {
    fn drop(&mut self) {
        if !self.1 {
            unsafe { ffi::cairo_region_destroy(self.0); }
        }
    }
}

impl PartialEq for Region {
    fn eq(&self, other: &Region) -> bool {
        unsafe {
            ffi::cairo_region_equal(self.0, other.0).as_bool()
        }
    }
}

impl Eq for Region { }

impl Region {
    #[inline]
    unsafe fn from_raw_none(ptr: *mut ffi::cairo_region_t) -> Region {
        assert!(!ptr.is_null());
        ffi::cairo_region_reference(ptr);
        Region(ptr, false)
    }

    #[inline]
    unsafe fn from_raw_borrow(ptr: *mut ffi::cairo_region_t) -> Region {
        assert!(!ptr.is_null());
        Region(ptr, true)
    }

    #[inline]
    unsafe fn from_raw_full(ptr: *mut ffi::cairo_region_t) -> Region {
        assert!(!ptr.is_null());
        Region(ptr, false)
    }

    #[doc(hidden)]
    pub fn to_raw_none(&self) -> *mut ffi::cairo_region_t {
        self.0
    }

    pub fn create() -> Region {
        unsafe {
            Self::from_raw_full(ffi::cairo_region_create())
        }
    }

    pub fn create_rectangle(rectangle: &RectangleInt) -> Region {
        unsafe {
            Self::from_raw_full(ffi::cairo_region_create_rectangle(rectangle.to_raw_none()))
        }
    }

    pub fn create_rectangles(rectangles: &[RectangleInt]) -> Region {
        unsafe {
            Self::from_raw_full(ffi::cairo_region_create_rectangles(rectangles.as_ptr() as *mut ffi::cairo_rectangle_int_t, rectangles.len() as i32))
        }
    }

    pub fn copy(&self) -> Region {
        unsafe {
            Self::from_raw_full(ffi::cairo_region_copy(self.0))
        }
    }

    pub fn status(&self) -> Status {
        unsafe {
            ffi::cairo_region_status(self.0)
        }
    }

    pub fn get_extents(&self, rectangle: &mut RectangleInt) {
        unsafe {
            ffi::cairo_region_get_extents(self.0, rectangle.to_raw_none())
        }
    }

    pub fn num_rectangles(&self) -> i32 {
        unsafe {
            ffi::cairo_region_num_rectangles(self.0)
        }
    }

    pub fn get_rectangle(&self, nth: i32) -> RectangleInt {
        unsafe {
            let rectangle: RectangleInt = ::std::mem::zeroed();
            ffi::cairo_region_get_rectangle(self.0, nth, rectangle.to_raw_none());
            rectangle
        }
    }

    pub fn is_empty(&self) -> bool {
        unsafe {
            ffi::cairo_region_is_empty(self.0).as_bool()
        }
    }

    pub fn contains_point(&self, x: i32, y: i32) -> bool {
        unsafe {
            ffi::cairo_region_contains_point(self.0, x, y).as_bool()
        }
    }

    pub fn contains_rectangle(&self, rectangle: &RectangleInt) -> RegionOverlap {
        unsafe {
            ffi::cairo_region_contains_rectangle(self.0, rectangle.to_raw_none())
        }
    }

    pub fn translate(&self, dx: i32, dy: i32) {
        unsafe {
            ffi::cairo_region_translate(self.0, dx, dy)
        }
    }

    pub fn intersect(&self, other: &Region) -> Status {
        unsafe {
            ffi::cairo_region_intersect(self.0, other.0)
        }
    }

    pub fn intersect_rectangle(&self, rectangle: &RectangleInt) -> Status {
        unsafe {
            ffi::cairo_region_intersect_rectangle(self.0, rectangle.to_raw_none())
        }
    }

    pub fn subtract(&self, other: &Region) -> Status {
        unsafe {
            ffi::cairo_region_subtract(self.0, other.0)
        }
    }

    pub fn subtract_rectangle(&self, rectangle: &RectangleInt) -> Status {
        unsafe {
            ffi::cairo_region_subtract_rectangle(self.0, rectangle.to_raw_none())
        }
    }

    pub fn union(&self, other: &Region) -> Status {
        unsafe {
            ffi::cairo_region_union(self.0, other.0)
        }
    }

    pub fn union_rectangle(&self, rectangle: &RectangleInt) -> Status {
        unsafe {
            ffi::cairo_region_union_rectangle(self.0, rectangle.to_raw_none())
        }
    }

    pub fn xor(&self, other: &Region) -> Status {
        unsafe {
            ffi::cairo_region_xor(self.0, other.0)
        }
    }

    pub fn xor_rectangle(&self, rectangle: &RectangleInt) -> Status {
        unsafe {
            ffi::cairo_region_xor_rectangle(self.0, rectangle.to_raw_none())
        }
    }
}
<|endoftext|>


<commit_before>use std::ascii::AsciiExt;
use std::mem;
use std::borrow::{ Cow };
use std::collections::{ HashMap };
use std::fmt::Write;

use maud::{ Escaper };
use pulldown_cmark::{ Event, Tag };

use escape::HrefEscaper;

pub struct Config {
  pub header_ids: bool,
}

struct Context<'a> {
  numbers: HashMap<Cow<'a, str>, usize>,
  within_image: bool,
  within_header: bool,
  header_queue: Vec<Event<'a>>,
  header_text: String,
  config: Config,
}

pub fn render_events<'a, I: Iterator<Item=Event<'a>>>(config: Config, events: I, mut w: &mut String) {
  let mut context = Context {
    numbers: HashMap::new(),
    within_image: false,
    within_header: false,
    header_queue: Vec::new(),
    header_text: String::new(),
    config: config,
  };
  render_events_internal(&mut context, events, w)
}

fn render_events_internal<'a, I: Iterator<Item=Event<'a>>>(context: &mut Context<'a>, events: I, mut w: &mut String) {
  for event in events {
    if context.within_header {
      render_event_within_header(event, context, &mut w);
    } else if context.within_image {
      render_event_within_image(event, context, &mut w);
    } else {
      render_event(event, context, &mut w);
    }
  }
}

fn render_event<'a>(event: Event<'a>, context: &mut Context<'a>, w: &mut String) {
  match event {
    Event::Start(tag) => render_start_tag(tag, context, w),
    Event::End(tag) => render_end_tag(tag, w),
    Event::Text(text) => Escaper::new(w).write_str(&*text).unwrap(),
    Event::Html(html) | Event::InlineHtml(html) => w.push_str(&*html),
    Event::SoftBreak => w.push('\n'),
    Event::HardBreak => w.push_str("
\n"),
    Event::FootnoteReference(name) => render_footnote_reference(name, &mut context.numbers, w),
  }
}

fn render_event_within_image<'a>(event: Event<'a>, context: &mut Context<'a>, w: &mut String) {
  match event {
    Event::Start(_) => unreachable!(),
    Event::End(Tag::Image(_, title)) => {
      context.within_image = false;
      render_image_end_tag(&*title, w);
    },
    Event::End(_) => unreachable!(),
    Event::Text(text) => Escaper::new(w).write_str(&*text).unwrap(),
    Event::Html(_) => unreachable!(),
    Event::InlineHtml(html) => Escaper::new(w).write_str(&*html).unwrap(),
    Event::SoftBreak | Event::HardBreak => w.push(' '),
    Event::FootnoteReference(name) => render_footnote_reference_within_image(name, &mut context.numbers, w),
  }
}

fn render_event_within_header<'a>(event: Event<'a>, context: &mut Context<'a>, w: &mut String) {
  match event {
    Event::Start(Tag::Header(_)) => {
      unreachable!();
    },
    Event::End(Tag::Header(level)) => {
      context.within_header = false;
      let id = mem::replace(&mut context.header_text, String::new());
      let events = mem::replace(&mut context.header_queue, Vec::new());
      render_header_start_tag(level as u8, Some(id), w);
      render_events_internal(context, events.into_iter(), w);
      render_header_end_tag(level as u8, w)
    },
    Event::Text(text) => {
      // TODO: WHY RUST WHY?
      // error: mismatched types:
      //  expected `&str`,
      //  found `[closure@src/render.rs:93:28: 93:72]`
      // let t = text.replace(|c: char| c.is_whitespace() || !c.is_ascii(), "-");
      let t: String = text.chars()
        .map(|c| if c.is_whitespace() || !c.is_ascii() { '-' } else { c.to_ascii_lowercase() })
        .collect();
      context.header_text.push_str(&*t);
      context.header_queue.push(Event::Text(text));
    },
    Event::SoftBreak | Event::HardBreak => {
      context.header_text.push('-');
      context.header_queue.push(event);
    },
    _ => {
      context.header_queue.push(event);
    },
  }
}

fn render_start_tag<'a>(tag: Tag<'a>, context: &mut Context<'a>, mut w: &mut String) {
  match tag {
    Tag::Rule => w.push_str("
\n"),
    Tag::Code => w.push_str(""),
    Tag::Strong => w.push_str(""),
    Tag::Emphasis => w.push_str(""),
    Tag::Paragraph => w.push_str("
"),
    Tag::BlockQuote => w.push_str("
\n"),

    Tag::Table(_) => w.push_str("
"),
    Tag::TableHead => w.push_str("

"),
    Tag::TableRow => w.push_str("
"),
    Tag::TableCell => w.push_str(""),

    Tag::Item => w.push_str("
"),
    Tag::List(None) => w.push_str("
\n"),
    Tag::List(Some(1)) => w.push_str("
\n"),
    Tag::List(Some(start)) => write!(w, "
\n", start).unwrap(),

    Tag::Header(level) => {
      if context.config.header_ids {
        context.within_header = true;
      } else {
        render_header_start_tag(level as u8, None, w)
      }
    },
    Tag::CodeBlock(info) => render_code_block_start_tag(&*info, w),
    Tag::Image(src, _) => {
      context.within_image = true;
      render_image_start_tag(&*src, w)
    },
    Tag::Link(dest, title) => render_link_start_tag(&*dest, &*title, w),
    Tag::FootnoteDefinition(name) => render_footnote_definition_start_tag(name, &mut context.numbers, w),
  }
}

fn render_end_tag<'a>(tag: Tag<'a>, mut w: &mut String) {
  match tag {
    Tag::Rule => {},
    Tag::Code => w.push_str(""),
    Tag::Strong => w.push_str(""),
    Tag::Emphasis => w.push_str(""),
    Tag::Paragraph => w.push_str("
\n"),
    Tag::BlockQuote => w.push_str("
\n"),

    Tag::Table(_) => w.push_str("
\n"),
    Tag::TableHead => w.push_str("

\n"),
    Tag::TableRow => w.push_str("
\n"),
    Tag::TableCell => w.push_str("	"),

    Tag::Item => w.push_str("
\n"),
    Tag::List(None) => w.push_str("
\n"),
    Tag::List(Some(_)) => w.push_str("
\n"),

    Tag::Header(level) => render_header_end_tag(level as u8, w),
    Tag::CodeBlock(_) => w.push_str("
\n"),
    Tag::Image(_, _) => unreachable!(),
    Tag::Link(_, _) => w.push_str(""),
    Tag::FootnoteDefinition(_) => w.push_str("
\n"),
  }
}

fn render_link_start_tag(dest: &str, title: &str, mut w: &mut String) {
  w.push_str("")
}

fn render_image_start_tag(src: &str, mut w: &mut String) {
  w.push_str("")
}

fn render_header_start_tag(level: u8, id: Option<String>, mut w: &mut String) {
  w.push_str("<h");
  w.push((b'0' + level) as char);
  if let Some(id) = id {
    w.push_str(" id=\"");
    w.push_str(&*id);
    w.push('"');
  }
  w.push('>')
}

fn render_header_end_tag(level: u8, mut w: &mut String) {
  w.push_str("</h");
  w.push((b'0' + level) as char);
  w.push_str(">\n")
}

fn render_code_block_start_tag(info: &str, mut w: &mut String) {
  let lang = info.split(' ').next().unwrap();
  if lang.is_empty() {
    w.push_str("
")
  } else {
    w.push_str("
")
  }
}

fn render_footnote_definition_start_tag<'a>(name: Cow<'a, str>, numbers: &mut HashMap<Cow<'a, str>, usize>, mut w: &mut String) {
  w.push_str("
{}", number).unwrap();
}

fn render_footnote_reference<'a>(name: Cow<'a, str>, numbers: &mut HashMap<Cow<'a, str>, usize>, mut w: &mut String) {
  w.push_str("{}", number).unwrap();
}

fn render_footnote_reference_within_image<'a>(name: Cow<'a, str>, numbers: &mut HashMap<Cow<'a, str>, usize>, mut w: &mut String) {
  let len = numbers.len();
  let number = numbers.entry(name).or_insert(len);
  write!(w, "[{}]", number).unwrap();
}

<commit_msg>Remove unreachable macros<commit_after>use std::ascii::AsciiExt;
use std::mem;
use std::borrow::{ Cow };
use std::collections::{ HashMap };
use std::fmt::Write;

use maud::{ Escaper };
use pulldown_cmark::{ Event, Tag };

use escape::HrefEscaper;

pub struct Config {
  pub header_ids: bool,
}

struct Context<'a> {
  numbers: HashMap<Cow<'a, str>, usize>,
  within_image: bool,
  within_header: bool,
  header_queue: Vec<Event<'a>>,
  header_text: String,
  config: Config,
}

pub fn render_events<'a, I: Iterator<Item=Event<'a>>>(config: Config, events: I, mut w: &mut String) {
  let mut context = Context {
    numbers: HashMap::new(),
    within_image: false,
    within_header: false,
    header_queue: Vec::new(),
    header_text: String::new(),
    config: config,
  };
  render_events_internal(&mut context, events, w)
}

fn render_events_internal<'a, I: Iterator<Item=Event<'a>>>(context: &mut Context<'a>, events: I, mut w: &mut String) {
  for event in events {
    if context.within_header {
      render_event_within_header(event, context, &mut w);
    } else if context.within_image {
      render_event_within_image(event, context, &mut w);
    } else {
      render_event(event, context, &mut w);
    }
  }
}

fn render_event<'a>(event: Event<'a>, context: &mut Context<'a>, w: &mut String) {
  match event {
    Event::Start(tag) => render_start_tag(tag, context, w),
    Event::End(tag) => render_end_tag(tag, w),
    Event::Text(text) => Escaper::new(w).write_str(&*text).unwrap(),
    Event::Html(html) | Event::InlineHtml(html) => w.push_str(&*html),
    Event::SoftBreak => w.push('\n'),
    Event::HardBreak => w.push_str("
\n"),
    Event::FootnoteReference(name) => render_footnote_reference(name, &mut context.numbers, w),
  }
}

fn render_event_within_image<'a>(event: Event<'a>, context: &mut Context<'a>, w: &mut String) {
  match event {
    Event::Start(_) => (),
    Event::End(Tag::Image(_, title)) => {
      context.within_image = false;
      render_image_end_tag(&*title, w);
    },
    Event::End(_) => (),
    Event::Text(text) => Escaper::new(w).write_str(&*text).unwrap(),
    Event::Html(_) => (),
    Event::InlineHtml(html) => Escaper::new(w).write_str(&*html).unwrap(),
    Event::SoftBreak | Event::HardBreak => w.push(' '),
    Event::FootnoteReference(name) => render_footnote_reference_within_image(name, &mut context.numbers, w),
  }
}

fn render_event_within_header<'a>(event: Event<'a>, context: &mut Context<'a>, w: &mut String) {
  match event {
    Event::Start(Tag::Header(_)) => { },
    Event::End(Tag::Header(level)) => {
      context.within_header = false;
      let id = mem::replace(&mut context.header_text, String::new());
      let events = mem::replace(&mut context.header_queue, Vec::new());
      render_header_start_tag(level as u8, Some(id), w);
      render_events_internal(context, events.into_iter(), w);
      render_header_end_tag(level as u8, w)
    },
    Event::Text(text) => {
      // TODO: WHY RUST WHY?
      // error: mismatched types:
      //  expected `&str`,
      //  found `[closure@src/render.rs:93:28: 93:72]`
      // let t = text.replace(|c: char| c.is_whitespace() || !c.is_ascii(), "-");
      let t: String = text.chars()
        .map(|c| if c.is_whitespace() || !c.is_ascii() { '-' } else { c.to_ascii_lowercase() })
        .collect();
      context.header_text.push_str(&*t);
      context.header_queue.push(Event::Text(text));
    },
    Event::SoftBreak | Event::HardBreak => {
      context.header_text.push('-');
      context.header_queue.push(event);
    },
    _ => {
      context.header_queue.push(event);
    },
  }
}

fn render_start_tag<'a>(tag: Tag<'a>, context: &mut Context<'a>, mut w: &mut String) {
  match tag {
    Tag::Rule => w.push_str("
\n"),
    Tag::Code => w.push_str(""),
    Tag::Strong => w.push_str(""),
    Tag::Emphasis => w.push_str(""),
    Tag::Paragraph => w.push_str("
"),
    Tag::BlockQuote => w.push_str("
\n"),

    Tag::Table(_) => w.push_str("
"),
    Tag::TableHead => w.push_str("

"),
    Tag::TableRow => w.push_str("
"),
    Tag::TableCell => w.push_str(""),

    Tag::Item => w.push_str("
"),
    Tag::List(None) => w.push_str("
\n"),
    Tag::List(Some(1)) => w.push_str("
\n"),
    Tag::List(Some(start)) => write!(w, "
\n", start).unwrap(),

    Tag::Header(level) => {
      if context.config.header_ids {
        context.within_header = true;
      } else {
        render_header_start_tag(level as u8, None, w)
      }
    },
    Tag::CodeBlock(info) => render_code_block_start_tag(&*info, w),
    Tag::Image(src, _) => {
      context.within_image = true;
      render_image_start_tag(&*src, w)
    },
    Tag::Link(dest, title) => render_link_start_tag(&*dest, &*title, w),
    Tag::FootnoteDefinition(name) => render_footnote_definition_start_tag(name, &mut context.numbers, w),
  }
}

fn render_end_tag<'a>(tag: Tag<'a>, mut w: &mut String) {
  match tag {
    Tag::Rule => {},
    Tag::Code => w.push_str(""),
    Tag::Strong => w.push_str(""),
    Tag::Emphasis => w.push_str(""),
    Tag::Paragraph => w.push_str("
\n"),
    Tag::BlockQuote => w.push_str("
\n"),

    Tag::Table(_) => w.push_str("
\n"),
    Tag::TableHead => w.push_str("

\n"),
    Tag::TableRow => w.push_str("
\n"),
    Tag::TableCell => w.push_str("	"),

    Tag::Item => w.push_str("
\n"),
    Tag::List(None) => w.push_str("
\n"),
    Tag::List(Some(_)) => w.push_str("
\n"),

    Tag::Header(level) => render_header_end_tag(level as u8, w),
    Tag::CodeBlock(_) => w.push_str("
\n"),
    Tag::Image(_, _) => (),
    Tag::Link(_, _) => w.push_str(""),
    Tag::FootnoteDefinition(_) => w.push_str("
\n"),
  }
}

fn render_link_start_tag(dest: &str, title: &str, mut w: &mut String) {
  w.push_str("")
}

fn render_image_start_tag(src: &str, mut w: &mut String) {
  w.push_str("")
}

fn render_header_start_tag(level: u8, id: Option<String>, mut w: &mut String) {
  w.push_str("<h");
  w.push((b'0' + level) as char);
  if let Some(id) = id {
    w.push_str(" id=\"");
    w.push_str(&*id);
    w.push('"');
  }
  w.push('>')
}

fn render_header_end_tag(level: u8, mut w: &mut String) {
  w.push_str("</h");
  w.push((b'0' + level) as char);
  w.push_str(">\n")
}

fn render_code_block_start_tag(info: &str, mut w: &mut String) {
  let lang = info.split(' ').next().unwrap();
  if lang.is_empty() {
    w.push_str("
")
  } else {
    w.push_str("
")
  }
}

fn render_footnote_definition_start_tag<'a>(name: Cow<'a, str>, numbers: &mut HashMap<Cow<'a, str>, usize>, mut w: &mut String) {
  w.push_str("
{}", number).unwrap();
}

fn render_footnote_reference<'a>(name: Cow<'a, str>, numbers: &mut HashMap<Cow<'a, str>, usize>, mut w: &mut String) {
  w.push_str("{}", number).unwrap();
}

fn render_footnote_reference_within_image<'a>(name: Cow<'a, str>, numbers: &mut HashMap<Cow<'a, str>, usize>, mut w: &mut String) {
  let len = numbers.len();
  let number = numbers.entry(name).or_insert(len);
  write!(w, "[{}]", number).unwrap();
}

<|endoftext|>


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

use std;
use gfx;
use gfx::traits::*;
use cgmath;
use cgmath::FixedArray;

static FLAT_VERTEX_SRC: &'static [u8] = b"
    #version 150 core

    in ivec2 i_Pos;
    in vec3 i_Color;
    out vec4 v_Color;

    uniform mat4 u_Transform;

    void main() {
        v_Color = vec4(i_Color, 1.0);
        gl_Position = u_Transform * vec4(i_Pos, 0.0, 1.0);
    }
";

static FLAT_FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core

    in vec4 v_Color;
    out vec4 o_Color;

    void main() {
        o_Color = v_Color;
    }
";

#[vertex_format]
#[derive(Clone, Copy)]
struct FlatVertex {
    #[name = "i_Pos"]
    pos: [u16; 2],

    #[name = "i_Color"]
    color: [f32; 3],
}

#[shader_param]
struct FlatParams<R: gfx::Resources> {
    #[name = "u_Transform"]
    transform: [[f32; 4]; 4],

    _dummy: std::marker::PhantomData<R>
}

pub struct RenderHelper<R: gfx::Resources> {
    solid_color_program: gfx::device::handle::Program<R>,
    draw_state: gfx::DrawState
}

impl<R: gfx::Resources> RenderHelper<R> {
    pub fn new<F: gfx::Factory<R>>(factory: &mut F) -> RenderHelper<R> {
        // Set up the stuff we'll need to render
        let solid_color_program = match factory.link_program(FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC) {
            Ok(v) => v,
            Err(e) => panic!(format!("{:?}", e))
        };
        let state = gfx::DrawState::new();

        RenderHelper {
            solid_color_program: solid_color_program,
            draw_state: state
        }
    }

    pub fn render<
        O: gfx::Output<R>,
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>
    >(
        &mut self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        data: RenderData<R>)
    {
        // Prepare the uniforms to be used for rendering
        let (x, y) = output.get_size();
        let proj = cgmath::ortho::<f32>(0.0, x as f32, y as f32, 0.0, 1.0, -1.0);
        let params = FlatParams::<R> {
            transform: proj.into_fixed(),
            _dummy: std::marker::PhantomData
        };

        // Render all rectangles
        for entry in &data.entries {
            match entry {
                &RenderEntry::Flat(ref data, color) =>
                    self.render_rect_flat(output, renderer, factory, data, color, &params),
                &RenderEntry::Textured(ref data, ref texture) =>
                    self.render_rect_textured(output, renderer, factory, data, texture, &params)
            }
        }
    }

    fn render_rect_flat<O: gfx::Output<R>, C: gfx::CommandBuffer<R>, F: gfx::Factory<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        rect: &Rectangle, color: [f32;3], params: &FlatParams<R>)
    {
        // Create a mesh from the rectangle
        let mut vertices = Vec::<FlatVertex>::new();
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        let mesh = factory.create_mesh(&vertices);

        // Actually render that mesh
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.solid_color_program, params);
        renderer.draw(&batch, output).unwrap();
    }

    fn render_rect_textured<O: gfx::Output<R>, C: gfx::CommandBuffer<R>, F: gfx::Factory<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        rect: &Rectangle, texture: &gfx::TextureHandle<R>, params: &FlatParams<R>)
    {
        let color: [f32;3] = [1.0, 0.0, 1.0];

        // Create a mesh from the rectangle
        let mut vertices = Vec::<FlatVertex>::new();
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        let mesh = factory.create_mesh(&vertices);

        // Actually render that mesh
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.solid_color_program, params);
        renderer.draw(&batch, output).unwrap();
    }
}

pub struct Rectangle {
    start: [u16;2],
    end: [u16;2]
}

impl Rectangle {
    fn new(position: [u16;2], size: [u16;2]) -> Rectangle {
        Rectangle {
            start: [position[0], position[1]],
            end: [position[0] + size[0], position[1] + size[1]]
        }
    }
}

pub enum RenderEntry<R: gfx::Resources> {
    Flat(Rectangle, [f32;3]),
    Textured(Rectangle, gfx::TextureHandle<R>)
}

pub struct RenderData<R: gfx::Resources>
{
    entries: Vec<RenderEntry<R>>
}

impl<R: gfx::Resources> RenderData<R> {
    pub fn new() -> RenderData<R> {
        RenderData {
            entries: Vec::new()
        }
    }

    pub fn push_rect_flat(&mut self, position: [u16;2], size: [u16;2], color: [f32;3]) {
        self.entries.push(RenderEntry::Flat(Rectangle::new(position, size), color));
    }

    pub fn push_rect_textured(&mut self, position: [u16;2], size: [u16;2], texture: gfx::TextureHandle<R>) {
        self.entries.push(RenderEntry::Textured(Rectangle::new(position, size), texture));
    }
}
<commit_msg>Add image rendering<commit_after>// Copyright 2015 The Athena Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std;
use gfx;
use gfx::traits::*;
use cgmath;
use cgmath::FixedArray;

static FLAT_VERTEX_SRC: &'static [u8] = b"
    #version 150 core

    in ivec2 i_Pos;
    in vec3 i_Color;
    out vec4 v_Color;

    uniform mat4 u_Transform;

    void main() {
        v_Color = vec4(i_Color, 1.0);
        gl_Position = u_Transform * vec4(i_Pos, 0.0, 1.0);
    }
";

static FLAT_FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core

    in vec4 v_Color;
    out vec4 o_Color;

    void main() {
        o_Color = v_Color;
    }
";

#[vertex_format]
#[derive(Clone, Copy)]
struct FlatVertex {
    #[name = "i_Pos"]
    pos: [u16;2],

    #[name = "i_Color"]
    color: [f32;3],
}

#[shader_param]
struct FlatParams<R: gfx::Resources> {
    #[name = "u_Transform"]
    transform: [[f32;4];4],

    _dummy: std::marker::PhantomData<R>
}

static TEXTURED_VERTEX_SRC: &'static [u8] = b"
    #version 150 core

    in ivec2 i_Pos;
    in vec2 i_TexCoord;
    out vec2 v_TexCoord;

    uniform mat4 u_Transform;

    void main() {
        v_TexCoord = i_TexCoord;
        gl_Position = u_Transform * vec4(i_Pos, 0.0, 1.0);
    }
";

static TEXTURED_FRAGMENT_SRC: &'static [u8] = b"
    #version 150 core

    in vec2 v_TexCoord;
    out vec4 o_Color;

    uniform sampler2D u_Texture;

    void main() {
        o_Color = texture(u_Texture, v_TexCoord);
    }
";

#[vertex_format]
#[derive(Clone, Copy)]
struct TexturedVertex {
    #[name = "i_Pos"]
    pos: [u16;2],

    #[name = "i_TexCoord"]
    tex_coord: [f32;2],
}

#[shader_param]
struct TexturedParams<R: gfx::Resources> {
    #[name = "u_Transform"]
    transform: [[f32;4];4],

    #[name = "u_Texture"]
    texture: gfx::shade::TextureParam<R>
}

pub struct RenderHelper<R: gfx::Resources> {
    flat_program: gfx::device::handle::Program<R>,
    textured_program: gfx::device::handle::Program<R>,
    draw_state: gfx::DrawState,
    sampler: gfx::device::handle::Sampler<R>
}

impl<R: gfx::Resources> RenderHelper<R> {
    pub fn new<F: gfx::Factory<R>>(factory: &mut F) -> RenderHelper<R> {
        // Set up the stuff we'll need to render
        let flat_program = match factory.link_program(FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC) {
            Ok(v) => v,
            Err(e) => panic!(format!("{:?}", e))
        };
        let textured_program = match factory.link_program(TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC) {
            Ok(v) => v,
            Err(e) => panic!(format!("{:?}", e))
        };

        let state = gfx::DrawState::new();
        let sampler = factory.create_sampler(
            gfx::tex::SamplerInfo::new(
                gfx::tex::FilterMethod::Bilinear,
                gfx::tex::WrapMode::Clamp));

        RenderHelper {
            flat_program: flat_program,
            textured_program: textured_program,
            draw_state: state,
            sampler: sampler
        }
    }

    pub fn render<
        O: gfx::Output<R>,
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>
    >(
        &mut self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        data: RenderData<R>)
    {
        // Prepare shared uniform data that never has to change
        let (x, y) = output.get_size();
        let proj = cgmath::ortho::<f32>(0.0, x as f32, y as f32, 0.0, 1.0, -1.0).into_fixed();
        let flat_params = FlatParams::<R> {
            transform: proj.clone(),
            _dummy: std::marker::PhantomData
        };

        // Render all rectangles
        for entry in &data.entries {
            match entry {
                &RenderEntry::Flat(ref data, color) =>
                    self.render_rect_flat(output, renderer, factory, data, color, &flat_params),
                &RenderEntry::Textured(ref data, ref texture) =>
                    self.render_rect_textured(output, renderer, factory, data, texture, &proj)
            }
        }
    }

    fn render_rect_flat<O: gfx::Output<R>, C: gfx::CommandBuffer<R>, F: gfx::Factory<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        rect: &Rectangle, color: [f32;3], params: &FlatParams<R>)
    {
        // Create a mesh from the rectangle
        let mut vertices = Vec::<FlatVertex>::new();
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.end[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.end[0], rect.start[1] ], color: color });
        vertices.push(FlatVertex { pos: [ rect.start[0], rect.end[1] ], color: color });
        let mesh = factory.create_mesh(&vertices);

        // Actually render that mesh
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.flat_program, params);
        renderer.draw(&batch, output).unwrap();
    }

    fn render_rect_textured<O: gfx::Output<R>, C: gfx::CommandBuffer<R>, F: gfx::Factory<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>, factory: &mut F,
        rect: &Rectangle, texture: &gfx::TextureHandle<R>, proj: &[[f32;4];4])
    {
        let textured_params = TexturedParams::<R> {
            transform: proj.clone(),
            texture: (texture.clone(), Some(self.sampler.clone()))
        };

        // Create a mesh from the rectangle
        let mut vertices = Vec::<TexturedVertex>::new();
        vertices.push(TexturedVertex { pos: [ rect.end[0], rect.start[1] ], tex_coord: [1.0, 0.0] });
        vertices.push(TexturedVertex { pos: [ rect.start[0], rect.start[1] ], tex_coord: [0.0, 0.0] });
        vertices.push(TexturedVertex { pos: [ rect.start[0], rect.end[1] ], tex_coord: [0.0, 1.0] });
        vertices.push(TexturedVertex { pos: [ rect.end[0], rect.end[1] ], tex_coord: [1.0, 1.0] });
        vertices.push(TexturedVertex { pos: [ rect.end[0], rect.start[1] ], tex_coord: [1.0, 0.0] });
        vertices.push(TexturedVertex { pos: [ rect.start[0], rect.end[1] ], tex_coord: [0.0, 1.0] });
        let mesh = factory.create_mesh(&vertices);

        // Actually render that mesh
        let slice = mesh.to_slice(gfx::PrimitiveType::TriangleList);
        let batch = gfx::batch::bind(&self.draw_state, &mesh, slice.clone(), &self.textured_program, &textured_params);
        renderer.draw(&batch, output).unwrap();
    }
}

struct Rectangle {
    start: [u16;2],
    end: [u16;2]
}

impl Rectangle {
    fn new(position: [u16;2], size: [u16;2]) -> Rectangle {
        Rectangle {
            start: [position[0], position[1]],
            end: [position[0] + size[0], position[1] + size[1]]
        }
    }
}

enum RenderEntry<R: gfx::Resources> {
    Flat(Rectangle, [f32;3]),
    Textured(Rectangle, gfx::TextureHandle<R>)
}

pub struct RenderData<R: gfx::Resources>
{
    entries: Vec<RenderEntry<R>>
}

impl<R: gfx::Resources> RenderData<R> {
    pub fn new() -> RenderData<R> {
        RenderData {
            entries: Vec::new()
        }
    }

    pub fn push_rect_flat(&mut self, position: [u16;2], size: [u16;2], color: [f32;3]) {
        self.entries.push(RenderEntry::Flat(Rectangle::new(position, size), color));
    }

    pub fn push_rect_textured(&mut self, position: [u16;2], size: [u16;2], texture: gfx::TextureHandle<R>) {
        self.entries.push(RenderEntry::Textured(Rectangle::new(position, size), texture));
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::fmt::{self, Display, Formatter};
use std::result;

use Class;

pub type Result<T> = result::Result<T, Error>;

#[derive(Debug, PartialEq)]
pub enum Error {
    ArgumentError(String),
    TypeError(String),
}

impl Error {
    /// Converts error to an exception class.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::result::Error;
    /// use ruru::{Class, VM};
    ///
    /// # VM::init();
    /// let argument_error = Error::ArgumentError("Argument is missing".to_string());
    /// let type_error = Error::TypeError("Wrong type".to_string());
    ///
    /// assert_eq!(argument_error.to_exception(), Class::from_existing("ArgumentError"));
    /// assert_eq!(type_error.to_exception(), Class::from_existing("TypeError"));
    /// ```
    pub fn to_exception(&self) -> Class {
        let class_name = match *self {
            Error::ArgumentError(_) => "ArgumentError",
            Error::TypeError(_) => "TypeError",
        };

        Class::from_existing(class_name)
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", <Error as error::Error>::description(&self))
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ArgumentError(ref message) => message,
            Error::TypeError(ref message) => message,
        }
    }
}
<commit_msg>Change result::Error::description()<commit_after>use std::error;
use std::fmt::{self, Display, Formatter};
use std::result;

use Class;

pub type Result<T> = result::Result<T, Error>;

#[derive(Debug, PartialEq)]
pub enum Error {
    ArgumentError(String),
    TypeError(String),
}

impl Error {
    /// Converts error to an exception class.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::result::Error;
    /// use ruru::{Class, VM};
    ///
    /// # VM::init();
    /// let argument_error = Error::ArgumentError("Argument is missing".to_string());
    /// let type_error = Error::TypeError("Wrong type".to_string());
    ///
    /// assert_eq!(argument_error.to_exception(), Class::from_existing("ArgumentError"));
    /// assert_eq!(type_error.to_exception(), Class::from_existing("TypeError"));
    /// ```
    pub fn to_exception(&self) -> Class {
        let class_name = match *self {
            Error::ArgumentError(_) => "ArgumentError",
            Error::TypeError(_) => "TypeError",
        };

        Class::from_existing(class_name)
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}", <Error as error::Error>::description(&self))
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ArgumentError(ref message) | Error::TypeError(ref message) => message,
        }
    }
}
<|endoftext|>