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

#[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>
{
    while let Some(token_with_context) = tokens.peek().cloned() {
        match token_with_context.token {
            Token::Semicolon => {
                let _ = tokens.next();
                break;
            }
            Token::Class => break,
            Token::Fun => break,
            Token::Var => break,
            Token::For => break,
            Token::If => break,
            Token::While => break,
            Token::Print => break,
            Token::Return => break,
            _ => {
                let _ = tokens.next();
            }
        }
    }
}

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) {
                match result {
                    Ok(subexpression) => right = subexpression,
                    _ => return Some(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) {
                match result {
                    Ok(unary_expression) => right = unary_expression,
                    _ => return Some(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) {
                        match result {
                            Ok(expression) => expr = expression,
                            _ => return Some(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>Introducede the try_wrap_err macro to remove some boilerplate code<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>
{
    while let Some(token_with_context) = tokens.peek().cloned() {
        match token_with_context.token {
            Token::Semicolon => {
                let _ = tokens.next();
                break;
            }
            Token::Class => break,
            Token::Fun => break,
            Token::Var => break,
            Token::For => break,
            Token::If => break,
            Token::While => break,
            Token::Print => break,
            Token::Return => break,
            _ => {
                let _ = tokens.next();
            }
        }
    }
}

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());
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate encoding;

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

use self::byteorder::{ByteOrder, BigEndian, LittleEndian};
use self::encoding::label::encoding_from_whatwg_label;
use self::encoding::types::EncodingRef;
use self::encoding::types::DecoderTrap::Strict;

use super::{Catalog, Message};
use metadata::parse_metadata;

#[allow(non_upper_case_globals)]
static utf8_encoding: EncodingRef = &encoding::codec::utf_8::UTF8Encoding;

/// Represents an error encountered while parsing an MO file.
#[derive(Debug)]
pub enum Error {
    /// An incorrect magic number has been encountered
    BadMagic,
    /// An invalid byte sequence for the given encoding has been encountered
    DecodingError,
    /// An unexpected EOF occured
    Eof,
    /// An I/O error occured
    Io(io::Error),
    /// Incorrect syntax encountered while parsing the meta information
    MalformedMetadata,
    /// Meta information string was not the first string in the catalog
    MisplacedMetadata,
    /// An unknown encoding was specified in the metadata
    UnknownEncoding,
}
// Can not use use `Error::*` as per this issue:
// (https://github.com/rust-lang/rust/issues/4865)
use Error::{BadMagic, DecodingError, Eof, Io, MalformedMetadata, MisplacedMetadata,
            UnknownEncoding};

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            BadMagic => "bad magic number",
            DecodingError => "invalid byte sequence in a string",
            Eof => "unxpected end of file",
            Io(ref err) => err.description(),
            MalformedMetadata => "metadata syntax error",
            MisplacedMetadata => "misplaced metadata",
            UnknownEncoding => "unknown encoding specified",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let self_err: &error::Error = self;
        write!(fmt, "{}", self_err.description())
    }
}

impl From<io::Error> for Error {
    fn from(inner: io::Error) -> Error {
        Io(inner)
    }
}

impl From<Cow<'static, str>> for Error {
    fn from(_: Cow<'static, str>) -> Error {
        DecodingError
    }
}

/// ParseOptions allows setting options for parsing MO catalogs.
///
/// # Examples
/// ```ignore
/// use std::fs::File;
///
/// extern crate encoding;
/// use encoding::all::ISO_8859_1;
///
/// let file = File::open("french.mo").unwrap();
/// let catalog = ParseOptions::new().force_encoding(ISO_8859_1).parse(file).unwrap();
/// ```
#[allow(missing_debug_implementations)]
pub struct ParseOptions {
    force_encoding: Option<EncodingRef>,
}

impl ParseOptions {
    /// Returns a new instance of ParseOptions with default options.
    pub fn new() -> Self {
        ParseOptions { force_encoding: None }
    }

    /// Tries to parse the catalog from the given reader using the specified options.
    pub fn parse<R: io::Read>(&self, reader: R) -> Result<Catalog, Error> {
        parse_catalog(reader, self)
    }

    /// Forces a use of a specific encoding
    /// when parsing strings from a catalog.
    /// If this option is not enabled,
    /// the parser tries to use the encoding specified in the metadata
    /// or UTF-8 if metadata is non-existent.
    pub fn force_encoding(&mut self, encoding: EncodingRef) -> &mut Self {
        self.force_encoding = Some(encoding);
        self
    }
}

/// According to the given magic number of a MO file,
/// returns the function which reads a `u32` in the relevant endianness.
fn get_read_u32_fn(magic: &[u8]) -> Option<fn(&[u8]) -> u32> {
    if magic == [0xde, 0x12, 0x04, 0x95] {
        Some(LittleEndian::read_u32)
    } else if magic == [0x95, 0x04, 0x12, 0xde] {
        Some(BigEndian::read_u32)
    } else {
        None
    }
}

pub fn parse_catalog<R: io::Read>(mut file: R, opts: &ParseOptions) -> Result<Catalog, Error> {
    let mut contents = vec![];
    let n = try!(file.read_to_end(&mut contents));
    if n < 28 {
        return Err(Eof);
    }

    let read_u32 = match get_read_u32_fn(&contents[0..4]) {
        Some(f) => f,
        None => return Err(BadMagic),
    };

    // ignore hashing tables (bytes at 20..28)
    let num_strings = read_u32(&contents[8..12]) as usize;
    let mut off_otable = read_u32(&contents[12..16]) as usize;
    let mut off_ttable = read_u32(&contents[16..20]) as usize;
    if n < off_otable || n < off_ttable {
        return Err(Eof);
    }

    let mut catalog = Catalog::new();
    let mut encoding = opts.force_encoding.unwrap_or(utf8_encoding);

    for i in 0..num_strings {
        let id;
        let context;
        let translated: Vec<String>;
        // Parse the original string
        {
            if n < off_otable + 8 {
                return Err(Eof);
            }
            let len = read_u32(&contents[off_otable..off_otable + 4]) as usize;
            let off = read_u32(&contents[off_otable + 4..off_otable + 8]) as usize;
            // +1 compensates for the ending NUL byte which is not included in length
            if n < off + len + 1 {
                return Err(Eof);
            }
            let mut original = &contents[off..off + len + 1];
            // check for context
            context = match original.iter().position(|x| *x == 4) {
                Some(idx) => {
                    let ctx = &original[..idx];
                    original = &original[idx + 1..];
                    Some(try!(encoding.decode(ctx, Strict)))
                }
                None => None,
            };
            // extract msg_id singular, ignoring the plural
            id = match original.iter().position(|x| *x == 0).map(|i| &original[..i]) {
                Some(b) => try!(encoding.decode(b, Strict)),
                None => return Err(Eof),
            };
            if id == "" && i != 0 {
                return Err(MisplacedMetadata);
            }
        }

        // Parse the translation strings
        {
            if n < off_ttable + 8 {
                return Err(Eof);
            }
            let len = read_u32(&contents[off_ttable..off_ttable + 4]) as usize;
            let off = read_u32(&contents[off_ttable + 4..off_ttable + 8]) as usize;
            // +1 compensates for the ending NUL byte which is not included in length
            if n < off + len + 1 {
                return Err(Eof);
            }
            translated = try!((&contents[off..off + len])
                                  .split(|x| *x == 0)
                                  .map(|b| encoding.decode(b, Strict))
                                  .collect::<Result<Vec<_>, _>>());
            if id == "" {
                let map = parse_metadata(&*translated[0]).unwrap();
                if let (Some(c), None) = (map.charset(), opts.force_encoding) {
                    encoding = match encoding_from_whatwg_label(c) {
                        Some(enc_ref) => enc_ref,
                        None => return Err(UnknownEncoding),
                    }
                }
            }
        }

        catalog.insert(Message::new(id, context, translated));

        off_otable += 8;
        off_ttable += 8;
    }

    Ok(catalog)
}

#[test]
fn test_get_read_u32_fn() {
    use std::mem;

    assert!(get_read_u32_fn(&[]).is_none());
    assert!(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95, 0x00]).is_none());

    {
        let le_ptr: *const ();
        let ret_ptr;
        unsafe {
            le_ptr = mem::transmute(LittleEndian::read_u32 as usize);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95]).unwrap());
        }
        assert_eq!(le_ptr, ret_ptr);
    }

    {
        let be_ptr: *const ();
        let ret_ptr;
        unsafe {
            be_ptr = mem::transmute(BigEndian::read_u32);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0x95, 0x04, 0x12, 0xde]).unwrap());
        }
        assert_eq!(be_ptr, ret_ptr);
    }
}

#[test]
fn test_parse_catalog() {
    macro_rules! assert_variant {
        ($value:expr, $variant:path) => {
            match $value {
                $variant => (),
                _ => panic!("Expected {:?}, got {:?}", $variant, $value),
            }
        };
    }

    let fluff = [0; 24]; // zeros to pad our magic test cases to satisfy the length requirements

    {
        let mut reader = vec![1u8, 2, 3];
        reader.extend(fluff.iter().cloned());
        let err = parse_catalog(&reader[..], &ParseOptions::new()).unwrap_err();
        assert_variant!(err, Eof);
    }

    {
        let mut reader = vec![1u8, 2, 3, 4];
        reader.extend(fluff.iter().cloned());
        let err = parse_catalog(&reader[..], &ParseOptions::new()).unwrap_err();
        assert_variant!(err, BadMagic);
    }

    {
        let mut reader = vec![0x95, 0x04, 0x12, 0xde];
        reader.extend(fluff.iter().cloned());
        assert!(parse_catalog(&reader[..], &ParseOptions::new()).is_ok());
    }

    {
        let mut reader = vec![0xde, 0x12, 0x04, 0x95];
        reader.extend(fluff.iter().cloned());
        assert!(parse_catalog(&reader[..], &ParseOptions::new()).is_ok());
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/1.mo");
        let catalog = parse_catalog(reader, &ParseOptions::new()).unwrap();
        assert_eq!(catalog.strings.len(), 1);
        assert_eq!(catalog.strings["this is context\x04Text"],
                   Message::new("Text", Some("this is context"), vec!["Tekstas", "Tekstai"]));
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/2.mo");
        let catalog = parse_catalog(reader, &ParseOptions::new()).unwrap();
        assert_eq!(catalog.strings.len(), 2);
        assert_eq!(catalog.strings["Image"],
                   Message::new("Image", None, vec!["Nuotrauka", "Nuotraukos"]));
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/invalid_utf8.mo");
        let err = parse_catalog(reader, &ParseOptions::new()).unwrap_err();
        assert_variant!(err, DecodingError);
    }

    // cp1257_meta
    {
        let reader: &[u8] = include_bytes!("../test_cases/cp1257_meta.mo");
        let catalog = parse_catalog(reader, &ParseOptions::new()).unwrap();
        assert_eq!(catalog.gettext("Garlic"), "Česnakas");
    }

    // cp1257_forced
    {
        let reader: &[u8] = include_bytes!("../test_cases/cp1257_forced.mo");
        for enc_name in &["cp1257", "windows-1257", "x-cp1257"] {
            let encoding = encoding_from_whatwg_label(enc_name).unwrap();
            let catalog = ParseOptions::new().force_encoding(encoding).parse(reader).unwrap();
            assert_eq!(catalog.gettext("Garlic"), "Česnakas");
        }
    }
}
<commit_msg>One more clippy lint<commit_after>extern crate byteorder;
extern crate encoding;

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

use self::byteorder::{ByteOrder, BigEndian, LittleEndian};
use self::encoding::label::encoding_from_whatwg_label;
use self::encoding::types::EncodingRef;
use self::encoding::types::DecoderTrap::Strict;

use super::{Catalog, Message};
use metadata::parse_metadata;

#[allow(non_upper_case_globals)]
static utf8_encoding: EncodingRef = &encoding::codec::utf_8::UTF8Encoding;

/// Represents an error encountered while parsing an MO file.
#[derive(Debug)]
pub enum Error {
    /// An incorrect magic number has been encountered
    BadMagic,
    /// An invalid byte sequence for the given encoding has been encountered
    DecodingError,
    /// An unexpected EOF occured
    Eof,
    /// An I/O error occured
    Io(io::Error),
    /// Incorrect syntax encountered while parsing the meta information
    MalformedMetadata,
    /// Meta information string was not the first string in the catalog
    MisplacedMetadata,
    /// An unknown encoding was specified in the metadata
    UnknownEncoding,
}
// Can not use use `Error::*` as per this issue:
// (https://github.com/rust-lang/rust/issues/4865)
use Error::{BadMagic, DecodingError, Eof, Io, MalformedMetadata, MisplacedMetadata,
            UnknownEncoding};

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            BadMagic => "bad magic number",
            DecodingError => "invalid byte sequence in a string",
            Eof => "unxpected end of file",
            Io(ref err) => err.description(),
            MalformedMetadata => "metadata syntax error",
            MisplacedMetadata => "misplaced metadata",
            UnknownEncoding => "unknown encoding specified",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let self_err: &error::Error = self;
        write!(fmt, "{}", self_err.description())
    }
}

impl From<io::Error> for Error {
    fn from(inner: io::Error) -> Error {
        Io(inner)
    }
}

impl From<Cow<'static, str>> for Error {
    fn from(_: Cow<'static, str>) -> Error {
        DecodingError
    }
}

/// ParseOptions allows setting options for parsing MO catalogs.
///
/// # Examples
/// ```ignore
/// use std::fs::File;
///
/// extern crate encoding;
/// use encoding::all::ISO_8859_1;
///
/// let file = File::open("french.mo").unwrap();
/// let catalog = ParseOptions::new().force_encoding(ISO_8859_1).parse(file).unwrap();
/// ```
#[allow(missing_debug_implementations)]
pub struct ParseOptions {
    force_encoding: Option<EncodingRef>,
}

impl ParseOptions {
    /// Returns a new instance of ParseOptions with default options.
    pub fn new() -> Self {
        ParseOptions { force_encoding: None }
    }

    /// Tries to parse the catalog from the given reader using the specified options.
    pub fn parse<R: io::Read>(&self, reader: R) -> Result<Catalog, Error> {
        parse_catalog(reader, self)
    }

    /// Forces a use of a specific encoding
    /// when parsing strings from a catalog.
    /// If this option is not enabled,
    /// the parser tries to use the encoding specified in the metadata
    /// or UTF-8 if metadata is non-existent.
    pub fn force_encoding(&mut self, encoding: EncodingRef) -> &mut Self {
        self.force_encoding = Some(encoding);
        self
    }
}

/// According to the given magic number of a MO file,
/// returns the function which reads a `u32` in the relevant endianness.
fn get_read_u32_fn(magic: &[u8]) -> Option<fn(&[u8]) -> u32> {
    if magic == [0xde, 0x12, 0x04, 0x95] {
        Some(LittleEndian::read_u32)
    } else if magic == [0x95, 0x04, 0x12, 0xde] {
        Some(BigEndian::read_u32)
    } else {
        None
    }
}

pub fn parse_catalog<R: io::Read>(mut file: R, opts: &ParseOptions) -> Result<Catalog, Error> {
    let mut contents = vec![];
    let n = try!(file.read_to_end(&mut contents));
    if n < 28 {
        return Err(Eof);
    }

    let read_u32 = match get_read_u32_fn(&contents[0..4]) {
        Some(f) => f,
        None => return Err(BadMagic),
    };

    // ignore hashing tables (bytes at 20..28)
    let num_strings = read_u32(&contents[8..12]) as usize;
    let mut off_otable = read_u32(&contents[12..16]) as usize;
    let mut off_ttable = read_u32(&contents[16..20]) as usize;
    if n < off_otable || n < off_ttable {
        return Err(Eof);
    }

    let mut catalog = Catalog::new();
    let mut encoding = opts.force_encoding.unwrap_or(utf8_encoding);

    for i in 0..num_strings {
        let id;
        let context;
        let translated: Vec<String>;
        // Parse the original string
        {
            if n < off_otable + 8 {
                return Err(Eof);
            }
            let len = read_u32(&contents[off_otable..off_otable + 4]) as usize;
            let off = read_u32(&contents[off_otable + 4..off_otable + 8]) as usize;
            // +1 compensates for the ending NUL byte which is not included in length
            if n < off + len + 1 {
                return Err(Eof);
            }
            let mut original = &contents[off..off + len + 1];
            // check for context
            context = match original.iter().position(|x| *x == 4) {
                Some(idx) => {
                    let ctx = &original[..idx];
                    original = &original[idx + 1..];
                    Some(try!(encoding.decode(ctx, Strict)))
                }
                None => None,
            };
            // extract msg_id singular, ignoring the plural
            id = match original.iter().position(|x| *x == 0).map(|i| &original[..i]) {
                Some(b) => try!(encoding.decode(b, Strict)),
                None => return Err(Eof),
            };
            if id == "" && i != 0 {
                return Err(MisplacedMetadata);
            }
        }

        // Parse the translation strings
        {
            if n < off_ttable + 8 {
                return Err(Eof);
            }
            let len = read_u32(&contents[off_ttable..off_ttable + 4]) as usize;
            let off = read_u32(&contents[off_ttable + 4..off_ttable + 8]) as usize;
            // +1 compensates for the ending NUL byte which is not included in length
            if n < off + len + 1 {
                return Err(Eof);
            }
            translated = try!((&contents[off..off + len])
                                  .split(|x| *x == 0)
                                  .map(|b| encoding.decode(b, Strict))
                                  .collect::<Result<Vec<_>, _>>());
            if id == "" {
                let map = parse_metadata(&*translated[0]).unwrap();
                if let (Some(c), None) = (map.charset(), opts.force_encoding) {
                    encoding = match encoding_from_whatwg_label(c) {
                        Some(enc_ref) => enc_ref,
                        None => return Err(UnknownEncoding),
                    }
                }
            }
        }

        catalog.insert(Message::new(id, context, translated));

        off_otable += 8;
        off_ttable += 8;
    }

    Ok(catalog)
}

#[test]
fn test_get_read_u32_fn() {
    use std::mem;

    assert!(get_read_u32_fn(&[]).is_none());
    assert!(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95, 0x00]).is_none());

    {
        let le_ptr: *const ();
        let ret_ptr;
        unsafe {
            le_ptr = mem::transmute(LittleEndian::read_u32 as usize);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0xde, 0x12, 0x04, 0x95]).unwrap());
        }
        assert_eq!(le_ptr, ret_ptr);
    }

    {
        let be_ptr: *const ();
        let ret_ptr;
        unsafe {
            be_ptr = mem::transmute(BigEndian::read_u32 as usize);
            ret_ptr = mem::transmute(get_read_u32_fn(&[0x95, 0x04, 0x12, 0xde]).unwrap());
        }
        assert_eq!(be_ptr, ret_ptr);
    }
}

#[test]
fn test_parse_catalog() {
    macro_rules! assert_variant {
        ($value:expr, $variant:path) => {
            match $value {
                $variant => (),
                _ => panic!("Expected {:?}, got {:?}", $variant, $value),
            }
        };
    }

    let fluff = [0; 24]; // zeros to pad our magic test cases to satisfy the length requirements

    {
        let mut reader = vec![1u8, 2, 3];
        reader.extend(fluff.iter().cloned());
        let err = parse_catalog(&reader[..], &ParseOptions::new()).unwrap_err();
        assert_variant!(err, Eof);
    }

    {
        let mut reader = vec![1u8, 2, 3, 4];
        reader.extend(fluff.iter().cloned());
        let err = parse_catalog(&reader[..], &ParseOptions::new()).unwrap_err();
        assert_variant!(err, BadMagic);
    }

    {
        let mut reader = vec![0x95, 0x04, 0x12, 0xde];
        reader.extend(fluff.iter().cloned());
        assert!(parse_catalog(&reader[..], &ParseOptions::new()).is_ok());
    }

    {
        let mut reader = vec![0xde, 0x12, 0x04, 0x95];
        reader.extend(fluff.iter().cloned());
        assert!(parse_catalog(&reader[..], &ParseOptions::new()).is_ok());
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/1.mo");
        let catalog = parse_catalog(reader, &ParseOptions::new()).unwrap();
        assert_eq!(catalog.strings.len(), 1);
        assert_eq!(catalog.strings["this is context\x04Text"],
                   Message::new("Text", Some("this is context"), vec!["Tekstas", "Tekstai"]));
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/2.mo");
        let catalog = parse_catalog(reader, &ParseOptions::new()).unwrap();
        assert_eq!(catalog.strings.len(), 2);
        assert_eq!(catalog.strings["Image"],
                   Message::new("Image", None, vec!["Nuotrauka", "Nuotraukos"]));
    }

    {
        let reader: &[u8] = include_bytes!("../test_cases/invalid_utf8.mo");
        let err = parse_catalog(reader, &ParseOptions::new()).unwrap_err();
        assert_variant!(err, DecodingError);
    }

    // cp1257_meta
    {
        let reader: &[u8] = include_bytes!("../test_cases/cp1257_meta.mo");
        let catalog = parse_catalog(reader, &ParseOptions::new()).unwrap();
        assert_eq!(catalog.gettext("Garlic"), "Česnakas");
    }

    // cp1257_forced
    {
        let reader: &[u8] = include_bytes!("../test_cases/cp1257_forced.mo");
        for enc_name in &["cp1257", "windows-1257", "x-cp1257"] {
            let encoding = encoding_from_whatwg_label(enc_name).unwrap();
            let catalog = ParseOptions::new().force_encoding(encoding).parse(reader).unwrap();
            assert_eq!(catalog.gettext("Garlic"), "Česnakas");
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix goto going to the wrong place<commit_after><|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Unix/ls#Rust
// Works only with correct paths or no arguments at all

use std::env;
use std::fs;
use std::path::Path;

fn main() {
    // ignoring all arguments except the 1st
    match env::args().nth(1) { // check if the program received an argument
        Some(path) => { print_files(Path::new(&path)); }
        _ => { print_files( &env::current_dir().unwrap() ); }
    // note that current_dir value might be invalid, so it's a Result
    }
}

fn print_files(path:&Path) {
    let mut entries: Vec<String> = fs::read_dir(path).unwrap()
        .map(|x|
            x.unwrap().path() // DirEntry to PathBuf
            .file_name().unwrap() // trim to file name
            .to_os_string()
            .into_string().unwrap()
        ).collect(); // collecting Vec of file names
    entries.sort();
    for x in entries {println!("{}", x); }
}
<commit_msg>Update unix_ls.rs<commit_after>// Implements http://rosettacode.org/wiki/Unix/ls#Rust
// Works only with correct paths or no arguments at all

use std::env;
use std::fs;
use std::path::Path;

fn main() {
    // ignoring all arguments except the 1st
    match env::args().nth(1) { // check if the program received an argument
        Some(path) => { print_files(Path::new(&path)); }
        _ => { print_files( &env::current_dir().unwrap() ); }
    // note that current_dir value might be invalid, so it's a Result
    }
}

fn print_files(path:&Path) {
    let mut entries: Vec<_> = fs::read_dir(path).unwrap()
        .map(|x| x.unwrap().file_name())
        .collect();
    entries.sort();
    for x in entries {
        println!("{}", x.to_string_lossy());
    }
}
<|endoftext|>


<commit_before>pub use response::mime::{Mime, TopLevel, SubLevel};
use response::mime::Param;
use std::default::Default;

use std::str::FromStr;
use std::borrow::Borrow;
use std::fmt;

use router::Collider;

#[derive(Debug, Clone)]
pub struct ContentType(pub TopLevel, pub SubLevel, pub Option<Vec<Param>>);

macro_rules! is_some {
    ($ct:ident, $name:ident: $top:ident/$sub:ident) => {
        pub fn $ct() -> ContentType {
            ContentType::of(TopLevel::$top, SubLevel::$sub)
        }

        is_some!($name: $top/$sub);
    };

    ($name:ident: $top:ident/$sub:ident) => {
        pub fn $name(&self) -> bool {
            self.0 == TopLevel::$top && self.1 == SubLevel::$sub
        }
    };
}

impl ContentType {
    #[inline(always)]
    pub fn new(t: TopLevel, s: SubLevel, params: Option<Vec<Param>>) -> ContentType {
        ContentType(t, s, params)
    }

    #[inline(always)]
    pub fn of(t: TopLevel, s: SubLevel) -> ContentType {
        ContentType(t, s, None)
    }

    #[inline(always)]
    pub fn any() -> ContentType {
        ContentType::of(TopLevel::Star, SubLevel::Star)
    }

    pub fn is_ext(&self) -> bool {
        if let TopLevel::Ext(_) = self.0 {
            true
        } else if let SubLevel::Ext(_) = self.1 {
            true
        } else {
            false
        }
    }

    is_some!(json, is_json: Application/Json);
    is_some!(xml, is_xml: Application/Xml);
    is_some!(is_any: Star/Star);
    is_some!(html, is_html: Application/Html);
    is_some!(is_form: Application/WwwFormUrlEncoded);
    is_some!(is_data: Multipart/FormData);

    pub fn from_extension(ext: &str) -> ContentType {
        let (top_level, sub_level) = match ext {
            "txt" => (TopLevel::Text, SubLevel::Plain),
            "html" => (TopLevel::Text, SubLevel::Html),
            "xml" => (TopLevel::Application, SubLevel::Xml),
            "js" => (TopLevel::Application, SubLevel::Javascript),
            "css" => (TopLevel::Text, SubLevel::Css),
            "json" => (TopLevel::Application, SubLevel::Json),
            "png" => (TopLevel::Image, SubLevel::Png),
            "gif" => (TopLevel::Image, SubLevel::Gif),
            "bmp" => (TopLevel::Image, SubLevel::Bmp),
            "jpeg" => (TopLevel::Image, SubLevel::Jpeg),
            "jpg" => (TopLevel::Image, SubLevel::Jpeg),
            "pdf" => (TopLevel::Application, SubLevel::Ext("pdf".into())),
            _ => (TopLevel::Star, SubLevel::Star),
        };

        ContentType::of(top_level, sub_level)
    }
}

impl Default for ContentType {
    #[inline(always)]
    fn default() -> ContentType {
        ContentType::any()
    }
}

impl Into<Mime> for ContentType {
    fn into(self) -> Mime {
        Mime(self.0, self.1, self.2.unwrap_or_default())
    }
}

impl<T: Borrow<Mime>> From<T> for ContentType {
    default fn from(mime: T) -> ContentType {
        let mime: Mime = mime.borrow().clone();
        ContentType::from(mime)
    }
}

impl From<Mime> for ContentType {
    fn from(mime: Mime) -> ContentType {
        let params = match mime.2.len() {
            0 => None,
            _ => Some(mime.2),
        };

        ContentType(mime.0, mime.1, params)
    }
}

fn is_valid_first_char(c: char) -> bool {
    match c {
        'a'...'z' | 'A'...'Z' | '0'...'9' | '*' => true,
        _ => false,
    }
}

fn is_valid_char(c: char) -> bool {
    is_valid_first_char(c) || match c {
        '!' | '#' | '$' | '&' | '-' | '^' | '.' | '+' | '_' => true,
        _ => false,
    }
}

impl FromStr for ContentType {
    type Err = &'static str;

    fn from_str(raw: &str) -> Result<ContentType, &'static str> {
        let slash = match raw.find('/') {
            Some(i) => i,
            None => return Err("Missing / in MIME type."),
        };

        let top_s = &raw[..slash];
        let (sub_s, _rest) = match raw.find(';') {
            Some(j) => (&raw[(slash + 1)..j], Some(&raw[(j + 1)..])),
            None => (&raw[(slash + 1)..], None),
        };

        if top_s.len() < 1 || sub_s.len() < 1 {
            return Err("Empty string.");
        }

        if !is_valid_first_char(top_s.chars().next().unwrap())
                || !is_valid_first_char(sub_s.chars().next().unwrap()) {
            return Err("Invalid first char.");
        }

        if top_s.contains(|c| !is_valid_char(c))
                || sub_s.contains(|c| !is_valid_char(c)) {
            return Err("Invalid character in string.");
        }

        let (top_s, sub_s) = (&*top_s.to_lowercase(), &*sub_s.to_lowercase());
        let top_level = TopLevel::from_str(top_s).map_err(|_| "Bad TopLevel")?;
        let sub_level = SubLevel::from_str(sub_s).map_err(|_| "Bad SubLevel")?;

        // FIXME: Use `rest` to find params.
        Ok(ContentType::new(top_level, sub_level, None))
    }
}

impl fmt::Display for ContentType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}/{}", self.0.as_str(), self.1.as_str())?;

        self.2.as_ref().map_or(Ok(()), |params| {
            for param in params.iter() {
                let (ref attr, ref value) = *param;
                write!(f, "; {}={}", attr, value)?;
            }

            Ok(())
        })
    }
}

impl Collider for ContentType {
    fn collides_with(&self, other: &ContentType) -> bool {
        self.0.collides_with(&other.0) && self.1.collides_with(&other.1)
    }
}

impl Collider for TopLevel {
    fn collides_with(&self, other: &TopLevel) -> bool {
        *self == TopLevel::Star || *other == TopLevel::Star || *self == *other
    }
}

impl Collider for SubLevel {
    fn collides_with(&self, other: &SubLevel) -> bool {
        *self == SubLevel::Star || *other == SubLevel::Star || *self == *other
    }
}

#[cfg(test)]
mod test {
    use super::ContentType;
    use hyper::mime::{TopLevel, SubLevel};
    use std::str::FromStr;

    macro_rules! assert_no_parse {
        ($string:expr) => ({
            let result = ContentType::from_str($string);
            if !result.is_err() {
                println!("{} parsed!", $string);
            }

            assert!(result.is_err());
        });
    }

    macro_rules! assert_parse {
        ($string:expr) => ({
            let result = ContentType::from_str($string);
            assert!(result.is_ok());
            result.unwrap()
        });
        ($string:expr, $top:tt/$sub:tt) => ({
            let c = assert_parse!($string);
            assert_eq!(c.0, TopLevel::$top);
            assert_eq!(c.1, SubLevel::$sub);
            c
        })
    }

    #[test]
    fn test_simple() {
        assert_parse!("application/json", Application/Json);
        assert_parse!("*/json", Star/Json);
        assert_parse!("text/html", Text/Html);
        assert_parse!("TEXT/html", Text/Html);
        assert_parse!("*/*", Star/Star);
        assert_parse!("application/*", Application/Star);
    }

    #[test]
    fn test_params() {
        assert_parse!("application/json; charset=utf8", Application/Json);
        assert_parse!("application/*;charset=utf8;else=1", Application/Star);
        assert_parse!("*/*;charset=utf8;else=1", Star/Star);
    }

    #[test]
    fn test_bad_parses() {
        assert_no_parse!("application//json");
        assert_no_parse!("application///json");
        assert_no_parse!("/json");
        assert_no_parse!("text/");
        assert_no_parse!("text//");
        assert_no_parse!("/");
        assert_no_parse!("*/");
        assert_no_parse!("/*");
        assert_no_parse!("///");
    }
}
<commit_msg>Document ContentType.<commit_after>pub use response::mime::{Mime, TopLevel, SubLevel};
use response::mime::Param;
use std::default::Default;

use std::str::FromStr;
use std::borrow::Borrow;
use std::fmt;

use router::Collider;

/// Rocket's representation of HTTP Content-Types.
///
/// This type wraps raw HTTP `Content-Type`s in a type-safe manner. It provides
/// methods to create and test against common HTTP content-types. It also
/// provides methods to parse HTTP Content-Type values
/// ([from_str](#method.from_str)) and to return the ContentType associated with
/// a file extension ([from_ext](#method.from_extension)).
#[derive(Debug, Clone, PartialEq)]
pub struct ContentType(pub TopLevel, pub SubLevel, Option<Vec<Param>>);

macro_rules! is_some {
    ($ct:ident, $name:ident: $top:ident/$sub:ident) => {
        /// Returns a new ContentType that matches the MIME for this method's
        /// name.
        pub fn $ct() -> ContentType {
            ContentType::of(TopLevel::$top, SubLevel::$sub)
        }

        is_some!($name: $top/$sub);
    };

    ($name:ident: $top:ident/$sub:ident) => {
        /// Returns true if `self` is the content type matching the method's
        /// name.
        pub fn $name(&self) -> bool {
            self.0 == TopLevel::$top && self.1 == SubLevel::$sub
        }
    };
}

impl ContentType {
    #[doc(hidden)]
    #[inline(always)]
    pub fn new(t: TopLevel, s: SubLevel, params: Option<Vec<Param>>) -> ContentType {
        ContentType(t, s, params)
    }

    /// Constructs a new content type of the given top level and sub level
    /// types.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rocket::ContentType;
    /// use rocket::response::mime::{TopLevel, SubLevel};
    ///
    /// let html = ContentType::of(TopLevel::Application, SubLevel::Html);
    /// assert!(html.is_html());
    /// ```
    #[inline(always)]
    pub fn of(t: TopLevel, s: SubLevel) -> ContentType {
        ContentType(t, s, None)
    }

    /// Returns a new ContentType for `*/*`, i.e., any.
    #[inline(always)]
    pub fn any() -> ContentType {
        ContentType::of(TopLevel::Star, SubLevel::Star)
    }

    /// Returns true if this content type is not one of the standard content
    /// types, that if, if it is an "extended" content type.
    pub fn is_ext(&self) -> bool {
        if let TopLevel::Ext(_) = self.0 {
            true
        } else if let SubLevel::Ext(_) = self.1 {
            true
        } else {
            false
        }
    }

    /// Returns true if the content type is JSON, i.e: `application/json`.
    is_some!(json, is_json: Application/Json);

    /// Returns true if the content type is XML, i.e: `application/xml`.
    is_some!(xml, is_xml: Application/Xml);

    /// Returns true if the content type is any, i.e.: `*/*`.
    is_some!(is_any: Star/Star);

    /// Returns true if the content type is HTML, i.e.: `application/html`.
    is_some!(html, is_html: Application/Html);

    /// Returns true if the content type is that for non-data HTTP forms, i.e.:
    /// `application/x-www-form-urlencoded`.
    is_some!(is_form: Application/WwwFormUrlEncoded);

    /// Returns true if the content type is that for data HTTP forms, i.e.:
    /// `multipart/form-data`.
    is_some!(is_data: Multipart/FormData);

    /// Returns the Content-Type associated with the extension `ext`. Not all
    /// extensions are recognized. If an extensions is not recognized, then this
    /// method returns a ContentType of `any`.
    ///
    /// # Example
    ///
    /// A recognized content type:
    ///
    /// ```rust
    /// use rocket::ContentType;
    ///
    /// let xml = ContentType::from_extension("xml");
    /// assert!(xml.is_xml());
    /// ```
    ///
    /// An unrecognized content type:
    ///
    /// ```rust
    /// use rocket::ContentType;
    ///
    /// let foo = ContentType::from_extension("foo");
    /// assert!(foo.is_any());
    /// ```
    pub fn from_extension(ext: &str) -> ContentType {
        let (top_level, sub_level) = match ext {
            "txt" => (TopLevel::Text, SubLevel::Plain),
            "html" => (TopLevel::Text, SubLevel::Html),
            "xml" => (TopLevel::Application, SubLevel::Xml),
            "js" => (TopLevel::Application, SubLevel::Javascript),
            "css" => (TopLevel::Text, SubLevel::Css),
            "json" => (TopLevel::Application, SubLevel::Json),
            "png" => (TopLevel::Image, SubLevel::Png),
            "gif" => (TopLevel::Image, SubLevel::Gif),
            "bmp" => (TopLevel::Image, SubLevel::Bmp),
            "jpeg" => (TopLevel::Image, SubLevel::Jpeg),
            "jpg" => (TopLevel::Image, SubLevel::Jpeg),
            "pdf" => (TopLevel::Application, SubLevel::Ext("pdf".into())),
            _ => (TopLevel::Star, SubLevel::Star),
        };

        ContentType::of(top_level, sub_level)
    }
}

impl Default for ContentType {
    /// Returns a ContentType of `any`, or `*/*`.
    #[inline(always)]
    fn default() -> ContentType {
        ContentType::any()
    }
}

#[doc(hidden)]
impl Into<Mime> for ContentType {
    fn into(self) -> Mime {
        Mime(self.0, self.1, self.2.unwrap_or_default())
    }
}

#[doc(hidden)]
impl<T: Borrow<Mime>> From<T> for ContentType {
    default fn from(mime: T) -> ContentType {
        let mime: Mime = mime.borrow().clone();
        ContentType::from(mime)
    }
}

#[doc(hidden)]
impl From<Mime> for ContentType {
    fn from(mime: Mime) -> ContentType {
        let params = match mime.2.len() {
            0 => None,
            _ => Some(mime.2),
        };

        ContentType(mime.0, mime.1, params)
    }
}

fn is_valid_first_char(c: char) -> bool {
    match c {
        'a'...'z' | 'A'...'Z' | '0'...'9' | '*' => true,
        _ => false,
    }
}

fn is_valid_char(c: char) -> bool {
    is_valid_first_char(c) || match c {
        '!' | '#' | '$' | '&' | '-' | '^' | '.' | '+' | '_' => true,
        _ => false,
    }
}

impl FromStr for ContentType {
    type Err = &'static str;

    /// Parses a ContentType from a given Content-Type header value.
    ///
    /// # Examples
    ///
    /// Parsing an `application/json`:
    ///
    /// ```rust
    /// use rocket::ContentType;
    /// use std::str::FromStr;
    ///
    /// let json = ContentType::from_str("application/json");
    /// assert_eq!(json, Ok(ContentType::json()));
    /// ```
    ///
    /// Parsing a content-type extension:
    ///
    /// ```rust
    /// use rocket::ContentType;
    /// use std::str::FromStr;
    /// use rocket::response::mime::{TopLevel, SubLevel};
    ///
    /// let custom = ContentType::from_str("application/x-custom").unwrap();
    /// assert!(custom.is_ext());
    /// assert_eq!(custom.0, TopLevel::Application);
    /// assert_eq!(custom.1, SubLevel::Ext("x-custom".into()));
    /// ```
    ///
    /// Parsing an invalid Content-Type value:
    ///
    /// ```rust
    /// use rocket::ContentType;
    /// use std::str::FromStr;
    ///
    /// let custom = ContentType::from_str("application//x-custom");
    /// assert!(custom.is_err());
    /// ```
    fn from_str(raw: &str) -> Result<ContentType, &'static str> {
        let slash = match raw.find('/') {
            Some(i) => i,
            None => return Err("Missing / in MIME type."),
        };

        let top_s = &raw[..slash];
        let (sub_s, _rest) = match raw.find(';') {
            Some(j) => (&raw[(slash + 1)..j], Some(&raw[(j + 1)..])),
            None => (&raw[(slash + 1)..], None),
        };

        if top_s.len() < 1 || sub_s.len() < 1 {
            return Err("Empty string.");
        }

        if !is_valid_first_char(top_s.chars().next().unwrap())
                || !is_valid_first_char(sub_s.chars().next().unwrap()) {
            return Err("Invalid first char.");
        }

        if top_s.contains(|c| !is_valid_char(c))
                || sub_s.contains(|c| !is_valid_char(c)) {
            return Err("Invalid character in string.");
        }

        let (top_s, sub_s) = (&*top_s.to_lowercase(), &*sub_s.to_lowercase());
        let top_level = TopLevel::from_str(top_s).map_err(|_| "Bad TopLevel")?;
        let sub_level = SubLevel::from_str(sub_s).map_err(|_| "Bad SubLevel")?;

        // FIXME: Use `rest` to find params.
        Ok(ContentType::new(top_level, sub_level, None))
    }
}

impl fmt::Display for ContentType {
    /// Formats the ContentType as an HTTP Content-Type value.
    ///
    /// # Example
    ///
    /// ```rust
    /// use rocket::ContentType;
    ///
    /// let http_ct = format!("{}", ContentType::xml());
    /// assert_eq!(http_ct, "application/xml".to_string());
    /// ```
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}/{}", self.0.as_str(), self.1.as_str())?;

        self.2.as_ref().map_or(Ok(()), |params| {
            for param in params.iter() {
                let (ref attr, ref value) = *param;
                write!(f, "; {}={}", attr, value)?;
            }

            Ok(())
        })
    }
}

impl Collider for ContentType {
    fn collides_with(&self, other: &ContentType) -> bool {
        self.0.collides_with(&other.0) && self.1.collides_with(&other.1)
    }
}

impl Collider for TopLevel {
    fn collides_with(&self, other: &TopLevel) -> bool {
        *self == TopLevel::Star || *other == TopLevel::Star || *self == *other
    }
}

impl Collider for SubLevel {
    fn collides_with(&self, other: &SubLevel) -> bool {
        *self == SubLevel::Star || *other == SubLevel::Star || *self == *other
    }
}

#[cfg(test)]
mod test {
    use super::ContentType;
    use hyper::mime::{TopLevel, SubLevel};
    use std::str::FromStr;

    macro_rules! assert_no_parse {
        ($string:expr) => ({
            let result = ContentType::from_str($string);
            if !result.is_err() {
                println!("{} parsed!", $string);
            }

            assert!(result.is_err());
        });
    }

    macro_rules! assert_parse {
        ($string:expr) => ({
            let result = ContentType::from_str($string);
            assert!(result.is_ok());
            result.unwrap()
        });
        ($string:expr, $top:tt/$sub:tt) => ({
            let c = assert_parse!($string);
            assert_eq!(c.0, TopLevel::$top);
            assert_eq!(c.1, SubLevel::$sub);
            c
        })
    }

    #[test]
    fn test_simple() {
        assert_parse!("application/json", Application/Json);
        assert_parse!("*/json", Star/Json);
        assert_parse!("text/html", Text/Html);
        assert_parse!("TEXT/html", Text/Html);
        assert_parse!("*/*", Star/Star);
        assert_parse!("application/*", Application/Star);
    }

    #[test]
    fn test_params() {
        assert_parse!("application/json; charset=utf8", Application/Json);
        assert_parse!("application/*;charset=utf8;else=1", Application/Star);
        assert_parse!("*/*;charset=utf8;else=1", Star/Star);
    }

    #[test]
    fn test_bad_parses() {
        assert_no_parse!("application//json");
        assert_no_parse!("application///json");
        assert_no_parse!("/json");
        assert_no_parse!("text/");
        assert_no_parse!("text//");
        assert_no_parse!("/");
        assert_no_parse!("*/");
        assert_no_parse!("/*");
        assert_no_parse!("///");
    }
}
<|endoftext|>


<commit_before>use std::rc::{Rc, Weak};
use std::sync::{Arc, Mutex};
use std::collections::{HashMap, VecDeque};

use ::job::Job;
use ::worker::Worker;

pub type JobQueue = VecDeque<Weak<Job>>;
pub type JobQueues = HashMap<Vec<u8>, [JobQueue; 3]>;

pub struct JobStorage {
    jobs: HashMap<Vec<u8>, Rc<Job>>, // Owns the job objects forever
    queues: JobQueues,
}

pub type SharedJobStorage = Arc<Mutex<JobStorage>>;

pub trait HandleJobStorage {
    fn new_job_storage() -> SharedJobStorage;
    fn add_job(&mut self, job: Rc<Job>, priority: JobQueuePriority);
    fn get_job(&mut self, worker: &mut Worker) -> bool;
    fn remove_job(&mut self, unique: &Vec<u8>);
}

pub type JobQueuePriority = usize;

const INIT_JOB_STORAGE_CAPACITY: usize = 10000000; // XXX This should be configurable
const INIT_JOB_FUNCTIONS_CAPACITY: usize = 4096; // XXX This should be configurable

impl JobStorage {
    fn new() -> JobStorage {
        JobStorage {
            jobs: HashMap::with_capacity(INIT_JOB_STORAGE_CAPACITY),
            queues: HashMap::with_capacity(INIT_JOB_FUNCTIONS_CAPACITY),
        }
    }

    pub fn queues(&self) -> &JobQueues {
        &self.queues
    }
}

impl HandleJobStorage for SharedJobStorage {
    fn new_job_storage() -> SharedJobStorage {
        Arc::new(Mutex::new(JobStorage::new()))
    }

    fn add_job(&mut self, job: Rc<Job>, priority: JobQueuePriority) {
        let mut storage = self.lock().unwrap();
        if !storage.queues.contains_key(&job.fname) {
            let high_queue = VecDeque::new();
            let norm_queue = VecDeque::new();
            let low_queue = VecDeque::new();
            storage.queues.insert(job.fname.clone(), [high_queue, norm_queue, low_queue]);
        }
        storage.jobs.insert(job.fname.clone(), job.clone());
        storage.queues.get_mut(&job.fname).unwrap()[priority].push_back(Rc::downgrade(&job));
    }

    fn get_job(&mut self, worker: &mut Worker) -> bool {
        let mut storage = self.lock().unwrap();
        let mut job: Option<Rc<Job>> = None;
        debug!("{:?}", &worker);
        for func in worker.iter() {
            debug!("func = {:?}", &func);
            match storage.queues.get_mut(&func) {
                None => {},
                Some(prios) => {
                    debug!("found func with {} priority queues", prios.len());
                    let mut i = 0;
                    for q in prios {
                        debug!("searching priority {}", i);
                        i = i + 1;
                        if !q.is_empty() {
                            debug!("Queue has items! {:?}", q.len());
                            loop {
                                match q.pop_front().unwrap().upgrade() { // Unwrap depends on queue!empty
                                    Some(j) => {
                                        job = Some(j);
                                        break
                                    },
                                    None => {
                                        debug!("Perhaps cancelled job.");
                                    }, // Cancelled job
                                }
                            }
                            match job {
                                None => {},
                                Some(_) => break,
                            }
                        }
                    }
                },
            }
        }
        match job {
            Some(job) => {
                worker.assign_job(&job);
                true
            },
            None => false,
        }
    }

    fn remove_job(&mut self, unique: &Vec<u8>) {
        let mut storage = self.lock().unwrap();
        match storage.jobs.get(unique) {
            None => return,
            Some(j) => {
                match Rc::weak_count(j) {
                    0 => {},
                    a @ _ => {
                        warn!("Removing job with weak references {:?} ({}+{})",
                              j, Rc::strong_count(j), a);
                    },
                }
            }
        }
        storage.jobs.remove(unique);
    }
}
<commit_msg>Weaks seem to be dying too fast<commit_after>use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::collections::{HashMap, VecDeque};

use ::job::Job;
use ::worker::Worker;

pub type JobQueue = VecDeque<Rc<Job>>;
pub type JobQueues = HashMap<Vec<u8>, [JobQueue; 3]>;

pub struct JobStorage {
    jobs: HashMap<Vec<u8>, Rc<Job>>, // Owns the job objects forever
    queues: JobQueues,
}

pub type SharedJobStorage = Arc<Mutex<JobStorage>>;

pub trait HandleJobStorage {
    fn new_job_storage() -> SharedJobStorage;
    fn add_job(&mut self, job: Rc<Job>, priority: JobQueuePriority);
    fn get_job(&mut self, worker: &mut Worker) -> bool;
    fn remove_job(&mut self, unique: &Vec<u8>);
}

pub type JobQueuePriority = usize;

const INIT_JOB_STORAGE_CAPACITY: usize = 10000000; // XXX This should be configurable
const INIT_JOB_FUNCTIONS_CAPACITY: usize = 4096; // XXX This should be configurable

impl JobStorage {
    fn new() -> JobStorage {
        JobStorage {
            jobs: HashMap::with_capacity(INIT_JOB_STORAGE_CAPACITY),
            queues: HashMap::with_capacity(INIT_JOB_FUNCTIONS_CAPACITY),
        }
    }

    pub fn queues(&self) -> &JobQueues {
        &self.queues
    }
}

impl HandleJobStorage for SharedJobStorage {
    fn new_job_storage() -> SharedJobStorage {
        Arc::new(Mutex::new(JobStorage::new()))
    }

    fn add_job(&mut self, job: Rc<Job>, priority: JobQueuePriority) {
        let mut storage = self.lock().unwrap();
        if !storage.queues.contains_key(&job.fname) {
            let high_queue = VecDeque::new();
            let norm_queue = VecDeque::new();
            let low_queue = VecDeque::new();
            storage.queues.insert(job.fname.clone(), [high_queue, norm_queue, low_queue]);
        }
        storage.jobs.insert(job.fname.clone(), job.clone());
        storage.queues.get_mut(&job.fname).unwrap()[priority].push_back(job.clone());
    }

    fn get_job(&mut self, worker: &mut Worker) -> bool {
        let mut storage = self.lock().unwrap();
        let mut job: Option<Rc<Job>> = None;
        debug!("{:?}", &worker);
        for func in worker.iter() {
            debug!("func = {:?}", &func);
            match storage.queues.get_mut(&func) {
                None => {},
                Some(prios) => {
                    debug!("found func with {} priority queues", prios.len());
                    let mut i = 0;
                    for q in prios {
                        debug!("searching priority {}", i);
                        i = i + 1;
                        if !q.is_empty() {
                            debug!("Queue has items! {:?}", q.len());
                            job = q.pop_front();
                            break
                        }
                    }
                },
            }
        }
        match job {
            Some(job) => {
                worker.assign_job(&job);
                true
            },
            None => false,
        }
    }

    fn remove_job(&mut self, unique: &Vec<u8>) {
        let mut storage = self.lock().unwrap();
        match storage.jobs.get(unique) {
            None => return,
            Some(j) => {
                match Rc::weak_count(j) {
                    0 => {},
                    a @ _ => {
                        warn!("Removing job with weak references {:?} ({}+{})",
                              j, Rc::strong_count(j), a);
                    },
                }
            }
        }
        storage.jobs.remove(unique);
    }
}
<|endoftext|>


<commit_before>use std::io::Read;

use errors::{Result, ErrorKind};
use message::Message;

use byteorder::ReadBytesExt;
use byteorder::LittleEndian as LE;

const WIRE_TYPE_VARINT: u8 = 0;
const WIRE_TYPE_FIXED64: u8 = 1;
const WIRE_TYPE_LENGTH_DELIMITED: u8 = 2;
const WIRE_TYPE_START_GROUP: u8 = 3;
const WIRE_TYPE_END_GROUP: u8 = 4;
const WIRE_TYPE_FIXED32: u8 = 5;

/// A struct to read protocol binary files
pub struct Reader<R> {
    inner: R,
    len: usize,
}

impl<R: Read> Reader<R> {

    /// Creates a new protocol buffer reader with the maximum len of bytes to read
    pub fn from_reader(r: R, len: usize) -> Reader<R> {
        Reader { inner: r, len: len }
    }

    /// Reads next tag, `None` if all bytes have been read
    pub fn next_tag(&mut self) -> Result<u32> {
        self.read_varint().map(|i| (i as u32))
    }

    fn read_varint(&mut self) -> Result<u64> {
        let mut r: u64 = 0;
        let mut i = 0;
        for _ in 0..9 {
            self.len -= 1;
            let b = self.inner.read_u8()?;
            r |= ((b & 0x7f) as u64) << i;
            if b < 0x80 {
                return Ok(r);
            }
            i += 7;
        }
        self.len -= 1;
        match self.inner.read_u8()? {
            0 => Ok(r),
            1 => {
                r |= 1 << 63;
                Ok(r)
            }
            _ => Err(ErrorKind::Varint.into()), // we have only one spare bit to fit into
        }
    }

    pub fn read_int32(&mut self) -> Result<i32> {
        self.read_varint().map(|i| i as i32)
    }

    pub fn read_int64(&mut self) -> Result<i64> {
        self.read_varint().map(|i| i as i64)
    }

    pub fn read_uint32(&mut self) -> Result<u32> {
        self.read_varint().map(|i| i as u32)
    }

    pub fn read_uint64(&mut self) -> Result<u64> {
        self.read_varint()
    }

    pub fn read_sint32(&mut self) -> Result<i32> {
        // zigzag
        let n = self.read_varint()? as u32;
        Ok(((n >> 1) as i32) ^ (-((n & 1) as i32)))
    }

    pub fn read_sint64(&mut self) -> Result<i64> {
        // zigzag
        let n = self.read_varint()?;
        Ok(((n >> 1) as i64) ^ (-((n & 1) as i64)))
    }

    pub fn read_fixed64(&mut self) -> Result<u64> {
        self.len -= 8;
        self.inner.read_u64::<LE>().map_err(|e| e.into())
    }

    pub fn read_fixed32(&mut self) -> Result<u32> {
        self.len -= 4;
        self.inner.read_u32::<LE>().map_err(|e| e.into())
    }

    pub fn read_sfixed64(&mut self) -> Result<i64> {
        self.len -= 8;
        self.inner.read_i64::<LE>().map_err(|e| e.into())
    }

    pub fn read_sfixed32(&mut self) -> Result<i32> {
        self.len -= 4;
        self.inner.read_i32::<LE>().map_err(|e| e.into())
    }

    pub fn read_float(&mut self) -> Result<f32> {
        self.len -= 4;
        self.inner.read_f32::<LE>().map_err(|e| e.into())
    }

    pub fn read_double(&mut self) -> Result<f64> {
        self.len -= 8;
        self.inner.read_f64::<LE>().map_err(|e| e.into())
    }

    pub fn read_bool(&mut self) -> Result<bool> {
        self.read_varint().map(|i| i != 0)
    }

    pub fn read_enum<E: From<u64>>(&mut self) -> Result<E> {
        self.read_varint().map(|i| i.into())
    }

    pub fn read_bytes(&mut self) -> Result<Vec<u8>> {
        let len = self.read_varint()? as usize;
        self.len -= len;
        let mut vec = Vec::with_capacity(len);
        unsafe { vec.set_len(len); }
        self.inner.read_exact(&mut vec[..])?;
        Ok(vec)
    }

    pub fn read_string(&mut self) -> Result<String> {
        let vec = self.read_bytes()?;
        String::from_utf8(vec).map_err(|e| e.into())
    }

    pub fn read_packed_repeated_field<M, F: FnMut(&mut Self) -> Result<M>>(&mut self, mut read: F) -> Result<Vec<M>> {
        let len = self.read_varint()? as usize;
        let cur_len = self.len;
        self.len = len;
        let mut v = Vec::new();
        while self.len > 0 {
            v.push(read(self)?);
        }
        self.len = cur_len - len;
        Ok(v)
    }

    pub fn read_message<M: Message>(&mut self) -> Result<M> {
        let len = self.read_varint()? as usize;
        let cur_len = self.len;
        self.len = len;
        let msg = M::from_reader(self)?;
        self.len = cur_len - len;
        Ok(msg)
    }

    pub fn read_unknown(&mut self, tag_value: u32) -> Result<()> {
        match (tag_value & 0x7) as u8 {
            WIRE_TYPE_VARINT => { self.read_varint()?; },
            WIRE_TYPE_FIXED64 => {
                self.len -= 8;
                self.inner.read_exact(&mut [0; 8])?;
            }
            WIRE_TYPE_FIXED32 => {
                self.len -= 4;
                self.inner.read_exact(&mut [0; 4])?;
            }
            WIRE_TYPE_LENGTH_DELIMITED => {
                let len = self.read_varint()? as usize;
                if len == 0 { return Ok(()); }
                self.len -= len;
                let mut buf = Vec::with_capacity(len);
                unsafe { buf.set_len(len); }
                self.inner.read_exact(&mut buf)?;
            },
            WIRE_TYPE_START_GROUP |
                WIRE_TYPE_END_GROUP => { return Err(ErrorKind::Deprecated("group").into()); },
            t => { return Err(ErrorKind::UnknownWireType(t).into()); },
        }
        Ok(())
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn inner(&mut self) -> &mut R {
        &mut self.inner
    }

    pub fn is_eof(&self) -> bool {
        self.len == 0
    }
}

#[test]
fn test_varint() {
    let data: &[u8] = &[0x96, 0x01];
    let mut r = Reader::from_reader(data, data.len());
    assert_eq!(150, r.read_varint().unwrap());
    assert!(r.next_tag_value().is_none());
}
<commit_msg>fix broken test<commit_after>use std::io::Read;

use errors::{Result, ErrorKind};
use message::Message;

use byteorder::ReadBytesExt;
use byteorder::LittleEndian as LE;

const WIRE_TYPE_VARINT: u8 = 0;
const WIRE_TYPE_FIXED64: u8 = 1;
const WIRE_TYPE_LENGTH_DELIMITED: u8 = 2;
const WIRE_TYPE_START_GROUP: u8 = 3;
const WIRE_TYPE_END_GROUP: u8 = 4;
const WIRE_TYPE_FIXED32: u8 = 5;

/// A struct to read protocol binary files
pub struct Reader<R> {
    inner: R,
    len: usize,
}

impl<R: Read> Reader<R> {

    /// Creates a new protocol buffer reader with the maximum len of bytes to read
    pub fn from_reader(r: R, len: usize) -> Reader<R> {
        Reader { inner: r, len: len }
    }

    /// Reads next tag, `None` if all bytes have been read
    pub fn next_tag(&mut self) -> Result<u32> {
        self.read_varint().map(|i| (i as u32))
    }

    fn read_varint(&mut self) -> Result<u64> {
        let mut r: u64 = 0;
        let mut i = 0;
        for _ in 0..9 {
            self.len -= 1;
            let b = self.inner.read_u8()?;
            r |= ((b & 0x7f) as u64) << i;
            if b < 0x80 {
                return Ok(r);
            }
            i += 7;
        }
        self.len -= 1;
        match self.inner.read_u8()? {
            0 => Ok(r),
            1 => {
                r |= 1 << 63;
                Ok(r)
            }
            _ => Err(ErrorKind::Varint.into()), // we have only one spare bit to fit into
        }
    }

    pub fn read_int32(&mut self) -> Result<i32> {
        self.read_varint().map(|i| i as i32)
    }

    pub fn read_int64(&mut self) -> Result<i64> {
        self.read_varint().map(|i| i as i64)
    }

    pub fn read_uint32(&mut self) -> Result<u32> {
        self.read_varint().map(|i| i as u32)
    }

    pub fn read_uint64(&mut self) -> Result<u64> {
        self.read_varint()
    }

    pub fn read_sint32(&mut self) -> Result<i32> {
        // zigzag
        let n = self.read_varint()? as u32;
        Ok(((n >> 1) as i32) ^ (-((n & 1) as i32)))
    }

    pub fn read_sint64(&mut self) -> Result<i64> {
        // zigzag
        let n = self.read_varint()?;
        Ok(((n >> 1) as i64) ^ (-((n & 1) as i64)))
    }

    pub fn read_fixed64(&mut self) -> Result<u64> {
        self.len -= 8;
        self.inner.read_u64::<LE>().map_err(|e| e.into())
    }

    pub fn read_fixed32(&mut self) -> Result<u32> {
        self.len -= 4;
        self.inner.read_u32::<LE>().map_err(|e| e.into())
    }

    pub fn read_sfixed64(&mut self) -> Result<i64> {
        self.len -= 8;
        self.inner.read_i64::<LE>().map_err(|e| e.into())
    }

    pub fn read_sfixed32(&mut self) -> Result<i32> {
        self.len -= 4;
        self.inner.read_i32::<LE>().map_err(|e| e.into())
    }

    pub fn read_float(&mut self) -> Result<f32> {
        self.len -= 4;
        self.inner.read_f32::<LE>().map_err(|e| e.into())
    }

    pub fn read_double(&mut self) -> Result<f64> {
        self.len -= 8;
        self.inner.read_f64::<LE>().map_err(|e| e.into())
    }

    pub fn read_bool(&mut self) -> Result<bool> {
        self.read_varint().map(|i| i != 0)
    }

    pub fn read_enum<E: From<u64>>(&mut self) -> Result<E> {
        self.read_varint().map(|i| i.into())
    }

    pub fn read_bytes(&mut self) -> Result<Vec<u8>> {
        let len = self.read_varint()? as usize;
        self.len -= len;
        let mut vec = Vec::with_capacity(len);
        unsafe { vec.set_len(len); }
        self.inner.read_exact(&mut vec[..])?;
        Ok(vec)
    }

    pub fn read_string(&mut self) -> Result<String> {
        let vec = self.read_bytes()?;
        String::from_utf8(vec).map_err(|e| e.into())
    }

    pub fn read_packed_repeated_field<M, F: FnMut(&mut Self) -> Result<M>>(&mut self, mut read: F) -> Result<Vec<M>> {
        let len = self.read_varint()? as usize;
        let cur_len = self.len;
        self.len = len;
        let mut v = Vec::new();
        while self.len > 0 {
            v.push(read(self)?);
        }
        self.len = cur_len - len;
        Ok(v)
    }

    pub fn read_message<M: Message>(&mut self) -> Result<M> {
        let len = self.read_varint()? as usize;
        let cur_len = self.len;
        self.len = len;
        let msg = M::from_reader(self)?;
        self.len = cur_len - len;
        Ok(msg)
    }

    pub fn read_unknown(&mut self, tag_value: u32) -> Result<()> {
        match (tag_value & 0x7) as u8 {
            WIRE_TYPE_VARINT => { self.read_varint()?; },
            WIRE_TYPE_FIXED64 => {
                self.len -= 8;
                self.inner.read_exact(&mut [0; 8])?;
            }
            WIRE_TYPE_FIXED32 => {
                self.len -= 4;
                self.inner.read_exact(&mut [0; 4])?;
            }
            WIRE_TYPE_LENGTH_DELIMITED => {
                let len = self.read_varint()? as usize;
                if len == 0 { return Ok(()); }
                self.len -= len;
                let mut buf = Vec::with_capacity(len);
                unsafe { buf.set_len(len); }
                self.inner.read_exact(&mut buf)?;
            },
            WIRE_TYPE_START_GROUP |
                WIRE_TYPE_END_GROUP => { return Err(ErrorKind::Deprecated("group").into()); },
            t => { return Err(ErrorKind::UnknownWireType(t).into()); },
        }
        Ok(())
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn inner(&mut self) -> &mut R {
        &mut self.inner
    }

    pub fn is_eof(&self) -> bool {
        self.len == 0
    }
}

#[test]
fn test_varint() {
    let data: &[u8] = &[0x96, 0x01];
    let mut r = Reader::from_reader(data, data.len());
    assert_eq!(150, r.read_varint().unwrap());
    assert!(r.is_eof());
}
<|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 VERTEX_SRC: &'static [u8] = b"
    #version 120

    attribute ivec2 a_Pos;
    attribute vec3 a_Color;
    varying vec4 v_Color;

    uniform mat4 u_Transform;

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

static FRAGMENT_SRC: &'static [u8] = b"
    #version 120

    varying vec4 v_Color;

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

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

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

#[shader_param]
struct Params<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(VERTEX_SRC, 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)
    {
        // Prepare the uniforms to be used for rendering
        let proj = cgmath::ortho::<f32>(0.0, 1280.0, 720.0, 0.0, 1.0, -1.0);
        let params = Params::<R> {
            transform: proj.into_fixed(),
            _dummy: std::marker::PhantomData
        };

        // Render all rectangles
        let rects_mesh = RenderHelper::<R>::create_rects_mesh(factory, data.rectangles);
        self.render_rects_mesh(output, renderer, &params, rects_mesh);
    }

    fn create_rects_mesh<F: gfx::Factory<R>>(factory: &mut F, rects: Vec<RectangleData>) -> gfx::Mesh<R> {
        let mut vertices = Vec::<Vertex>::new();

        for rect in rects {
            // Add our rectangle's vertices
            vertices.push(Vertex { pos: [ rect.end[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.end[1] ], color: rect.color });

            vertices.push(Vertex { pos: [ rect.end[0], rect.end[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.end[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.end[1] ], color: rect.color });
        }

        // Turn the vertices into a mesh
        factory.create_mesh(&vertices)
    }

    fn render_rects_mesh<O: gfx::Output<R>, C: gfx::CommandBuffer<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>,
        params: &Params<R>, mesh: gfx::Mesh<R>)
    {
        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 RenderData {
    rectangles: Vec<RectangleData>
}

pub struct RectangleData {
    start: [u16;2],
    end: [u16;2],
    color: [f32;3]
}

impl RenderData {
    pub fn new() -> RenderData {
        RenderData {
            rectangles: Vec::<RectangleData>::new()
        }
    }

    pub fn push_rectangle(&mut self, position: [u16;2], size: [u16;2], color: [f32;3]) {
        let data = RectangleData {
            start: [position[0], position[1]],
            end: [position[0] + size[0], position[1] + size[1]],
            color: color
        };

        self.rectangles.push(data);
    }
}
<commit_msg>Fixes #2<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 VERTEX_SRC: &'static [u8] = b"
    #version 120

    attribute ivec2 a_Pos;
    attribute vec3 a_Color;
    varying vec4 v_Color;

    uniform mat4 u_Transform;

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

static FRAGMENT_SRC: &'static [u8] = b"
    #version 120

    varying vec4 v_Color;

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

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

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

#[shader_param]
struct Params<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(VERTEX_SRC, 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)
    {
        // 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 = Params::<R> {
            transform: proj.into_fixed(),
            _dummy: std::marker::PhantomData
        };

        // Render all rectangles
        let rects_mesh = RenderHelper::<R>::create_rects_mesh(factory, data.rectangles);
        self.render_rects_mesh(output, renderer, &params, rects_mesh);
    }

    fn create_rects_mesh<F: gfx::Factory<R>>(factory: &mut F, rects: Vec<RectangleData>) -> gfx::Mesh<R> {
        let mut vertices = Vec::<Vertex>::new();

        for rect in rects {
            // Add our rectangle's vertices
            vertices.push(Vertex { pos: [ rect.end[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.end[1] ], color: rect.color });

            vertices.push(Vertex { pos: [ rect.end[0], rect.end[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.end[0], rect.start[1] ], color: rect.color });
            vertices.push(Vertex { pos: [ rect.start[0], rect.end[1] ], color: rect.color });
        }

        // Turn the vertices into a mesh
        factory.create_mesh(&vertices)
    }

    fn render_rects_mesh<O: gfx::Output<R>, C: gfx::CommandBuffer<R>>(
        &self,
        output: &mut O, renderer: &mut gfx::Renderer<R, C>,
        params: &Params<R>, mesh: gfx::Mesh<R>)
    {
        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 RenderData {
    rectangles: Vec<RectangleData>
}

pub struct RectangleData {
    start: [u16;2],
    end: [u16;2],
    color: [f32;3]
}

impl RenderData {
    pub fn new() -> RenderData {
        RenderData {
            rectangles: Vec::<RectangleData>::new()
        }
    }

    pub fn push_rectangle(&mut self, position: [u16;2], size: [u16;2], color: [f32;3]) {
        let data = RectangleData {
            start: [position[0], position[1]],
            end: [position[0] + size[0], position[1] + size[1]],
            color: color
        };

        self.rectangles.push(data);
    }
}
<|endoftext|>