<commit_before>use token::Token;
use tokenizer::{Tokenizer, LexerError};

pub type Program = Vec<Statement>;

#[derive(PartialEq, Debug)]
pub enum Statement {
    NamedFunction {
        name: String,
        definition: Function,
    },
    AnonymousFunction(Function),
    Assignment {
        name: String,
        value: Expr,
    },
    Expression(Expr),
}

pub type Expr = Vec<ExprItem>;

#[derive(PartialEq, Debug)]
pub enum ExprItem {
    AnonymousFunction(Function),
    SingleTerm(Term),
    Group(Expr),
}

#[derive(PartialEq, Debug)]
pub struct Function {
    params: Vec<String>,
    body: Expr,
}

#[derive(PartialEq, Debug)]
pub enum Term {
    Symbol(String),
    Number(f64),
    StringLiteral(String),
}

pub struct Parser {
    lexer: Tokenizer,
}

// Private type just for internal functions since the public interface
// cannot return option
type ParseResult<T> = Result<Option<T>, ParseError>;

#[derive(PartialEq, Debug)]
pub enum ParseError {
    ExpectedToken(Token),
    SyntaxError(LexerError),
}

impl Parser {
    pub fn new(lexer: Tokenizer) -> Parser {
        Parser {
            lexer: lexer,
        }
    }

    pub fn parse(&mut self) -> Result<Program, ParseError> {
        let mut statements: Program = Vec::new();

        loop {
            let statement = try!(self.statement());
            if statement.is_none() {
                break;
            }

            let statement = statement.unwrap();
            statements.push(statement);
        }

        Ok(statements)
    }

    fn statement(&mut self) -> ParseResult<Statement> {
        let line = try!(self.line());
        if line.is_none() {
            return Ok(None);
        }

        let line = line.unwrap();
        self.dispatch_statement(line)
    }

    fn line(&mut self) -> ParseResult<Vec<Token>> {
        let mut line_tokens: Vec<Token> = Vec::new();

        let mut reached_eof = true;
        for next_token in &mut self.lexer {
            let next_token = try!(
                next_token.map_err(|e| ParseError::SyntaxError(e))
            );

            if next_token == Token::EOL {
                reached_eof = false;
                break;
            }

            line_tokens.push(next_token);
        }

        if reached_eof && line_tokens.is_empty() {
            return Ok(None);
        }

        Ok(Some(line_tokens))
    }

    fn dispatch_statement(&mut self, statement_tokens: Vec<Token>) -> ParseResult<Statement> {
        Ok(None)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use scanner::Scanner;
    use tokenizer::Tokenizer;

    #[test]
    fn complete_program() {
        let mut parser = parser_for(r#"
        defineUnit "km/h"

        my_var = 30 km/h
        f x yy = x km/h * 2 + (my_var / -3.5) * (8 ** yy) - 1.3e-3
        print (f 30)

        operator INFIX 6 "$$" (\x y = x * y + x)
        "#);

        let syntax_tree: Program = vec![
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("defineUnit".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::StringLiteral("km/h".to_owned())
                ),
            ]),
            Statement::Assignment {
                name: "my_var".to_owned(),
                value: vec![
                    ExprItem::SingleTerm(Term::Number(30f64)),
                    ExprItem::SingleTerm(Term::Symbol("km/h".to_owned())),
                ],
            },
            Statement::NamedFunction {
                name: "f".to_owned(),
                definition: Function {
                    params: vec![
                        "x".to_owned(),
                        "yy".to_owned()
                    ],
                    body: vec![
                        ExprItem::SingleTerm(
                            Term::Symbol("x".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("km/h".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(2f64)
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("+".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Symbol("my_var".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("/".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Number(-3.5f64)
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Number(8f64)
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("**".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("yy".to_owned())
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("-".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(1.3e-3f64)
                        ),
                    ],
                },
            },
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("print".to_owned())
                ),
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(
                        Term::Symbol("f".to_owned())
                    ),
                    ExprItem::SingleTerm(
                        Term::Number(30f64)
                    ),
                ]),
            ]),
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("operator".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::Symbol("INFIX".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::Number(6f64)
                ),
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(
                        Term::StringLiteral("$$".to_owned())
                    ),
                    ExprItem::Group(vec![
                        ExprItem::AnonymousFunction(
                            Function {
                                params: vec![
                                    "x".to_owned(),
                                    "y".to_owned()
                                ],
                                body: vec![
                                    ExprItem::SingleTerm(
                                        Term::Symbol("x".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("*".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("y".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("+".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("x".to_owned())
                                    ),
                                ],
                            },
                        ),
                    ]),
                ]),
            ]),
        ];

        let parsed = parser.parse().unwrap();
        assert_eq!(parsed, syntax_tree);
    }

    fn parser_for(string: &str) -> Parser {
        Parser::new(Tokenizer::new(Scanner::from_str(string)))
    }
}

<commit_msg>Added tests for an anonymous function statement and an anonymous function being assigned to a variable<commit_after>use token::Token;
use tokenizer::{Tokenizer, LexerError};

pub type Program = Vec<Statement>;

#[derive(PartialEq, Debug)]
pub enum Statement {
    NamedFunction {
        name: String,
        definition: Function,
    },
    AnonymousFunction(Function),
    Assignment {
        name: String,
        value: Expr,
    },
    Expression(Expr),
}

pub type Expr = Vec<ExprItem>;

#[derive(PartialEq, Debug)]
pub enum ExprItem {
    AnonymousFunction(Function),
    SingleTerm(Term),
    Group(Expr),
}

#[derive(PartialEq, Debug)]
pub struct Function {
    params: Vec<String>,
    body: Expr,
}

#[derive(PartialEq, Debug)]
pub enum Term {
    Symbol(String),
    Number(f64),
    StringLiteral(String),
}

pub struct Parser {
    lexer: Tokenizer,
}

// Private type just for internal functions since the public interface
// cannot return option
type ParseResult<T> = Result<Option<T>, ParseError>;

#[derive(PartialEq, Debug)]
pub enum ParseError {
    ExpectedToken(Token),
    SyntaxError(LexerError),
}

impl Parser {
    pub fn new(lexer: Tokenizer) -> Parser {
        Parser {
            lexer: lexer,
        }
    }

    pub fn parse(&mut self) -> Result<Program, ParseError> {
        let mut statements: Program = Vec::new();

        loop {
            let statement = try!(self.statement());
            if statement.is_none() {
                break;
            }

            let statement = statement.unwrap();
            statements.push(statement);
        }

        Ok(statements)
    }

    fn statement(&mut self) -> ParseResult<Statement> {
        let line = try!(self.line());
        if line.is_none() {
            return Ok(None);
        }

        let line = line.unwrap();
        self.dispatch_statement(line)
    }

    fn line(&mut self) -> ParseResult<Vec<Token>> {
        let mut line_tokens: Vec<Token> = Vec::new();

        let mut reached_eof = true;
        for next_token in &mut self.lexer {
            let next_token = try!(
                next_token.map_err(|e| ParseError::SyntaxError(e))
            );

            if next_token == Token::EOL {
                reached_eof = false;
                break;
            }

            line_tokens.push(next_token);
        }

        if reached_eof && line_tokens.is_empty() {
            return Ok(None);
        }

        Ok(Some(line_tokens))
    }

    fn dispatch_statement(&mut self, statement_tokens: Vec<Token>) -> ParseResult<Statement> {
        Ok(None)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use scanner::Scanner;
    use tokenizer::Tokenizer;

    #[test]
    fn complete_program() {
        let mut parser = parser_for(r#"
        defineUnit "km/h"

        my_var = 30 km/h
        f x yy = x km/h * 2 + (my_var / -3.5) * (8 ** yy) - 1.3e-3
        print (f 30)

        \q r = q / (r - 3)
        doubleMe = \e = e * 2
        operator INFIX 6 "$$" (\x y = x * y + x)
        "#);

        let syntax_tree: Program = vec![
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("defineUnit".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::StringLiteral("km/h".to_owned())
                ),
            ]),
            Statement::Assignment {
                name: "my_var".to_owned(),
                value: vec![
                    ExprItem::SingleTerm(Term::Number(30f64)),
                    ExprItem::SingleTerm(Term::Symbol("km/h".to_owned())),
                ],
            },
            Statement::NamedFunction {
                name: "f".to_owned(),
                definition: Function {
                    params: vec![
                        "x".to_owned(),
                        "yy".to_owned()
                    ],
                    body: vec![
                        ExprItem::SingleTerm(
                            Term::Symbol("x".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("km/h".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(2f64)
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("+".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Symbol("my_var".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("/".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Number(-3.5f64)
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("*".to_owned())
                        ),
                        ExprItem::Group(vec![
                            ExprItem::SingleTerm(
                                Term::Number(8f64)
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("**".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("yy".to_owned())
                            ),
                        ]),
                        ExprItem::SingleTerm(
                            Term::Symbol("-".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(1.3e-3f64)
                        ),
                    ],
                },
            },
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("print".to_owned())
                ),
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(
                        Term::Symbol("f".to_owned())
                    ),
                    ExprItem::SingleTerm(
                        Term::Number(30f64)
                    ),
                ]),
            ]),
            Statement::AnonymousFunction(Function {
                params: vec!["q".to_owned(), "r".to_owned()],
                body: vec![
                    ExprItem::SingleTerm(
                        Term::Symbol("q".to_owned())
                    ),
                    ExprItem::SingleTerm(
                        Term::Symbol("/".to_owned())
                    ),
                    ExprItem::Group(vec![
                        ExprItem::SingleTerm(
                            Term::Symbol("r".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Symbol("-".to_owned())
                        ),
                        ExprItem::SingleTerm(
                            Term::Number(3f64)
                        ),
                    ]),
                ],
            }),
            Statement::Assignment {
                name: "doubleMe".to_owned(),
                value: vec![
                    ExprItem::AnonymousFunction(Function {
                        params: vec!["e".to_owned()],
                        body: vec![
                            ExprItem::SingleTerm(
                                Term::Symbol("e".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Symbol("*".to_owned())
                            ),
                            ExprItem::SingleTerm(
                                Term::Number(2f64)
                            ),
                        ],
                    }),
                ],
            },
            Statement::Expression(vec![
                ExprItem::SingleTerm(
                    Term::Symbol("operator".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::Symbol("INFIX".to_owned())
                ),
                ExprItem::SingleTerm(
                    Term::Number(6f64)
                ),
                ExprItem::Group(vec![
                    ExprItem::SingleTerm(
                        Term::StringLiteral("$$".to_owned())
                    ),
                    ExprItem::Group(vec![
                        ExprItem::AnonymousFunction(
                            Function {
                                params: vec![
                                    "x".to_owned(),
                                    "y".to_owned()
                                ],
                                body: vec![
                                    ExprItem::SingleTerm(
                                        Term::Symbol("x".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("*".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("y".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("+".to_owned())
                                    ),
                                    ExprItem::SingleTerm(
                                        Term::Symbol("x".to_owned())
                                    ),
                                ],
                            },
                        ),
                    ]),
                ]),
            ]),
        ];

        let parsed = parser.parse().unwrap();
        assert_eq!(parsed, syntax_tree);
    }

    fn parser_for(string: &str) -> Parser {
        Parser::new(Tokenizer::new(Scanner::from_str(string)))
    }
}

<|endoftext|>


<commit_before>//! A private parser implementation of IPv4 and IPv6 network addresses.
//!
//! The existing `std::net::parser module` cannot be extended because it
//! is private. It is copied and extended here with methods for parsing
//! IP network addresses.

use std::error::Error;
use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use ipnet::{IpNet, Ipv4Net, Ipv6Net};

pub struct Parser<'a> {
    // parsing as ASCII, so can use byte array
    s: &'a [u8],
    pos: usize,
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            s: s.as_bytes(),
            pos: 0,
        }
    }

    fn is_eof(&self) -> bool {
        self.pos == self.s.len()
    }

    // Commit only if parser returns Some
    fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        let pos = self.pos;
        let r = cb(self);
        if r.is_none() {
            self.pos = pos;
        }
        r
    }

    // Commit only if parser read till EOF
    fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        self.read_atomically(move |p| {
            match cb(p) {
                Some(x) => if p.is_eof() {Some(x)} else {None},
                None => None,
            }
        })
    }

    // Return result of first successful parser
    fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
               -> Option<T> {
        for pf in parsers {
            if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
                return Some(r);
            }
        }
        None
    }

    // Apply 3 parsers sequentially
    fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
                                       pa: PA,
                                       pb: PB,
                                       pc: PC)
                                       -> Option<(A, B, C)> where
        PA: FnOnce(&mut Parser) -> Option<A>,
        PB: FnOnce(&mut Parser) -> Option<B>,
        PC: FnOnce(&mut Parser) -> Option<C>,
    {
        self.read_atomically(move |p| {
            let a = pa(p);
            let b = if a.is_some() { pb(p) } else { None };
            let c = if b.is_some() { pc(p) } else { None };
            match (a, b, c) {
                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
                _ => None
            }
        })
    }

    // Read next char
    fn read_char(&mut self) -> Option<char> {
        if self.is_eof() {
            None
        } else {
            let r = self.s[self.pos] as char;
            self.pos += 1;
            Some(r)
        }
    }

    // Return char and advance iff next char is equal to requested
    fn read_given_char(&mut self, c: char) -> Option<char> {
        self.read_atomically(|p| {
            match p.read_char() {
                Some(next) if next == c => Some(next),
                _ => None,
            }
        })
    }

    // Read digit
    fn read_digit(&mut self, radix: u8) -> Option<u8> {
        fn parse_digit(c: char, radix: u8) -> Option<u8> {
            let c = c as u8;
            // assuming radix is either 10 or 16
            if c >= b'0' && c <= b'9' {
                Some(c - b'0')
            } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
                Some(c - b'a' + 10)
            } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
                Some(c - b'A' + 10)
            } else {
                None
            }
        }

        self.read_atomically(|p| {
            p.read_char().and_then(|c| parse_digit(c, radix))
        })
    }

    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        let mut r = 0;
        let mut digit_count = 0;
        loop {
            match self.read_digit(radix) {
                Some(d) => {
                    r = r * (radix as u32) + (d as u32);
                    digit_count += 1;
                    if digit_count > max_digits || r >= upto {
                        return None
                    }
                }
                None => {
                    if digit_count == 0 {
                        return None
                    } else {
                        return Some(r)
                    }
                }
            };
        }
    }

    // Read number, failing if max_digits of number value exceeded
    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
    }

    fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
        let mut bs = [0; 4];
        let mut i = 0;
        while i < 4 {
            if i != 0 && self.read_given_char('.').is_none() {
                return None;
            }

            let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
            match octet {
                Some(d) => bs[i] = d,
                None => return None,
            };
            i += 1;
        }
        Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
    }

    // Read IPv4 address
    fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
        self.read_atomically(|p| p.read_ipv4_addr_impl())
    }

    fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
            assert!(head.len() + tail.len() <= 8);
            let mut gs = [0; 8];
            gs[..head.len()].copy_from_slice(head);
            gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
            Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
        }

        fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
                       -> (usize, bool) {
            let mut i = 0;
            while i < limit {
                if i < limit - 1 {
                    let ipv4 = p.read_atomically(|p| {
                        if i == 0 || p.read_given_char(':').is_some() {
                            p.read_ipv4_addr()
                        } else {
                            None
                        }
                    });
                    if let Some(v4_addr) = ipv4 {
                        let octets = v4_addr.octets();
                        groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
                        groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
                        return (i + 2, true);
                    }
                }

                let group = p.read_atomically(|p| {
                    if i == 0 || p.read_given_char(':').is_some() {
                        p.read_number(16, 4, 0x10000).map(|n| n as u16)
                    } else {
                        None
                    }
                });
                match group {
                    Some(g) => groups[i] = g,
                    None => return (i, false)
                }
                i += 1;
            }
            (i, false)
        }

        let mut head = [0; 8];
        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);

        if head_size == 8 {
            return Some(Ipv6Addr::new(
                head[0], head[1], head[2], head[3],
                head[4], head[5], head[6], head[7]))
        }

        // IPv4 part is not allowed before `::`
        if head_ipv4 {
            return None
        }

        // read `::` if previous code parsed less than 8 groups
        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
            return None;
        }

        let mut tail = [0; 8];
        let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
        Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
    }

    fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
        self.read_atomically(|p| p.read_ipv6_addr_impl())
    }

    // read_ip_addr is not used.
    //fn read_ip_addr(&mut self) -> Option<IpAddr> {
    //    let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr().map(IpAddr::V4);
    //    let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr().map(IpAddr::V6);
    //    self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
    //}

    /* Additions for IpNet below. */

    // Read IPv4 network
    fn read_ipv4_net(&mut self) -> Option<Ipv4Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 2, 33).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv4Addr, char, u8) = t;
            Ipv4Net::new(ip, prefix_len)
        })
    }

    // Read Ipv6 network
    fn read_ipv6_net(&mut self) -> Option<Ipv6Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 3, 129).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv6Addr, char, u8) = t;
            Ipv6Net::new(ip, prefix_len)
        })
    }

    fn read_ip_net(&mut self) -> Option<IpNet> {
        let ipv4_net = |p: &mut Parser| p.read_ipv4_net().map(IpNet::V4);
        let ipv6_net = |p: &mut Parser| p.read_ipv6_net().map(IpNet::V6);
        self.read_or(&mut [Box::new(ipv4_net), Box::new(ipv6_net)])
    }

    /* Additions for IpNet above. */
}

/* Additions for IpNet below. */

impl FromStr for IpNet {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<IpNet, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ip_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv4Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv4_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv6Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv6_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

/* Additions for IpNet above. */

/// An error which can be returned when parsing an IP network address.
///
/// This error is used as the error type for the [`FromStr`] implementation for
/// [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`].
///
/// TODO: This is copied from the std::net::parser module. I'm not sure
/// why I couldn't re-use it that implementation given it is public.
///
/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
/// [`IpNet`]: enum.IpNet.html
/// [`Ipv4Net`]: struct.Ipv4Net.html
/// [`Ipv6Net`]: struct.Ipv6Net.html
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddrParseError(());

impl fmt::Display for AddrParseError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for AddrParseError {
    fn description(&self) -> &str {
        "invalid IP address syntax"
    }
}<commit_msg>Removing TODO item and commented code<commit_after>//! A private parser implementation of IPv4 and IPv6 network addresses.
//!
//! The existing `std::net::parser` module cannot be extended because it
//! is private. It is copied and extended here with methods for parsing
//! IP network addresses.

use std::error::Error;
use std::fmt;
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;

use ipnet::{IpNet, Ipv4Net, Ipv6Net};

pub struct Parser<'a> {
    // parsing as ASCII, so can use byte array
    s: &'a [u8],
    pos: usize,
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            s: s.as_bytes(),
            pos: 0,
        }
    }

    fn is_eof(&self) -> bool {
        self.pos == self.s.len()
    }

    // Commit only if parser returns Some
    fn read_atomically<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        let pos = self.pos;
        let r = cb(self);
        if r.is_none() {
            self.pos = pos;
        }
        r
    }

    // Commit only if parser read till EOF
    fn read_till_eof<T, F>(&mut self, cb: F) -> Option<T> where
        F: FnOnce(&mut Parser) -> Option<T>,
    {
        self.read_atomically(move |p| {
            match cb(p) {
                Some(x) => if p.is_eof() {Some(x)} else {None},
                None => None,
            }
        })
    }

    // Return result of first successful parser
    fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
               -> Option<T> {
        for pf in parsers {
            if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
                return Some(r);
            }
        }
        None
    }

    // Apply 3 parsers sequentially
    fn read_seq_3<A, B, C, PA, PB, PC>(&mut self,
                                       pa: PA,
                                       pb: PB,
                                       pc: PC)
                                       -> Option<(A, B, C)> where
        PA: FnOnce(&mut Parser) -> Option<A>,
        PB: FnOnce(&mut Parser) -> Option<B>,
        PC: FnOnce(&mut Parser) -> Option<C>,
    {
        self.read_atomically(move |p| {
            let a = pa(p);
            let b = if a.is_some() { pb(p) } else { None };
            let c = if b.is_some() { pc(p) } else { None };
            match (a, b, c) {
                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
                _ => None
            }
        })
    }

    // Read next char
    fn read_char(&mut self) -> Option<char> {
        if self.is_eof() {
            None
        } else {
            let r = self.s[self.pos] as char;
            self.pos += 1;
            Some(r)
        }
    }

    // Return char and advance iff next char is equal to requested
    fn read_given_char(&mut self, c: char) -> Option<char> {
        self.read_atomically(|p| {
            match p.read_char() {
                Some(next) if next == c => Some(next),
                _ => None,
            }
        })
    }

    // Read digit
    fn read_digit(&mut self, radix: u8) -> Option<u8> {
        fn parse_digit(c: char, radix: u8) -> Option<u8> {
            let c = c as u8;
            // assuming radix is either 10 or 16
            if c >= b'0' && c <= b'9' {
                Some(c - b'0')
            } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
                Some(c - b'a' + 10)
            } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
                Some(c - b'A' + 10)
            } else {
                None
            }
        }

        self.read_atomically(|p| {
            p.read_char().and_then(|c| parse_digit(c, radix))
        })
    }

    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        let mut r = 0;
        let mut digit_count = 0;
        loop {
            match self.read_digit(radix) {
                Some(d) => {
                    r = r * (radix as u32) + (d as u32);
                    digit_count += 1;
                    if digit_count > max_digits || r >= upto {
                        return None
                    }
                }
                None => {
                    if digit_count == 0 {
                        return None
                    } else {
                        return Some(r)
                    }
                }
            };
        }
    }

    // Read number, failing if max_digits of number value exceeded
    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
        self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
    }

    fn read_ipv4_addr_impl(&mut self) -> Option<Ipv4Addr> {
        let mut bs = [0; 4];
        let mut i = 0;
        while i < 4 {
            if i != 0 && self.read_given_char('.').is_none() {
                return None;
            }

            let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
            match octet {
                Some(d) => bs[i] = d,
                None => return None,
            };
            i += 1;
        }
        Some(Ipv4Addr::new(bs[0], bs[1], bs[2], bs[3]))
    }

    // Read IPv4 address
    fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
        self.read_atomically(|p| p.read_ipv4_addr_impl())
    }

    fn read_ipv6_addr_impl(&mut self) -> Option<Ipv6Addr> {
        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
            assert!(head.len() + tail.len() <= 8);
            let mut gs = [0; 8];
            gs[..head.len()].copy_from_slice(head);
            gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
            Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
        }

        fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: usize)
                       -> (usize, bool) {
            let mut i = 0;
            while i < limit {
                if i < limit - 1 {
                    let ipv4 = p.read_atomically(|p| {
                        if i == 0 || p.read_given_char(':').is_some() {
                            p.read_ipv4_addr()
                        } else {
                            None
                        }
                    });
                    if let Some(v4_addr) = ipv4 {
                        let octets = v4_addr.octets();
                        groups[i + 0] = ((octets[0] as u16) << 8) | (octets[1] as u16);
                        groups[i + 1] = ((octets[2] as u16) << 8) | (octets[3] as u16);
                        return (i + 2, true);
                    }
                }

                let group = p.read_atomically(|p| {
                    if i == 0 || p.read_given_char(':').is_some() {
                        p.read_number(16, 4, 0x10000).map(|n| n as u16)
                    } else {
                        None
                    }
                });
                match group {
                    Some(g) => groups[i] = g,
                    None => return (i, false)
                }
                i += 1;
            }
            (i, false)
        }

        let mut head = [0; 8];
        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);

        if head_size == 8 {
            return Some(Ipv6Addr::new(
                head[0], head[1], head[2], head[3],
                head[4], head[5], head[6], head[7]))
        }

        // IPv4 part is not allowed before `::`
        if head_ipv4 {
            return None
        }

        // read `::` if previous code parsed less than 8 groups
        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
            return None;
        }

        let mut tail = [0; 8];
        let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
        Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
    }

    fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
        self.read_atomically(|p| p.read_ipv6_addr_impl())
    }

    // read_ip_addr is not used.
    //fn read_ip_addr(&mut self) -> Option<IpAddr> {
    //    let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr().map(IpAddr::V4);
    //    let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr().map(IpAddr::V6);
    //    self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
    //}

    /* Additions for IpNet below. */

    // Read IPv4 network
    fn read_ipv4_net(&mut self) -> Option<Ipv4Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 2, 33).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv4Addr, char, u8) = t;
            Ipv4Net::new(ip, prefix_len)
        })
    }

    // Read Ipv6 network
    fn read_ipv6_net(&mut self) -> Option<Ipv6Net> {
        let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
        let slash = |p: &mut Parser| p.read_given_char('/');
        let prefix_len = |p: &mut Parser| {
            p.read_number(10, 3, 129).map(|n| n as u8)
        };

        self.read_seq_3(ip_addr, slash, prefix_len).map(|t| {
            let (ip, _, prefix_len): (Ipv6Addr, char, u8) = t;
            Ipv6Net::new(ip, prefix_len)
        })
    }

    fn read_ip_net(&mut self) -> Option<IpNet> {
        let ipv4_net = |p: &mut Parser| p.read_ipv4_net().map(IpNet::V4);
        let ipv6_net = |p: &mut Parser| p.read_ipv6_net().map(IpNet::V6);
        self.read_or(&mut [Box::new(ipv4_net), Box::new(ipv6_net)])
    }

    /* Additions for IpNet above. */
}

/* Additions for IpNet below. */

impl FromStr for IpNet {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<IpNet, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ip_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv4Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv4Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv4_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

impl FromStr for Ipv6Net {
    type Err = AddrParseError;
    fn from_str(s: &str) -> Result<Ipv6Net, AddrParseError> {
        match Parser::new(s).read_till_eof(|p| p.read_ipv6_net()) {
            Some(s) => Ok(s),
            None => Err(AddrParseError(()))
        }
    }
}

/* Additions for IpNet above. */

/// An error which can be returned when parsing an IP network address.
///
/// This error is used as the error type for the [`FromStr`] implementation for
/// [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`].
///
/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
/// [`IpNet`]: enum.IpNet.html
/// [`Ipv4Net`]: struct.Ipv4Net.html
/// [`Ipv6Net`]: struct.Ipv6Net.html
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddrParseError(());

impl fmt::Display for AddrParseError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for AddrParseError {
    fn description(&self) -> &str {
        "invalid IP address syntax"
    }
}<|endoftext|>


<commit_before>use grammar::*;

use peruse::slice_parsers::*;

pub fn program() -> Box<SliceParser<I=[Token], O=Block>> {

  fn expression() -> Box<SliceParser<I=[Token], O=Expr>> {
    let simple_term = matcher(|token| match token {
      Token::Ident(name) => Some(Expr::Variable(name)),
      Token::Number(i)   => Some(Expr::Num(i)),
      _ => None
    });

    let paren_expr = || lit(Token::OpenParen).then_r(recursive(|| expression())).then_l(lit(Token::CloseParen));

    let term = paren_expr().or(simple_term);

    let multop = matcher(|token| match token {
      Token::MultSign     => Some(MultOp::Multiply),
      Token::DivideSign   => Some(MultOp::Divide),
      Token::ModuloSign   => Some(MultOp::Modulo),
      _ => None
    });

    let addop = matcher(|token| match token {
      Token::PlusSign     => Some(AddOp::Add),
      Token::MinusSign    => Some(AddOp::Subtract),
      _ => None
    });

    let mult =  {
      let p = term.clone().then(multop.then(term).repeat()).map(|(first, seq)| {
        let mut ops = Vec::new();
        ops.push(MultTerm(MultOp::Multiply, first));
        for &(ref op, ref value) in seq.iter() {
          ops.push(MultTerm(op.clone(), value.clone())); //maybe box the value instead
        }
        Expr::MultDiv(ops)
      });
      boxed(Box::new(p))
    };

    let plus = {
      let p = mult.clone().then(addop.then(mult).repeat()).map(|(first, seq)| {
        let mut ops = Vec::new();
        ops.push(AddTerm(AddOp::Add, first));
        for &(ref op, ref value) in seq.iter() {
          ops.push(AddTerm(op.clone(), value.clone()));
        }
        Expr::AddSub(ops)
      });
      boxed(Box::new(p))
    };

    Box::new(plus)
  }

  let assignment = {
    let target = matcher(|token| match token {
      Token::Ident(name) => Some(name),
      _ => None
    });
    boxed(Box::new(target
      .then_l(lit(Token::Equals))
      .then(recursive(|| expression()))
      .map(|(target, expr)| Statement::Assign(target, expr))))
  };

  let comparator = || matcher(|token| match token {
    Token::Cmp(cmp) => Some(cmp),
    _ => None
  });

  fn code_block() -> Box<SliceParser<I=[Token], O=Block>> {
    Box::new(lit(Token::OpenBrace)
    .then_r(recursive(|| program()))
    .then_l(lit(Token::CloseBrace)))
  }

  fn if_stmt() -> Box<SliceParser<I=[Token], O=Statement>> {

    let comparator = || matcher(|token| match token {
      Token::Cmp(cmp) => Some(cmp),
      _ => None
    });

    let else_block = lit(Token::ElseKeyword)
      .then_r(
        recursive(|| if_stmt()).map(|i| Block(vec![i]))
        .or(boxed(code_block()))
      );

    let p = lit(Token::IfKeyword)
      .then_r(recursive(|| expression()))
      .then(comparator())
      .then(recursive(|| expression()))
      .then_l(lit(Token::OpenBrace))
      .then(recursive(|| program()))
      .then_l(lit(Token::CloseBrace))
      .then(opt(else_block))
      .map(|((((l, cmp), r), block), else_opt)| Statement::If(l, cmp, r, block, else_opt));

    Box::new(p)
  };

  let while_stmt = {
    let p = lit(Token::WhileKeyword)
      .then_r(recursive(|| expression()))
      .then(comparator())
      .then(recursive(|| expression()))
      .then_l(lit(Token::OpenBrace))
      .then(recursive(|| program()))
      .then_l(lit(Token::CloseBrace))
      .map(|(((l, cmp), r), block)| Statement::While(l, cmp, r, block));
    boxed(Box::new(p))
  };

  let output = boxed(Box::new(lit(Token::OutputCmd).then_r(recursive(|| expression())).map(|e| Statement::Output(e))));

  let statements = one_of(vec![assignment, output, boxed(if_stmt()), while_stmt]).then_l(lit(Token::NewLine)).repeat();

  Box::new(statements.map(|v| Block(v)))
}

<commit_msg>removing unecessary closures, static functions support Fn!<commit_after>use grammar::*;

use peruse::slice_parsers::*;

pub fn program() -> Box<SliceParser<I=[Token], O=Block>> {

  fn expression() -> Box<SliceParser<I=[Token], O=Expr>> {
    let simple_term = matcher(|token| match token {
      Token::Ident(name) => Some(Expr::Variable(name)),
      Token::Number(i)   => Some(Expr::Num(i)),
      _ => None
    });

    let paren_expr = || lit(Token::OpenParen).then_r(recursive(|| expression())).then_l(lit(Token::CloseParen));

    let term = paren_expr().or(simple_term);

    let multop = matcher(|token| match token {
      Token::MultSign     => Some(MultOp::Multiply),
      Token::DivideSign   => Some(MultOp::Divide),
      Token::ModuloSign   => Some(MultOp::Modulo),
      _ => None
    });

    let addop = matcher(|token| match token {
      Token::PlusSign     => Some(AddOp::Add),
      Token::MinusSign    => Some(AddOp::Subtract),
      _ => None
    });

    let mult =  {
      let p = term.clone().then(multop.then(term).repeat()).map(|(first, seq)| {
        let mut ops = Vec::new();
        ops.push(MultTerm(MultOp::Multiply, first));
        for &(ref op, ref value) in seq.iter() {
          ops.push(MultTerm(op.clone(), value.clone())); //maybe box the value instead
        }
        Expr::MultDiv(ops)
      });
      boxed(Box::new(p))
    };

    let plus = {
      let p = mult.clone().then(addop.then(mult).repeat()).map(|(first, seq)| {
        let mut ops = Vec::new();
        ops.push(AddTerm(AddOp::Add, first));
        for &(ref op, ref value) in seq.iter() {
          ops.push(AddTerm(op.clone(), value.clone()));
        }
        Expr::AddSub(ops)
      });
      boxed(Box::new(p))
    };

    Box::new(plus)
  }

  let assignment = {
    let target = matcher(|token| match token {
      Token::Ident(name) => Some(name),
      _ => None
    });
    boxed(Box::new(target
      .then_l(lit(Token::Equals))
      .then(recursive(|| expression()))
      .map(|(target, expr)| Statement::Assign(target, expr))))
  };

  let comparator = || matcher(|token| match token {
    Token::Cmp(cmp) => Some(cmp),
    _ => None
  });

  fn code_block() -> Box<SliceParser<I=[Token], O=Block>> {
    Box::new(lit(Token::OpenBrace)
    .then_r(recursive(|| program()))
    .then_l(lit(Token::CloseBrace)))
  }

  fn if_stmt() -> Box<SliceParser<I=[Token], O=Statement>> {

    let comparator = || matcher(|token| match token {
      Token::Cmp(cmp) => Some(cmp),
      _ => None
    });

    let else_block = lit(Token::ElseKeyword)
      .then_r(
        recursive(if_stmt).map(|i| Block(vec![i]))
        .or(boxed(code_block()))
      );

    let p = lit(Token::IfKeyword)
      .then_r(recursive(|| expression()))
      .then(comparator())
      .then(recursive(expression))
      .then_l(lit(Token::OpenBrace))
      .then(recursive(program))
      .then_l(lit(Token::CloseBrace))
      .then(opt(else_block))
      .map(|((((l, cmp), r), block), else_opt)| Statement::If(l, cmp, r, block, else_opt));

    Box::new(p)
  };

  let while_stmt = {
    let p = lit(Token::WhileKeyword)
      .then_r(recursive(expression))
      .then(comparator())
      .then(recursive(expression))
      .then_l(lit(Token::OpenBrace))
      .then(recursive(program))
      .then_l(lit(Token::CloseBrace))
      .map(|(((l, cmp), r), block)| Statement::While(l, cmp, r, block));
    boxed(Box::new(p))
  };

  let output = boxed(Box::new(lit(Token::OutputCmd).then_r(recursive(|| expression())).map(|e| Statement::Output(e))));

  let statements = one_of(vec![assignment, output, boxed(if_stmt()), while_stmt]).then_l(lit(Token::NewLine)).repeat();

  Box::new(statements.map(|v| Block(v)))
}

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_id = "github.com/mozilla/servo"]
#![comment = "The Servo Parallel Browser Project"]
#![license = "MPL"]

#![feature(globs, macro_rules, phase, thread_local)]

#[phase(plugin, link)]
extern crate log;

extern crate debug;

extern crate compositing;
extern crate rustuv;
extern crate servo_net = "net";
extern crate servo_msg = "msg";
#[phase(plugin, link)]
extern crate servo_util = "util";
extern crate script;
extern crate layout;
extern crate green;
extern crate gfx;
extern crate libc;
extern crate native;
extern crate rustrt;
extern crate url = "url_";

#[cfg(not(test))]
use compositing::{CompositorChan, CompositorTask, Constellation};
#[cfg(not(test))]
use servo_msg::constellation_msg::{ConstellationChan, InitLoadUrlMsg};
#[cfg(not(test))]
use script::dom::bindings::codegen::RegisterBindings;

#[cfg(not(test))]
use servo_net::image_cache_task::ImageCacheTask;
#[cfg(not(test))]
use servo_net::resource_task::new_resource_task;
#[cfg(not(test))]
use gfx::font_cache_task::FontCacheTask;
#[cfg(not(test))]
use servo_util::time::TimeProfiler;
#[cfg(not(test))]
use servo_util::memory::MemoryProfiler;

#[cfg(not(test))]
use servo_util::opts;

#[cfg(not(test))]
use url::{Url, UrlParser};

#[cfg(not(test), not(target_os="android"))]
use std::os;
#[cfg(not(test), target_os="android")]
use std::str;
#[cfg(not(test))]
use rustrt::task::TaskOpts;

#[cfg(not(test), target_os="linux")]
#[cfg(not(test), target_os="macos")]
#[start]
#[allow(dead_code)]
fn start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, proc() {
        opts::from_cmdline_args(os::args().as_slice()).map(run);
    })
}

#[cfg(not(test), target_os="android")]
#[no_mangle]
#[allow(dead_code)]
pub extern "C" fn android_start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, proc() {
        let mut args: Vec<String> = vec!();
        for i in range(0u, argc as uint) {
            unsafe {
                args.push(str::raw::from_c_str(*argv.offset(i as int) as *i8));
            }
        }

        let mut opts = opts::from_cmdline_args(args.as_slice());
        match opts {
            Some(mut o) => {
                // Always use CPU rendering on android.
                o.cpu_painting = true;
                run(o);
            },
            None => {}
        }
    })
}

#[cfg(not(test))]
pub fn run(opts: opts::Opts) {
    ::servo_util::opts::set_experimental_enabled(opts.enable_experimental);
    RegisterBindings::RegisterProxyHandlers();

    let mut pool_config = green::PoolConfig::new();
    pool_config.event_loop_factory = rustuv::event_loop;
    let mut pool = green::SchedPool::new(pool_config);

    let (compositor_port, compositor_chan) = CompositorChan::new();
    let time_profiler_chan = TimeProfiler::create(opts.time_profiler_period);
    let memory_profiler_chan = MemoryProfiler::create(opts.memory_profiler_period);

    let opts_clone = opts.clone();
    let time_profiler_chan_clone = time_profiler_chan.clone();

    let (result_chan, result_port) = channel();
    pool.spawn(TaskOpts::new(), proc() {
        let opts = &opts_clone;
        // Create a Servo instance.
        let resource_task = new_resource_task();
        // If we are emitting an output file, then we need to block on
        // image load or we risk emitting an output file missing the
        // image.
        let image_cache_task = if opts.output_file.is_some() {
                ImageCacheTask::new_sync(resource_task.clone())
            } else {
                ImageCacheTask::new(resource_task.clone())
            };
        let font_cache_task = FontCacheTask::new();
        let constellation_chan = Constellation::<layout::layout_task::LayoutTask>::start(
                                                      compositor_chan,
                                                      opts,
                                                      resource_task,
                                                      image_cache_task,
                                                      font_cache_task,
                                                      time_profiler_chan_clone);

        let base_url = Url::from_directory_path(&os::getcwd()).unwrap();
        let mut url_parser = UrlParser::new();
        let url_parser = url_parser.base_url(&base_url);
        // Send the URL command to the constellation.
        for url in opts.urls.iter() {
            let url = url_parser.parse(url.as_slice()).ok().expect("URL parsing failed");

            let ConstellationChan(ref chan) = constellation_chan;
            chan.send(InitLoadUrlMsg(url));
        }

        // Send the constallation Chan as the result
        result_chan.send(constellation_chan);
    });

    let constellation_chan = result_port.recv();

    debug!("preparing to enter main loop");
    CompositorTask::create(opts,
                           compositor_port,
                           constellation_chan,
                           time_profiler_chan,
                           memory_profiler_chan);

    pool.shutdown();
}

<commit_msg>Fix compile error and warning on Android<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_id = "github.com/mozilla/servo"]
#![comment = "The Servo Parallel Browser Project"]
#![license = "MPL"]

#![feature(globs, macro_rules, phase, thread_local)]

#[phase(plugin, link)]
extern crate log;

extern crate debug;

extern crate compositing;
extern crate rustuv;
extern crate servo_net = "net";
extern crate servo_msg = "msg";
#[phase(plugin, link)]
extern crate servo_util = "util";
extern crate script;
extern crate layout;
extern crate green;
extern crate gfx;
extern crate libc;
extern crate native;
extern crate rustrt;
extern crate url = "url_";

#[cfg(not(test))]
use compositing::{CompositorChan, CompositorTask, Constellation};
#[cfg(not(test))]
use servo_msg::constellation_msg::{ConstellationChan, InitLoadUrlMsg};
#[cfg(not(test))]
use script::dom::bindings::codegen::RegisterBindings;

#[cfg(not(test))]
use servo_net::image_cache_task::ImageCacheTask;
#[cfg(not(test))]
use servo_net::resource_task::new_resource_task;
#[cfg(not(test))]
use gfx::font_cache_task::FontCacheTask;
#[cfg(not(test))]
use servo_util::time::TimeProfiler;
#[cfg(not(test))]
use servo_util::memory::MemoryProfiler;

#[cfg(not(test))]
use servo_util::opts;

#[cfg(not(test))]
use url::{Url, UrlParser};

#[cfg(not(test))]
use std::os;
#[cfg(not(test), target_os="android")]
use std::str;
#[cfg(not(test))]
use rustrt::task::TaskOpts;

#[cfg(not(test), target_os="linux")]
#[cfg(not(test), target_os="macos")]
#[start]
#[allow(dead_code)]
fn start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, proc() {
        opts::from_cmdline_args(os::args().as_slice()).map(run);
    })
}

#[cfg(not(test), target_os="android")]
#[no_mangle]
#[allow(dead_code)]
pub extern "C" fn android_start(argc: int, argv: **u8) -> int {
    native::start(argc, argv, proc() {
        let mut args: Vec<String> = vec!();
        for i in range(0u, argc as uint) {
            unsafe {
                args.push(str::raw::from_c_str(*argv.offset(i as int) as *i8));
            }
        }

        let opts = opts::from_cmdline_args(args.as_slice());
        match opts {
            Some(mut o) => {
                // Always use CPU rendering on android.
                o.cpu_painting = true;
                run(o);
            },
            None => {}
        }
    })
}

#[cfg(not(test))]
pub fn run(opts: opts::Opts) {
    ::servo_util::opts::set_experimental_enabled(opts.enable_experimental);
    RegisterBindings::RegisterProxyHandlers();

    let mut pool_config = green::PoolConfig::new();
    pool_config.event_loop_factory = rustuv::event_loop;
    let mut pool = green::SchedPool::new(pool_config);

    let (compositor_port, compositor_chan) = CompositorChan::new();
    let time_profiler_chan = TimeProfiler::create(opts.time_profiler_period);
    let memory_profiler_chan = MemoryProfiler::create(opts.memory_profiler_period);

    let opts_clone = opts.clone();
    let time_profiler_chan_clone = time_profiler_chan.clone();

    let (result_chan, result_port) = channel();
    pool.spawn(TaskOpts::new(), proc() {
        let opts = &opts_clone;
        // Create a Servo instance.
        let resource_task = new_resource_task();
        // If we are emitting an output file, then we need to block on
        // image load or we risk emitting an output file missing the
        // image.
        let image_cache_task = if opts.output_file.is_some() {
                ImageCacheTask::new_sync(resource_task.clone())
            } else {
                ImageCacheTask::new(resource_task.clone())
            };
        let font_cache_task = FontCacheTask::new();
        let constellation_chan = Constellation::<layout::layout_task::LayoutTask>::start(
                                                      compositor_chan,
                                                      opts,
                                                      resource_task,
                                                      image_cache_task,
                                                      font_cache_task,
                                                      time_profiler_chan_clone);

        let base_url = Url::from_directory_path(&os::getcwd()).unwrap();
        let mut url_parser = UrlParser::new();
        let url_parser = url_parser.base_url(&base_url);
        // Send the URL command to the constellation.
        for url in opts.urls.iter() {
            let url = url_parser.parse(url.as_slice()).ok().expect("URL parsing failed");

            let ConstellationChan(ref chan) = constellation_chan;
            chan.send(InitLoadUrlMsg(url));
        }

        // Send the constallation Chan as the result
        result_chan.send(constellation_chan);
    });

    let constellation_chan = result_port.recv();

    debug!("preparing to enter main loop");
    CompositorTask::create(opts,
                           compositor_port,
                           constellation_chan,
                           time_profiler_chan,
                           memory_profiler_chan);

    pool.shutdown();
}

<|endoftext|>


<commit_before>extern crate tokio_io;
extern crate futures;

use futures::future::ok;
use std::rc::Rc;
use std::cell::RefCell;

use super::{Peer, BoxedNewPeerFuture};

use tokio_io::{AsyncRead,AsyncWrite};
use std::io::{Read, Write, Error as IoError};

use std::ops::DerefMut;
use futures::Future;
use super::{once,Specifier,Handle,ProgramState,PeerConstructor,Options};

#[derive(Debug)]
pub struct Reuser<T:Specifier>(pub T);
impl<T:Specifier> Specifier for Reuser<T> {
    fn construct(&self, h:&Handle, ps: &mut ProgramState, opts: &Options) -> PeerConstructor {
        let mut reuser = ps.reuser.clone();
        let inner = self.0.construct(h, ps, opts).get_only_first_conn();
        once(connection_reuser(&mut reuser, inner))
    }
    specifier_boilerplate!(singleconnect has_subspec typ=Reuser globalstate);
    self_0_is_subspecifier!(...);
}

type PeerSlot = Rc<RefCell<Option<Peer>>>;

#[derive(Default,Clone)]
pub struct GlobalState(PeerSlot);

#[derive(Clone)]
struct PeerHandle(PeerSlot);

impl Read for PeerHandle {
    fn read (&mut self, b:&mut [u8]) -> Result<usize, IoError> {
        if let Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.0.read(b)
        } else {
            unreachable!()
        }
    }
}
impl AsyncRead for PeerHandle{}

impl Write for PeerHandle {
    fn write (&mut self, b: &[u8]) -> Result<usize, IoError> {
        if let Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.write(b)
        } else {
            unreachable!()
        }
    }
    fn flush (&mut self) -> Result<(), IoError> {
        if let Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.flush()
        } else {
            unreachable!()
        }
    }
}
impl AsyncWrite for PeerHandle {
    fn shutdown(&mut self) -> futures::Poll<(),IoError> {
        if let Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.shutdown()
        } else {
            unreachable!()
        }
    }
}

pub fn connection_reuser(s: &mut GlobalState, inner_peer : BoxedNewPeerFuture) -> BoxedNewPeerFuture
{
    let need_init = s.0.borrow().is_none();

    let rc = s.0.clone();

    if need_init {
        Box::new(inner_peer.and_then(move |inner| {
            {
                let mut b = rc.borrow_mut();
                let x : &mut Option<Peer> = b.deref_mut();
                *x = Some(inner);
            }

            let ps : PeerSlot = rc.clone();

            let ph1 = PeerHandle(ps);
            let ph2 = ph1.clone();
            let peer = Peer::new(ph1, ph2);
            ok(peer)
        })) as BoxedNewPeerFuture
    } else {
        let ps : PeerSlot = rc.clone();

        let ph1 = PeerHandle(ps);
        let ph2 = ph1.clone();
        let peer = Peer::new(ph1, ph2);
        Box::new(ok(peer)) as BoxedNewPeerFuture
    }
}
<commit_msg>Fix reuse:<commit_after>extern crate tokio_io;
extern crate futures;

use futures::future::ok;
use std::rc::Rc;
use std::cell::RefCell;

use super::{Peer, BoxedNewPeerFuture};

use tokio_io::{AsyncRead,AsyncWrite};
use std::io::{Read, Write, Error as IoError};

use std::ops::DerefMut;
use futures::Future;
use super::{once,Specifier,Handle,ProgramState,PeerConstructor,Options};

#[derive(Debug)]
pub struct Reuser(pub Rc<Specifier>);
impl Specifier for Reuser {
    fn construct(&self, h:&Handle, ps: &mut ProgramState, opts: &Options) -> PeerConstructor {
        let mut reuser = ps.reuser.clone();
        let inner = ||self.0.construct(h, ps, opts).get_only_first_conn();
        once(connection_reuser(&mut reuser, inner))
    }
    specifier_boilerplate!(singleconnect has_subspec typ=Reuser globalstate);
    self_0_is_subspecifier!(...);
}

type PeerSlot = Rc<RefCell<Option<Peer>>>;

#[derive(Default,Clone)]
pub struct GlobalState(PeerSlot);

#[derive(Clone)]
struct PeerHandle(PeerSlot);

impl Read for PeerHandle {
    fn read (&mut self, b:&mut [u8]) -> Result<usize, IoError> {
        if let Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.0.read(b)
        } else {
            unreachable!()
        }
    }
}
impl AsyncRead for PeerHandle{}

impl Write for PeerHandle {
    fn write (&mut self, b: &[u8]) -> Result<usize, IoError> {
        if let Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.write(b)
        } else {
            unreachable!()
        }
    }
    fn flush (&mut self) -> Result<(), IoError> {
        if let Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.flush()
        } else {
            unreachable!()
        }
    }
}
impl AsyncWrite for PeerHandle {
    fn shutdown(&mut self) -> futures::Poll<(),IoError> {
        if let Some(ref mut x) = self.0.borrow_mut().deref_mut() {
            x.1.shutdown()
        } else {
            unreachable!()
        }
    }
}

pub fn connection_reuser<F:FnOnce()->BoxedNewPeerFuture>(s: &mut GlobalState, inner_peer : F) -> BoxedNewPeerFuture
{
    let need_init = s.0.borrow().is_none();

    let rc = s.0.clone();

    if need_init {
        info!("Initializing");
        Box::new(inner_peer().and_then(move |inner| {
            {
                let mut b = rc.borrow_mut();
                let x : &mut Option<Peer> = b.deref_mut();
                *x = Some(inner);
            }

            let ps : PeerSlot = rc.clone();

            let ph1 = PeerHandle(ps);
            let ph2 = ph1.clone();
            let peer = Peer::new(ph1, ph2);
            ok(peer)
        })) as BoxedNewPeerFuture
    } else {
        info!("Reusing");
        let ps : PeerSlot = rc.clone();

        let ph1 = PeerHandle(ps);
        let ph2 = ph1.clone();
        let peer = Peer::new(ph1, ph2);
        Box::new(ok(peer)) as BoxedNewPeerFuture
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of
// the Mozilla Public License, v. 2.0. If a copy of
// the MPL was not distributed with this file, You
// can obtain one at http://mozilla.org/MPL/2.0/.

//! Generate random `cbor::Value`s.
//!
//! This module is only available with `--features="random"`.

use quickcheck::{Arbitrary, Gen};
use rand::Rng;
use std::collections::{BTreeMap, LinkedList};
use types::Tag;
use values::{Value, Simple, Key, Bytes, Text};

/// Generare a random `cbor::Value`.
/// Mostly useful for quickcheck related tests.
/// The parameter `level` denotes the maximum nesting of this value.
pub fn gen_value<G: Gen>(level: u16, g: &mut G) -> Value {
    match g.gen_range(0, 19) {
        0  => Value::Null,
        1  => Value::Undefined,
        2  => Value::U8(g.gen()),
        3  => Value::U16(g.gen()),
        4  => Value::U32(g.gen()),
        5  => Value::U64(g.gen()),
        6  => Value::I8(g.gen()),
        7  => Value::I16(g.gen()),
        8  => Value::I32(g.gen()),
        9  => Value::I64(g.gen()),
        10 => Value::F32(g.gen()),
        11 => Value::F64(g.gen()),
        12 => Value::Text(gen_text(g)),
        13 => Value::Bytes(gen_bytes(g)),
        14 => Value::Array(
                if level > 0 {
                    gen_array(level - 1, g)
                } else {
                    Vec::with_capacity(0)
                }),
        15 => Value::Bool(g.gen()),
        16 => Value::Simple(gen_simple(g)),
        17 => Value::Map(
                if level > 0 {
                    gen_map(level - 1, g)
                } else {
                    BTreeMap::new()
                }),
        _ => gen_tagged(g)
    }
}

fn gen_array<G: Gen>(level: u16, g: &mut G) -> Vec<Value> {
    let     len = g.gen_range(0, 64);
    let mut vec = Vec::with_capacity(len);
    for _ in 0 .. len {
        vec.push(gen_value(level, g))
    }
    vec
}

fn gen_map<G: Gen>(level: u16, g: &mut G) -> BTreeMap<Key, Value> {
    let     len = g.gen_range(0, 64);
    let mut map = BTreeMap::new();
    for _ in 0 .. len {
        map.insert(gen_key(g), gen_value(level, g));
    }
    map
}

fn gen_key<G: Gen>(g: &mut G) -> Key {
    match g.gen_range(0, 5) {
        0 => Key::U64(g.gen()),
        1 => Key::I64(g.gen()),
        2 => Key::Text(gen_text(g)),
        3 => Key::Bytes(gen_bytes(g)),
        _ => Key::Bool(g.gen()),
    }
}

fn gen_tag<G: Gen>(g: &mut G) -> Tag {
    match g.gen_range(0, 20) {
        0  => Tag::DateTime,
        1  => Tag::Timestamp,
        2  => Tag::Bignum,
        3  => Tag::NegativeBignum,
        4  => Tag::Decimal,
        5  => Tag::Bigfloat,
        6  => Tag::ToBase64Url,
        7  => Tag::ToBase64,
        8  => Tag::ToBase16,
        9  => Tag::Cbor,
        10 => Tag::Uri,
        11 => Tag::Base64Url,
        12 => Tag::Base64,
        13 => Tag::Regex,
        14 => Tag::Mime,
        15 => Tag::CborSelf,
        tg => Tag::Unassigned(tg)
    }
}

fn gen_text<G: Gen>(g: &mut G) -> Text {
    match g.gen() {
        true  => Text::Text(Arbitrary::arbitrary(g)),
        false => Text::Chunks(gen_chunks(g))
    }
}

fn gen_bytes<G: Gen>(g: &mut G) -> Bytes {
    match g.gen() {
        true  => Bytes::Bytes(Arbitrary::arbitrary(g)),
        false => Bytes::Chunks(gen_chunks(g))
    }
}

fn gen_chunks<A: Arbitrary, G: Gen>(g: &mut G) -> LinkedList<A> {
    let mut xs = LinkedList::new();
    for _ in 0 .. g.gen_range(0, 64) {
        xs.push_back(Arbitrary::arbitrary(g))
    }
    xs
}

fn gen_simple<G: Gen>(g: &mut G) -> Simple {
    match g.gen() {
        true => match g.gen() {
            n @ 0u8...19 | n @ 28...30 => Simple::Unassigned(n),
            n @ 32...255               => Simple::Unassigned(n),
            _                          => Simple::Unassigned(0)
        },
        false => match g.gen() {
            n @ 0u8...31 => Simple::Reserved(n),
            _            => Simple::Reserved(0)
        }
    }
}

fn gen_tagged<G: Gen>(g: &mut G) -> Value {
    match gen_tag(g) {
        t@Tag::DateTime  => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::Timestamp => match g.gen_range(0, 10) {
            0 => Value::Tagged(t, Box::new(Value::U8(g.gen()))),
            1 => Value::Tagged(t, Box::new(Value::U16(g.gen()))),
            2 => Value::Tagged(t, Box::new(Value::U32(g.gen()))),
            3 => Value::Tagged(t, Box::new(Value::U64(g.gen()))),
            4 => Value::Tagged(t, Box::new(Value::I8(g.gen()))),
            5 => Value::Tagged(t, Box::new(Value::I16(g.gen()))),
            6 => Value::Tagged(t, Box::new(Value::I32(g.gen()))),
            7 => Value::Tagged(t, Box::new(Value::I64(g.gen()))),
            8 => Value::Tagged(t, Box::new(Value::F32(g.gen()))),
            _ => Value::Tagged(t, Box::new(Value::F64(g.gen())))
        },
        t@Tag::Bignum         => Value::Tagged(t, Box::new(Value::Bytes(gen_bytes(g)))),
        t@Tag::NegativeBignum => Value::Tagged(t, Box::new(Value::Bytes(gen_bytes(g)))),
        t@Tag::Uri            => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::Base64         => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::ToBase64Url    => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::Regex          => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::Decimal        => Value::Tagged(t, Box::new(Value::Array(vec![Value::U64(g.gen()), Value::U64(g.gen())]))),
        t@Tag::Bigfloat       => Value::Tagged(t, Box::new(Value::Array(vec![Value::U64(g.gen()), Value::U64(g.gen())]))),
        _                     => Value::Tagged(Tag::Mime, Box::new(Value::Text(gen_text(g))))
    }
}

<commit_msg>Fix typo.<commit_after>// This Source Code Form is subject to the terms of
// the Mozilla Public License, v. 2.0. If a copy of
// the MPL was not distributed with this file, You
// can obtain one at http://mozilla.org/MPL/2.0/.

//! Generate random `cbor::Value`s.
//!
//! This module is only available with `--features="random"`.

use quickcheck::{Arbitrary, Gen};
use rand::Rng;
use std::collections::{BTreeMap, LinkedList};
use types::Tag;
use values::{Value, Simple, Key, Bytes, Text};

/// Generate a random `cbor::Value`.
/// Mostly useful for quickcheck related tests.
/// The parameter `level` denotes the maximum nesting of this value.
pub fn gen_value<G: Gen>(level: u16, g: &mut G) -> Value {
    match g.gen_range(0, 19) {
        0  => Value::Null,
        1  => Value::Undefined,
        2  => Value::U8(g.gen()),
        3  => Value::U16(g.gen()),
        4  => Value::U32(g.gen()),
        5  => Value::U64(g.gen()),
        6  => Value::I8(g.gen()),
        7  => Value::I16(g.gen()),
        8  => Value::I32(g.gen()),
        9  => Value::I64(g.gen()),
        10 => Value::F32(g.gen()),
        11 => Value::F64(g.gen()),
        12 => Value::Text(gen_text(g)),
        13 => Value::Bytes(gen_bytes(g)),
        14 => Value::Array(
                if level > 0 {
                    gen_array(level - 1, g)
                } else {
                    Vec::with_capacity(0)
                }),
        15 => Value::Bool(g.gen()),
        16 => Value::Simple(gen_simple(g)),
        17 => Value::Map(
                if level > 0 {
                    gen_map(level - 1, g)
                } else {
                    BTreeMap::new()
                }),
        _ => gen_tagged(g)
    }
}

fn gen_array<G: Gen>(level: u16, g: &mut G) -> Vec<Value> {
    let     len = g.gen_range(0, 64);
    let mut vec = Vec::with_capacity(len);
    for _ in 0 .. len {
        vec.push(gen_value(level, g))
    }
    vec
}

fn gen_map<G: Gen>(level: u16, g: &mut G) -> BTreeMap<Key, Value> {
    let     len = g.gen_range(0, 64);
    let mut map = BTreeMap::new();
    for _ in 0 .. len {
        map.insert(gen_key(g), gen_value(level, g));
    }
    map
}

fn gen_key<G: Gen>(g: &mut G) -> Key {
    match g.gen_range(0, 5) {
        0 => Key::U64(g.gen()),
        1 => Key::I64(g.gen()),
        2 => Key::Text(gen_text(g)),
        3 => Key::Bytes(gen_bytes(g)),
        _ => Key::Bool(g.gen()),
    }
}

fn gen_tag<G: Gen>(g: &mut G) -> Tag {
    match g.gen_range(0, 20) {
        0  => Tag::DateTime,
        1  => Tag::Timestamp,
        2  => Tag::Bignum,
        3  => Tag::NegativeBignum,
        4  => Tag::Decimal,
        5  => Tag::Bigfloat,
        6  => Tag::ToBase64Url,
        7  => Tag::ToBase64,
        8  => Tag::ToBase16,
        9  => Tag::Cbor,
        10 => Tag::Uri,
        11 => Tag::Base64Url,
        12 => Tag::Base64,
        13 => Tag::Regex,
        14 => Tag::Mime,
        15 => Tag::CborSelf,
        tg => Tag::Unassigned(tg)
    }
}

fn gen_text<G: Gen>(g: &mut G) -> Text {
    match g.gen() {
        true  => Text::Text(Arbitrary::arbitrary(g)),
        false => Text::Chunks(gen_chunks(g))
    }
}

fn gen_bytes<G: Gen>(g: &mut G) -> Bytes {
    match g.gen() {
        true  => Bytes::Bytes(Arbitrary::arbitrary(g)),
        false => Bytes::Chunks(gen_chunks(g))
    }
}

fn gen_chunks<A: Arbitrary, G: Gen>(g: &mut G) -> LinkedList<A> {
    let mut xs = LinkedList::new();
    for _ in 0 .. g.gen_range(0, 64) {
        xs.push_back(Arbitrary::arbitrary(g))
    }
    xs
}

fn gen_simple<G: Gen>(g: &mut G) -> Simple {
    match g.gen() {
        true => match g.gen() {
            n @ 0u8...19 | n @ 28...30 => Simple::Unassigned(n),
            n @ 32...255               => Simple::Unassigned(n),
            _                          => Simple::Unassigned(0)
        },
        false => match g.gen() {
            n @ 0u8...31 => Simple::Reserved(n),
            _            => Simple::Reserved(0)
        }
    }
}

fn gen_tagged<G: Gen>(g: &mut G) -> Value {
    match gen_tag(g) {
        t@Tag::DateTime  => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::Timestamp => match g.gen_range(0, 10) {
            0 => Value::Tagged(t, Box::new(Value::U8(g.gen()))),
            1 => Value::Tagged(t, Box::new(Value::U16(g.gen()))),
            2 => Value::Tagged(t, Box::new(Value::U32(g.gen()))),
            3 => Value::Tagged(t, Box::new(Value::U64(g.gen()))),
            4 => Value::Tagged(t, Box::new(Value::I8(g.gen()))),
            5 => Value::Tagged(t, Box::new(Value::I16(g.gen()))),
            6 => Value::Tagged(t, Box::new(Value::I32(g.gen()))),
            7 => Value::Tagged(t, Box::new(Value::I64(g.gen()))),
            8 => Value::Tagged(t, Box::new(Value::F32(g.gen()))),
            _ => Value::Tagged(t, Box::new(Value::F64(g.gen())))
        },
        t@Tag::Bignum         => Value::Tagged(t, Box::new(Value::Bytes(gen_bytes(g)))),
        t@Tag::NegativeBignum => Value::Tagged(t, Box::new(Value::Bytes(gen_bytes(g)))),
        t@Tag::Uri            => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::Base64         => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::ToBase64Url    => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::Regex          => Value::Tagged(t, Box::new(Value::Text(gen_text(g)))),
        t@Tag::Decimal        => Value::Tagged(t, Box::new(Value::Array(vec![Value::U64(g.gen()), Value::U64(g.gen())]))),
        t@Tag::Bigfloat       => Value::Tagged(t, Box::new(Value::Array(vec![Value::U64(g.gen()), Value::U64(g.gen())]))),
        _                     => Value::Tagged(Tag::Mime, Box::new(Value::Text(gen_text(g))))
    }
}

<|endoftext|>


<commit_before>//============================================================================
//
//  A Tagged Image File Format (TIFF) Library for Rust
//
//  Based on the TIFF 6.0 specification:
//
//      https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
//
//  Copyright (c) 2014 by Gavin Baker <gavinb@antonym.org>
//  Published under the MIT License
//
//============================================================================

use std::io::{Result, Error, ErrorKind, Read, Seek, SeekFrom};
use std::path::Path;
use std::fs::File;

use byteorder::{ReadBytesExt, WriteBytesExt, ByteOrder, BigEndian, LittleEndian};

use {TIFFByteOrder, HeaderMagic, TIFFHeader, IFD, IFDEntry, decode_tag, decode_tag_type, SeekableReader};

pub struct TIFFReader;

impl TIFFReader {

    pub fn load(&self, filename: &str) -> Result<Box<TIFFHeader>> {

        let filepath = Path::new(filename);
        let mut reader = File::open(&filepath).unwrap();

        self.read::<LittleEndian>(&mut reader)
    }

    pub fn read_byte_order(&self, reader: &mut SeekableReader) -> Result<Box<TIFFHeader>> {
        Err(Error::new(ErrorKind::Other, ""))
    }

    pub fn read<E: ByteOrder>(&self, reader: &mut SeekableReader) -> Result<Box<TIFFHeader>> {

        // @todo Ensure file is >= min size

        // Read and validate ByteOrder

        let byte_order_field = try!(reader.read_u16::<LittleEndian>());
        let byte_order: TIFFByteOrder;

        if byte_order_field == TIFFByteOrder::LittleEndian as u16 {
            byte_order = TIFFByteOrder::LittleEndian;
        } else if byte_order_field == TIFFByteOrder::BigEndian as u16 {
            byte_order = TIFFByteOrder::BigEndian;
        } else {
            return Err(Error::new(ErrorKind::Other,
                                  format!("Invalid byte order in header: {:04x}", byte_order_field)));
        }
        println!("byte_order {:?}", byte_order);

        // Read and validate HeaderMagic

        let magic_field = match byte_order {
            TIFFByteOrder::LittleEndian => try!(reader.read_u16::<LittleEndian>()),
            TIFFByteOrder::BigEndian => try!(reader.read_u16::<BigEndian>()),
        };

        let magic: HeaderMagic;

        if magic_field == HeaderMagic::LittleEndian as u16 {
            magic = HeaderMagic::LittleEndian;
        }
        else if magic_field == HeaderMagic::BigEndian as u16 {
            magic = HeaderMagic::BigEndian;
        } else {
            return Err(Error::new(ErrorKind::Other, "Invalid magic number in header"));
        }

        // Read offset to first IFD

        let ifd_offset_field = match byte_order {
            TIFFByteOrder::LittleEndian => try!(reader.read_u32::<LittleEndian>()),
            TIFFByteOrder::BigEndian => try!(reader.read_u32::<BigEndian>()),
        };

        // Assemble validated header

        let header = Box::new(TIFFHeader {
            byte_order: byte_order,
            magic: magic,
            ifd_offset: ifd_offset_field,
        });

        try!(reader.seek(SeekFrom::Start(ifd_offset_field as u64)));
        println!("IFD offset: {:?}", ifd_offset_field);

        try!(self.read_IFD(reader));

        Ok(header)
    }

    #[allow(non_snake_case)]
    fn read_IFD(&self, reader: &mut SeekableReader) -> Result<Box<IFD>> {

        let entry_count = try!(reader.read_u16::<LittleEndian>());

        println!("IFD entry count: {}", entry_count);

        let mut ifd = Box::new(IFD { count: entry_count, entries: Vec::with_capacity(entry_count as usize) });

        println!("IFD entry count: {}", entry_count);

        for entry_number in 0..entry_count as usize {
            ifd.entries.push(*self.read_tag(entry_number, reader).unwrap());
        }

        Ok(ifd)
    }

    fn read_tag(&self, entry_number: usize, reader: &mut SeekableReader) -> Result<Box<IFDEntry>> {

        let tag_value = try!(reader.read_u16::<LittleEndian>());
        let typ_value = try!(reader.read_u16::<LittleEndian>());
        let count_value = try!(reader.read_u32::<LittleEndian>());
        let value_offset_value = try!(reader.read_u32::<LittleEndian>());

        let tag_msg = format!("Invalid tag {:x}", tag_value);
        let tag = decode_tag(tag_value).expect(&tag_msg);

        let typ_msg = format!("Invalid tag type {:x}", typ_value);
        let typ = decode_tag_type(typ_value).expect(&typ_msg);

        let e0 = Box::new(IFDEntry {
            tag: tag,
            typ: typ,
            count: count_value,
            value_offset: value_offset_value,
        });

        println!("IFD[{:?}] {:?} {:?} {:x} {}", entry_number, e0.tag, e0.typ, e0.count, e0.value_offset);
        Ok(e0)
    }
}
<commit_msg>Start splitting up reader to parameterise over endianness<commit_after>//============================================================================
//
//  A Tagged Image File Format (TIFF) Library for Rust
//
//  Based on the TIFF 6.0 specification:
//
//      https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
//
//  Copyright (c) 2014 by Gavin Baker <gavinb@antonym.org>
//  Published under the MIT License
//
//============================================================================

use std::io::{Result, Error, ErrorKind, Read, Seek, SeekFrom};
use std::path::Path;
use std::fs::File;

use byteorder::{ReadBytesExt, WriteBytesExt, ByteOrder, BigEndian, LittleEndian};

use {TIFFByteOrder, HeaderMagic, TIFFHeader, IFD, IFDEntry, decode_tag, decode_tag_type, SeekableReader};

pub struct TIFFReader;

impl TIFFReader {

    pub fn load(&self, filename: &str) -> Result<Box<TIFFHeader>> {

        let filepath = Path::new(filename);
        let mut reader = File::open(&filepath).unwrap();

        self.read(&mut reader)
    }

    pub fn read(&self, reader: &mut SeekableReader) -> Result<Box<TIFFHeader>> {

        let byte_order = self.read_byte_order(reader).unwrap();

        let magic = match byte_order {
            TIFFByteOrder::LittleEndian => self.read_magic::<LittleEndian>(reader),
            TIFFByteOrder::BigEndian => self.read_magic::<BigEndian>(reader),
        };

        Err(Error::new(ErrorKind::Other, "Not implemented"))
    }

    pub fn read_byte_order(&self, reader: &mut SeekableReader) -> Result<TIFFByteOrder> {

        // Bytes 0-1: "II" or "MM"
        // Read and validate ByteOrder

        let byte_order_field = try!(reader.read_u16::<LittleEndian>());
        let byte_order: TIFFByteOrder;

        if byte_order_field == TIFFByteOrder::LittleEndian as u16 {
            byte_order = TIFFByteOrder::LittleEndian;
        } else if byte_order_field == TIFFByteOrder::BigEndian as u16 {
            byte_order = TIFFByteOrder::BigEndian;
        } else {
            return Err(Error::new(ErrorKind::Other,
                                  format!("Invalid byte order in header: {:04x}", byte_order_field)));
        }
        println!("byte_order {:?}", byte_order);

        Ok(byte_order)
    }

    pub fn read_magic<Endian: ByteOrder>(&self, reader: &mut SeekableReader) -> Result<HeaderMagic> {

        // Read and validate HeaderMagic
        // Bytes 2-3: 42

        let magic_field = try!(reader.read_u16::<Endian>());

        let magic: HeaderMagic;

        if magic_field == HeaderMagic::LittleEndian as u16 {
            Ok(HeaderMagic::LittleEndian)
        }
        else if magic_field == HeaderMagic::BigEndian as u16 {
            Ok(HeaderMagic::BigEndian)
        } else {
            Err(Error::new(ErrorKind::Other, "Invalid magic number in header"))
        }
    }

    pub fn read_<Endian: ByteOrder>(&self, reader: &mut SeekableReader) -> Result<Box<TIFFHeader>> {

        // @todo Ensure file is >= min size

        // Read offset to first IFD

        let ifd_offset_field = try!(reader.read_u32::<Endian>());

        // Assemble validated header

        let header = Box::new(TIFFHeader {
            byte_order: TIFFByteOrder::LittleEndian,
            magic: HeaderMagic::LittleEndian,
            ifd_offset: ifd_offset_field,
        });

        try!(reader.seek(SeekFrom::Start(ifd_offset_field as u64)));
        println!("IFD offset: {:?}", ifd_offset_field);

        try!(self.read_IFD(reader));

        Ok(header)
    }

    #[allow(non_snake_case)]
    fn read_IFD(&self, reader: &mut SeekableReader) -> Result<Box<IFD>> {

        let entry_count = try!(reader.read_u16::<LittleEndian>());

        println!("IFD entry count: {}", entry_count);

        let mut ifd = Box::new(IFD { count: entry_count, entries: Vec::with_capacity(entry_count as usize) });

        println!("IFD entry count: {}", entry_count);

        for entry_number in 0..entry_count as usize {
            ifd.entries.push(*self.read_tag(entry_number, reader).unwrap());
        }

        Ok(ifd)
    }

    fn read_tag(&self, entry_number: usize, reader: &mut SeekableReader) -> Result<Box<IFDEntry>> {

        let tag_value = try!(reader.read_u16::<LittleEndian>());
        let typ_value = try!(reader.read_u16::<LittleEndian>());
        let count_value = try!(reader.read_u32::<LittleEndian>());
        let value_offset_value = try!(reader.read_u32::<LittleEndian>());

        let tag_msg = format!("Invalid tag {:x}", tag_value);
        let tag = decode_tag(tag_value).expect(&tag_msg);

        let typ_msg = format!("Invalid tag type {:x}", typ_value);
        let typ = decode_tag_type(typ_value).expect(&typ_msg);

        let e0 = Box::new(IFDEntry {
            tag: tag,
            typ: typ,
            count: count_value,
            value_offset: value_offset_value,
        });

        println!("IFD[{:?}] {:?} {:?} {:x} {}", entry_number, e0.tag, e0.typ, e0.count, e0.value_offset);
        Ok(e0)
    }
}
<|endoftext|>


<commit_before>extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate lazy_static;
extern crate nalgebra;
extern crate rand;

use nalgebra::ToHomogeneous;
use std::convert::AsRef;

use cube::{self, CubeRef, Spatial};
use math::{IntoSpace, FMatrix4, FPoint3, FScalar, FVector3, FVector4};
use mesh::{Conjoint, DecomposePolygon, DecomposePrimitive, Indexed, UCube};
use super::OptionExt;

pub type Index = u32;

gfx_pipeline!{
    pipeline {
        vertex_buffer: gfx::VertexBuffer<RawVertex> = (),
        transform: gfx::Global<[[f32; 4]; 4]> = "u_transform",
        output: gfx::RenderTarget<gfx::format::Rgba8> = "f_target0",
    }
}

gfx_vertex_struct!{
    RawVertex {
        position: [f32; 3] = "a_position",
        color: [f32; 4] = "a_color",
    }
}

impl From<Vertex> for RawVertex {
    fn from(vertex: Vertex) -> Self {
        RawVertex {
            position: *vertex.position.as_ref(),
            color: *vertex.color.as_ref(),
        }
    }
}

pub struct Vertex {
    pub position: FPoint3,
    pub color: FVector4,
}

impl Vertex {
    pub fn new(position: FPoint3, color: FVector4) -> Self {
        Vertex {
            position: position,
            color: color,
        }
    }
}

pub struct MeshBuffer {
    pub vertices: Vec<RawVertex>,
    pub indeces: Vec<Index>,
}

impl MeshBuffer {
    pub fn new() -> Self {
        MeshBuffer {
            vertices: vec![],
            indeces: vec![],
        }
    }

    pub fn extend(&mut self, buffer: &Self) {
        let offset = self.vertices.len();
        self.vertices.extend(buffer.vertices.iter());
        self.indeces.extend(buffer.indeces
            .iter()
            .map(|index| index + offset as Index));
    }
}

pub trait Mesh {
    fn mesh_buffer(&self) -> MeshBuffer;
}

impl<'a> Mesh for CubeRef<'a> {
    fn mesh_buffer(&self) -> MeshBuffer {
        let mut buffer = MeshBuffer::new();
        if let Some(leaf) = self.try_as_leaf().and_if(|leaf| !leaf.geometry.is_empty()) {
            let origin: FVector3 = self.partition().origin().to_vector().into_space();
            let width = cube::exp(self.partition().width()) as FScalar;
            let color = random_color();

            buffer.vertices.extend(UCube::with_unit_width().conjoint_points()
                .map(|point| leaf.geometry.map_unit_cube_point(&point))
                .map(|point| (point * width) + origin)
                .map(|point| RawVertex::from(Vertex::new(point, color))));
            buffer.indeces.extend(UCube::with_unit_width().indexed_polygons()
                .triangulate()
                .points()
                .map(|index| index as Index));
        }
        buffer
    }
}

pub fn vertex_buffer_from_cube<R, F>(cube: &CubeRef,
                                     factory: &mut F)
                                     -> (gfx::handle::Buffer<R, RawVertex>, gfx::Slice<R>)
    where R: gfx::Resources,
          F: gfx::traits::FactoryExt<R>
{
    let mut buffer = MeshBuffer::new();
    for cube in cube.iter().filter(|cube| cube.is_leaf()) {
        buffer.extend(&cube.mesh_buffer());
    }
    factory.create_vertex_buffer_with_slice(buffer.vertices.as_slice(), buffer.indeces.as_slice())
}

pub fn projection_from_window(window: &glutin::Window) -> FMatrix4 {
    let aspect = {
        let (width, height) = window.get_inner_size_pixels().unwrap();
        width as f32 / height as f32
    };
    nalgebra::PerspectiveMatrix3::new(aspect, 1.0, -1.0, 1.0).to_matrix()
}

pub fn look_at_cube<C>(cube: &C, from: &FPoint3) -> FMatrix4
    where C: Spatial
{
    nalgebra::Isometry3::look_at_rh(from,
                                    &cube.partition().midpoint().into_space(),
                                    &FVector3::new(0.0, 0.0, 1.0))
        .to_homogeneous()
}

fn random_color() -> FVector4 {
    FVector4::new(rand::random::<FScalar>(),
                  rand::random::<FScalar>(),
                  rand::random::<FScalar>(),
                  1.0)
}

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Only create one unit cube mesh.<commit_after>extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate lazy_static;
extern crate nalgebra;
extern crate rand;

use nalgebra::ToHomogeneous;
use std::convert::AsRef;

use cube::{self, CubeRef, Spatial};
use math::{IntoSpace, FMatrix4, FPoint3, FScalar, FVector3, FVector4};
use mesh::{Conjoint, DecomposePolygon, DecomposePrimitive, Indexed, UCube};
use super::OptionExt;

pub type Index = u32;

gfx_pipeline!{
    pipeline {
        vertex_buffer: gfx::VertexBuffer<RawVertex> = (),
        transform: gfx::Global<[[f32; 4]; 4]> = "u_transform",
        output: gfx::RenderTarget<gfx::format::Rgba8> = "f_target0",
    }
}

gfx_vertex_struct!{
    RawVertex {
        position: [f32; 3] = "a_position",
        color: [f32; 4] = "a_color",
    }
}

impl From<Vertex> for RawVertex {
    fn from(vertex: Vertex) -> Self {
        RawVertex {
            position: *vertex.position.as_ref(),
            color: *vertex.color.as_ref(),
        }
    }
}

pub struct Vertex {
    pub position: FPoint3,
    pub color: FVector4,
}

impl Vertex {
    pub fn new(position: FPoint3, color: FVector4) -> Self {
        Vertex {
            position: position,
            color: color,
        }
    }
}

pub struct MeshBuffer {
    pub vertices: Vec<RawVertex>,
    pub indeces: Vec<Index>,
}

impl MeshBuffer {
    pub fn new() -> Self {
        MeshBuffer {
            vertices: vec![],
            indeces: vec![],
        }
    }

    pub fn extend(&mut self, buffer: &Self) {
        let offset = self.vertices.len();
        self.vertices.extend(buffer.vertices.iter());
        self.indeces.extend(buffer.indeces
            .iter()
            .map(|index| index + offset as Index));
    }
}

pub trait Mesh {
    fn mesh_buffer(&self) -> MeshBuffer;
}

impl<'a> Mesh for CubeRef<'a> {
    fn mesh_buffer(&self) -> MeshBuffer {
        let mut buffer = MeshBuffer::new();
        if let Some(leaf) = self.try_as_leaf().and_if(|leaf| !leaf.geometry.is_empty()) {
            let origin: FVector3 = self.partition().origin().to_vector().into_space();
            let width = cube::exp(self.partition().width()) as FScalar;
            let color = random_color();

            let cube = UCube::with_unit_width();
            buffer.vertices.extend(cube.conjoint_points()
                .map(|point| leaf.geometry.map_unit_cube_point(&point))
                .map(|point| (point * width) + origin)
                .map(|point| RawVertex::from(Vertex::new(point, color))));
            buffer.indeces.extend(cube.indexed_polygons()
                .triangulate()
                .points()
                .map(|index| index as Index));
        }
        buffer
    }
}

pub fn vertex_buffer_from_cube<R, F>(cube: &CubeRef,
                                     factory: &mut F)
                                     -> (gfx::handle::Buffer<R, RawVertex>, gfx::Slice<R>)
    where R: gfx::Resources,
          F: gfx::traits::FactoryExt<R>
{
    let mut buffer = MeshBuffer::new();
    for cube in cube.iter().filter(|cube| cube.is_leaf()) {
        buffer.extend(&cube.mesh_buffer());
    }
    factory.create_vertex_buffer_with_slice(buffer.vertices.as_slice(), buffer.indeces.as_slice())
}

pub fn projection_from_window(window: &glutin::Window) -> FMatrix4 {
    let aspect = {
        let (width, height) = window.get_inner_size_pixels().unwrap();
        width as f32 / height as f32
    };
    nalgebra::PerspectiveMatrix3::new(aspect, 1.0, -1.0, 1.0).to_matrix()
}

pub fn look_at_cube<C>(cube: &C, from: &FPoint3) -> FMatrix4
    where C: Spatial
{
    nalgebra::Isometry3::look_at_rh(from,
                                    &cube.partition().midpoint().into_space(),
                                    &FVector3::new(0.0, 0.0, 1.0))
        .to_homogeneous()
}

fn random_color() -> FVector4 {
    FVector4::new(rand::random::<FScalar>(),
                  rand::random::<FScalar>(),
                  rand::random::<FScalar>(),
                  1.0)
}

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>