<commit_before>#[derive(Debug,Clone,PartialEq)]
pub enum Token {
  // Structure
  EOF,
  Enter,
  Exit,

  // Literals
  Null,
  Bool(bool),
  Float(f64),
  Int(i64),
  StrLit(String),
  Name(String),

  // Keywords
  Break,
  Continue,
  Else,
  For,
  Func,
  If,
  Return,
  While,

  // Symbols
  Arr, // ->
  Col, // :
  Com, // ,
  Dot, // .
  Ass, // =

  // Braces
  Cul, // {
  Cur, // }
  Pal, // (
  Par, // )
  Sql, // [
  Sqr, // ]

  // Operators
  Add, // +
  Div, // /
  Mul, // *
  Sub, // -
  Dol, // $
  Pct, // %
  Car, // ^
  And, // &
  Or,  // |
  Not, // !
  Neg, // ~

  // Comparisons
  Gt,  // >
  Ge,  // >=
  Lt,  // <
  Le,  // <=
  Ne,  // !=
  Eql, // ==
}

use self::Token::*;

pub fn lex(input: &str) {
  let mut tokens: Vec<Token> = Vec::new();
  let mut it = input.chars().peekable();

  while let Some(&c) = it.peek() {
    match c {
      '-' => {
        it.next();
        match it.peek() {
          Some(&'>') => {
            tokens.push(Arr);
            it.next();
          }
          _ => {
            tokens.push(Sub);
          }
        }
      }
      '+' => {tokens.push(Add); it.next();}
      '/' => {tokens.push(Div); it.next();}
      '*' => {tokens.push(Mul); it.next();}
      '(' => {tokens.push(Pal); it.next();}
      ')' => {tokens.push(Par); it.next();}
      '[' => {tokens.push(Sql); it.next();}
      ']' => {tokens.push(Sqr); it.next();}
      '{' => {tokens.push(Cul); it.next();}
      '}' => {tokens.push(Cur); it.next();}
      '<' => {tokens.push(Lt); it.next();}
      '>' => {tokens.push(Gt); it.next();}
      _ => {it.next();}
    }
  }

  println!("{:?}", tokens);
}
<commit_msg>lexer: Add number lexing<commit_after>use std;

#[derive(Debug,Clone,PartialEq)]
pub enum Token {
  // Structure
  EOF,
  Enter,
  Exit,

  // Literals
  Null,
  Bool(bool),
  Float(f64),
  Int(i64),
  StrLit(String),
  Name(String),

  // Keywords
  Break,
  Continue,
  Else,
  For,
  Func,
  If,
  Return,
  While,

  // Symbols
  Arr, // ->
  Col, // :
  Com, // ,
  Dot, // .
  Ass, // =

  // Braces
  Cul, // {
  Cur, // }
  Pal, // (
  Par, // )
  Sql, // [
  Sqr, // ]

  // Operators
  Add, // +
  Div, // /
  Mul, // *
  Sub, // -
  Dol, // $
  Pct, // %
  Car, // ^
  And, // &
  Or,  // |
  Not, // !
  Neg, // ~

  // Comparisons
  Gt,  // >
  Ge,  // >=
  Lt,  // <
  Le,  // <=
  Ne,  // !=
  Eql, // ==
}

use self::Token::*;

fn lex_number(it: &mut std::iter::Peekable<std::str::Chars>) -> Token {
  let mut digits = String::new();
  while let Some(&c) = it.peek() {
    match c {
      '0'...'9' | '.' => {
        it.next();
        digits.push(c);
      }
      _ => {break}
    }
  }

  match digits.contains(".") {
    true => Float(digits.parse::<f64>().unwrap()),
    false => Int(digits.parse::<i64>().unwrap())
  }
}

pub fn lex(input: &str) {
  let mut tokens: Vec<Token> = Vec::new();
  let mut it = input.chars().peekable();

  while let Some(&c) = it.peek() {
    match c {
      '0'...'9' => {
        tokens.push(lex_number(&mut it));
      }
      '-' => {
        it.next();
        match it.peek() {
          Some(&'>') => {
            tokens.push(Arr);
            it.next();
          }
          _ => {
            tokens.push(Sub);
          }
        }
      }
      '+' => {tokens.push(Add); it.next();}
      '/' => {tokens.push(Div); it.next();}
      '*' => {tokens.push(Mul); it.next();}
      '(' => {tokens.push(Pal); it.next();}
      ')' => {tokens.push(Par); it.next();}
      '[' => {tokens.push(Sql); it.next();}
      ']' => {tokens.push(Sqr); it.next();}
      '{' => {tokens.push(Cul); it.next();}
      '}' => {tokens.push(Cur); it.next();}
      '<' => {tokens.push(Lt); it.next();}
      '>' => {tokens.push(Gt); it.next();}
      _ => {it.next();}
    }
  }

  println!("{:?}", tokens);
}
<|endoftext|>


<commit_before>use std::char::is_whitespace;
use error::InputPos;

#[deriving(PartialEq, Clone, Show)]
pub enum TokenValue {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,

    Let,
    Assignment,
    RightArrow,

    Comma,
    Colon,
    SemiColon,

    Equal,
    Plus,
    PlusEq,
    Minus,
    MinusEq,

    Eof,

    For,
    While,
    Loop,
    Break,
    Return,

    If,
    Else,
    Struct,
    Fn,
    Asm,

    Bool,
    Int,
    Uint,

    True,
    False,
    LitNum(int),
    LitString(String),
    Ident(String),
}

#[deriving(Show)]
pub struct Token {
    pub value: TokenValue,
    pub pos: InputPos,
}

pub struct Lexer<'a> {
    remaining: &'a str,
    pos: InputPos,
}

impl<'a> Lexer<'a> {
    pub fn new(source: &str) -> Lexer {
        Lexer {
            remaining: source,
            pos: InputPos::start(),
        }
    }

    fn bump(&mut self) {
        let (val, rest) = self.remaining.slice_shift_char();
        match val {
            // Move to the next line
            Some('\n') => {
                self.pos.line += 1;
                self.pos.col = 0;
            },

            // Discard carrage return characters
            Some('\r') => {},

            // For other characters increase the column position
            Some(_) => self.pos.col += 1,

            None => {},
        }
        self.remaining = rest;
    }

    fn read_white_space_or_comment(&mut self) {
        while self.remaining.len() > 0 {
            match self.remaining.char_at(0) {
                // Match whitespace
                c if is_whitespace(c) => self.bump(),

                // Match comments
                '#' => {
                    let comment_line = self.pos.line;
                    while self.pos.line == comment_line {
                        self.bump()
                    }
                },

                // Match other chars
                _ => break,
            }
        }
    }
}

impl<'a> Iterator<Token> for Lexer<'a> {
    fn next(&mut self) -> Option<Token> {
        // Read up to the next proper token
        self.read_white_space_or_comment();

        let len = self.remaining.len();
        if len == 0 {
            return None;
        }

        let mut token_len = 1;
        let token_val = match self.remaining.char_at(0) {
            '(' => LeftParen,

            ')' => RightParen,

            '{' => LeftBrace,

            '}' => RightBrace,

            ';' => SemiColon,

            ':' => Colon,

            ',' => Comma,

            '=' => {
                if len == 1 { Assignment }
                else {
                    match self.remaining.char_at(1) {
                        '=' => { token_len += 1; Equal },
                        _ => Assignment
                    }
                }
            },

            '+' => {
                if len == 1 { Plus }
                else {
                    match self.remaining.char_at(1) {
                        '=' => { token_len += 1; PlusEq },
                        _ => Plus
                    }
                }
            },

            '-' => {
                if len == 1 { Minus }
                else {
                    match self.remaining.char_at(1) {
                        '=' => { token_len += 1; MinusEq },
                        '>' => { token_len += 1; RightArrow },
                        _ => Minus
                    }
                }
            },

            '0'..'9' => {
                token_len = scan_token(self.remaining);
                let number_str = self.remaining.slice_to(token_len);
                match from_str(number_str) {
                    Some(n) => LitNum(n),
                    None => fail!("Invalid number"),
                }
            },

            '"' => {
                self.bump();
                token_len = match self.remaining.find('"') {
                    Some(offset) => offset,
                    None => {
                        fail!("Unclosed \" ");
                    },
                };
                let result = LitString(self.remaining.slice_to(token_len).into_string());
                token_len += 1;
                result
            },

            _ => {
                token_len = scan_token(self.remaining);
                let token_str = self.remaining.slice_to(token_len);
                match token_str {
                    "let"    => Let,
                    "if"     => If,
                    "for"    => For,
                    "while"  => While,
                    "loop"   => Loop,
                    "break"  => Break,
                    "return" => Return,
                    "else"   => Else,
                    "asm"    => Asm,
                    "fn"     => Fn,
                    "struct" => Struct,
                    "true"   => True,
                    "false"  => False,
                    "int"    => Int,
                    "bool"   => Bool,
                    _        => Ident(token_str.to_string())
                }
            }
        };

        let token = Token {
            value: token_val,
            pos: self.pos.clone(),
        };

        self.pos.col += token_len;

        self.remaining = self.remaining.slice_from(token_len);

        Some(token)
    }
}

/// Scans till the end of the token returning the index of the end of the token
fn scan_token(string: &str) -> uint {
    static TOKEN_BOUNDS: &'static [char] = &[
        ' ', '\t', '\n', '#', ':', ';', ',', '(', ')', '{', '}', '.', '=', '+', '-', '"'
    ];

    match string.find(TOKEN_BOUNDS) {
        Some(n) => n,
        None => string.len()
    }
}
<commit_msg>Fix bug where lexer could go in infinite loop when the last line was a comment.<commit_after>use std::char::is_whitespace;
use error::InputPos;

#[deriving(PartialEq, Clone, Show)]
pub enum TokenValue {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,

    Let,
    Assignment,
    RightArrow,

    Comma,
    Colon,
    SemiColon,

    Equal,
    Plus,
    PlusEq,
    Minus,
    MinusEq,

    Eof,

    For,
    While,
    Loop,
    Break,
    Return,

    If,
    Else,
    Struct,
    Fn,
    Asm,

    Bool,
    Int,
    Uint,

    True,
    False,
    LitNum(int),
    LitString(String),
    Ident(String),
}

#[deriving(Show)]
pub struct Token {
    pub value: TokenValue,
    pub pos: InputPos,
}

pub struct Lexer<'a> {
    remaining: &'a str,
    pos: InputPos,
}

impl<'a> Lexer<'a> {
    pub fn new(source: &str) -> Lexer {
        Lexer {
            remaining: source,
            pos: InputPos::start(),
        }
    }

    fn bump(&mut self) {
        let (val, rest) = self.remaining.slice_shift_char();
        match val {
            // Move to the next line
            Some('\n') => {
                self.pos.line += 1;
                self.pos.col = 0;
            },

            // Discard carrage return characters
            Some('\r') => {},

            // For other characters increase the column position
            Some(_) => self.pos.col += 1,

            None => {},
        }
        self.remaining = rest;
    }

    fn read_white_space_or_comment(&mut self) {
        while self.remaining.len() > 0 {
            match self.remaining.char_at(0) {
                // Match whitespace
                c if is_whitespace(c) => self.bump(),

                // Match comments
                '#' => {
                    let comment_line = self.pos.line;
                    while self.pos.line == comment_line && self.remaining.len() > 0 {
                        self.bump();
                    }
                },

                // Match other chars
                _ => break,
            }
        }
    }
}

impl<'a> Iterator<Token> for Lexer<'a> {
    fn next(&mut self) -> Option<Token> {
        // Read up to the next proper token
        self.read_white_space_or_comment();

        let len = self.remaining.len();
        if len == 0 {
            return None;
        }

        let mut token_len = 1;
        let token_val = match self.remaining.char_at(0) {
            '(' => LeftParen,

            ')' => RightParen,

            '{' => LeftBrace,

            '}' => RightBrace,

            ';' => SemiColon,

            ':' => Colon,

            ',' => Comma,

            '=' => {
                if len == 1 { Assignment }
                else {
                    match self.remaining.char_at(1) {
                        '=' => { token_len += 1; Equal },
                        _ => Assignment
                    }
                }
            },

            '+' => {
                if len == 1 { Plus }
                else {
                    match self.remaining.char_at(1) {
                        '=' => { token_len += 1; PlusEq },
                        _ => Plus
                    }
                }
            },

            '-' => {
                if len == 1 { Minus }
                else {
                    match self.remaining.char_at(1) {
                        '=' => { token_len += 1; MinusEq },
                        '>' => { token_len += 1; RightArrow },
                        _ => Minus
                    }
                }
            },

            '0'..'9' => {
                token_len = scan_token(self.remaining);
                let number_str = self.remaining.slice_to(token_len);
                match from_str(number_str) {
                    Some(n) => LitNum(n),
                    None => fail!("Invalid number"),
                }
            },

            '"' => {
                self.bump();
                token_len = match self.remaining.find('"') {
                    Some(offset) => offset,
                    None => {
                        fail!("Unclosed \" ");
                    },
                };
                let result = LitString(self.remaining.slice_to(token_len).into_string());
                token_len += 1;
                result
            },

            _ => {
                token_len = scan_token(self.remaining);
                let token_str = self.remaining.slice_to(token_len);
                match token_str {
                    "let"    => Let,
                    "if"     => If,
                    "for"    => For,
                    "while"  => While,
                    "loop"   => Loop,
                    "break"  => Break,
                    "return" => Return,
                    "else"   => Else,
                    "asm"    => Asm,
                    "fn"     => Fn,
                    "struct" => Struct,
                    "true"   => True,
                    "false"  => False,
                    "int"    => Int,
                    "bool"   => Bool,
                    _        => Ident(token_str.to_string())
                }
            }
        };

        let token = Token {
            value: token_val,
            pos: self.pos.clone(),
        };

        self.pos.col += token_len;

        self.remaining = self.remaining.slice_from(token_len);

        Some(token)
    }
}

/// Scans till the end of the token returning the index of the end of the token
fn scan_token(string: &str) -> uint {
    static TOKEN_BOUNDS: &'static [char] = &[
        ' ', '\t', '\n', '#', ':', ';', ',', '(', ')', '{', '}', '.', '=', '+', '-', '"'
    ];

    match string.find(TOKEN_BOUNDS) {
        Some(n) => n,
        None => string.len()
    }
}
<|endoftext|>


<commit_before>extern crate gtk;

use gtk::prelude::*;
use std::ops::Not;
use std::sync::{Arc, RwLock};

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = gtk::Window::new(gtk::WindowType::Toplevel);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    let button = gtk::Button::new_with_label("Hello World! ");

    window.add(&button);

    let lock = Arc::new(RwLock::new(false));

    let lock_button = lock.clone();
    button.connect_clicked(move |_| {
        let mut reverse = lock_button.write().unwrap();
        *reverse = reverse.not();
    });

    let lock_thread = lock.clone();
    gtk::timeout_add(100, move || {
        let reverse = lock_thread.read().unwrap();
        let mut text = button.get_label().unwrap();
        let len = &text.len();

        if *reverse {
            let begin = &text.split_off(1);
            &text.insert_str(0, begin);
        } else {
            let end = &text.split_off(len - 1);
            &text.insert_str(0, end);
        }

        &button.set_label(&format!("{}", text));

        gtk::Continue(true)
    });

    window.show_all();
    gtk::main();
}
<commit_msg>Some little cosmetics<commit_after>extern crate gtk;

use gtk::prelude::*;
use std::ops::Not;
use std::sync::{Arc, RwLock};

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = gtk::Window::new(gtk::WindowType::Toplevel);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    let button = gtk::Button::new_with_label("Hello World! ");

    window.add(&button);

    let lock = Arc::new(RwLock::new(false));

    let lock_button = lock.clone();
    button.connect_clicked(move |_| {
        let mut reverse = lock_button.write().unwrap();
        *reverse = reverse.not();
    });

    let lock_thread = lock.clone();
    gtk::timeout_add(100, move || {
        let reverse = lock_thread.read().unwrap();
        let mut text = button.get_label().unwrap();
        let len = &text.len();

        if *reverse {
            let begin = &text.split_off(1);
            text.insert_str(0, begin);
        } else {
            let end = &text.split_off(len - 1);
            text.insert_str(0, end);
        }

        button.set_label(&text);

        gtk::Continue(true)
    });

    window.show_all();
    gtk::main();
}
<|endoftext|>


<commit_before>// Copyright (C) 2019, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;

use ring::rand::*;

const LOCAL_CONN_ID_LEN: usize = 16;

const MAX_DATAGRAM_SIZE: usize = 1350;

const USAGE: &str = "Usage:
  http3-client [options] URL
  http3-client -h | --help

Options:
  --wire-version VERSION  The version number to send to the server [default: babababa].
  --no-verify             Don't verify server's certificate.
  -h --help               Show this screen.
";

fn main() -> Result<(), Box<std::error::Error>> {
    let mut buf = [0; 65535];
    let mut out = [0; MAX_DATAGRAM_SIZE];

    env_logger::init();

    let args = docopt::Docopt::new(USAGE)
        .and_then(|dopt| dopt.parse())
        .unwrap_or_else(|e| e.exit());

    let url = url::Url::parse(args.get_str("URL"))?;

    let socket = std::net::UdpSocket::bind("0.0.0.0:0")?;
    socket.connect(&url)?;

    let poll = mio::Poll::new()?;
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket)?;
    poll.register(
        &socket,
        mio::Token(0),
        mio::Ready::readable(),
        mio::PollOpt::edge(),
    )?;

    let mut scid = [0; LOCAL_CONN_ID_LEN];
    SystemRandom::new().fill(&mut scid[..])?;

    let version = args.get_str("--wire-version");
    let version = u32::from_str_radix(version, 16)?;

    let mut config = quiche::Config::new(version)?;

    config.verify_peer(true);

    config.set_application_protos(b"\x05h3-18")?;

    config.set_idle_timeout(30);
    config.set_max_packet_size(MAX_DATAGRAM_SIZE as u64);
    config.set_initial_max_data(10_000_000);
    config.set_initial_max_stream_data_bidi_local(1_000_000);
    config.set_initial_max_stream_data_bidi_remote(1_000_000);
    config.set_initial_max_stream_data_uni(1_000_000);
    config.set_initial_max_streams_bidi(100);
    config.set_initial_max_streams_uni(100);
    config.set_disable_migration(true);

    let mut http3_conn = None;

    if args.get_bool("--no-verify") {
        config.verify_peer(false);
    }

    if std::env::var_os("SSLKEYLOGFILE").is_some() {
        config.log_keys();
    }

    let mut conn = quiche::connect(url.domain(), &scid, &mut config)?;

    let write = match conn.send(&mut out) {
        Ok(v) => v,

        Err(e) => panic!("{} initial send failed: {:?}", conn.trace_id(), e),
    };

    socket.send(&out[..write])?;

    debug!("{} written {}", conn.trace_id(), write);

    let req_start = std::time::Instant::now();

    loop {
        poll.poll(&mut events, conn.timeout())?;

        'read: loop {
            if events.is_empty() {
                debug!("timed out");

                conn.on_timeout();

                break 'read;
            }

            let len = match socket.recv(&mut buf) {
                Ok(v) => v,

                Err(e) => {
                    if e.kind() == std::io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            debug!("{} got {} bytes", conn.trace_id(), len);

            // Process potentially coalesced packets.
            let read = match conn.recv(&mut buf[..len]) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("{} done reading", conn.trace_id());
                    break;
                },

                Err(e) => {
                    error!("{} recv failed: {:?}", conn.trace_id(), e);
                    conn.close(false, e.to_wire(), b"fail")?;
                    break 'read;
                },
            };

            debug!("{} processed {} bytes", conn.trace_id(), read);
        }

        if conn.is_closed() {
            info!("{} connection closed, {:?}", conn.trace_id(), conn.stats());
            break;
        }

        if conn.is_established() && http3_conn.is_none() {
            if conn.application_proto() != b"h3-18" {
                // TODO a better error code?
                conn.close(false, 0x0, b"I don't support your ALPNs")?;
                break;
            }

            let h3_config = quiche::h3::Config::new(0, 1024, 0, 0)?;

            let mut h3_conn =
                quiche::h3::Connection::with_transport(&mut conn, &h3_config)?;

            let mut path = String::from(url.path());

            if let Some(query) = url.query() {
                path.push('?');
                path.push_str(query);
            }

            let req = vec![
                quiche::h3::Header::new(":method", "GET"),
                quiche::h3::Header::new(":scheme", url.scheme()),
                quiche::h3::Header::new(":authority", url.host_str().unwrap()),
                quiche::h3::Header::new(":path", &path),
                quiche::h3::Header::new("user-agent", "quiche"),
            ];

            info!("{} sending HTTP request {:?}", conn.trace_id(), req);

            if let Err(e) = h3_conn.send_request(&mut conn, &req, true) {
                error!("{} failed to send request {:?}", conn.trace_id(), e);
                break;
            }

            http3_conn = Some(h3_conn);
        }

        if let Some(http3_conn) = &mut http3_conn {
            loop {
                match http3_conn.poll(&mut conn) {
                    Ok((stream_id, quiche::h3::Event::Headers(headers))) => {
                        info!(
                            "{} got response headers {:?} on stream id {}",
                            conn.trace_id(),
                            headers,
                            stream_id
                        );

                        if conn.stream_finished(stream_id) {
                            info!(
                                "{} response received in {:?}, closing...",
                                conn.trace_id(),
                                req_start.elapsed()
                            );

                            match conn.close(true, 0x00, b"kthxbye") {
                                // Already closed.
                                Ok(_) | Err(quiche::Error::Done) => (),

                                Err(e) => panic!("error closing conn: {:?}", e),
                            }
                        }
                    },

                    Ok((stream_id, quiche::h3::Event::Data(data))) => {
                        debug!(
                            "{} got response data of length {} in stream id {}",
                            conn.trace_id(),
                            data.len(),
                            stream_id
                        );

                        print!("{}", unsafe {
                            std::str::from_utf8_unchecked(&data)
                        });

                        if conn.stream_finished(stream_id) {
                            info!(
                                "{} response received in {:?}, closing...",
                                conn.trace_id(),
                                req_start.elapsed()
                            );

                            match conn.close(true, 0x00, b"kthxbye") {
                                // Already closed.
                                Ok(_) | Err(quiche::Error::Done) => (),

                                Err(e) => panic!("error closing conn: {:?}", e),
                            }
                        }
                    },

                    Err(quiche::h3::Error::Done) => {
                        break;
                    },

                    Err(e) => {
                        error!(
                            "{} HTTP/3 processing failed: {:?}",
                            conn.trace_id(),
                            e
                        );

                        break;
                    },
                }
            }
        }

        loop {
            let write = match conn.send(&mut out) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("{} done writing", conn.trace_id());
                    break;
                },

                Err(e) => {
                    error!("{} send failed: {:?}", conn.trace_id(), e);
                    conn.close(false, e.to_wire(), b"fail")?;
                    break;
                },
            };

            // TODO: coalesce packets.
            socket.send(&out[..write])?;

            debug!("{} written {}", conn.trace_id(), write);
        }

        if conn.is_closed() {
            info!("{} connection closed, {:?}", conn.trace_id(), conn.stats());
            break;
        }
    }

    Ok(())
}
<commit_msg>http3-client: close connection only once<commit_after>// Copyright (C) 2019, Cloudflare, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;

use ring::rand::*;

const LOCAL_CONN_ID_LEN: usize = 16;

const MAX_DATAGRAM_SIZE: usize = 1350;

const USAGE: &str = "Usage:
  http3-client [options] URL
  http3-client -h | --help

Options:
  --wire-version VERSION  The version number to send to the server [default: babababa].
  --no-verify             Don't verify server's certificate.
  -h --help               Show this screen.
";

fn main() -> Result<(), Box<std::error::Error>> {
    let mut buf = [0; 65535];
    let mut out = [0; MAX_DATAGRAM_SIZE];

    env_logger::init();

    let args = docopt::Docopt::new(USAGE)
        .and_then(|dopt| dopt.parse())
        .unwrap_or_else(|e| e.exit());

    let url = url::Url::parse(args.get_str("URL"))?;

    let socket = std::net::UdpSocket::bind("0.0.0.0:0")?;
    socket.connect(&url)?;

    let poll = mio::Poll::new()?;
    let mut events = mio::Events::with_capacity(1024);

    let socket = mio::net::UdpSocket::from_socket(socket)?;
    poll.register(
        &socket,
        mio::Token(0),
        mio::Ready::readable(),
        mio::PollOpt::edge(),
    )?;

    let mut scid = [0; LOCAL_CONN_ID_LEN];
    SystemRandom::new().fill(&mut scid[..])?;

    let version = args.get_str("--wire-version");
    let version = u32::from_str_radix(version, 16)?;

    let mut config = quiche::Config::new(version)?;

    config.verify_peer(true);

    config.set_application_protos(b"\x05h3-18")?;

    config.set_idle_timeout(30);
    config.set_max_packet_size(MAX_DATAGRAM_SIZE as u64);
    config.set_initial_max_data(10_000_000);
    config.set_initial_max_stream_data_bidi_local(1_000_000);
    config.set_initial_max_stream_data_bidi_remote(1_000_000);
    config.set_initial_max_stream_data_uni(1_000_000);
    config.set_initial_max_streams_bidi(100);
    config.set_initial_max_streams_uni(100);
    config.set_disable_migration(true);

    let mut http3_conn = None;

    if args.get_bool("--no-verify") {
        config.verify_peer(false);
    }

    if std::env::var_os("SSLKEYLOGFILE").is_some() {
        config.log_keys();
    }

    let mut conn = quiche::connect(url.domain(), &scid, &mut config)?;

    let write = match conn.send(&mut out) {
        Ok(v) => v,

        Err(e) => panic!("{} initial send failed: {:?}", conn.trace_id(), e),
    };

    socket.send(&out[..write])?;

    debug!("{} written {}", conn.trace_id(), write);

    let req_start = std::time::Instant::now();

    loop {
        poll.poll(&mut events, conn.timeout())?;

        'read: loop {
            if events.is_empty() {
                debug!("timed out");

                conn.on_timeout();

                break 'read;
            }

            let len = match socket.recv(&mut buf) {
                Ok(v) => v,

                Err(e) => {
                    if e.kind() == std::io::ErrorKind::WouldBlock {
                        debug!("recv() would block");
                        break 'read;
                    }

                    panic!("recv() failed: {:?}", e);
                },
            };

            debug!("{} got {} bytes", conn.trace_id(), len);

            // Process potentially coalesced packets.
            let read = match conn.recv(&mut buf[..len]) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("{} done reading", conn.trace_id());
                    break;
                },

                Err(e) => {
                    error!("{} recv failed: {:?}", conn.trace_id(), e);
                    conn.close(false, e.to_wire(), b"fail")?;
                    break 'read;
                },
            };

            debug!("{} processed {} bytes", conn.trace_id(), read);
        }

        if conn.is_closed() {
            info!("{} connection closed, {:?}", conn.trace_id(), conn.stats());
            break;
        }

        if conn.is_established() && http3_conn.is_none() {
            if conn.application_proto() != b"h3-18" {
                // TODO a better error code?
                conn.close(false, 0x0, b"I don't support your ALPNs")?;
                break;
            }

            let h3_config = quiche::h3::Config::new(0, 1024, 0, 0)?;

            let mut h3_conn =
                quiche::h3::Connection::with_transport(&mut conn, &h3_config)?;

            let mut path = String::from(url.path());

            if let Some(query) = url.query() {
                path.push('?');
                path.push_str(query);
            }

            let req = vec![
                quiche::h3::Header::new(":method", "GET"),
                quiche::h3::Header::new(":scheme", url.scheme()),
                quiche::h3::Header::new(":authority", url.host_str().unwrap()),
                quiche::h3::Header::new(":path", &path),
                quiche::h3::Header::new("user-agent", "quiche"),
            ];

            info!("{} sending HTTP request {:?}", conn.trace_id(), req);

            if let Err(e) = h3_conn.send_request(&mut conn, &req, true) {
                error!("{} failed to send request {:?}", conn.trace_id(), e);
                break;
            }

            http3_conn = Some(h3_conn);
        }

        if let Some(http3_conn) = &mut http3_conn {
            loop {
                match http3_conn.poll(&mut conn) {
                    Ok((stream_id, quiche::h3::Event::Headers(headers))) => {
                        info!(
                            "{} got response headers {:?} on stream id {}",
                            conn.trace_id(),
                            headers,
                            stream_id
                        );
                    },

                    Ok((stream_id, quiche::h3::Event::Data(data))) => {
                        debug!(
                            "{} got response data of length {} in stream id {}",
                            conn.trace_id(),
                            data.len(),
                            stream_id
                        );

                        print!("{}", unsafe {
                            std::str::from_utf8_unchecked(&data)
                        });

                        if conn.stream_finished(stream_id) {
                            info!(
                                "{} response received in {:?}, closing...",
                                conn.trace_id(),
                                req_start.elapsed()
                            );

                            match conn.close(true, 0x00, b"kthxbye") {
                                // Already closed.
                                Ok(_) | Err(quiche::Error::Done) => (),

                                Err(e) => panic!("error closing conn: {:?}", e),
                            }
                        }
                    },

                    Err(quiche::h3::Error::Done) => {
                        break;
                    },

                    Err(e) => {
                        error!(
                            "{} HTTP/3 processing failed: {:?}",
                            conn.trace_id(),
                            e
                        );

                        break;
                    },
                }
            }
        }

        loop {
            let write = match conn.send(&mut out) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    debug!("{} done writing", conn.trace_id());
                    break;
                },

                Err(e) => {
                    error!("{} send failed: {:?}", conn.trace_id(), e);
                    conn.close(false, e.to_wire(), b"fail")?;
                    break;
                },
            };

            // TODO: coalesce packets.
            socket.send(&out[..write])?;

            debug!("{} written {}", conn.trace_id(), write);
        }

        if conn.is_closed() {
            info!("{} connection closed, {:?}", conn.trace_id(), conn.stats());
            break;
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;

use textwrap::{core, wrap_algorithms, WordSeparator};

#[wasm_bindgen]
extern "C" {
    // https://github.com/rustwasm/wasm-bindgen/issues/2069#issuecomment-774038243
    type ExtendedTextMetrics;

    #[wasm_bindgen(method, getter, js_name = actualBoundingBoxLeft)]
    fn actual_bounding_box_left(this: &ExtendedTextMetrics) -> f64;

    #[wasm_bindgen(method, getter, js_name = actualBoundingBoxRight)]
    fn actual_bounding_box_right(this: &ExtendedTextMetrics) -> f64;

    #[wasm_bindgen(method, getter, js_name = actualBoundingBoxAscent)]
    fn actual_bounding_box_ascent(this: &ExtendedTextMetrics) -> f64;

    #[wasm_bindgen(method, getter, js_name = actualBoundingBoxDescent)]
    fn actual_bounding_box_descent(this: &ExtendedTextMetrics) -> f64;

    // TODO: Enable when Firefox and Edge support these methods, see
    // https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics
    //
    // #[wasm_bindgen(method, getter, js_name = fontBoundingBoxAscent)]
    // fn font_bounding_box_ascent(this: &ExtendedTextMetrics) -> f64;
    //
    // #[wasm_bindgen(method, getter, js_name = fontBoundingBoxDescent)]
    // fn font_bounding_box_descent(this: &ExtendedTextMetrics) -> f64;

    #[wasm_bindgen(method, getter)]
    fn width(this: &ExtendedTextMetrics) -> f64;
}

fn canvas_width(ctx: &web_sys::CanvasRenderingContext2d, text: &str) -> f64 {
    ctx.measure_text(text).unwrap().width()
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct CanvasWord<'a> {
    word: &'a str,
    width: f64,
    whitespace: &'a str,
    whitespace_width: f64,
    penalty: &'a str,
    penalty_width: f64,
}

impl<'a> CanvasWord<'a> {
    fn from(ctx: &'_ web_sys::CanvasRenderingContext2d, word: core::Word<'a>) -> Self {
        CanvasWord {
            word: word.word,
            width: canvas_width(ctx, word.word),
            whitespace: word.whitespace,
            whitespace_width: canvas_width(ctx, word.whitespace),
            penalty: word.penalty,
            penalty_width: canvas_width(ctx, word.penalty),
        }
    }
}

const PRECISION: usize = 10;

impl core::Fragment for CanvasWord<'_> {
    #[inline]
    fn width(&self) -> usize {
        (self.width * PRECISION as f64) as usize
    }

    #[inline]
    fn whitespace_width(&self) -> usize {
        (self.whitespace_width * PRECISION as f64) as usize
    }

    #[inline]
    fn penalty_width(&self) -> usize {
        (self.penalty_width * PRECISION as f64) as usize
    }
}

fn draw_path(
    ctx: &web_sys::CanvasRenderingContext2d,
    style: &str,
    (mut x, mut y): (f64, f64),
    steps: &[(f64, f64)],
) {
    ctx.save();
    ctx.set_stroke_style(&style.into());
    ctx.begin_path();
    ctx.move_to(x, y);
    for (delta_x, delta_y) in steps {
        x += delta_x;
        y += delta_y;
        ctx.line_to(x, y);
    }
    ctx.stroke();
    ctx.restore();
}

// We offset all text by the width of the round slider. This ensures
// no clipping due to anti-aliasing.
const X_OFFSET: f64 = 8.0;

fn draw_word(
    ctx: &web_sys::CanvasRenderingContext2d,
    x: f64,
    y: f64,
    word: &CanvasWord,
    last_word: bool,
) -> Result<(), JsValue> {
    ctx.fill_text(word.word, x, y)?;

    draw_path(
        ctx,
        "orange",
        (x, y - 10.0),
        &[(0.0, 10.0), (word.width, 0.0)],
    );

    ctx.save();
    ctx.set_font("10px sans-serif");
    ctx.set_text_align("center");
    ctx.set_text_baseline("top");
    ctx.fill_text(
        &format!("{:.1}px", word.width),
        x + word.width / 2.0,
        y + 3.0,
    )?;
    ctx.restore();

    let x = x + word.width;
    if last_word {
        ctx.fill_text(word.penalty, x, y)?;
        draw_path(ctx, "red", (x, y), &[(word.penalty_width, 0.0)]);
    } else {
        ctx.fill_text(word.whitespace, x, y)?;
        draw_path(ctx, "lightblue", (x, y), &[(word.whitespace_width, 0.0)]);
    }

    Ok(())
}

#[wasm_bindgen]
pub fn draw_wrapped_text(
    ctx: &web_sys::CanvasRenderingContext2d,
    text: &str,
    width: usize,
) -> Result<(), JsValue> {
    console_error_panic_hook::set_once();

    let metrics: web_sys::TextMetrics = ctx.measure_text("│").unwrap();
    let metrics: ExtendedTextMetrics = metrics.unchecked_into();
    // TODO: use metrics.font_bounding_box_ascent() +
    // metrics.font_bounding_box_descent() and measure "" instead of a
    // tall character when supported by Firefox.
    let line_height = metrics.actual_bounding_box_ascent() + metrics.actual_bounding_box_descent();
    let baseline_distance = 1.5 * line_height;
    let options = textwrap::Options::from(width);

    let mut lineno = 0;
    for line in text.split('\n') {
        let words = options.word_separator.find_words(line);
        let split_words = core::split_words(words, &options);

        let canvas_words = split_words
            .map(|word| CanvasWord::from(ctx, word))
            .collect::<Vec<_>>();

        let line_lengths = [width * PRECISION];
        let wrapped_words = wrap_algorithms::wrap_first_fit(&canvas_words, &line_lengths);

        for words_in_line in wrapped_words {
            lineno += 1;
            let mut x = X_OFFSET;
            let y = baseline_distance * lineno as f64;

            for (i, word) in words_in_line.iter().enumerate() {
                let last_word = i == words_in_line.len() - 1;
                draw_word(ctx, x, y, word, last_word)?;
                x += word.width;
                x += if last_word {
                    word.penalty_width
                } else {
                    word.whitespace_width
                };
            }

            ctx.save();
            ctx.set_font("10px sans-serif");
            ctx.fill_text(
                &format!("{:.1}px", x - X_OFFSET),
                1.5 * X_OFFSET + width as f64,
                y,
            )?;
            ctx.restore();
        }
    }

    draw_path(
        ctx,
        "blue",
        (
            X_OFFSET + width as f64,
            metrics.actual_bounding_box_ascent(),
        ),
        &[(0.0, baseline_distance * lineno as f64)],
    );

    Ok(())
}
<commit_msg>Fix Wasm demo after #361<commit_after>use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;

use textwrap::{core, wrap_algorithms, WordSeparator};

#[wasm_bindgen]
extern "C" {
    // https://github.com/rustwasm/wasm-bindgen/issues/2069#issuecomment-774038243
    type ExtendedTextMetrics;

    #[wasm_bindgen(method, getter, js_name = actualBoundingBoxLeft)]
    fn actual_bounding_box_left(this: &ExtendedTextMetrics) -> f64;

    #[wasm_bindgen(method, getter, js_name = actualBoundingBoxRight)]
    fn actual_bounding_box_right(this: &ExtendedTextMetrics) -> f64;

    #[wasm_bindgen(method, getter, js_name = actualBoundingBoxAscent)]
    fn actual_bounding_box_ascent(this: &ExtendedTextMetrics) -> f64;

    #[wasm_bindgen(method, getter, js_name = actualBoundingBoxDescent)]
    fn actual_bounding_box_descent(this: &ExtendedTextMetrics) -> f64;

    // TODO: Enable when Firefox and Edge support these methods, see
    // https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics
    //
    // #[wasm_bindgen(method, getter, js_name = fontBoundingBoxAscent)]
    // fn font_bounding_box_ascent(this: &ExtendedTextMetrics) -> f64;
    //
    // #[wasm_bindgen(method, getter, js_name = fontBoundingBoxDescent)]
    // fn font_bounding_box_descent(this: &ExtendedTextMetrics) -> f64;

    #[wasm_bindgen(method, getter)]
    fn width(this: &ExtendedTextMetrics) -> f64;
}

fn canvas_width(ctx: &web_sys::CanvasRenderingContext2d, text: &str) -> f64 {
    ctx.measure_text(text).unwrap().width()
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct CanvasWord<'a> {
    word: &'a str,
    width: f64,
    whitespace: &'a str,
    whitespace_width: f64,
    penalty: &'a str,
    penalty_width: f64,
}

impl<'a> CanvasWord<'a> {
    fn from(ctx: &'_ web_sys::CanvasRenderingContext2d, word: core::Word<'a>) -> Self {
        CanvasWord {
            word: word.word,
            width: canvas_width(ctx, word.word),
            whitespace: word.whitespace,
            whitespace_width: canvas_width(ctx, word.whitespace),
            penalty: word.penalty,
            penalty_width: canvas_width(ctx, word.penalty),
        }
    }
}

const PRECISION: usize = 10;

impl core::Fragment for CanvasWord<'_> {
    #[inline]
    fn width(&self) -> usize {
        (self.width * PRECISION as f64) as usize
    }

    #[inline]
    fn whitespace_width(&self) -> usize {
        (self.whitespace_width * PRECISION as f64) as usize
    }

    #[inline]
    fn penalty_width(&self) -> usize {
        (self.penalty_width * PRECISION as f64) as usize
    }
}

fn draw_path(
    ctx: &web_sys::CanvasRenderingContext2d,
    style: &str,
    (mut x, mut y): (f64, f64),
    steps: &[(f64, f64)],
) {
    ctx.save();
    ctx.set_stroke_style(&style.into());
    ctx.begin_path();
    ctx.move_to(x, y);
    for (delta_x, delta_y) in steps {
        x += delta_x;
        y += delta_y;
        ctx.line_to(x, y);
    }
    ctx.stroke();
    ctx.restore();
}

// We offset all text by the width of the round slider. This ensures
// no clipping due to anti-aliasing.
const X_OFFSET: f64 = 8.0;

fn draw_word(
    ctx: &web_sys::CanvasRenderingContext2d,
    x: f64,
    y: f64,
    word: &CanvasWord,
    last_word: bool,
) -> Result<(), JsValue> {
    ctx.fill_text(word.word, x, y)?;

    draw_path(
        ctx,
        "orange",
        (x, y - 10.0),
        &[(0.0, 10.0), (word.width, 0.0)],
    );

    ctx.save();
    ctx.set_font("10px sans-serif");
    ctx.set_text_align("center");
    ctx.set_text_baseline("top");
    ctx.fill_text(
        &format!("{:.1}px", word.width),
        x + word.width / 2.0,
        y + 3.0,
    )?;
    ctx.restore();

    let x = x + word.width;
    if last_word {
        ctx.fill_text(word.penalty, x, y)?;
        draw_path(ctx, "red", (x, y), &[(word.penalty_width, 0.0)]);
    } else {
        ctx.fill_text(word.whitespace, x, y)?;
        draw_path(ctx, "lightblue", (x, y), &[(word.whitespace_width, 0.0)]);
    }

    Ok(())
}

#[wasm_bindgen]
pub fn draw_wrapped_text(
    ctx: &web_sys::CanvasRenderingContext2d,
    text: &str,
    width: usize,
) -> Result<(), JsValue> {
    console_error_panic_hook::set_once();

    let metrics: web_sys::TextMetrics = ctx.measure_text("│").unwrap();
    let metrics: ExtendedTextMetrics = metrics.unchecked_into();
    // TODO: use metrics.font_bounding_box_ascent() +
    // metrics.font_bounding_box_descent() and measure "" instead of a
    // tall character when supported by Firefox.
    let line_height = metrics.actual_bounding_box_ascent() + metrics.actual_bounding_box_descent();
    let baseline_distance = 1.5 * line_height;
    let options = textwrap::Options::from(width);

    let mut lineno = 0;
    for line in text.split('\n') {
        let words = options.word_separator.find_words(line);
        let split_words = core::split_words(words, &options.splitter);

        let canvas_words = split_words
            .map(|word| CanvasWord::from(ctx, word))
            .collect::<Vec<_>>();

        let line_lengths = [width * PRECISION];
        let wrapped_words = wrap_algorithms::wrap_first_fit(&canvas_words, &line_lengths);

        for words_in_line in wrapped_words {
            lineno += 1;
            let mut x = X_OFFSET;
            let y = baseline_distance * lineno as f64;

            for (i, word) in words_in_line.iter().enumerate() {
                let last_word = i == words_in_line.len() - 1;
                draw_word(ctx, x, y, word, last_word)?;
                x += word.width;
                x += if last_word {
                    word.penalty_width
                } else {
                    word.whitespace_width
                };
            }

            ctx.save();
            ctx.set_font("10px sans-serif");
            ctx.fill_text(
                &format!("{:.1}px", x - X_OFFSET),
                1.5 * X_OFFSET + width as f64,
                y,
            )?;
            ctx.restore();
        }
    }

    draw_path(
        ctx,
        "blue",
        (
            X_OFFSET + width as f64,
            metrics.actual_bounding_box_ascent(),
        ),
        &[(0.0, baseline_distance * lineno as f64)],
    );

    Ok(())
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate itertools;

use std::collections::HashMap;

use self::itertools::Itertools;
use self::rustc_serialize::json;

use ngrams::ngrams;

pub struct Model {
    pub ngram_ranks: HashMap<String, usize>,
}

impl Model {
    pub fn build_from_text(text: &str) -> Model {
        let mut ngram_counts = HashMap::new();
        for n in 1..6 {
            for ngram in ngrams(text, n) {
                // If you don't want to unecessarily allocate strings, this is
                // the only way to do it. This RFC should fix this if it ever
                // gets accepted: // https://github.com/rust-lang/rfcs/pull/1533
                if let Some(count) = ngram_counts.get_mut(ngram) {
                    *count += 1;
                    continue;
                }
                ngram_counts.insert(ngram.to_owned(), 1);
            }
        }

        let ngrams = ngram_counts
            .into_iter()
            .sorted_by(|a, b| Ord::cmp(&b.1, &a.1))
            .into_iter()
            .map(|(ngram, _count)| ngram);

        // Nicer way to build a hash map.
        Model { ngram_ranks: ngrams.enumerate().map(|(a, b)| (b, a)).collect() }
    }

    pub fn deserialize(bytes: Vec<u8>) -> Model {
        let string = String::from_utf8(bytes).unwrap();
        let ngram_ranks = json::decode(string.as_str()).unwrap();
        Model { ngram_ranks: ngram_ranks }
    }

    pub fn serialize(&self) -> Vec<u8> {
        json::encode(&self.ngram_ranks).unwrap().into_bytes()
    }

    pub fn compare(&self, other: &Model) -> usize {
        let max_difference = other.ngram_ranks.len();
        let mut difference = 0;
        for (ngram, rank) in self.ngram_ranks.iter() {
            difference += match other.ngram_ranks.get(ngram) {
                Some(other_rank) => get_difference(*rank, *other_rank),
                None => max_difference,
            }
        }
        difference
    }
}

fn get_difference(a: usize, b: usize) -> usize {
    if a > b { a - b } else { b - a }
}
<commit_msg>Restrict the number of ngrams used for classification<commit_after>extern crate rustc_serialize;
extern crate itertools;

use std::collections::HashMap;

use self::itertools::Itertools;
use self::rustc_serialize::json;

use ngrams::ngrams;

pub struct Model {
    pub ngram_ranks: HashMap<String, usize>,
}

impl Model {
    pub fn build_from_text(text: &str) -> Model {
        let mut ngram_counts = HashMap::new();
        for n in 1..6 {
            for ngram in ngrams(text, n) {
                // If you don't want to unecessarily allocate strings, this is
                // the only way to do it. This RFC should fix this if it ever
                // gets accepted: // https://github.com/rust-lang/rfcs/pull/1533
                if let Some(count) = ngram_counts.get_mut(ngram) {
                    *count += 1;
                    continue;
                }
                ngram_counts.insert(ngram.to_owned(), 1);
            }
        }

        let ngrams = ngram_counts
            .into_iter()
            .sorted_by(|a, b| Ord::cmp(&b.1, &a.1))
            .into_iter()
            .take(300)
            .map(|(ngram, _count)| ngram);

        // Nicer way to build a hash map.
        Model { ngram_ranks: ngrams.enumerate().map(|(a, b)| (b, a)).collect() }
    }

    pub fn deserialize(bytes: Vec<u8>) -> Model {
        let string = String::from_utf8(bytes).unwrap();
        let ngram_ranks = json::decode(string.as_str()).unwrap();
        Model { ngram_ranks: ngram_ranks }
    }

    pub fn serialize(&self) -> Vec<u8> {
        json::encode(&self.ngram_ranks).unwrap().into_bytes()
    }

    pub fn compare(&self, other: &Model) -> usize {
        let max_difference = other.ngram_ranks.len();
        let mut difference = 0;
        for (ngram, rank) in self.ngram_ranks.iter() {
            difference += match other.ngram_ranks.get(ngram) {
                Some(other_rank) => get_difference(*rank, *other_rank),
                None => max_difference,
            }
        }
        difference
    }
}

fn get_difference(a: usize, b: usize) -> usize {
    if a > b { a - b } else { b - a }
}
<|endoftext|>


<commit_before>extern crate piston_window;
extern crate image as im;

use im::GenericImage;
use piston_window::*;

fn main() {
    let opengl = OpenGL::V3_2;
    let (width, height) = (300, 300);
    let window: PistonWindow =
        WindowSettings::new("piston: paint", (width, height))
        .exit_on_esc(true)
        .opengl(opengl)
        .build()
        .unwrap();

    let mut canvas = im::ImageBuffer::new(width, height);
    let mut draw = false;
    let mut texture = Texture::from_image(
            &mut *window.factory.borrow_mut(),
            &canvas,
            &TextureSettings::new()
        ).unwrap();
    for e in window {
        e.draw_2d(|c, g| {
            clear([1.0; 4], g);
            image(&texture, c.transform, g);
        });
        if let Some(button) = e.press_args() {
            if button == Button::Mouse(MouseButton::Left) {
                draw = true
            }
        };
        if let Some(button) = e.release_args() {
            if button == Button::Mouse(MouseButton::Left) {
                draw = false
            }
        };
        if draw {
            if let Some(pos) = e.mouse_cursor_args() {
                let (x, y) = (pos[0] as u32, pos[1] as u32);
                if x < width && y < height {
                    canvas.put_pixel(x, y, im::Rgba([0, 0, 0, 255]));
                    texture.update(&mut*e.factory.borrow_mut(), &canvas).unwrap();
                }
            };
        }
    }
}

<commit_msg>connect the dots in paint example app to smooth out line<commit_after>extern crate piston_window;
extern crate image as im;
extern crate vecmath;

use im::GenericImage;
use piston_window::*;
use vecmath::*;

fn main() {
    let opengl = OpenGL::V3_2;
    let (width, height) = (300, 300);
    let window: PistonWindow =
        WindowSettings::new("piston: paint", (width, height))
        .exit_on_esc(true)
        .opengl(opengl)
        .build()
        .unwrap();

    let mut canvas = im::ImageBuffer::new(width, height);
    let mut draw = false;
    let mut texture = Texture::from_image(
            &mut *window.factory.borrow_mut(),
            &canvas,
            &TextureSettings::new()
        ).unwrap();

    let mut last_pos = None;

    for e in window {
        e.draw_2d(|c, g| {
            clear([1.0; 4], g);
            image(&texture, c.transform, g);
        });
        if let Some(button) = e.press_args() {
            if button == Button::Mouse(MouseButton::Left) {
                draw = true;
                last_pos = e.mouse_cursor_args()
            }
        };
        if let Some(button) = e.release_args() {
            if button == Button::Mouse(MouseButton::Left) {
                draw = false;
                last_pos = None
            }
        };
        if draw {
            if let Some(pos) = e.mouse_cursor_args() {
                let (x, y) = (pos[0] as f32, pos[1] as f32);

                match last_pos {
                    Some(p) => {
                        let (last_x, last_y) = (p[0] as f32, p[1] as f32);
                        let distance = vec2_len(vec2_sub(p, pos)) as u32;

                        for i in 0..distance {
                            let diff_x = (x - last_x) as f32;
                            let diff_y = (y - last_y) as f32;
                            let delta = i as f32 / distance as f32;
                            let new_x = (last_x + (diff_x * delta)) as u32;
                            let new_y = (last_y + (diff_y * delta)) as u32;
                            if new_x < width && new_y < height {
                                canvas.put_pixel(new_x, new_y, im::Rgba([0, 0, 0, 255]));
                                texture.update(&mut*e.factory.borrow_mut(), &canvas).unwrap();
                            };
                        };
                    },
                    None => {}
                };

                last_pos = Some(pos)
            };

        }
    }
}

<|endoftext|>


<commit_before>use syntax::{ast, codemap};
use syntax::ext::base;
use syntax::parse::token;

use syntax::ptr::P;
use syntax::parse::parser::Parser;

use test::Test;
use bench::Bench;
use describe::{DescribeState, TestBlock, BenchBlock, DescribeBlock};

/// Trait that means something can be parsed with a configuration.
pub trait Parse<Cfg> {
    /// Parse Self from a Parser and a configuration object.
    fn parse(&mut Parser, Cfg) -> Self;
}

impl Parse<bool> for Test {
    fn parse(parser: &mut Parser, failing: bool) -> Test {
        // Description of this test.
        let (description, _) = parser.parse_str();

        Test {
            // Get as a String
            description: description.get().to_string(),

            // The associated block
            block: parser.parse_block(),

            failing: failing
        }
    }
}

impl Parse<()> for Bench {
    fn parse(parser: &mut Parser, _: ()) -> Bench {
        // Description of this benchmark
        let (description, _) = parser.parse_str();

        let name = match (parser.bump_and_get(), parser.parse_ident(), parser.bump_and_get()) {
            (token::LPAREN, ident, token::RPAREN) => { ident },

            (one, two, three) => {
                parser.fatal(format!("Expected `($ident)`, found {}{}{}", one, two, three).as_slice())
            }
        };

        Bench {
            description: description.get().to_string(),
            block: parser.parse_block(),
            bench: P(name)
        }
    }
}

static BEFORE_EACH: &'static str = "before_each";
static AFTER_EACH:  &'static str = "after_each";
static BEFORE:      &'static str = "before";
static AFTER:       &'static str = "after";
static IT:          &'static str = "it";
static DESCRIBE:    &'static str = "describe";
static FAILING:     &'static str = "failing";
static BENCH:       &'static str = "bench";

impl<'a, 'b> Parse<(codemap::Span, &'a mut base::ExtCtxt<'b>, Option<ast::Ident>)> for DescribeState {
    fn parse(parser: &mut Parser,
             (sp, cx, name): (codemap::Span, &'a mut base::ExtCtxt, Option<ast::Ident>)) -> DescribeState {
        let mut state = DescribeState {
            name: None, before: None, after: None,
            before_each: None, after_each: None, subblocks: vec![]
        };

        state.name = match name {
            // Top-level describe block.
            Some(name) => Some(name),
            // Nested describe block.
            None => {
                // Get the name of this describe block
                let name = parser.parse_ident();
                // Move past the opening {
                try(parser, token::LBRACE, "{ after the name of a describe! block");
                Some(name)
            }
        };

        // Now parse all tests and subsections:
        while parser.token != token::RBRACE && parser.token != token::EOF {
            // Get the name of this block, must be either:
            //     - before_each
            //     - after_each
            //     - before
            //     - after
            //     - it
            //     - failing
            //     - bench
            //     - describe!
            //
            // Any other top-level idents are not allowed.
            let block_name = parser.parse_ident();

            match block_name.as_str() {
                BEFORE_EACH => {
                    if state.before_each.is_some() { parser.fatal("Only one `before_each` block is allowed per `describe!` block.") }
                    state.before_each = Some(parser.parse_block());
                },

                AFTER_EACH => {
                    if state.after_each.is_some() { parser.fatal("Only one `after_each` block is allowed per `describe!` block.") }
                    state.after_each = Some(parser.parse_block());
                },

                BEFORE => {
                    if state.before.is_some() { parser.fatal("Only one `before` block is allowed per `describe!` block.") }
                    state.before = Some(parser.parse_block());
                },

                AFTER => {
                    if state.after.is_some() { parser.fatal("Only one `after` block is allowed per `describe!` block.") }
                    state.after = Some(parser.parse_block());
                },

                // Regular `#[test]`.
                IT => { state.subblocks.push(TestBlock(Parse::parse(parser, false))) },

                // `#[should_fail]` test.
                FAILING => { state.subblocks.push(TestBlock(Parse::parse(parser, true))) },

                // #[bench] benchmark.
                BENCH => { state.subblocks.push(BenchBlock(Parse::parse(parser, ()))) }

                // Nested `describe!` block.
                DESCRIBE => {
                    // Skip over the ! in describe!
                    try(parser, token::NOT, "!");

                    // Parse this subblock, generate new item.
                    state.subblocks.push(DescribeBlock(Parse::parse(parser, (sp, &mut*cx, None))));

                    // Move past closing bracket and paren.
                    //
                    // This has to go in here because it is EOF on the highest-level invocation.
                    try(parser, token::RBRACE, "}} to close `describe!`")
                }

                otherwise => { illegal(parser, otherwise) }
            }
        }

        state
    }
}

fn try(parser: &mut Parser, token: token::Token, err: &str) {
    let real = parser.bump_and_get();
    if real != token {
        parser.fatal(format!("Expected {}, but found `{}`", err, real).as_slice())
    }
}

fn illegal(parser: &mut Parser, banned: &str) {
    // Illegal block name.
    let span = parser.span;
    parser.span_fatal(span, format!("Expected one of: `{}`, but found: `{}`",
        format!("{}, {}, {}, {}, {}, {}, {}, {}",
                BEFORE_EACH, AFTER_EACH, BEFORE, AFTER,
                IT, BENCH, FAILING, DESCRIBE).as_slice(),
        banned).as_slice());
}

<commit_msg>(fix) static to const.<commit_after>use syntax::{ast, codemap};
use syntax::ext::base;
use syntax::parse::token;

use syntax::ptr::P;
use syntax::parse::parser::Parser;

use test::Test;
use bench::Bench;
use describe::{DescribeState, TestBlock, BenchBlock, DescribeBlock};

/// Trait that means something can be parsed with a configuration.
pub trait Parse<Cfg> {
    /// Parse Self from a Parser and a configuration object.
    fn parse(&mut Parser, Cfg) -> Self;
}

impl Parse<bool> for Test {
    fn parse(parser: &mut Parser, failing: bool) -> Test {
        // Description of this test.
        let (description, _) = parser.parse_str();

        Test {
            // Get as a String
            description: description.get().to_string(),

            // The associated block
            block: parser.parse_block(),

            failing: failing
        }
    }
}

impl Parse<()> for Bench {
    fn parse(parser: &mut Parser, _: ()) -> Bench {
        // Description of this benchmark
        let (description, _) = parser.parse_str();

        let name = match (parser.bump_and_get(), parser.parse_ident(), parser.bump_and_get()) {
            (token::LPAREN, ident, token::RPAREN) => { ident },

            (one, two, three) => {
                parser.fatal(format!("Expected `($ident)`, found {}{}{}", one, two, three).as_slice())
            }
        };

        Bench {
            description: description.get().to_string(),
            block: parser.parse_block(),
            bench: P(name)
        }
    }
}

const BEFORE_EACH: &'static str = "before_each";
const AFTER_EACH:  &'static str = "after_each";
const BEFORE:      &'static str = "before";
const AFTER:       &'static str = "after";
const IT:          &'static str = "it";
const DESCRIBE:    &'static str = "describe";
const FAILING:     &'static str = "failing";
const BENCH:       &'static str = "bench";

impl<'a, 'b> Parse<(codemap::Span, &'a mut base::ExtCtxt<'b>, Option<ast::Ident>)> for DescribeState {
    fn parse(parser: &mut Parser,
             (sp, cx, name): (codemap::Span, &'a mut base::ExtCtxt, Option<ast::Ident>)) -> DescribeState {
        let mut state = DescribeState {
            name: None, before: None, after: None,
            before_each: None, after_each: None, subblocks: vec![]
        };

        state.name = match name {
            // Top-level describe block.
            Some(name) => Some(name),
            // Nested describe block.
            None => {
                // Get the name of this describe block
                let name = parser.parse_ident();
                // Move past the opening {
                try(parser, token::LBRACE, "{ after the name of a describe! block");
                Some(name)
            }
        };

        // Now parse all tests and subsections:
        while parser.token != token::RBRACE && parser.token != token::EOF {
            // Get the name of this block, must be either:
            //     - before_each
            //     - after_each
            //     - before
            //     - after
            //     - it
            //     - failing
            //     - bench
            //     - describe!
            //
            // Any other top-level idents are not allowed.
            let block_name = parser.parse_ident();

            match block_name.as_str() {
                BEFORE_EACH => {
                    if state.before_each.is_some() { parser.fatal("Only one `before_each` block is allowed per `describe!` block.") }
                    state.before_each = Some(parser.parse_block());
                },

                AFTER_EACH => {
                    if state.after_each.is_some() { parser.fatal("Only one `after_each` block is allowed per `describe!` block.") }
                    state.after_each = Some(parser.parse_block());
                },

                BEFORE => {
                    if state.before.is_some() { parser.fatal("Only one `before` block is allowed per `describe!` block.") }
                    state.before = Some(parser.parse_block());
                },

                AFTER => {
                    if state.after.is_some() { parser.fatal("Only one `after` block is allowed per `describe!` block.") }
                    state.after = Some(parser.parse_block());
                },

                // Regular `#[test]`.
                IT => { state.subblocks.push(TestBlock(Parse::parse(parser, false))) },

                // `#[should_fail]` test.
                FAILING => { state.subblocks.push(TestBlock(Parse::parse(parser, true))) },

                // #[bench] benchmark.
                BENCH => { state.subblocks.push(BenchBlock(Parse::parse(parser, ()))) }

                // Nested `describe!` block.
                DESCRIBE => {
                    // Skip over the ! in describe!
                    try(parser, token::NOT, "!");

                    // Parse this subblock, generate new item.
                    state.subblocks.push(DescribeBlock(Parse::parse(parser, (sp, &mut*cx, None))));

                    // Move past closing bracket and paren.
                    //
                    // This has to go in here because it is EOF on the highest-level invocation.
                    try(parser, token::RBRACE, "}} to close `describe!`")
                }

                otherwise => { illegal(parser, otherwise) }
            }
        }

        state
    }
}

fn try(parser: &mut Parser, token: token::Token, err: &str) {
    let real = parser.bump_and_get();
    if real != token {
        parser.fatal(format!("Expected {}, but found `{}`", err, real).as_slice())
    }
}

fn illegal(parser: &mut Parser, banned: &str) {
    // Illegal block name.
    let span = parser.span;
    parser.span_fatal(span, format!("Expected one of: `{}`, but found: `{}`",
        format!("{}, {}, {}, {}, {}, {}, {}, {}",
                BEFORE_EACH, AFTER_EACH, BEFORE, AFTER,
                IT, BENCH, FAILING, DESCRIBE).as_slice(),
        banned).as_slice());
}

<|endoftext|>


<commit_before>use syntax::{ast, codemap};
use syntax::ext::base;
use syntax::parse::token;

use syntax::ptr::P;
use syntax::parse::parser::Parser;

use test::Test;
use bench::Bench;
use describe::{DescribeState, TestBlock, BenchBlock, DescribeBlock};

/// Trait that means something can be parsed with a configuration.
pub trait Parse<Cfg> {
    /// Parse Self from a Parser and a configuration object.
    fn parse(&mut Parser, Cfg) -> Self;
}

impl Parse<bool> for Test {
    fn parse(parser: &mut Parser, failing: bool) -> Test {
        // Description of this test.
        let (description, _) = parser.parse_str();

        Test {
            // Get as a String
            description: description.get().to_string(),

            // The associated block
            block: parser.parse_block(),

            failing: failing
        }
    }
}

impl Parse<()> for Bench {
    fn parse(parser: &mut Parser, _: ()) -> Bench {
        // Description of this benchmark
        let (description, _) = parser.parse_str();

        let name = match (parser.bump_and_get(), parser.parse_ident(), parser.bump_and_get()) {
            (token::LPAREN, ident, token::RPAREN) => { ident },

            (one, two, three) => {
                parser.fatal(format!("Expected `($ident)`, found {}{}{}", one, two, three).as_slice())
            }
        };

        Bench {
            description: description.get().to_string(),
            block: parser.parse_block(),
            bench: P(name)
        }
    }
}

const BEFORE_EACH: &'static str = "before_each";
const AFTER_EACH:  &'static str = "after_each";
const BEFORE:      &'static str = "before";
const AFTER:       &'static str = "after";
const IT:          &'static str = "it";
const DESCRIBE:    &'static str = "describe";
const FAILING:     &'static str = "failing";
const BENCH:       &'static str = "bench";

impl<'a, 'b> Parse<(codemap::Span, &'a mut base::ExtCtxt<'b>, Option<ast::Ident>)> for DescribeState {
    fn parse(parser: &mut Parser,
             (sp, cx, name): (codemap::Span, &'a mut base::ExtCtxt, Option<ast::Ident>)) -> DescribeState {
        let mut state = DescribeState {
            name: None, before: None, after: None,
            before_each: None, after_each: None, subblocks: vec![]
        };

        state.name = match name {
            // Top-level describe block.
            Some(name) => Some(name),
            // Nested describe block.
            None => {
                // Get the name of this describe block
                let name = parser.parse_ident();
                // Move past the opening {
                try(parser, token::LBRACE, "{ after the name of a describe! block");
                Some(name)
            }
        };

        // Now parse all tests and subsections:
        while parser.token != token::RBRACE && parser.token != token::EOF {
            // Get the name of this block, must be either:
            //     - before_each
            //     - after_each
            //     - before
            //     - after
            //     - it
            //     - failing
            //     - bench
            //     - describe!
            //
            // Any other top-level idents are not allowed.
            let block_name = parser.parse_ident();

            match block_name.as_str() {
                BEFORE_EACH => {
                    if state.before_each.is_some() { parser.fatal("Only one `before_each` block is allowed per `describe!` block.") }
                    state.before_each = Some(parser.parse_block());
                },

                AFTER_EACH => {
                    if state.after_each.is_some() { parser.fatal("Only one `after_each` block is allowed per `describe!` block.") }
                    state.after_each = Some(parser.parse_block());
                },

                BEFORE => {
                    if state.before.is_some() { parser.fatal("Only one `before` block is allowed per `describe!` block.") }
                    state.before = Some(parser.parse_block());
                },

                AFTER => {
                    if state.after.is_some() { parser.fatal("Only one `after` block is allowed per `describe!` block.") }
                    state.after = Some(parser.parse_block());
                },

                // Regular `#[test]`.
                IT => { state.subblocks.push(TestBlock(Parse::parse(parser, false))) },

                // `#[should_fail]` test.
                FAILING => { state.subblocks.push(TestBlock(Parse::parse(parser, true))) },

                // #[bench] benchmark.
                BENCH => { state.subblocks.push(BenchBlock(Parse::parse(parser, ()))) }

                // Nested `describe!` block.
                DESCRIBE => {
                    // Skip over the ! in describe!
                    try(parser, token::NOT, "!");

                    // Parse this subblock, generate new item.
                    state.subblocks.push(DescribeBlock(Parse::parse(parser, (sp, &mut*cx, None))));

                    // Move past closing bracket and paren.
                    //
                    // This has to go in here because it is EOF on the highest-level invocation.
                    try(parser, token::RBRACE, "}} to close `describe!`")
                }

                otherwise => { illegal(parser, otherwise) }
            }
        }

        state
    }
}

fn try(parser: &mut Parser, token: token::Token, err: &str) {
    let real = parser.bump_and_get();
    if real != token {
        parser.fatal(format!("Expected {}, but found `{}`", err, real).as_slice())
    }
}

fn illegal(parser: &mut Parser, banned: &str) {
    // Illegal block name.
    let span = parser.span;
    parser.span_fatal(span, format!("Expected one of: `{}`, but found: `{}`",
        format!("{}, {}, {}, {}, {}, {}, {}, {}",
                BEFORE_EACH, AFTER_EACH, BEFORE, AFTER,
                IT, BENCH, FAILING, DESCRIBE).as_slice(),
        banned).as_slice());
}

<commit_msg>(fix) Update for renames of Token variants.<commit_after>use syntax::{ast, codemap};
use syntax::ext::base;
use syntax::parse::token;

use syntax::ptr::P;
use syntax::parse::parser::Parser;

use test::Test;
use bench::Bench;
use describe::{DescribeState, TestBlock, BenchBlock, DescribeBlock};

/// Trait that means something can be parsed with a configuration.
pub trait Parse<Cfg> {
    /// Parse Self from a Parser and a configuration object.
    fn parse(&mut Parser, Cfg) -> Self;
}

impl Parse<bool> for Test {
    fn parse(parser: &mut Parser, failing: bool) -> Test {
        // Description of this test.
        let (description, _) = parser.parse_str();

        Test {
            // Get as a String
            description: description.get().to_string(),

            // The associated block
            block: parser.parse_block(),

            failing: failing
        }
    }
}

impl Parse<()> for Bench {
    fn parse(parser: &mut Parser, _: ()) -> Bench {
        // Description of this benchmark
        let (description, _) = parser.parse_str();

        let name = match (parser.bump_and_get(), parser.parse_ident(), parser.bump_and_get()) {
            (token::LParen, ident, token::RParen) => { ident },

            (one, two, three) => {
                parser.fatal(format!("Expected `($ident)`, found {}{}{}", one, two, three).as_slice())
            }
        };

        Bench {
            description: description.get().to_string(),
            block: parser.parse_block(),
            bench: P(name)
        }
    }
}

const BEFORE_EACH: &'static str = "before_each";
const AFTER_EACH:  &'static str = "after_each";
const BEFORE:      &'static str = "before";
const AFTER:       &'static str = "after";
const IT:          &'static str = "it";
const DESCRIBE:    &'static str = "describe";
const FAILING:     &'static str = "failing";
const BENCH:       &'static str = "bench";

impl<'a, 'b> Parse<(codemap::Span, &'a mut base::ExtCtxt<'b>, Option<ast::Ident>)> for DescribeState {
    fn parse(parser: &mut Parser,
             (sp, cx, name): (codemap::Span, &'a mut base::ExtCtxt, Option<ast::Ident>)) -> DescribeState {
        let mut state = DescribeState {
            name: None, before: None, after: None,
            before_each: None, after_each: None, subblocks: vec![]
        };

        state.name = match name {
            // Top-level describe block.
            Some(name) => Some(name),
            // Nested describe block.
            None => {
                // Get the name of this describe block
                let name = parser.parse_ident();
                // Move past the opening {
                try(parser, token::LBrace, "{ after the name of a describe! block");
                Some(name)
            }
        };

        // Now parse all tests and subsections:
        while parser.token != token::RBrace && parser.token != token::Eof {
            // Get the name of this block, must be either:
            //     - before_each
            //     - after_each
            //     - before
            //     - after
            //     - it
            //     - failing
            //     - bench
            //     - describe!
            //
            // Any other top-level idents are not allowed.
            let block_name = parser.parse_ident();

            match block_name.as_str() {
                BEFORE_EACH => {
                    if state.before_each.is_some() { parser.fatal("Only one `before_each` block is allowed per `describe!` block.") }
                    state.before_each = Some(parser.parse_block());
                },

                AFTER_EACH => {
                    if state.after_each.is_some() { parser.fatal("Only one `after_each` block is allowed per `describe!` block.") }
                    state.after_each = Some(parser.parse_block());
                },

                BEFORE => {
                    if state.before.is_some() { parser.fatal("Only one `before` block is allowed per `describe!` block.") }
                    state.before = Some(parser.parse_block());
                },

                AFTER => {
                    if state.after.is_some() { parser.fatal("Only one `after` block is allowed per `describe!` block.") }
                    state.after = Some(parser.parse_block());
                },

                // Regular `#[test]`.
                IT => { state.subblocks.push(TestBlock(Parse::parse(parser, false))) },

                // `#[should_fail]` test.
                FAILING => { state.subblocks.push(TestBlock(Parse::parse(parser, true))) },

                // #[bench] benchmark.
                BENCH => { state.subblocks.push(BenchBlock(Parse::parse(parser, ()))) }

                // Nested `describe!` block.
                DESCRIBE => {
                    // Skip over the ! in describe!
                    try(parser, token::Not, "!");

                    // Parse this subblock, generate new item.
                    state.subblocks.push(DescribeBlock(Parse::parse(parser, (sp, &mut*cx, None))));

                    // Move past closing bracket and paren.
                    //
                    // This has to go in here because it is EOF on the highest-level invocation.
                    try(parser, token::RBrace, "}} to close `describe!`")
                }

                otherwise => { illegal(parser, otherwise) }
            }
        }

        state
    }
}

fn try(parser: &mut Parser, token: token::Token, err: &str) {
    let real = parser.bump_and_get();
    if real != token {
        parser.fatal(format!("Expected {}, but found `{}`", err, real).as_slice())
    }
}

fn illegal(parser: &mut Parser, banned: &str) {
    // Illegal block name.
    let span = parser.span;
    parser.span_fatal(span, format!("Expected one of: `{}`, but found: `{}`",
        format!("{}, {}, {}, {}, {}, {}, {}, {}",
                BEFORE_EACH, AFTER_EACH, BEFORE, AFTER,
                IT, BENCH, FAILING, DESCRIBE).as_slice(),
        banned).as_slice());
}

<|endoftext|>


<commit_before>use super::ByteSize;

impl std::str::FromStr for ByteSize {
    type Err = String;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        match value.parse::<u64>() {
            Ok(v) => return Ok(Self(v)), // simple case, bytes
            Err(_) => {}
        };
        let number: String = value
            .chars()
            .take_while(|c| c.is_digit(10) || c == &'.')
            .collect();
        match number.parse::<f64>() {
            Ok(v) => {
                let suffix: String = value
                    .chars()
                    .skip_while(|c| c.is_whitespace() || c.is_digit(10) || c == &'.')
                    .collect();
                match suffix.parse::<Unit>() {
                    Ok(u) => Ok(Self((v * u.factor() as f64) as u64)),
                    Err(error) => Err(format!(
                        "couldn't parse {:?} into a known SI unit, {}",
                        suffix, error
                    )),
                }
            }
            Err(error) => Err(format!(
                "couldn't parse {:?} into a ByteSize, {}",
                value, error
            )),
        }
    }
}

enum Unit {
    Byte,
    // power of tens
    KiloByte,
    MegaByte,
    GigaByte,
    TeraByte,
    PetaByte,
    // power of twos
    KibiByte,
    MebiByte,
    GibiByte,
    TebiByte,
    PebiByte,
}

impl Unit {
    fn factor(&self) -> u64 {
        match self {
            Self::Byte => super::B,
            // power of tens
            Self::KiloByte => super::KB,
            Self::MegaByte => super::MB,
            Self::GigaByte => super::GB,
            Self::TeraByte => super::TB,
            Self::PetaByte => super::PB,
            // power of twos
            Self::KibiByte => super::KIB,
            Self::MebiByte => super::MIB,
            Self::GibiByte => super::GIB,
            Self::TebiByte => super::TIB,
            Self::PebiByte => super::PIB,
        }
    }
}

impl std::str::FromStr for Unit {
    type Err = String;

    fn from_str(unit: &str) -> Result<Self, Self::Err> {
        match unit.to_lowercase().as_str() {
            "b" => Ok(Self::Byte),
            // power of tens
            "k" | "kb" => Ok(Self::KiloByte),
            "m" | "mb" => Ok(Self::MegaByte),
            "g" | "gb" => Ok(Self::GigaByte),
            "t" | "tb" => Ok(Self::TeraByte),
            "p" | "pb" => Ok(Self::PetaByte),
            // power of twos
            "ki" | "kib" => Ok(Self::KibiByte),
            "mi" | "mib" => Ok(Self::MebiByte),
            "gi" | "gib" => Ok(Self::GibiByte),
            "ti" | "tib" => Ok(Self::TebiByte),
            "pi" | "pib" => Ok(Self::PebiByte),
            _ => Err(format!("couldn't parse unit of {:?}", unit)),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn when_ok() {
        // shortcut for writing test cases
        fn parse(s: &str) -> u64 {
            s.parse::<ByteSize>().unwrap().0
        }

        assert_eq!("0".parse::<ByteSize>().unwrap().0, 0);
        assert_eq!(parse("0"), 0);
        assert_eq!(parse("500"), 500);
        assert_eq!(parse("1K"), 1 * crate::KB);
        assert_eq!(parse("1Ki"), 1 * crate::KIB);
        assert_eq!(parse("1.5Ki"), (1.5 * crate::KIB as f64) as u64);
        assert_eq!(parse("1KiB"), 1 * crate::KIB);
        assert_eq!(parse("1.5KiB"), (1.5 * crate::KIB as f64) as u64);
        assert_eq!(parse("3 MB"), 3 * crate::MB);
        assert_eq!(parse("4 MiB"), 4 * crate::MIB);
        assert_eq!(parse("6 GB"), 6 * crate::GB);
        assert_eq!(parse("4 GiB"), 4 * crate::GIB);
        assert_eq!(parse("88TB"), 88 * crate::TB);
        assert_eq!(parse("521TiB"), 521 * crate::TIB);
        assert_eq!(parse("8 PB"), 8 * crate::PB);
        assert_eq!(parse("8P"), 8 * crate::PB);
        assert_eq!(parse("12 PiB"), 12 * crate::PIB);
    }

    #[test]
    fn when_err() {
        // shortcut for writing test cases
        fn parse(s: &str) -> Result<ByteSize, String> {
            s.parse::<ByteSize>()
        }

        assert!(parse("").is_err());
        assert!(parse("a124GB").is_err());
    }

    #[test]
    fn to_and_from_str() {
        // shortcut for writing test cases
        fn parse(s: &str) -> u64 {
            s.parse::<ByteSize>().unwrap().0
        }

        assert_eq!(parse(&format!("{}", parse("128GB"))), 128 * crate::GB);
        assert_eq!(
            parse(&crate::to_string(parse("128.000 GiB"), true)),
            128 * crate::GIB
        );
    }
}
<commit_msg>cosmetic<commit_after>use super::ByteSize;

impl std::str::FromStr for ByteSize {
    type Err = String;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        if let Ok(v) = value.parse::<u64>() {
            return Ok(Self(v));
        }
        let number: String = value
            .chars()
            .take_while(|c| c.is_digit(10) || c == &'.')
            .collect();
        match number.parse::<f64>() {
            Ok(v) => {
                let suffix: String = value
                    .chars()
                    .skip_while(|c| c.is_whitespace() || c.is_digit(10) || c == &'.')
                    .collect();
                match suffix.parse::<Unit>() {
                    Ok(u) => Ok(Self((v * u.factor() as f64) as u64)),
                    Err(error) => Err(format!(
                        "couldn't parse {:?} into a known SI unit, {}",
                        suffix, error
                    )),
                }
            }
            Err(error) => Err(format!(
                "couldn't parse {:?} into a ByteSize, {}",
                value, error
            )),
        }
    }
}

enum Unit {
    Byte,
    // power of tens
    KiloByte,
    MegaByte,
    GigaByte,
    TeraByte,
    PetaByte,
    // power of twos
    KibiByte,
    MebiByte,
    GibiByte,
    TebiByte,
    PebiByte,
}

impl Unit {
    fn factor(&self) -> u64 {
        match self {
            Self::Byte => super::B,
            // power of tens
            Self::KiloByte => super::KB,
            Self::MegaByte => super::MB,
            Self::GigaByte => super::GB,
            Self::TeraByte => super::TB,
            Self::PetaByte => super::PB,
            // power of twos
            Self::KibiByte => super::KIB,
            Self::MebiByte => super::MIB,
            Self::GibiByte => super::GIB,
            Self::TebiByte => super::TIB,
            Self::PebiByte => super::PIB,
        }
    }
}

impl std::str::FromStr for Unit {
    type Err = String;

    fn from_str(unit: &str) -> Result<Self, Self::Err> {
        match unit.to_lowercase().as_str() {
            "b" => Ok(Self::Byte),
            // power of tens
            "k" | "kb" => Ok(Self::KiloByte),
            "m" | "mb" => Ok(Self::MegaByte),
            "g" | "gb" => Ok(Self::GigaByte),
            "t" | "tb" => Ok(Self::TeraByte),
            "p" | "pb" => Ok(Self::PetaByte),
            // power of twos
            "ki" | "kib" => Ok(Self::KibiByte),
            "mi" | "mib" => Ok(Self::MebiByte),
            "gi" | "gib" => Ok(Self::GibiByte),
            "ti" | "tib" => Ok(Self::TebiByte),
            "pi" | "pib" => Ok(Self::PebiByte),
            _ => Err(format!("couldn't parse unit of {:?}", unit)),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn when_ok() {
        // shortcut for writing test cases
        fn parse(s: &str) -> u64 {
            s.parse::<ByteSize>().unwrap().0
        }

        assert_eq!("0".parse::<ByteSize>().unwrap().0, 0);
        assert_eq!(parse("0"), 0);
        assert_eq!(parse("500"), 500);
        assert_eq!(parse("1K"), 1 * crate::KB);
        assert_eq!(parse("1Ki"), 1 * crate::KIB);
        assert_eq!(parse("1.5Ki"), (1.5 * crate::KIB as f64) as u64);
        assert_eq!(parse("1KiB"), 1 * crate::KIB);
        assert_eq!(parse("1.5KiB"), (1.5 * crate::KIB as f64) as u64);
        assert_eq!(parse("3 MB"), 3 * crate::MB);
        assert_eq!(parse("4 MiB"), 4 * crate::MIB);
        assert_eq!(parse("6 GB"), 6 * crate::GB);
        assert_eq!(parse("4 GiB"), 4 * crate::GIB);
        assert_eq!(parse("88TB"), 88 * crate::TB);
        assert_eq!(parse("521TiB"), 521 * crate::TIB);
        assert_eq!(parse("8 PB"), 8 * crate::PB);
        assert_eq!(parse("8P"), 8 * crate::PB);
        assert_eq!(parse("12 PiB"), 12 * crate::PIB);
    }

    #[test]
    fn when_err() {
        // shortcut for writing test cases
        fn parse(s: &str) -> Result<ByteSize, String> {
            s.parse::<ByteSize>()
        }

        assert!(parse("").is_err());
        assert!(parse("a124GB").is_err());
    }

    #[test]
    fn to_and_from_str() {
        // shortcut for writing test cases
        fn parse(s: &str) -> u64 {
            s.parse::<ByteSize>().unwrap().0
        }

        assert_eq!(parse(&format!("{}", parse("128GB"))), 128 * crate::GB);
        assert_eq!(
            parse(&crate::to_string(parse("128.000 GiB"), true)),
            128 * crate::GIB
        );
    }
}
<|endoftext|>


<commit_before>use std::ops::{Sub, Div};

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

impl Point {
    pub fn new(x: f64, y: f64) -> Self {
        Point { x: x, y: y }
    }

    pub fn cross(self, other: Point) -> f64 {
        return self.x * other.y - other.x * self.y;
    }

    pub fn dot(self, other: Point) -> f64 {
        return self.x * other.x + self.y * other.y;
    }
}

impl Sub<Point> for Point {
    type Output = Point;

    fn sub(self, other: Point) -> Self::Output {
        return Point {
            x: self.x - other.x,
            y: self.y - other.y,
        };
    }
}

impl Div<f64> for Point {
    type Output = Point;

    fn div(self, other: f64) -> Self::Output {
        return Point {
            x: self.x / other,
            y: self.y / other,
        };
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use expectest::prelude::*;

    const P1: Point = Point { x: 2.0, y: 3.0 };
    const P1_TIMES_2: Point = Point { x: 4.0, y: 6.0 };
    const P2: Point = Point { x: 5.0, y: 7.0 };

    #[test]
    fn test_new() {
        expect!(Point::new(2.0, 3.0)).to(be_equal_to(P1));
    }

    #[test]
    fn test_cross() {
        expect!(P1.cross(P2)).to(be_equal_to(-1.0));
    }

    #[test]
    fn test_dot() {
        expect!(P1.dot(P2)).to(be_equal_to(31.0));
    }

    #[test]
    fn test_ops() {
        expect!(P1_TIMES_2 - P1).to(be_equal_to(P1));
        expect!(P1_TIMES_2 / 2.0).to(be_equal_to(P1));
    }
}
<commit_msg>Add mul and add implementations<commit_after>use std::ops::{Add, Div, Mul, Sub};

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Point {
    pub x: f64,
    pub y: f64,
}

impl Point {
    pub fn new(x: f64, y: f64) -> Self {
        Point { x: x, y: y }
    }

    pub fn cross(self, other: Point) -> f64 {
        return self.x * other.y - other.x * self.y;
    }

    pub fn dot(self, other: Point) -> f64 {
        return self.x * other.x + self.y * other.y;
    }
}

impl Add<Point> for Point {
    type Output = Point;

    fn add(self, other: Point) -> Self::Output {
        return Point {
            x: self.x + other.x,
            y: self.y + other.y,
        };
    }
}

impl Mul<f64> for Point {
    type Output = Point;

    fn mul(self, other: f64) -> Self::Output {
        return Point {
            x: self.x * other,
            y: self.y * other,
        };
    }
}

impl Sub<Point> for Point {
    type Output = Point;

    fn sub(self, other: Point) -> Self::Output {
        return Point {
            x: self.x - other.x,
            y: self.y - other.y,
        };
    }
}

impl Div<f64> for Point {
    type Output = Point;

    fn div(self, other: f64) -> Self::Output {
        return Point {
            x: self.x / other,
            y: self.y / other,
        };
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use expectest::prelude::*;

    const P1: Point = Point { x: 2.0, y: 3.0 };
    const P1_TIMES_2: Point = Point { x: 4.0, y: 6.0 };
    const P2: Point = Point { x: 5.0, y: 7.0 };

    #[test]
    fn test_new() {
        expect!(Point::new(2.0, 3.0)).to(be_equal_to(P1));
    }

    #[test]
    fn test_cross() {
        expect!(P1.cross(P2)).to(be_equal_to(-1.0));
    }

    #[test]
    fn test_dot() {
        expect!(P1.dot(P2)).to(be_equal_to(31.0));
    }

    #[test]
    fn test_ops() {
        expect!(P1 + P1).to(be_equal_to(P1_TIMES_2));
        expect!(P1_TIMES_2 - P1).to(be_equal_to(P1));
        expect!(P1_TIMES_2 / 2.0).to(be_equal_to(P1));
        expect!(P1 * 2.0).to(be_equal_to(P1_TIMES_2));
    }
}
<|endoftext|>