<commit_before>use std::iter::repeat;

use term_grid as grid;

use column::{Column, Cell};
use dir::Dir;
use file::File;
use output::details::{Details, Table};
use output::grid::Grid;

#[derive(PartialEq, Debug, Copy, Clone)]
pub struct GridDetails {
    pub grid: Grid,
    pub details: Details,
}

impl GridDetails {
    pub fn view(&self, dir: Option<&Dir>, files: &[File]) {
        let columns_for_dir = self.details.columns.for_dir(dir);
        let mut first_table = Table::with_options(self.details.colours, columns_for_dir.clone());
        let cells: Vec<_> = files.iter().map(|file| first_table.cells_for_file(file)).collect();

        let mut last_working_table = self.make_grid(1, &*columns_for_dir, files, cells.clone());

        for column_count in 2.. {
            let grid = self.make_grid(column_count, &*columns_for_dir, files, cells.clone());

            if grid.fit_into_columns(column_count).width() <= self.grid.console_width {
                last_working_table = grid;
            }
            else {
                print!("{}", last_working_table.fit_into_columns(column_count - 1));
                return;
            }
        }
    }

    pub fn make_grid(&self, column_count: usize, columns_for_dir: &[Column], files: &[File], cells: Vec<Vec<Cell>>) -> grid::Grid {
        let make_table = || {
            let mut table = Table::with_options(self.details.colours, columns_for_dir.into());
            if self.details.header { table.add_header() }
            table
        };

        let mut tables: Vec<_> = repeat(()).map(|_| make_table()).take(column_count).collect();

        let mut height = cells.len() / column_count;
        if cells.len() % column_count != 0 {
            height += 1;
        }

        for (i, (file, row)) in files.iter().zip(cells.into_iter()).enumerate() {
            tables[i / height].add_file_with_cells(row, file, 0, false, false);
        }

        let columns: Vec<_> = tables.iter().map(|t| t.print_table(false, false)).collect();

        let direction = grid::Direction::TopToBottom;
        let mut grid = grid::Grid::new(grid::GridOptions {
            direction:        direction,
            separator_width:  4,
        });

        for column in columns.iter() {
            for cell in column.iter() {
                let cell = grid::Cell {
                    contents: cell.text.clone(),
                    width:    cell.length,
                };

                grid.add(cell);
            }
        }

        grid
    }
}
<commit_msg>Fix bug where unfilled displays were being checked<commit_after>use std::iter::repeat;

use term_grid as grid;

use column::{Column, Cell};
use dir::Dir;
use file::File;
use output::details::{Details, Table};
use output::grid::Grid;

#[derive(PartialEq, Debug, Copy, Clone)]
pub struct GridDetails {
    pub grid: Grid,
    pub details: Details,
}

impl GridDetails {
    pub fn view(&self, dir: Option<&Dir>, files: &[File]) {
        let columns_for_dir = self.details.columns.for_dir(dir);
        let mut first_table = Table::with_options(self.details.colours, columns_for_dir.clone());
        let cells: Vec<_> = files.iter().map(|file| first_table.cells_for_file(file)).collect();

        let mut last_working_table = self.make_grid(1, &*columns_for_dir, files, cells.clone());

        for column_count in 2.. {
            let grid = self.make_grid(column_count, &*columns_for_dir, files, cells.clone());

            let the_grid_fits = {
                let d = grid.fit_into_columns(column_count);
                d.is_complete() && d.width() <= self.grid.console_width
            };

            if the_grid_fits {
                last_working_table = grid;
            }
            else {
                print!("{}", last_working_table.fit_into_columns(column_count - 1));
                return;
            }
        }
    }

    pub fn make_grid(&self, column_count: usize, columns_for_dir: &[Column], files: &[File], cells: Vec<Vec<Cell>>) -> grid::Grid {
        let make_table = || {
            let mut table = Table::with_options(self.details.colours, columns_for_dir.into());
            if self.details.header { table.add_header() }
            table
        };

        let mut tables: Vec<_> = repeat(()).map(|_| make_table()).take(column_count).collect();

        let mut height = cells.len() / column_count;
        if cells.len() % column_count != 0 {
            height += 1;
        }

        for (i, (file, row)) in files.iter().zip(cells.into_iter()).enumerate() {
            tables[i / height].add_file_with_cells(row, file, 0, false, false);
        }

        let columns: Vec<_> = tables.iter().map(|t| t.print_table(false, false)).collect();

        let direction = grid::Direction::TopToBottom;
        let mut grid = grid::Grid::new(grid::GridOptions {
            direction:        direction,
            separator_width:  4,
        });

        for column in columns.iter() {
            for cell in column.iter() {
                let cell = grid::Cell {
                    contents: cell.text.clone(),
                    width:    cell.length,
                };

                grid.add(cell);
            }
        }

        grid
    }
}
<|endoftext|>


<commit_before>//! A simple connection pool
#![deprecated="Use https://github.com/sfackler/r2d2-postgres instead"]

use std::sync::{Arc, Mutex};

use {PostgresConnectParams, IntoConnectParams, PostgresConnection, SslMode};
use error::PostgresConnectError;

struct InnerConnectionPool {
    params: PostgresConnectParams,
    ssl: SslMode,
    pool: Vec<PostgresConnection>,
}

impl InnerConnectionPool {
    fn add_connection(&mut self) -> Result<(), PostgresConnectError> {
        PostgresConnection::connect(self.params.clone(), &self.ssl)
            .map(|c| self.pool.push(c))
    }
}

/// A simple fixed-size Postgres connection pool.
///
/// It can be shared across tasks.
///
/// ## Example
///
/// ```rust,no_run
/// # #![allow(deprecated)]
/// # use postgres::NoSsl;
/// # use postgres::pool::PostgresConnectionPool;
/// let pool = PostgresConnectionPool::new("postgres://postgres@localhost",
///                                        NoSsl, 5).unwrap();
/// for _ in range(0u, 10) {
///     let pool = pool.clone();
///     spawn(proc() {
///         let conn = pool.get_connection();
///         conn.execute("UPDATE foo SET bar = 1", []).unwrap();
///     });
/// }
/// ```
#[deriving(Clone)]
pub struct PostgresConnectionPool {
    pool: Arc<Mutex<InnerConnectionPool>>
}

impl PostgresConnectionPool {
    /// Creates a new pool with the specified number of connections.
    ///
    /// Returns an error if the specified number of connections cannot be
    /// created.
    pub fn new<T: IntoConnectParams>(params: T, ssl: SslMode, pool_size: uint)
            -> Result<PostgresConnectionPool, PostgresConnectError> {
        let mut pool = InnerConnectionPool {
            params: try!(params.into_connect_params()),
            ssl: ssl,
            pool: vec![],
        };

        for _ in range(0, pool_size) {
            try!(pool.add_connection());
        }

        Ok(PostgresConnectionPool {
            pool: Arc::new(Mutex::new(pool))
        })
    }

    /// Retrieves a connection from the pool.
    ///
    /// If all connections are in use, blocks until one becomes available.
    pub fn get_connection(&self) -> PooledPostgresConnection {
        let mut pool = self.pool.lock();

        loop {
            match pool.pool.pop() {
                Some(conn) => {
                    return PooledPostgresConnection {
                        pool: self.clone(),
                        conn: Some(conn),
                    };
                }
                None => pool.cond.wait()
            }
        }
    }
}

/// A Postgres connection pulled from a connection pool.
///
/// It will be returned to the pool when it falls out of scope, even due to
/// task failure.
pub struct PooledPostgresConnection {
    pool: PostgresConnectionPool,
    // TODO remove the Option wrapper when drop takes self by value
    conn: Option<PostgresConnection>
}

impl Drop for PooledPostgresConnection {
    fn drop(&mut self) {
        let mut pool = self.pool.pool.lock();
        pool.pool.push(self.conn.take_unwrap());
        pool.cond.signal();
    }
}

impl Deref<PostgresConnection> for PooledPostgresConnection {
    fn deref<'a>(&'a self) -> &'a PostgresConnection {
        self.conn.get_ref()
    }
}
<commit_msg>Allow deprecation in a deprecated module<commit_after>//! A simple connection pool
#![deprecated="Use https://github.com/sfackler/r2d2-postgres instead"]
#![allow(deprecated)]

use std::sync::{Arc, Mutex};

use {PostgresConnectParams, IntoConnectParams, PostgresConnection, SslMode};
use error::PostgresConnectError;

struct InnerConnectionPool {
    params: PostgresConnectParams,
    ssl: SslMode,
    pool: Vec<PostgresConnection>,
}

impl InnerConnectionPool {
    fn add_connection(&mut self) -> Result<(), PostgresConnectError> {
        PostgresConnection::connect(self.params.clone(), &self.ssl)
            .map(|c| self.pool.push(c))
    }
}

/// A simple fixed-size Postgres connection pool.
///
/// It can be shared across tasks.
///
/// ## Example
///
/// ```rust,no_run
/// # #![allow(deprecated)]
/// # use postgres::NoSsl;
/// # use postgres::pool::PostgresConnectionPool;
/// let pool = PostgresConnectionPool::new("postgres://postgres@localhost",
///                                        NoSsl, 5).unwrap();
/// for _ in range(0u, 10) {
///     let pool = pool.clone();
///     spawn(proc() {
///         let conn = pool.get_connection();
///         conn.execute("UPDATE foo SET bar = 1", []).unwrap();
///     });
/// }
/// ```
#[deriving(Clone)]
pub struct PostgresConnectionPool {
    pool: Arc<Mutex<InnerConnectionPool>>
}

impl PostgresConnectionPool {
    /// Creates a new pool with the specified number of connections.
    ///
    /// Returns an error if the specified number of connections cannot be
    /// created.
    pub fn new<T: IntoConnectParams>(params: T, ssl: SslMode, pool_size: uint)
            -> Result<PostgresConnectionPool, PostgresConnectError> {
        let mut pool = InnerConnectionPool {
            params: try!(params.into_connect_params()),
            ssl: ssl,
            pool: vec![],
        };

        for _ in range(0, pool_size) {
            try!(pool.add_connection());
        }

        Ok(PostgresConnectionPool {
            pool: Arc::new(Mutex::new(pool))
        })
    }

    /// Retrieves a connection from the pool.
    ///
    /// If all connections are in use, blocks until one becomes available.
    pub fn get_connection(&self) -> PooledPostgresConnection {
        let mut pool = self.pool.lock();

        loop {
            match pool.pool.pop() {
                Some(conn) => {
                    return PooledPostgresConnection {
                        pool: self.clone(),
                        conn: Some(conn),
                    };
                }
                None => pool.cond.wait()
            }
        }
    }
}

/// A Postgres connection pulled from a connection pool.
///
/// It will be returned to the pool when it falls out of scope, even due to
/// task failure.
pub struct PooledPostgresConnection {
    pool: PostgresConnectionPool,
    // TODO remove the Option wrapper when drop takes self by value
    conn: Option<PostgresConnection>
}

impl Drop for PooledPostgresConnection {
    fn drop(&mut self) {
        let mut pool = self.pool.pool.lock();
        pool.pool.push(self.conn.take_unwrap());
        pool.cond.signal();
    }
}

impl Deref<PostgresConnection> for PooledPostgresConnection {
    fn deref<'a>(&'a self) -> &'a PostgresConnection {
        self.conn.get_ref()
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(plugin, rustc_private, str_char, collections)]

extern crate syntax;
extern crate rustc;

#[macro_use]
extern crate log;

use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::{BufRead, Read};
use std::path::Path;

use syntax::parse;
use syntax::parse::lexer;
use rustc::session::{self, config};
use rustc::middle::cstore::DummyCrateStore;

use std::rc::Rc;
use syntax::ast;
use syntax::ast::Name;
use syntax::codemap;
use syntax::codemap::Pos;
use syntax::parse::token;
use syntax::parse::lexer::TokenAndSpan;

fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
    fn id() -> token::Token {
        token::Ident(ast::Ident::with_empty_ctxt(Name(0)), token::Plain)
    }

    let mut res = HashMap::new();

    res.insert("-1".to_string(), token::Eof);

    for line in file.split('\n') {
        let eq = match line.trim().rfind('=') {
            Some(val) => val,
            None => continue
        };

        let val = &line[..eq];
        let num = &line[eq + 1..];

        let tok = match val {
            "SHR"               => token::BinOp(token::Shr),
            "DOLLAR"            => token::Dollar,
            "LT"                => token::Lt,
            "STAR"              => token::BinOp(token::Star),
            "FLOAT_SUFFIX"      => id(),
            "INT_SUFFIX"        => id(),
            "SHL"               => token::BinOp(token::Shl),
            "LBRACE"            => token::OpenDelim(token::Brace),
            "RARROW"            => token::RArrow,
            "LIT_STR"           => token::Literal(token::Str_(Name(0)), None),
            "DOTDOT"            => token::DotDot,
            "MOD_SEP"           => token::ModSep,
            "DOTDOTDOT"         => token::DotDotDot,
            "NOT"               => token::Not,
            "AND"               => token::BinOp(token::And),
            "LPAREN"            => token::OpenDelim(token::Paren),
            "ANDAND"            => token::AndAnd,
            "AT"                => token::At,
            "LBRACKET"          => token::OpenDelim(token::Bracket),
            "LIT_STR_RAW"       => token::Literal(token::StrRaw(Name(0), 0), None),
            "RPAREN"            => token::CloseDelim(token::Paren),
            "SLASH"             => token::BinOp(token::Slash),
            "COMMA"             => token::Comma,
            "LIFETIME"          => token::Lifetime(ast::Ident::with_empty_ctxt(Name(0))),
            "CARET"             => token::BinOp(token::Caret),
            "TILDE"             => token::Tilde,
            "IDENT"             => id(),
            "PLUS"              => token::BinOp(token::Plus),
            "LIT_CHAR"          => token::Literal(token::Char(Name(0)), None),
            "LIT_BYTE"          => token::Literal(token::Byte(Name(0)), None),
            "EQ"                => token::Eq,
            "RBRACKET"          => token::CloseDelim(token::Bracket),
            "COMMENT"           => token::Comment,
            "DOC_COMMENT"       => token::DocComment(Name(0)),
            "DOT"               => token::Dot,
            "EQEQ"              => token::EqEq,
            "NE"                => token::Ne,
            "GE"                => token::Ge,
            "PERCENT"           => token::BinOp(token::Percent),
            "RBRACE"            => token::CloseDelim(token::Brace),
            "BINOP"             => token::BinOp(token::Plus),
            "POUND"             => token::Pound,
            "OROR"              => token::OrOr,
            "LIT_INTEGER"       => token::Literal(token::Integer(Name(0)), None),
            "BINOPEQ"           => token::BinOpEq(token::Plus),
            "LIT_FLOAT"         => token::Literal(token::Float(Name(0)), None),
            "WHITESPACE"        => token::Whitespace,
            "UNDERSCORE"        => token::Underscore,
            "MINUS"             => token::BinOp(token::Minus),
            "SEMI"              => token::Semi,
            "COLON"             => token::Colon,
            "FAT_ARROW"         => token::FatArrow,
            "OR"                => token::BinOp(token::Or),
            "GT"                => token::Gt,
            "LE"                => token::Le,
            "LIT_BYTE_STR"      => token::Literal(token::ByteStr(Name(0)), None),
            "LIT_BYTE_STR_RAW"  => token::Literal(token::ByteStrRaw(Name(0), 0), None),
            "QUESTION"          => token::Question,
            "SHEBANG"           => token::Shebang(Name(0)),
            _                   => continue,
        };

        res.insert(num.to_string(), tok);
    }

    debug!("Token map: {:?}", res);
    res
}

fn str_to_binop(s: &str) -> token::BinOpToken {
    match s {
        "+"     => token::Plus,
        "/"     => token::Slash,
        "-"     => token::Minus,
        "*"     => token::Star,
        "%"     => token::Percent,
        "^"     => token::Caret,
        "&"     => token::And,
        "|"     => token::Or,
        "<<"    => token::Shl,
        ">>"    => token::Shr,
        _       => panic!("Bad binop str `{}`", s),
    }
}

/// Assuming a string/byte string literal, strip out the leading/trailing
/// hashes and surrounding quotes/raw/byte prefix.
fn fix(mut lit: &str) -> ast::Name {
    if lit.char_at(0) == 'r' {
        if lit.char_at(1) == 'b' {
            lit = &lit[2..]
        } else {
            lit = &lit[1..];
        }
    } else if lit.char_at(0) == 'b' {
        lit = &lit[1..];
    }

    let leading_hashes = count(lit);

    // +1/-1 to adjust for single quotes
    parse::token::intern(&lit[leading_hashes + 1..lit.len() - leading_hashes - 1])
}

/// Assuming a char/byte literal, strip the 'b' prefix and the single quotes.
fn fixchar(mut lit: &str) -> ast::Name {
    if lit.char_at(0) == 'b' {
        lit = &lit[1..];
    }

    parse::token::intern(&lit[1..lit.len() - 1])
}

fn count(lit: &str) -> usize {
    lit.chars().take_while(|c| *c == '#').count()
}

fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>, surrogate_pairs_pos: &[usize],
                     has_bom: bool)
                     -> TokenAndSpan {
    // old regex:
    // \[@(?P<seq>\d+),(?P<start>\d+):(?P<end>\d+)='(?P<content>.+?)',<(?P<toknum>-?\d+)>,\d+:\d+]
    let start = s.find("[@").unwrap();
    let comma = start + s[start..].find(",").unwrap();
    let colon = comma + s[comma..].find(":").unwrap();
    let content_start = colon + s[colon..].find("='").unwrap();
    // Use rfind instead of find, because we don't want to stop at the content
    let content_end = content_start + s[content_start..].rfind("',<").unwrap();
    let toknum_end = content_end + s[content_end..].find(">,").unwrap();

    let start = &s[comma + 1 .. colon];
    let end = &s[colon + 1 .. content_start];
    let content = &s[content_start + 2 .. content_end];
    let toknum = &s[content_end + 3 .. toknum_end];

    let not_found = format!("didn't find token {:?} in the map", toknum);
    let proto_tok = tokens.get(toknum).expect(&not_found[..]);

    let nm = parse::token::intern(content);

    debug!("What we got: content (`{}`), proto: {:?}", content, proto_tok);

    let real_tok = match *proto_tok {
        token::BinOp(..)           => token::BinOp(str_to_binop(content)),
        token::BinOpEq(..)         => token::BinOpEq(str_to_binop(&content[..content.len() - 1])),
        token::Literal(token::Str_(..), n)      => token::Literal(token::Str_(fix(content)), n),
        token::Literal(token::StrRaw(..), n)    => token::Literal(token::StrRaw(fix(content),
                                                                             count(content)), n),
        token::Literal(token::Char(..), n)      => token::Literal(token::Char(fixchar(content)), n),
        token::Literal(token::Byte(..), n)      => token::Literal(token::Byte(fixchar(content)), n),
        token::DocComment(..)      => token::DocComment(nm),
        token::Literal(token::Integer(..), n)   => token::Literal(token::Integer(nm), n),
        token::Literal(token::Float(..), n)     => token::Literal(token::Float(nm), n),
        token::Literal(token::ByteStr(..), n)    => token::Literal(token::ByteStr(nm), n),
        token::Literal(token::ByteStrRaw(..), n) => token::Literal(token::ByteStrRaw(fix(content),
                                                                                count(content)), n),
        token::Ident(..)           => token::Ident(ast::Ident::with_empty_ctxt(nm),
                                                   token::ModName),
        token::Lifetime(..)        => token::Lifetime(ast::Ident::with_empty_ctxt(nm)),
        ref t => t.clone()
    };

    let start_offset = if real_tok == token::Eof {
        1
    } else {
        0
    };

    let offset = if has_bom { 1 } else { 0 };

    let mut lo = start.parse::<u32>().unwrap() - start_offset - offset;
    let mut hi = end.parse::<u32>().unwrap() + 1 - offset;

    // Adjust the span: For each surrogate pair already encountered, subtract one position.
    lo -= surrogate_pairs_pos.binary_search(&(lo as usize)).unwrap_or_else(|x| x) as u32;
    hi -= surrogate_pairs_pos.binary_search(&(hi as usize)).unwrap_or_else(|x| x) as u32;

    let sp = codemap::Span {
        lo: codemap::BytePos(lo),
        hi: codemap::BytePos(hi),
        expn_id: codemap::NO_EXPANSION
    };

    TokenAndSpan {
        tok: real_tok,
        sp: sp
    }
}

fn tok_cmp(a: &token::Token, b: &token::Token) -> bool {
    match a {
        &token::Ident(id, _) => match b {
                &token::Ident(id2, _) => id == id2,
                _ => false
        },
        _ => a == b
    }
}

fn span_cmp(antlr_sp: codemap::Span, rust_sp: codemap::Span, cm: &codemap::CodeMap) -> bool {
    antlr_sp.expn_id == rust_sp.expn_id &&
        antlr_sp.lo.to_usize() == cm.bytepos_to_file_charpos(rust_sp.lo).to_usize() &&
        antlr_sp.hi.to_usize() == cm.bytepos_to_file_charpos(rust_sp.hi).to_usize()
}

fn main() {
    fn next(r: &mut lexer::StringReader) -> TokenAndSpan {
        use syntax::parse::lexer::Reader;
        r.next_token()
    }

    let mut args = env::args().skip(1);
    let filename = args.next().unwrap();
    if filename.find("parse-fail").is_some() {
        return;
    }

    // Rust's lexer
    let mut code = String::new();
    File::open(&Path::new(&filename)).unwrap().read_to_string(&mut code).unwrap();

    let surrogate_pairs_pos: Vec<usize> = code.chars().enumerate()
                                                     .filter(|&(_, c)| c as usize > 0xFFFF)
                                                     .map(|(n, _)| n)
                                                     .enumerate()
                                                     .map(|(x, n)| x + n)
                                                     .collect();

    let has_bom = code.starts_with("\u{feff}");

    debug!("Pairs: {:?}", surrogate_pairs_pos);

    let options = config::basic_options();
    let session = session::build_session(options, None,
                                         syntax::diagnostics::registry::Registry::new(&[]),
                                         Rc::new(DummyCrateStore));
    let filemap = session.parse_sess.codemap().new_filemap(String::from("<n/a>"), code);
    let mut lexer = lexer::StringReader::new(session.diagnostic(), filemap);
    let cm = session.codemap();

    // ANTLR
    let mut token_file = File::open(&Path::new(&args.next().unwrap())).unwrap();
    let mut token_list = String::new();
    token_file.read_to_string(&mut token_list).unwrap();
    let token_map = parse_token_list(&token_list[..]);

    let stdin = std::io::stdin();
    let lock = stdin.lock();
    let lines = lock.lines();
    let antlr_tokens = lines.map(|l| parse_antlr_token(l.unwrap().trim(),
                                                       &token_map,
                                                       &surrogate_pairs_pos[..],
                                                       has_bom));

    for antlr_tok in antlr_tokens {
        let rustc_tok = next(&mut lexer);
        if rustc_tok.tok == token::Eof && antlr_tok.tok == token::Eof {
            continue
        }

        assert!(span_cmp(antlr_tok.sp, rustc_tok.sp, cm), "{:?} and {:?} have different spans",
                rustc_tok,
                antlr_tok);

        macro_rules! matches {
            ( $($x:pat),+ ) => (
                match rustc_tok.tok {
                    $($x => match antlr_tok.tok {
                        $x => {
                            if !tok_cmp(&rustc_tok.tok, &antlr_tok.tok) {
                                // FIXME #15677: needs more robust escaping in
                                // antlr
                                warn!("Different names for {:?} and {:?}", rustc_tok, antlr_tok);
                            }
                        }
                        _ => panic!("{:?} is not {:?}", antlr_tok, rustc_tok)
                    },)*
                    ref c => assert!(c == &antlr_tok.tok, "{:?} is not {:?}", antlr_tok, rustc_tok)
                }
            )
        }

        matches!(
            token::Literal(token::Byte(..), _),
            token::Literal(token::Char(..), _),
            token::Literal(token::Integer(..), _),
            token::Literal(token::Float(..), _),
            token::Literal(token::Str_(..), _),
            token::Literal(token::StrRaw(..), _),
            token::Literal(token::ByteStr(..), _),
            token::Literal(token::ByteStrRaw(..), _),
            token::Ident(..),
            token::Lifetime(..),
            token::Interpolated(..),
            token::DocComment(..),
            token::Shebang(..)
        );
    }
}
<commit_msg>antlr grammar verification script now compiles under latest nightly<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(plugin, rustc_private)]

extern crate syntax;
extern crate rustc;

#[macro_use]
extern crate log;

use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io::{BufRead, Read};
use std::path::Path;

use syntax::parse;
use syntax::parse::lexer;
use rustc::dep_graph::DepGraph;
use rustc::session::{self, config};
use rustc::middle::cstore::DummyCrateStore;

use std::rc::Rc;
use syntax::ast;
use syntax::ast::Name;
use syntax::codemap;
use syntax::codemap::Pos;
use syntax::parse::token::{self, BinOpToken, DelimToken, Lit, Token};
use syntax::parse::lexer::TokenAndSpan;

fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
    fn id() -> token::Token {
        Token::Ident(ast::Ident::with_empty_ctxt(Name(0)))
    }

    let mut res = HashMap::new();

    res.insert("-1".to_string(), Token::Eof);

    for line in file.split('\n') {
        let eq = match line.trim().rfind('=') {
            Some(val) => val,
            None => continue
        };

        let val = &line[..eq];
        let num = &line[eq + 1..];

        let tok = match val {
            "SHR"               => Token::BinOp(BinOpToken::Shr),
            "DOLLAR"            => Token::Dollar,
            "LT"                => Token::Lt,
            "STAR"              => Token::BinOp(BinOpToken::Star),
            "FLOAT_SUFFIX"      => id(),
            "INT_SUFFIX"        => id(),
            "SHL"               => Token::BinOp(BinOpToken::Shl),
            "LBRACE"            => Token::OpenDelim(DelimToken::Brace),
            "RARROW"            => Token::RArrow,
            "LIT_STR"           => Token::Literal(Lit::Str_(Name(0)), None),
            "DOTDOT"            => Token::DotDot,
            "MOD_SEP"           => Token::ModSep,
            "DOTDOTDOT"         => Token::DotDotDot,
            "NOT"               => Token::Not,
            "AND"               => Token::BinOp(BinOpToken::And),
            "LPAREN"            => Token::OpenDelim(DelimToken::Paren),
            "ANDAND"            => Token::AndAnd,
            "AT"                => Token::At,
            "LBRACKET"          => Token::OpenDelim(DelimToken::Bracket),
            "LIT_STR_RAW"       => Token::Literal(Lit::StrRaw(Name(0), 0), None),
            "RPAREN"            => Token::CloseDelim(DelimToken::Paren),
            "SLASH"             => Token::BinOp(BinOpToken::Slash),
            "COMMA"             => Token::Comma,
            "LIFETIME"          => Token::Lifetime(ast::Ident::with_empty_ctxt(Name(0))),
            "CARET"             => Token::BinOp(BinOpToken::Caret),
            "TILDE"             => Token::Tilde,
            "IDENT"             => id(),
            "PLUS"              => Token::BinOp(BinOpToken::Plus),
            "LIT_CHAR"          => Token::Literal(Lit::Char(Name(0)), None),
            "LIT_BYTE"          => Token::Literal(Lit::Byte(Name(0)), None),
            "EQ"                => Token::Eq,
            "RBRACKET"          => Token::CloseDelim(DelimToken::Bracket),
            "COMMENT"           => Token::Comment,
            "DOC_COMMENT"       => Token::DocComment(Name(0)),
            "DOT"               => Token::Dot,
            "EQEQ"              => Token::EqEq,
            "NE"                => Token::Ne,
            "GE"                => Token::Ge,
            "PERCENT"           => Token::BinOp(BinOpToken::Percent),
            "RBRACE"            => Token::CloseDelim(DelimToken::Brace),
            "BINOP"             => Token::BinOp(BinOpToken::Plus),
            "POUND"             => Token::Pound,
            "OROR"              => Token::OrOr,
            "LIT_INTEGER"       => Token::Literal(Lit::Integer(Name(0)), None),
            "BINOPEQ"           => Token::BinOpEq(BinOpToken::Plus),
            "LIT_FLOAT"         => Token::Literal(Lit::Float(Name(0)), None),
            "WHITESPACE"        => Token::Whitespace,
            "UNDERSCORE"        => Token::Underscore,
            "MINUS"             => Token::BinOp(BinOpToken::Minus),
            "SEMI"              => Token::Semi,
            "COLON"             => Token::Colon,
            "FAT_ARROW"         => Token::FatArrow,
            "OR"                => Token::BinOp(BinOpToken::Or),
            "GT"                => Token::Gt,
            "LE"                => Token::Le,
            "LIT_BINARY"        => Token::Literal(Lit::ByteStr(Name(0)), None),
            "LIT_BINARY_RAW"    => Token::Literal(Lit::ByteStrRaw(Name(0), 0), None),
            "QUESTION"          => Token::Question,
            "SHEBANG"           => Token::Shebang(Name(0)),
            _                   => continue,
        };

        res.insert(num.to_string(), tok);
    }

    debug!("Token map: {:?}", res);
    res
}

fn str_to_binop(s: &str) -> token::BinOpToken {
    match s {
        "+"     => BinOpToken::Plus,
        "/"     => BinOpToken::Slash,
        "-"     => BinOpToken::Minus,
        "*"     => BinOpToken::Star,
        "%"     => BinOpToken::Percent,
        "^"     => BinOpToken::Caret,
        "&"     => BinOpToken::And,
        "|"     => BinOpToken::Or,
        "<<"    => BinOpToken::Shl,
        ">>"    => BinOpToken::Shr,
        _       => panic!("Bad binop str `{}`", s),
    }
}

/// Assuming a string/byte string literal, strip out the leading/trailing
/// hashes and surrounding quotes/raw/byte prefix.
fn fix(mut lit: &str) -> ast::Name {
    let prefix: Vec<char> = lit.chars().take(2).collect();
    if prefix[0] == 'r' {
        if prefix[1] == 'b' {
            lit = &lit[2..]
        } else {
            lit = &lit[1..];
        }
    } else if prefix[0] == 'b' {
        lit = &lit[1..];
    }

    let leading_hashes = count(lit);

    // +1/-1 to adjust for single quotes
    parse::token::intern(&lit[leading_hashes + 1..lit.len() - leading_hashes - 1])
}

/// Assuming a char/byte literal, strip the 'b' prefix and the single quotes.
fn fixchar(mut lit: &str) -> ast::Name {
    let prefix = lit.chars().next().unwrap();
    if prefix == 'b' {
        lit = &lit[1..];
    }

    parse::token::intern(&lit[1..lit.len() - 1])
}

fn count(lit: &str) -> usize {
    lit.chars().take_while(|c| *c == '#').count()
}

fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>, surrogate_pairs_pos: &[usize],
                     has_bom: bool)
                     -> TokenAndSpan {
    // old regex:
    // \[@(?P<seq>\d+),(?P<start>\d+):(?P<end>\d+)='(?P<content>.+?)',<(?P<toknum>-?\d+)>,\d+:\d+]
    let start = s.find("[@").unwrap();
    let comma = start + s[start..].find(",").unwrap();
    let colon = comma + s[comma..].find(":").unwrap();
    let content_start = colon + s[colon..].find("='").unwrap();
    // Use rfind instead of find, because we don't want to stop at the content
    let content_end = content_start + s[content_start..].rfind("',<").unwrap();
    let toknum_end = content_end + s[content_end..].find(">,").unwrap();

    let start = &s[comma + 1 .. colon];
    let end = &s[colon + 1 .. content_start];
    let content = &s[content_start + 2 .. content_end];
    let toknum = &s[content_end + 3 .. toknum_end];

    let not_found = format!("didn't find token {:?} in the map", toknum);
    let proto_tok = tokens.get(toknum).expect(&not_found[..]);

    let nm = parse::token::intern(content);

    debug!("What we got: content (`{}`), proto: {:?}", content, proto_tok);

    let real_tok = match *proto_tok {
        Token::BinOp(..)           => Token::BinOp(str_to_binop(content)),
        Token::BinOpEq(..)         => Token::BinOpEq(str_to_binop(&content[..content.len() - 1])),
        Token::Literal(Lit::Str_(..), n)      => Token::Literal(Lit::Str_(fix(content)), n),
        Token::Literal(Lit::StrRaw(..), n)    => Token::Literal(Lit::StrRaw(fix(content),
                                                                             count(content)), n),
        Token::Literal(Lit::Char(..), n)      => Token::Literal(Lit::Char(fixchar(content)), n),
        Token::Literal(Lit::Byte(..), n)      => Token::Literal(Lit::Byte(fixchar(content)), n),
        Token::DocComment(..)      => Token::DocComment(nm),
        Token::Literal(Lit::Integer(..), n)   => Token::Literal(Lit::Integer(nm), n),
        Token::Literal(Lit::Float(..), n)     => Token::Literal(Lit::Float(nm), n),
        Token::Literal(Lit::ByteStr(..), n)    => Token::Literal(Lit::ByteStr(nm), n),
        Token::Literal(Lit::ByteStrRaw(..), n) => Token::Literal(Lit::ByteStrRaw(fix(content),
                                                                                count(content)), n),
        Token::Ident(..)           => Token::Ident(ast::Ident::with_empty_ctxt(nm)),
        Token::Lifetime(..)        => Token::Lifetime(ast::Ident::with_empty_ctxt(nm)),
        ref t => t.clone()
    };

    let start_offset = if real_tok == Token::Eof {
        1
    } else {
        0
    };

    let offset = if has_bom { 1 } else { 0 };

    let mut lo = start.parse::<u32>().unwrap() - start_offset - offset;
    let mut hi = end.parse::<u32>().unwrap() + 1 - offset;

    // Adjust the span: For each surrogate pair already encountered, subtract one position.
    lo -= surrogate_pairs_pos.binary_search(&(lo as usize)).unwrap_or_else(|x| x) as u32;
    hi -= surrogate_pairs_pos.binary_search(&(hi as usize)).unwrap_or_else(|x| x) as u32;

    let sp = codemap::Span {
        lo: codemap::BytePos(lo),
        hi: codemap::BytePos(hi),
        expn_id: codemap::NO_EXPANSION
    };

    TokenAndSpan {
        tok: real_tok,
        sp: sp
    }
}

fn tok_cmp(a: &token::Token, b: &token::Token) -> bool {
    match a {
        &Token::Ident(id) => match b {
                &Token::Ident(id2) => id == id2,
                _ => false
        },
        _ => a == b
    }
}

fn span_cmp(antlr_sp: codemap::Span, rust_sp: codemap::Span, cm: &codemap::CodeMap) -> bool {
    antlr_sp.expn_id == rust_sp.expn_id &&
        antlr_sp.lo.to_usize() == cm.bytepos_to_file_charpos(rust_sp.lo).to_usize() &&
        antlr_sp.hi.to_usize() == cm.bytepos_to_file_charpos(rust_sp.hi).to_usize()
}

fn main() {
    fn next(r: &mut lexer::StringReader) -> TokenAndSpan {
        use syntax::parse::lexer::Reader;
        r.next_token()
    }

    let mut args = env::args().skip(1);
    let filename = args.next().unwrap();
    if filename.find("parse-fail").is_some() {
        return;
    }

    // Rust's lexer
    let mut code = String::new();
    File::open(&Path::new(&filename)).unwrap().read_to_string(&mut code).unwrap();

    let surrogate_pairs_pos: Vec<usize> = code.chars().enumerate()
                                                     .filter(|&(_, c)| c as usize > 0xFFFF)
                                                     .map(|(n, _)| n)
                                                     .enumerate()
                                                     .map(|(x, n)| x + n)
                                                     .collect();

    let has_bom = code.starts_with("\u{feff}");

    debug!("Pairs: {:?}", surrogate_pairs_pos);

    let options = config::basic_options();
    let session = session::build_session(options, &DepGraph::new(false), None,
                                         syntax::diagnostics::registry::Registry::new(&[]),
                                         Rc::new(DummyCrateStore));
    let filemap = session.parse_sess.codemap().new_filemap(String::from("<n/a>"), code);
    let mut lexer = lexer::StringReader::new(session.diagnostic(), filemap);
    let cm = session.codemap();

    // ANTLR
    let mut token_file = File::open(&Path::new(&args.next().unwrap())).unwrap();
    let mut token_list = String::new();
    token_file.read_to_string(&mut token_list).unwrap();
    let token_map = parse_token_list(&token_list[..]);

    let stdin = std::io::stdin();
    let lock = stdin.lock();
    let lines = lock.lines();
    let antlr_tokens = lines.map(|l| parse_antlr_token(l.unwrap().trim(),
                                                       &token_map,
                                                       &surrogate_pairs_pos[..],
                                                       has_bom));

    for antlr_tok in antlr_tokens {
        let rustc_tok = next(&mut lexer);
        if rustc_tok.tok == Token::Eof && antlr_tok.tok == Token::Eof {
            continue
        }

        assert!(span_cmp(antlr_tok.sp, rustc_tok.sp, cm), "{:?} and {:?} have different spans",
                rustc_tok,
                antlr_tok);

        macro_rules! matches {
            ( $($x:pat),+ ) => (
                match rustc_tok.tok {
                    $($x => match antlr_tok.tok {
                        $x => {
                            if !tok_cmp(&rustc_tok.tok, &antlr_tok.tok) {
                                // FIXME #15677: needs more robust escaping in
                                // antlr
                                warn!("Different names for {:?} and {:?}", rustc_tok, antlr_tok);
                            }
                        }
                        _ => panic!("{:?} is not {:?}", antlr_tok, rustc_tok)
                    },)*
                    ref c => assert!(c == &antlr_tok.tok, "{:?} is not {:?}", antlr_tok, rustc_tok)
                }
            )
        }

        matches!(
            Token::Literal(Lit::Byte(..), _),
            Token::Literal(Lit::Char(..), _),
            Token::Literal(Lit::Integer(..), _),
            Token::Literal(Lit::Float(..), _),
            Token::Literal(Lit::Str_(..), _),
            Token::Literal(Lit::StrRaw(..), _),
            Token::Literal(Lit::ByteStr(..), _),
            Token::Literal(Lit::ByteStrRaw(..), _),
            Token::Ident(..),
            Token::Lifetime(..),
            Token::Interpolated(..),
            Token::DocComment(..),
            Token::Shebang(..)
        );
    }
}
<|endoftext|>


<commit_before>
use constants::*;
use utils::*;
use crypto_types::*;
use cipherstate::*;
use symmetricstate::*;
use patterns::*;

pub const MAXMSGLEN : usize = 65535;

#[derive(Debug)]
pub enum NoiseError {DecryptError}

pub struct HandshakeState<'a> {
    rng : &'a mut RandomType,                    /* for generating ephemerals */
    symmetricstate : &'a mut SymmetricStateType, /* for handshaking */
    cipherstate1: &'a mut CipherStateType,       /* for I->R transport msgs */
    cipherstate2: &'a mut CipherStateType,       /* for I<-R transport msgs */
    s: &'a DhType,
    e: &'a mut DhType,
    rs: &'a mut [u8],
    re: &'a mut [u8],
    has_s: bool,
    has_e: bool,
    has_rs: bool,
    has_re: bool,
    my_turn_to_send : bool,
    message_patterns : [[Token; 10]; 10],
    message_index: usize,
}

impl<'a> HandshakeState<'a> {

    pub fn new(rng: &'a mut RandomType,
               symmetricstate: &'a mut SymmetricStateType,
               cipherstate1: &'a mut CipherStateType,
               cipherstate2: &'a mut CipherStateType,
               s : &'a DhType,
               e : &'a mut DhType,
               rs: &'a mut [u8],
               re: &'a mut [u8],
               has_s: bool,
               has_e: bool,
               has_rs: bool,
               has_re: bool,
               initiator: bool,
               handshake_pattern: HandshakePattern,
               prologue: &[u8],
               optional_preshared_key: Option<&[u8]>) -> HandshakeState<'a> {
        let mut handshake_name = [0u8; 128];
        let mut name_len: usize;
        let mut premsg_pattern_i = [Token::Empty; 2];
        let mut premsg_pattern_r = [Token::Empty; 2];
        let mut message_patterns = [[Token::Empty; 10]; 10];

        if let Some(_) = optional_preshared_key {
            copy_memory("NoisePSK_".as_bytes(), &mut handshake_name);
            name_len = 9;
        } else {
            copy_memory("Noise_".as_bytes(), &mut handshake_name);
            name_len = 6;
        }
        name_len += resolve_handshake_pattern(handshake_pattern,
                                              &mut handshake_name[name_len..],
                                              &mut premsg_pattern_i,
                                              &mut premsg_pattern_r,
                                              &mut message_patterns);
        handshake_name[name_len] = '_' as u8;
        name_len += 1;
        name_len += s.name(&mut handshake_name[name_len..]);
        handshake_name[name_len] = '_' as u8;
        name_len += 1;
        name_len += symmetricstate.cipher_name(&mut handshake_name[name_len..]);
        handshake_name[name_len] = '_' as u8;
        name_len += 1;
        name_len += symmetricstate.hash_name(&mut handshake_name[name_len..]);

        symmetricstate.initialize(&handshake_name[..name_len]);
        symmetricstate.mix_hash(prologue);

        if let Some(preshared_key) = optional_preshared_key {
            symmetricstate.mix_preshared_key(preshared_key);
        }

        if initiator {
            for token in &premsg_pattern_i {
                match *token {
                    Token::S => {assert!(has_s); symmetricstate.mix_hash(s.pubkey());},
                    Token::E => {assert!(has_e); symmetricstate.mix_hash(e.pubkey());},
                    Token::Empty => break,
                    _ => unreachable!()
                }
            }
            for token in &premsg_pattern_r {
                match *token {
                    Token::S => {assert!(has_rs); symmetricstate.mix_hash(rs);},
                    Token::E => {assert!(has_re); symmetricstate.mix_hash(re);},
                    Token::Empty => break,
                    _ => unreachable!()
                }
            }
        } else {
            for token in &premsg_pattern_i {
                match *token {
                    Token::S => {assert!(has_rs); symmetricstate.mix_hash(rs);},
                    Token::E => {assert!(has_re); symmetricstate.mix_hash(re);},
                    Token::Empty => break,
                    _ => unreachable!()
                }
            }
            for token in &premsg_pattern_r {
                match *token {
                    Token::S => {assert!(has_s); symmetricstate.mix_hash(s.pubkey());},
                    Token::E => {assert!(has_e); symmetricstate.mix_hash(e.pubkey());},
                    Token::Empty => break,
                    _ => unreachable!()
                }
            }
        }

        HandshakeState{
            rng: rng,
            symmetricstate: symmetricstate,
            cipherstate1: cipherstate1,
            cipherstate2: cipherstate2,
            s: s,
            e: e,
            rs: rs,
            re: re,
            has_s: has_s,
            has_e: has_e,
            has_rs: has_rs,
            has_re: has_re,
            my_turn_to_send: initiator,
            message_patterns: message_patterns,
            message_index: 0,
            }
    }

    fn dh_len(&self) -> usize {
        self.s.pub_len()
    }

    fn dh(&mut self, local_s: bool, remote_s: bool) {
        assert!(!local_s || self.has_s);
        assert!(local_s || self.has_e);
        assert!(!remote_s || self.has_rs);
        assert!(remote_s || self.has_re);

        let dh_len = self.dh_len();
        let mut dh_out = [0u8; MAXDHLEN];
        if local_s && remote_s {
            self.s.dh(self.rs, &mut dh_out);
        }
        if local_s && !remote_s {
            self.s.dh(self.re, &mut dh_out);
        }
        if !local_s && remote_s {
            self.e.dh(self.rs, &mut dh_out);
        }
        if !local_s && !remote_s {
            self.e.dh(self.re, &mut dh_out);
        }
        self.symmetricstate.mix_key(&dh_out[..dh_len]);
    }

    pub fn write_message(&mut self,
                         payload: &[u8],
                         message: &mut [u8]) -> (usize, bool) {
        assert!(self.my_turn_to_send);
        let tokens = self.message_patterns[self.message_index];
        let mut last = false;
        if let Token::Empty = self.message_patterns[self.message_index+1][0] {
            last = true;
        }
        self.message_index += 1;

        let mut byte_index = 0;
        for token in &tokens {
            match *token {
                Token::E => {
                    self.e.generate(self.rng);
                    let pubkey = self.e.pubkey();
                    copy_memory(pubkey, &mut message[byte_index..]);
                    byte_index += self.s.pub_len();
                    self.symmetricstate.mix_hash(&pubkey);
                    if self.symmetricstate.has_preshared_key() {
                        self.symmetricstate.mix_key(&pubkey);
                    }
                    self.has_e = true;
                },
                Token::S => {
                    assert!(self.has_s);
                    byte_index += self.symmetricstate.encrypt_and_hash(
                                        &self.s.pubkey(),
                                        &mut message[byte_index..]);
                },
                Token::Dhee => self.dh(false, false),
                Token::Dhes => self.dh(false, true),
                Token::Dhse => self.dh(true, false),
                Token::Dhss => self.dh(true, true),
                Token::Empty => break
            }
        }
        self.my_turn_to_send = false;
        byte_index += self.symmetricstate.encrypt_and_hash(payload, &mut message[byte_index..]);
        assert!(byte_index <= MAXMSGLEN);
        if last {
            self.symmetricstate.split(self.cipherstate1, self.cipherstate2);
        }
        (byte_index, last)
    }

    pub fn read_message(&mut self,
                        message: &[u8],
                        payload: &mut [u8]) -> Result<(usize, bool), NoiseError> {
        assert!(self.my_turn_to_send == false);
        assert!(message.len() <= MAXMSGLEN);

        let tokens = self.message_patterns[self.message_index];
        let mut last = false;
        if let Token::Empty = self.message_patterns[self.message_index+1][0] {
            last = true;
        }
        self.message_index += 1;

        let mut ptr = message;
        for token in &tokens {
            match *token {
                Token::E => {
                    copy_memory(&ptr[..self.dh_len()], self.re);
                    ptr = &ptr[self.dh_len()..];
                    self.symmetricstate.mix_hash(self.re);
                    if self.symmetricstate.has_preshared_key() {
                        self.symmetricstate.mix_key(self.re);
                    }
                    self.has_re = true;
                },
                Token::S => {
                    let data = if self.symmetricstate.has_key() {
                        let temp = &ptr[..self.dh_len() + TAGLEN];
                        ptr = &ptr[self.dh_len() + TAGLEN..];
                        temp
                    } else {
                        let temp = &ptr[..self.dh_len()];
                        ptr = &ptr[self.dh_len()..];
                        temp
                    };
                    if !self.symmetricstate.decrypt_and_hash(data, self.rs) {
                        return Err(NoiseError::DecryptError);
                    }
                    self.has_rs = true;
                },
                Token::Dhee => self.dh(false, false),
                Token::Dhes => self.dh(true, false),
                Token::Dhse => self.dh(false, true),
                Token::Dhss => self.dh(true, true),
                Token::Empty => break
            }
        }
        if !self.symmetricstate.decrypt_and_hash(ptr, payload) {
            return Err(NoiseError::DecryptError);
        }
        self.my_turn_to_send = true;
        if last {
            self.symmetricstate.split(self.cipherstate1, self.cipherstate2);
        }
        let payload_len = if self.symmetricstate.has_key() { ptr.len() - TAGLEN } else { ptr.len() };
        Ok((payload_len, last))
    }

}

<commit_msg>Check trait objects point to consistent objects.<commit_after>
use constants::*;
use utils::*;
use crypto_types::*;
use cipherstate::*;
use symmetricstate::*;
use patterns::*;

pub const MAXMSGLEN : usize = 65535;

#[derive(Debug)]
pub enum NoiseError {DecryptError}

pub struct HandshakeState<'a> {
    rng : &'a mut RandomType,                    /* for generating ephemerals */
    symmetricstate : &'a mut SymmetricStateType, /* for handshaking */
    cipherstate1: &'a mut CipherStateType,       /* for I->R transport msgs */
    cipherstate2: &'a mut CipherStateType,       /* for I<-R transport msgs */
    s: &'a DhType,
    e: &'a mut DhType,
    rs: &'a mut [u8],
    re: &'a mut [u8],
    has_s: bool,
    has_e: bool,
    has_rs: bool,
    has_re: bool,
    my_turn_to_send : bool,
    message_patterns : [[Token; 10]; 10],
    message_index: usize,
}

impl<'a> HandshakeState<'a> {

    pub fn new(rng: &'a mut RandomType,
               symmetricstate: &'a mut SymmetricStateType,
               cipherstate1: &'a mut CipherStateType,
               cipherstate2: &'a mut CipherStateType,
               s : &'a DhType,
               e : &'a mut DhType,
               rs: &'a mut [u8],
               re: &'a mut [u8],
               has_s: bool,
               has_e: bool,
               has_rs: bool,
               has_re: bool,
               initiator: bool,
               handshake_pattern: HandshakePattern,
               prologue: &[u8],
               optional_preshared_key: Option<&[u8]>) -> HandshakeState<'a> {
        let mut handshake_name = [0u8; 128];
        let mut name_len: usize;
        let mut premsg_pattern_i = [Token::Empty; 2];
        let mut premsg_pattern_r = [Token::Empty; 2];
        let mut message_patterns = [[Token::Empty; 10]; 10];

        // Check that trait objects are pointing to consistent types
        // (same cipher, same DH) by looking at names
        {
            let mut test_name1 = [0u8; 32];
            let mut test_name2 = [0u8; 32];

            test_name1 = [0u8; 32];
            test_name2 = [0u8; 32];
            assert!(symmetricstate.cipher_name(&mut test_name1) < 32);
            cipherstate1.name(&mut test_name2);
            assert!(test_name1 == test_name2);
            cipherstate2.name(&mut test_name2);
            assert!(test_name1 == test_name2);

            test_name1 = [0u8; 32];
            test_name2 = [0u8; 32];
            assert!(s.name(&mut test_name1) < 32);
            e.name(&mut test_name2);
            assert!(test_name1 == test_name2);
        }

        if let Some(_) = optional_preshared_key {
            copy_memory("NoisePSK_".as_bytes(), &mut handshake_name);
            name_len = 9;
        } else {
            copy_memory("Noise_".as_bytes(), &mut handshake_name);
            name_len = 6;
        }
        name_len += resolve_handshake_pattern(handshake_pattern,
                                              &mut handshake_name[name_len..],
                                              &mut premsg_pattern_i,
                                              &mut premsg_pattern_r,
                                              &mut message_patterns);
        handshake_name[name_len] = '_' as u8;
        name_len += 1;
        name_len += s.name(&mut handshake_name[name_len..]);
        handshake_name[name_len] = '_' as u8;
        name_len += 1;
        name_len += symmetricstate.cipher_name(&mut handshake_name[name_len..]);
        handshake_name[name_len] = '_' as u8;
        name_len += 1;
        name_len += symmetricstate.hash_name(&mut handshake_name[name_len..]);

        symmetricstate.initialize(&handshake_name[..name_len]);
        symmetricstate.mix_hash(prologue);

        if let Some(preshared_key) = optional_preshared_key {
            symmetricstate.mix_preshared_key(preshared_key);
        }

        if initiator {
            for token in &premsg_pattern_i {
                match *token {
                    Token::S => {assert!(has_s); symmetricstate.mix_hash(s.pubkey());},
                    Token::E => {assert!(has_e); symmetricstate.mix_hash(e.pubkey());},
                    Token::Empty => break,
                    _ => unreachable!()
                }
            }
            for token in &premsg_pattern_r {
                match *token {
                    Token::S => {assert!(has_rs); symmetricstate.mix_hash(rs);},
                    Token::E => {assert!(has_re); symmetricstate.mix_hash(re);},
                    Token::Empty => break,
                    _ => unreachable!()
                }
            }
        } else {
            for token in &premsg_pattern_i {
                match *token {
                    Token::S => {assert!(has_rs); symmetricstate.mix_hash(rs);},
                    Token::E => {assert!(has_re); symmetricstate.mix_hash(re);},
                    Token::Empty => break,
                    _ => unreachable!()
                }
            }
            for token in &premsg_pattern_r {
                match *token {
                    Token::S => {assert!(has_s); symmetricstate.mix_hash(s.pubkey());},
                    Token::E => {assert!(has_e); symmetricstate.mix_hash(e.pubkey());},
                    Token::Empty => break,
                    _ => unreachable!()
                }
            }
        }

        HandshakeState{
            rng: rng,
            symmetricstate: symmetricstate,
            cipherstate1: cipherstate1,
            cipherstate2: cipherstate2,
            s: s,
            e: e,
            rs: rs,
            re: re,
            has_s: has_s,
            has_e: has_e,
            has_rs: has_rs,
            has_re: has_re,
            my_turn_to_send: initiator,
            message_patterns: message_patterns,
            message_index: 0,
            }
    }

    fn dh_len(&self) -> usize {
        self.s.pub_len()
    }

    fn dh(&mut self, local_s: bool, remote_s: bool) {
        assert!(!local_s || self.has_s);
        assert!(local_s || self.has_e);
        assert!(!remote_s || self.has_rs);
        assert!(remote_s || self.has_re);

        let dh_len = self.dh_len();
        let mut dh_out = [0u8; MAXDHLEN];
        if local_s && remote_s {
            self.s.dh(self.rs, &mut dh_out);
        }
        if local_s && !remote_s {
            self.s.dh(self.re, &mut dh_out);
        }
        if !local_s && remote_s {
            self.e.dh(self.rs, &mut dh_out);
        }
        if !local_s && !remote_s {
            self.e.dh(self.re, &mut dh_out);
        }
        self.symmetricstate.mix_key(&dh_out[..dh_len]);
    }

    pub fn write_message(&mut self,
                         payload: &[u8],
                         message: &mut [u8]) -> (usize, bool) {
        assert!(self.my_turn_to_send);
        let tokens = self.message_patterns[self.message_index];
        let mut last = false;
        if let Token::Empty = self.message_patterns[self.message_index+1][0] {
            last = true;
        }
        self.message_index += 1;

        let mut byte_index = 0;
        for token in &tokens {
            match *token {
                Token::E => {
                    self.e.generate(self.rng);
                    let pubkey = self.e.pubkey();
                    copy_memory(pubkey, &mut message[byte_index..]);
                    byte_index += self.s.pub_len();
                    self.symmetricstate.mix_hash(&pubkey);
                    if self.symmetricstate.has_preshared_key() {
                        self.symmetricstate.mix_key(&pubkey);
                    }
                    self.has_e = true;
                },
                Token::S => {
                    assert!(self.has_s);
                    byte_index += self.symmetricstate.encrypt_and_hash(
                                        &self.s.pubkey(),
                                        &mut message[byte_index..]);
                },
                Token::Dhee => self.dh(false, false),
                Token::Dhes => self.dh(false, true),
                Token::Dhse => self.dh(true, false),
                Token::Dhss => self.dh(true, true),
                Token::Empty => break
            }
        }
        self.my_turn_to_send = false;
        byte_index += self.symmetricstate.encrypt_and_hash(payload, &mut message[byte_index..]);
        assert!(byte_index <= MAXMSGLEN);
        if last {
            self.symmetricstate.split(self.cipherstate1, self.cipherstate2);
        }
        (byte_index, last)
    }

    pub fn read_message(&mut self,
                        message: &[u8],
                        payload: &mut [u8]) -> Result<(usize, bool), NoiseError> {
        assert!(self.my_turn_to_send == false);
        assert!(message.len() <= MAXMSGLEN);

        let tokens = self.message_patterns[self.message_index];
        let mut last = false;
        if let Token::Empty = self.message_patterns[self.message_index+1][0] {
            last = true;
        }
        self.message_index += 1;

        let mut ptr = message;
        for token in &tokens {
            match *token {
                Token::E => {
                    copy_memory(&ptr[..self.dh_len()], self.re);
                    ptr = &ptr[self.dh_len()..];
                    self.symmetricstate.mix_hash(self.re);
                    if self.symmetricstate.has_preshared_key() {
                        self.symmetricstate.mix_key(self.re);
                    }
                    self.has_re = true;
                },
                Token::S => {
                    let data = if self.symmetricstate.has_key() {
                        let temp = &ptr[..self.dh_len() + TAGLEN];
                        ptr = &ptr[self.dh_len() + TAGLEN..];
                        temp
                    } else {
                        let temp = &ptr[..self.dh_len()];
                        ptr = &ptr[self.dh_len()..];
                        temp
                    };
                    if !self.symmetricstate.decrypt_and_hash(data, self.rs) {
                        return Err(NoiseError::DecryptError);
                    }
                    self.has_rs = true;
                },
                Token::Dhee => self.dh(false, false),
                Token::Dhes => self.dh(true, false),
                Token::Dhse => self.dh(false, true),
                Token::Dhss => self.dh(true, true),
                Token::Empty => break
            }
        }
        if !self.symmetricstate.decrypt_and_hash(ptr, payload) {
            return Err(NoiseError::DecryptError);
        }
        self.my_turn_to_send = true;
        if last {
            self.symmetricstate.split(self.cipherstate1, self.cipherstate2);
        }
        let payload_len = if self.symmetricstate.has_key() { ptr.len() - TAGLEN } else { ptr.len() };
        Ok((payload_len, last))
    }

}

<|endoftext|>


<commit_before>use std::time::SystemTime;

const PI: f64 = 3.141592654;
pub const RAND_MAX: u32 = 32767;

pub enum Rand {
    Basic(u32),
    PMrand(u32, u32),
    Gauss(u32, u32),
	// BMgauss(u32, f64, f64, u32),
}

impl Rand {
	pub fn new() -> Self {
		Rand::Basic(time_get() as u32)
	}
    pub fn srand(&mut self, seed: u32) {
        match *self {
            Rand::Basic(_) => *self = Rand::Basic(seed),
            Rand::PMrand(_, a) => *self = Rand::PMrand(seed, a),
            Rand::Gauss(_, nsum) => *self = Rand::Gauss(seed, nsum),
        }
    }
    pub fn rand(&mut self) -> f64 {
        match *self {
            Rand::Basic(seed) => {
                let mut foo = seed;
                let bar = basic(&mut foo);
                self.srand(foo);
                bar as f64
            }
            Rand::PMrand(seed, a) => {
                let mut foo = seed;
                let bar = pmrand(&mut foo, a);
                self.srand(foo);
                bar as f64
            }
            Rand::Gauss(seed, nsum) => {
                let mut foo = seed;
                let bar = gauss(&mut foo, nsum);
                self.srand(foo);
                bar
            }
        }
    }
}

fn time_get() -> i64 {
    let sys_time = SystemTime::now();
    let foo_string = format!("{:?}", sys_time);
    let mut seed: i64 = 0;
    let mut flag = false;
    for num in foo_string.chars() {
        match num {
            e @ '0'...'9' => {
                flag = true;
                seed = seed * 10 + (e as u8 - 48) as i64;
                if seed >= i32::max_value() as i64 {
                    break;
                }
            }
            _ => {
                if flag {
                    break;
                }
            }
        }
    }
    seed
}

fn basic(seed: &mut u32) -> u32 {
    *seed = (((*seed as u64 * 1103515245) as u32) as u64 + 12345) as u32;
    *seed >> 16 & RAND_MAX
}

fn pmrand(seed: &mut u32, a: u32) -> u32 {
    let m: u64 = 2147483647;
    let q = m / a as u64;
    let r = m % a as u64;
    let hi = *seed as u64 / q;
    let lo = *seed as u64 % q;
    let test = a as u64 * lo - r * hi;
    if test > 0 {
        *seed = test as u32;
    } else {
        *seed = (test + m) as u32;
    }
    *seed
}

fn gauss(seed: &mut u32, nsum: u32) -> f64 {
    let mut x = 0.0;
    for _ in 0..nsum {
        x += basic(seed) as f64 / RAND_MAX as f64;
    }
    x -= nsum as f64 / 2.0;
    x /= (nsum as f64 / 12.0).sqrt();
    x
}

// fn bmgauss(seed: &mut u32)
<commit_msg>Update<commit_after>use std::time::SystemTime;

const PI: f64 = 3.141592654;
pub const RAND_MAX: u32 = 32767;

pub enum Rand {
    Basic(u32),
    PMrand(u32, u32),
    Gauss(u32, u32),
	BMgauss(u32, f64, f64, bool),
}

impl Rand {
	pub fn new() -> Self {
		Rand::Basic(time_get() as u32)
	}
    pub fn srand(&mut self, seed: u32) {
        match *self {
            Rand::Basic(_) => *self = Rand::Basic(seed),
            Rand::PMrand(_, a) => *self = Rand::PMrand(seed, a),
            Rand::Gauss(_, nsum) => *self = Rand::Gauss(seed, nsum),
			Rand::BMgauss(_, u, v, phase) => *self = Rand::BMgauss(seed, u, v, phase),
        }
    }
    pub fn rand(&mut self) -> f64 {
        match *self {
            Rand::Basic(seed) => {
                let mut foo = seed;
                let bar = basic(&mut foo);
                self.srand(foo);
                bar as f64
            }
            Rand::PMrand(seed, a) => {
                let mut foo = seed;
                let bar = pmrand(&mut foo, a);
                self.srand(foo);
                bar as f64
            }
            Rand::Gauss(seed, nsum) => {
                let mut foo = seed;
                let bar = gauss(&mut foo, nsum);
                self.srand(foo);
                bar
            }
        }
    }
}

fn time_get() -> i64 {
    let sys_time = SystemTime::now();
    let foo_string = format!("{:?}", sys_time);
    let mut seed: i64 = 0;
    let mut flag = false;
    for num in foo_string.chars() {
        match num {
            e @ '0'...'9' => {
                flag = true;
                seed = seed * 10 + (e as u8 - 48) as i64;
                if seed >= i32::max_value() as i64 {
                    break;
                }
            }
            _ => {
                if flag {
                    break;
                }
            }
        }
    }
    seed
}

fn basic(seed: &mut u32) -> u32 {
    *seed = (((*seed as u64 * 1103515245) as u32) as u64 + 12345) as u32;
    *seed >> 16 & RAND_MAX
}

fn pmrand(seed: &mut u32, a: u32) -> u32 {
    let m: u64 = 2147483647;
    let q = m / a as u64;
    let r = m % a as u64;
    let hi = *seed as u64 / q;
    let lo = *seed as u64 % q;
    let test = a as u64 * lo - r * hi;
    if test > 0 {
        *seed = test as u32;
    } else {
        *seed = (test + m) as u32;
    }
    *seed
}

fn gauss(seed: &mut u32, nsum: u32) -> f64 {
    let mut x = 0.0;
    for _ in 0..nsum {
        x += basic(seed) as f64 / RAND_MAX as f64;
    }
    x -= nsum as f64 / 2.0;
    x /= (nsum as f64 / 12.0).sqrt();
    x
}

fn bmgauss(seed: &mut u32, u: &mut f64, v: &mut f64, phase: &mut bool) -> f64 {
	let mut z = 0.0;
	if phase {
		phase = false
	} else {
		phase = true
		(-2.0*(*u)).sqrt()*(2.0*PI*v)
	}
}
<|endoftext|>


<commit_before>use flate2::bufread::GzDecoder;

use errors::*;

use std::fs;
use std::io;
use std::io::Read;
use std::str;

pub fn make_reader(input_file: &str) -> Result<GzDecoder<io::BufReader<fs::File>>,
                                               WikiError> {
    let f = fs::File::open(input_file)?;
    let bf = io::BufReader::new(f);
    let rdr = GzDecoder::new(bf)?;
    Ok(rdr)
}

pub struct Streamer {
    buffer: String,
    bytes: io::Bytes<GzDecoder<io::BufReader<fs::File>>>,
}

impl Streamer {
    pub fn new(input_file: &str) -> Result<Streamer, WikiError> {
        let f = fs::File::open(input_file)?;
        let bf = io::BufReader::new(f);
        let rdr = GzDecoder::new(bf)?;
        let bytes = rdr.bytes();
        Ok(Streamer { buffer: String::new(),
                      bytes: bytes })
    }

    fn advance_to_eol(&mut self) {
        for b in &mut self.bytes {
            if let Ok(bite) = b {
                if bite == 0xA {
                    break;
                } else {
                    if let Ok(bb) = str::from_utf8(&[bite]) {
                        self.buffer.push_str(bb);
                    }
                }
            }
        }
    }
}

// TODO: Can we make the iterator return string slices?
impl Iterator for Streamer {
    type Item = String;
    fn next(&mut self) -> Option<String> {
        self.buffer.clear();
        self.advance_to_eol();
        if self.buffer.len() > 0 {
            Some(self.buffer.to_owned())
        } else {
            None
        }
    }
}
<commit_msg>Adding TODO<commit_after>use flate2::bufread::GzDecoder;

use errors::*;

use std::fs;
use std::io;
use std::io::Read;
use std::str;

pub fn make_reader(input_file: &str) -> Result<GzDecoder<io::BufReader<fs::File>>,
                                               WikiError> {
    let f = fs::File::open(input_file)?;
    let bf = io::BufReader::new(f);
    let rdr = GzDecoder::new(bf)?;
    Ok(rdr)
}

pub struct Streamer {
    buffer: String,
    bytes: io::Bytes<GzDecoder<io::BufReader<fs::File>>>,
}

// TODO: Is the fact that we are copying into "buffer" costing us a lot?
impl Streamer {
    pub fn new(input_file: &str) -> Result<Streamer, WikiError> {
        let f = fs::File::open(input_file)?;
        let bf = io::BufReader::new(f);
        let rdr = GzDecoder::new(bf)?;
        let bytes = rdr.bytes();
        Ok(Streamer { buffer: String::new(),
                      bytes: bytes })
    }

    fn advance_to_eol(&mut self) {
        for b in &mut self.bytes {
            if let Ok(bite) = b {
                if bite == 0xA {
                    break;
                } else {
                    if let Ok(bb) = str::from_utf8(&[bite]) {
                        self.buffer.push_str(bb);
                    }
                }
            }
        }
    }
}

// TODO: Can we make the iterator return string slices?
impl Iterator for Streamer {
    type Item = String;
    fn next(&mut self) -> Option<String> {
        self.buffer.clear();
        self.advance_to_eol();
        if self.buffer.len() > 0 {
            Some(self.buffer.to_owned())
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::fmt;
use std::error;
use std::str::{ FromStr, from_utf8 };
use std::num;

use {
    Value,
    ScopeType,
    IdCode,
    Scope,
    Var,
    ScopeItem,
    SimulationCommand,
    Header,
    Command
};

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Parse(&'static str),
}

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

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(..) => "VCD IO error",
            Error::Parse(..) => "VCD parse error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref err) => Some(err),
            _ => None,
        }
    }
}

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

impl From<num::ParseIntError> for Error {
    fn from(_: num::ParseIntError) -> Error { Error::Parse("Invalid number") }
}

impl From<num::ParseFloatError> for Error {
    fn from(_: num::ParseFloatError) -> Error { Error::Parse("Invalid number") }
}

impl From<::std::str::Utf8Error> for Error {
    fn from(_: ::std::str::Utf8Error) -> Error { Error::Parse("Invalid UTF8") }
}

impl From<::std::string::FromUtf8Error> for Error {
    fn from(_: ::std::string::FromUtf8Error) -> Error { Error::Parse("Invalid UTF8") }
}

impl From<()> for Error {
    fn from(_: ()) -> Error { Error::Parse("Unknown") }
}

fn whitespace_byte(b: u8) -> bool {
    match b {
        b' ' | b'\n' | b'\r' | b'\t' => true,
        _ => false,
    }
}

pub struct Parser<R: io::Read> {
    bytes_iter: io::Bytes<R>,
    simulation_command: Option<SimulationCommand>,
}

impl<R: io::Read> Parser<R> {
    pub fn new(r: R) -> Parser<R> {
        Parser {
            bytes_iter: r.bytes(),
            simulation_command: None,
        }
    }

    fn read_byte(&mut self) -> Result<u8, Error> {
        match self.bytes_iter.next() {
            Some(Ok(b)) => Ok(b),
            Some(Err(e)) => return Err(Error::from(e)),
            None => return Err(Error::Parse("Unexpected EOF")),
        }
    }

    fn read_token<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8], Error> {
        let mut len = 0;
        loop {
            let b = try!(self.read_byte());
            if whitespace_byte(b) {
                if len > 0 { break; } else { continue; }
            }

            if let Some(p) = buf.get_mut(len) {
                *p = b;
            } else {
                return Err(Error::Parse("Token too long"));
            }

            len += 1;
        }
        Ok(&buf[..len])
    }

    fn read_token_parse<E, T>(&mut self) -> Result<T, Error> where Error: From<E>, T: FromStr<Err=E> {
        let mut buf = [0; 32];
        let tok = try!(self.read_token(&mut buf));

        if tok == b"$end" {
            return Err(Error::Parse("Unexpected $end"));
        }

        let s = try!(from_utf8(tok));
        Ok(try!(s.parse()))
    }

    fn read_command_end(&mut self) -> Result<(), Error> {
        let mut buf = [0; 8];
        let tok = try!(self.read_token(&mut buf));
        if tok == b"$end" { Ok(()) } else { Err(Error::Parse("Expected $end")) }
    }

    fn read_string_command(&mut self) -> Result<String, Error> {
        let mut r = Vec::new();
        loop {
            r.push(try!(self.read_byte()));
            if r.ends_with(b"$end") { break; }
        }
        let len = r.len() - 4;
        r.truncate(len);
        Ok(try!(String::from_utf8(r)).trim().to_string()) // TODO: don't reallocate
    }

    fn parse_command(&mut self) -> Result<Command, Error> {
        use super::Command::*;
        use super::SimulationCommand::*;

        let mut cmdbuf = [0; 16];
        let cmd = try!(self.read_token(&mut cmdbuf));

        match cmd {
            b"comment" => Ok(Comment(try!(self.read_string_command()))),
            b"date"    => Ok(Date(try!(self.read_string_command()))),
            b"version" => Ok(Version(try!(self.read_string_command()))),
            b"timescale" => {
                let (mut buf, mut buf2) = ([0; 8], [0; 8]);
                let tok = try!(from_utf8(try!(self.read_token(&mut buf))));
                // Support both "1ps" and "1 ps"
                let (num_str, unit_str) = match tok.find(|c: char| !c.is_numeric()) {
                    Some(idx) => (&tok[0..idx], &tok[idx..]),
                    None => (tok, try!(from_utf8(try!(self.read_token(&mut buf2)))))
                };
                try!(self.read_command_end());
                Ok(Timescale(try!(num_str.parse()), try!(unit_str.parse())))
            }
            b"scope" => {
                let scope_type = try!(self.read_token_parse());
                let identifier = try!(self.read_token_parse());
                try!(self.read_command_end());
                Ok(ScopeDef(scope_type, identifier))
            }
            b"upscope" => {
                try!(self.read_command_end());
                Ok(Upscope)
            }
            b"var" => {
                let var_type = try!(self.read_token_parse());
                let size = try!(self.read_token_parse());
                let code = try!(self.read_token_parse());
                let reference = try!(self.read_token_parse());
                try!(self.read_command_end());
                Ok(VarDef(var_type, size, code, reference))
            }
            b"enddefinitions" => {
                try!(self.read_command_end());
                Ok(Enddefinitions)
            }

            // Simulation commands
            b"dumpall" => self.begin_simulation_command(Dumpall),
            b"dumpoff" => self.begin_simulation_command(Dumpoff),
            b"dumpon" => self.begin_simulation_command(Dumpon),
            b"dumpvars" => self.begin_simulation_command(Dumpvars),

            b"end" => {
                if let Some(c) = self.simulation_command.take() {
                    Ok(End(c))
                } else {
                    Err(Error::Parse("Unmatched $end"))
                }
            }

            _ => Err(Error::Parse("Invalid keyword"))
        }
    }

    fn begin_simulation_command(&mut self, c: SimulationCommand) -> Result<Command, Error> {
        self.simulation_command = Some(c);
        Ok(Command::Begin(c))
    }

    fn parse_timestamp(&mut self) -> Result<Command, Error> {
        Ok(Command::Timestamp(try!(self.read_token_parse())))
    }

    fn parse_scalar(&mut self, initial: u8) ->Result<Command, Error> {
        let id = try!(self.read_token_parse());
        let val = try!(Value::parse(initial));
        Ok(Command::ChangeScalar(id, val))
    }

    fn parse_vector(&mut self) -> Result<Command, Error> {
        let mut buf = [0; 32];
        let val = try!(try!(self.read_token(&mut buf)).iter().cloned().map(Value::parse).collect());
        let id = try!(IdCode::new(try!(self.read_token(&mut buf))));
        Ok(Command::ChangeVector(id, val))
    }

    fn parse_real(&mut self) -> Result<Command, Error> {
        let mut buf = [0; 32];
        // work around https://github.com/rust-lang/rust/issues/24748
        let val = try!(try!(from_utf8(try!(self.read_token(&mut buf)))).parse().or(Err(Error::Parse("Invalid number"))));
        let id = try!(IdCode::new(try!(self.read_token(&mut buf))));
        Ok(Command::ChangeReal(id, val))
    }

    fn parse_scope(&mut self, scope_type: ScopeType, reference: String) -> Result<Scope, Error> {
        use super::Command::*;
        let mut children = Vec::new();

        loop {
            match self.next() {
                Some(Ok(Upscope)) => break,
                Some(Ok(ScopeDef(tp, id))) => {
                    children.push(ScopeItem::Scope(try!(self.parse_scope(tp, id))));
                }
                Some(Ok(VarDef(tp, size, id, r))) => {
                    children.push(ScopeItem::Var(
                        Var { var_type: tp, size: size, code: id, reference: r }
                    ));
                }
                Some(Ok(_)) => return Err(Error::Parse("Unexpected command in $scope")),
                Some(Err(e)) => return Err(Error::from(e)),
                None => return Err(Error::Parse("Unexpected EOF in $scope"))
            }
        }

        Ok(Scope { scope_type: scope_type, identifier: reference, children: children })
    }

    pub fn parse_header(&mut self) -> Result<Header, Error> {
        use super::Command::*;
        let mut header: Header = Default::default();
        loop {
            match self.next() {
                Some(Ok(Enddefinitions)) => break,
                Some(Ok(Comment(s))) => { header.comment = Some(s); }
                Some(Ok(Date(s)))    => { header.date    = Some(s); }
                Some(Ok(Version(s))) => { header.version = Some(s); }
                Some(Ok(Timescale(val, unit))) => { header.timescale = Some((val, unit)); }
                Some(Ok(ScopeDef(tp, id))) => {
                    header.scope = try!(self.parse_scope(tp, id));
                }
                Some(Ok(_)) => {
                    return Err(Error::Parse("Unexpected command in header"))
                }
                Some(Err(e)) => return Err(Error::from(e)),
                None => return Err(Error::Parse("Unexpected EOF in header"))
            }
        }
        Ok(header)
    }
}

impl<P: io::Read> Iterator for Parser<P> {
    type Item = Result<Command, Error>;
    fn next(&mut self) -> Option<Result<Command, Error>> {
        while let Some(b) = self.bytes_iter.next() {
            let b = match b {
                Ok(b) => b,
                Err(e) => return Some(Err(Error::from(e)))
            };
            match b {
                b' ' | b'\n' | b'\r' | b'\t' => (),
                b'$' => return Some(self.parse_command()),
                b'#' => return Some(self.parse_timestamp()),
                b'0' | b'1' | b'z' | b'Z' | b'x' | b'X' => return Some(self.parse_scalar(b)),
                b'b' | b'B' => return Some(self.parse_vector()),
                b'r' | b'R' => return Some(self.parse_real()),
                _ => panic!("Unexpected character {}", b)
            }
        }
        None
    }
}

#[test]
fn wikipedia_sample() {
    use super::Command::*;
    use super::SimulationCommand::*;
    use super::Value::*;
    use super::TimescaleUnit;

    let sample = b"
    $date
       Date text.
    $end
    $version
       VCD generator text.
    $end
    $comment
       Any comment text.
    $end
    $timescale 100 ns $end
    $scope module logic $end
    $var wire 8 # data $end
    $var wire 1 $ data_valid $end
    $var wire 1 % en $end
    $var wire 1 & rx_en $end
    $var wire 1 ' tx_en $end
    $var wire 1 ( empty $end
    $var wire 1 ) underrun $end
    $upscope $end
    $enddefinitions $end
    $dumpvars
    bxxxxxxxx #
    x$
    0%
    x&
    x'
    1(
    0)
    $end
    #0
    b10000001 #
    0$
    1%
    #2211
    0'
    #2296
    b0 #
    1$
    #2302
    0$
    #2303
        ";

    let mut b = Parser::new(&sample[..]);

    let header = b.parse_header().unwrap();
    assert_eq!(header.comment, Some("Any comment text.".to_string()));
    assert_eq!(header.date, Some("Date text.".to_string()));
    assert_eq!(header.version, Some("VCD generator text.".to_string()));
    assert_eq!(header.timescale, Some((100, TimescaleUnit::NS)));

    let expected = &[
        Begin(Dumpvars),
        ChangeVector(IdCode(2), vec![X, X, X, X, X, X, X, X]),
        ChangeScalar(IdCode(3), X),
        ChangeScalar(IdCode(4), V0),
        ChangeScalar(IdCode(5), X),
        ChangeScalar(IdCode(6), X),
        ChangeScalar(IdCode(7), V1),
        ChangeScalar(IdCode(8), V0),
        End(Dumpvars),
        Timestamp(0),
        ChangeVector(IdCode(2), vec![V1, V0, V0, V0, V0, V0, V0, V1]),
        ChangeScalar(IdCode(3), V0),
        ChangeScalar(IdCode(4), V1),
        Timestamp(2211),
        ChangeScalar(IdCode(6), V0),
        Timestamp(2296),
        ChangeVector(IdCode(2), vec![V0]),
        ChangeScalar(IdCode(3), V1),
        Timestamp(2302),
        ChangeScalar(IdCode(3), V0),
        Timestamp(2303),
    ];

    for (i, e) in b.zip(expected.iter()) {
        assert_eq!(&i.unwrap(), e);
    }
}
<commit_msg>rust: Work around String FromStr destabilization from rust-lang/rust#25006<commit_after>use std::io;
use std::fmt;
use std::error;
use std::str::{ FromStr, from_utf8 };
use std::num;

use {
    Value,
    ScopeType,
    Scope,
    Var,
    ScopeItem,
    SimulationCommand,
    Header,
    Command
};

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Parse(&'static str),
}

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

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(..) => "VCD IO error",
            Error::Parse(..) => "VCD parse error",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref err) => Some(err),
            _ => None,
        }
    }
}

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

impl From<num::ParseIntError> for Error {
    fn from(_: num::ParseIntError) -> Error { Error::Parse("Invalid number") }
}

impl From<num::ParseFloatError> for Error {
    fn from(_: num::ParseFloatError) -> Error { Error::Parse("Invalid number") }
}

impl From<::std::str::Utf8Error> for Error {
    fn from(_: ::std::str::Utf8Error) -> Error { Error::Parse("Invalid UTF8") }
}

impl From<::std::string::FromUtf8Error> for Error {
    fn from(_: ::std::string::FromUtf8Error) -> Error { Error::Parse("Invalid UTF8") }
}

fn whitespace_byte(b: u8) -> bool {
    match b {
        b' ' | b'\n' | b'\r' | b'\t' => true,
        _ => false,
    }
}

pub struct Parser<R: io::Read> {
    bytes_iter: io::Bytes<R>,
    simulation_command: Option<SimulationCommand>,
}

impl<R: io::Read> Parser<R> {
    pub fn new(r: R) -> Parser<R> {
        Parser {
            bytes_iter: r.bytes(),
            simulation_command: None,
        }
    }

    fn read_byte(&mut self) -> Result<u8, Error> {
        match self.bytes_iter.next() {
            Some(Ok(b)) => Ok(b),
            Some(Err(e)) => return Err(Error::from(e)),
            None => return Err(Error::Parse("Unexpected EOF")),
        }
    }

    fn read_token<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8], Error> {
        let mut len = 0;
        loop {
            let b = try!(self.read_byte());
            if whitespace_byte(b) {
                if len > 0 { break; } else { continue; }
            }

            if let Some(p) = buf.get_mut(len) {
                *p = b;
            } else {
                return Err(Error::Parse("Token too long"));
            }

            len += 1;
        }
        Ok(&buf[..len])
    }

    fn read_token_string(&mut self) -> Result<String, Error> {
        let mut r = Vec::new();
        loop {
            let b = try!(self.read_byte());
            if whitespace_byte(b) {
                if r.len() > 0 { break; } else { continue; }
            }
            r.push(b);
        }
        Ok(try!(String::from_utf8(r)))
    }

    fn read_token_parse<E, T>(&mut self) -> Result<T, Error> where Error: From<E>, T: FromStr<Err=E> {
        let mut buf = [0; 32];
        let tok = try!(self.read_token(&mut buf));

        if tok == b"$end" {
            return Err(Error::Parse("Unexpected $end"));
        }

        let s = try!(from_utf8(tok));
        Ok(try!(s.parse()))
    }

    fn read_command_end(&mut self) -> Result<(), Error> {
        let mut buf = [0; 8];
        let tok = try!(self.read_token(&mut buf));
        if tok == b"$end" { Ok(()) } else { Err(Error::Parse("Expected $end")) }
    }

    fn read_string_command(&mut self) -> Result<String, Error> {
        let mut r = Vec::new();
        loop {
            r.push(try!(self.read_byte()));
            if r.ends_with(b"$end") { break; }
        }
        let len = r.len() - 4;
        r.truncate(len);
        Ok(try!(String::from_utf8(r)).trim().to_string()) // TODO: don't reallocate
    }

    fn parse_command(&mut self) -> Result<Command, Error> {
        use super::Command::*;
        use super::SimulationCommand::*;

        let mut cmdbuf = [0; 16];
        let cmd = try!(self.read_token(&mut cmdbuf));

        match cmd {
            b"comment" => Ok(Comment(try!(self.read_string_command()))),
            b"date"    => Ok(Date(try!(self.read_string_command()))),
            b"version" => Ok(Version(try!(self.read_string_command()))),
            b"timescale" => {
                let (mut buf, mut buf2) = ([0; 8], [0; 8]);
                let tok = try!(from_utf8(try!(self.read_token(&mut buf))));
                // Support both "1ps" and "1 ps"
                let (num_str, unit_str) = match tok.find(|c: char| !c.is_numeric()) {
                    Some(idx) => (&tok[0..idx], &tok[idx..]),
                    None => (tok, try!(from_utf8(try!(self.read_token(&mut buf2)))))
                };
                try!(self.read_command_end());
                Ok(Timescale(try!(num_str.parse()), try!(unit_str.parse())))
            }
            b"scope" => {
                let scope_type = try!(self.read_token_parse());
                let identifier = try!(self.read_token_string());
                try!(self.read_command_end());
                Ok(ScopeDef(scope_type, identifier))
            }
            b"upscope" => {
                try!(self.read_command_end());
                Ok(Upscope)
            }
            b"var" => {
                let var_type = try!(self.read_token_parse());
                let size = try!(self.read_token_parse());
                let code = try!(self.read_token_parse());
                let reference = try!(self.read_token_string());
                try!(self.read_command_end());
                Ok(VarDef(var_type, size, code, reference))
            }
            b"enddefinitions" => {
                try!(self.read_command_end());
                Ok(Enddefinitions)
            }

            // Simulation commands
            b"dumpall" => self.begin_simulation_command(Dumpall),
            b"dumpoff" => self.begin_simulation_command(Dumpoff),
            b"dumpon" => self.begin_simulation_command(Dumpon),
            b"dumpvars" => self.begin_simulation_command(Dumpvars),

            b"end" => {
                if let Some(c) = self.simulation_command.take() {
                    Ok(End(c))
                } else {
                    Err(Error::Parse("Unmatched $end"))
                }
            }

            _ => Err(Error::Parse("Invalid keyword"))
        }
    }

    fn begin_simulation_command(&mut self, c: SimulationCommand) -> Result<Command, Error> {
        self.simulation_command = Some(c);
        Ok(Command::Begin(c))
    }

    fn parse_timestamp(&mut self) -> Result<Command, Error> {
        Ok(Command::Timestamp(try!(self.read_token_parse())))
    }

    fn parse_scalar(&mut self, initial: u8) ->Result<Command, Error> {
        let id = try!(self.read_token_parse());
        let val = try!(Value::parse(initial));
        Ok(Command::ChangeScalar(id, val))
    }

    fn parse_vector(&mut self) -> Result<Command, Error> {
        let mut buf = [0; 32];
        let val = try!(try!(self.read_token(&mut buf)).iter().cloned().map(Value::parse).collect());
        let id = try!(self.read_token_parse());
        Ok(Command::ChangeVector(id, val))
    }

    fn parse_real(&mut self) -> Result<Command, Error> {
        let val = try!(self.read_token_parse());
        let id = try!(self.read_token_parse());
        Ok(Command::ChangeReal(id, val))
    }

    fn parse_scope(&mut self, scope_type: ScopeType, reference: String) -> Result<Scope, Error> {
        use super::Command::*;
        let mut children = Vec::new();

        loop {
            match self.next() {
                Some(Ok(Upscope)) => break,
                Some(Ok(ScopeDef(tp, id))) => {
                    children.push(ScopeItem::Scope(try!(self.parse_scope(tp, id))));
                }
                Some(Ok(VarDef(tp, size, id, r))) => {
                    children.push(ScopeItem::Var(
                        Var { var_type: tp, size: size, code: id, reference: r }
                    ));
                }
                Some(Ok(_)) => return Err(Error::Parse("Unexpected command in $scope")),
                Some(Err(e)) => return Err(Error::from(e)),
                None => return Err(Error::Parse("Unexpected EOF in $scope"))
            }
        }

        Ok(Scope { scope_type: scope_type, identifier: reference, children: children })
    }

    pub fn parse_header(&mut self) -> Result<Header, Error> {
        use super::Command::*;
        let mut header: Header = Default::default();
        loop {
            match self.next() {
                Some(Ok(Enddefinitions)) => break,
                Some(Ok(Comment(s))) => { header.comment = Some(s); }
                Some(Ok(Date(s)))    => { header.date    = Some(s); }
                Some(Ok(Version(s))) => { header.version = Some(s); }
                Some(Ok(Timescale(val, unit))) => { header.timescale = Some((val, unit)); }
                Some(Ok(ScopeDef(tp, id))) => {
                    header.scope = try!(self.parse_scope(tp, id));
                }
                Some(Ok(_)) => {
                    return Err(Error::Parse("Unexpected command in header"))
                }
                Some(Err(e)) => return Err(Error::from(e)),
                None => return Err(Error::Parse("Unexpected EOF in header"))
            }
        }
        Ok(header)
    }
}

impl<P: io::Read> Iterator for Parser<P> {
    type Item = Result<Command, Error>;
    fn next(&mut self) -> Option<Result<Command, Error>> {
        while let Some(b) = self.bytes_iter.next() {
            let b = match b {
                Ok(b) => b,
                Err(e) => return Some(Err(Error::from(e)))
            };
            match b {
                b' ' | b'\n' | b'\r' | b'\t' => (),
                b'$' => return Some(self.parse_command()),
                b'#' => return Some(self.parse_timestamp()),
                b'0' | b'1' | b'z' | b'Z' | b'x' | b'X' => return Some(self.parse_scalar(b)),
                b'b' | b'B' => return Some(self.parse_vector()),
                b'r' | b'R' => return Some(self.parse_real()),
                _ => panic!("Unexpected character {}", b)
            }
        }
        None
    }
}

#[test]
fn wikipedia_sample() {
    use super::Command::*;
    use super::SimulationCommand::*;
    use super::Value::*;
    use super::{ TimescaleUnit, IdCode };

    let sample = b"
    $date
       Date text.
    $end
    $version
       VCD generator text.
    $end
    $comment
       Any comment text.
    $end
    $timescale 100 ns $end
    $scope module logic $end
    $var wire 8 # data $end
    $var wire 1 $ data_valid $end
    $var wire 1 % en $end
    $var wire 1 & rx_en $end
    $var wire 1 ' tx_en $end
    $var wire 1 ( empty $end
    $var wire 1 ) underrun $end
    $upscope $end
    $enddefinitions $end
    $dumpvars
    bxxxxxxxx #
    x$
    0%
    x&
    x'
    1(
    0)
    $end
    #0
    b10000001 #
    0$
    1%
    #2211
    0'
    #2296
    b0 #
    1$
    #2302
    0$
    #2303
        ";

    let mut b = Parser::new(&sample[..]);

    let header = b.parse_header().unwrap();
    assert_eq!(header.comment, Some("Any comment text.".to_string()));
    assert_eq!(header.date, Some("Date text.".to_string()));
    assert_eq!(header.version, Some("VCD generator text.".to_string()));
    assert_eq!(header.timescale, Some((100, TimescaleUnit::NS)));

    let expected = &[
        Begin(Dumpvars),
        ChangeVector(IdCode(2), vec![X, X, X, X, X, X, X, X]),
        ChangeScalar(IdCode(3), X),
        ChangeScalar(IdCode(4), V0),
        ChangeScalar(IdCode(5), X),
        ChangeScalar(IdCode(6), X),
        ChangeScalar(IdCode(7), V1),
        ChangeScalar(IdCode(8), V0),
        End(Dumpvars),
        Timestamp(0),
        ChangeVector(IdCode(2), vec![V1, V0, V0, V0, V0, V0, V0, V1]),
        ChangeScalar(IdCode(3), V0),
        ChangeScalar(IdCode(4), V1),
        Timestamp(2211),
        ChangeScalar(IdCode(6), V0),
        Timestamp(2296),
        ChangeVector(IdCode(2), vec![V0]),
        ChangeScalar(IdCode(3), V1),
        Timestamp(2302),
        ChangeScalar(IdCode(3), V0),
        Timestamp(2303),
    ];

    for (i, e) in b.zip(expected.iter()) {
        assert_eq!(&i.unwrap(), e);
    }
}
<|endoftext|>