<commit_before>extern crate "rust-crypto" as rust_crypto;
extern crate serialize;

use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::{File, BufferedStream};
use std::string::String;
use std::os;

use rust_crypto::sha1::Sha1;
use rust_crypto::digest::Digest;
use serialize::base64::{ToBase64, STANDARD};

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const COLON: u8 = b':';
pub const CRLF: &'static [u8] = &[CR,LF];

struct RequestedRoute {
    method: String,
    pathname: String
}

struct ClientHeader {
    key: String,
    value: String
}

enum Payload {
    Text(String)
}

enum Opcode {
    TextOp = 0x1
}

struct Message {
    payload: Payload,
    opcode: Opcode
 }

impl Message {
    fn send (msg: &[u8],
             mut stream: BufferedStream<TcpStream>,
             headers: Vec<ClientHeader>) {
        let payload = match msg {
            String => Payload::Text(msg.to_string())
        };
        let payload = payload;
        let opcode = Opcode::TextOp;
        let length = msg.len() as u8;

        stream.write_u8(0b1000_0000 | opcode as u8).unwrap();
        stream.write_u8(length).unwrap();
        stream.write(msg).unwrap();
    }

    fn snd (self,
            mut stream: BufferedStream<TcpStream>,
            headers: Vec<ClientHeader>) {

        let msg = match self.payload {
            Payload::Text(s) => s
        };

        let length = msg.len() as u8;

        println!("msg: {}, opcode: {}", msg, self.opcode as u8);

        stream.write_u8(0b1000_0000 | self.opcode as u8).unwrap();
        stream.write_u8(length).unwrap();
        stream.write(msg.into_bytes().as_slice()).unwrap();

    }
}

fn get_header_by_name (header: &[u8], headers: &Vec<ClientHeader>) -> String {
    let mut result = String::new();

    for h in headers.iter() {
        if h.key.as_bytes() == header {
            result = h.value.clone();
            break;
        }
    }

    return result;
}

fn parse_request_line (header: &str) -> RequestedRoute {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }

    return RequestedRoute {method: method, pathname: pathname};
}

fn parse_normal_header (header: &str) -> ClientHeader {
    let mut lhs = String::new(); // lhs of ':' in header
    let mut rhs = String::new(); // rhs of ':' in header
    let mut found_colon = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];
        if !found_colon && cbyte == COLON {
            found_colon = true;
            continue;
        }

        if cbyte == CR || cbyte == LF {
            continue;
        }

        if !found_colon {
            lhs.push_str(ch);
        } else {
            rhs.push_str(ch);
        }
    }

    return ClientHeader {
        key:lhs.trim().to_string(),
        value:rhs.trim().to_string()
    };
}

fn get_normal_body (path_on_disk: &str) -> String {
    let path = Path::new(path_on_disk);
    let display = path.display();
    let mut file = match File::open(&path) {
        Ok(f) => f,
        Err(err) => panic!("file error: {}", err)
    };

    let content = match file.read_to_end() {
        Ok(c) => c,
        Err(err) => panic!("{}", err)
    };

    let s = String::from_utf8(content).unwrap();
    return s;
}

fn sec_handshake (from_server: &[u8]) -> String {

    let guid = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    let mut sha = Sha1::new();

    sha.input(from_server);
    sha.input(guid);
    let mut out = [0u8, ..20];
    sha.result(out.as_mut_slice());

    return out.to_base64(STANDARD);
}

fn ws_handshake (mut stream: BufferedStream<TcpStream>,
                 headers: Vec<ClientHeader>) {

    let header_sec_key = b"Sec-WebSocket-Key";

    let from_server = get_header_by_name(header_sec_key, &headers);
    let accept = sec_handshake(from_server.as_bytes());

    let sec_header = format!("Sec-WebSocket-Accept: {}\r\n", accept);

    stream.write(b"HTTP/1.1 101 Switching Protocols\r\n").unwrap();
    stream.write(b"Upgrade: websocket\r\n").unwrap();
    stream.write(b"Connection: Upgrade\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Version: 13\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Protocol: protocolOne\r\n").unwrap();
    stream.write(sec_header.as_bytes().as_slice()).unwrap();
    stream.write(b"\r\n");

    ws_listen(stream, headers);
}

fn ws_listen(mut stream: BufferedStream<TcpStream>,
             headers: Vec<ClientHeader>) {
    //let msg = Message::send(b"hello world", stream, headers);

    let string_msg = "this is a message".to_string();
    let opcode = Opcode::TextOp;
    let payload: Payload = match opcode {
        Opcode::TextOp => Payload::Text(string_msg),
    };

    let msg2 = box Message {
        payload: payload,
        opcode: opcode
    };

    msg2.snd(stream, headers);
}

fn main () {

    for argument in os::args().iter() {
        println!("arg: {}", argument);
    }

    let addr = "127.0.0.1:8099";

    let listener = TcpListener::bind(addr).unwrap();
    let mut acceptor = listener.listen().unwrap();
    println!("Listening on {}", addr);

    fn handle_client(mut stream: BufferedStream<TcpStream>) {
        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;
        let mut req: RequestedRoute = RequestedRoute {
            pathname: String::new(),
            method: String::new()
        };

        let mut headers: Vec<ClientHeader> = Vec::new();
        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF {
                break;
            }

            if ii == 0u { // the Request-Line is always the first line
                req = parse_request_line(cur_line.as_slice());
                println!("{}", req.pathname);
                ii += 1;
            } else { // this should be  "normal" key-value type header
                headers.push(parse_normal_header(cur_line.as_slice()));
            }

        }

        println!("pathname {} method {}", req.pathname, req.method);

        if req.pathname.as_bytes() == b"/" {
            body = get_normal_body("../html/ws1.html");
        } else if req.pathname.as_bytes() == b"/ws1.js" {
            body = get_normal_body("../html/ws1.js");
        } else if req.pathname.as_bytes() == b"/ws" {
            ws_handshake(stream, headers);
            return;
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap();
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Done handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<commit_msg>use ref so we can use as_bytes()<commit_after>extern crate "rust-crypto" as rust_crypto;
extern crate serialize;

use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::{File, BufferedStream};
use std::string::String;
use std::os;

use rust_crypto::sha1::Sha1;
use rust_crypto::digest::Digest;
use serialize::base64::{ToBase64, STANDARD};

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const COLON: u8 = b':';
pub const CRLF: &'static [u8] = &[CR,LF];

struct RequestedRoute {
    method: String,
    pathname: String
}

struct ClientHeader {
    key: String,
    value: String
}

enum Payload {
    Text(String)
}

enum Opcode {
    TextOp = 0x1
}

struct Message {
    payload: Payload,
    opcode: Opcode
 }

impl Message {
    fn send (msg: &[u8],
             mut stream: BufferedStream<TcpStream>,
             headers: Vec<ClientHeader>) {
        let payload = match msg {
            String => Payload::Text(msg.to_string())
        };
        let payload = payload;
        let opcode = Opcode::TextOp;
        let length = msg.len() as u8;

        stream.write_u8(0b1000_0000 | opcode as u8).unwrap();
        stream.write_u8(length).unwrap();
        stream.write(msg).unwrap();
    }

    fn snd (self,
            mut stream: BufferedStream<TcpStream>,
            headers: Vec<ClientHeader>) {

        let msg = match self.payload {
            Payload::Text(ref s) => s.as_bytes()
        };

        let length = msg.len() as u8;

        println!("msg: {}, opcode: {}", msg, self.opcode as u8);

        stream.write_u8(0b1000_0000 | self.opcode as u8).unwrap();
        stream.write_u8(length).unwrap();
        stream.write(msg).unwrap();

    }
}

fn get_header_by_name (header: &[u8], headers: &Vec<ClientHeader>) -> String {
    let mut result = String::new();

    for h in headers.iter() {
        if h.key.as_bytes() == header {
            result = h.value.clone();
            break;
        }
    }

    return result;
}

fn parse_request_line (header: &str) -> RequestedRoute {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }

    return RequestedRoute {method: method, pathname: pathname};
}

fn parse_normal_header (header: &str) -> ClientHeader {
    let mut lhs = String::new(); // lhs of ':' in header
    let mut rhs = String::new(); // rhs of ':' in header
    let mut found_colon = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];
        if !found_colon && cbyte == COLON {
            found_colon = true;
            continue;
        }

        if cbyte == CR || cbyte == LF {
            continue;
        }

        if !found_colon {
            lhs.push_str(ch);
        } else {
            rhs.push_str(ch);
        }
    }

    return ClientHeader {
        key:lhs.trim().to_string(),
        value:rhs.trim().to_string()
    };
}

fn get_normal_body (path_on_disk: &str) -> String {
    let path = Path::new(path_on_disk);
    let display = path.display();
    let mut file = match File::open(&path) {
        Ok(f) => f,
        Err(err) => panic!("file error: {}", err)
    };

    let content = match file.read_to_end() {
        Ok(c) => c,
        Err(err) => panic!("{}", err)
    };

    let s = String::from_utf8(content).unwrap();
    return s;
}

fn sec_handshake (from_server: &[u8]) -> String {

    let guid = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

    let mut sha = Sha1::new();

    sha.input(from_server);
    sha.input(guid);
    let mut out = [0u8, ..20];
    sha.result(out.as_mut_slice());

    return out.to_base64(STANDARD);
}

fn ws_handshake (mut stream: BufferedStream<TcpStream>,
                 headers: Vec<ClientHeader>) {

    let header_sec_key = b"Sec-WebSocket-Key";

    let from_server = get_header_by_name(header_sec_key, &headers);
    let accept = sec_handshake(from_server.as_bytes());

    let sec_header = format!("Sec-WebSocket-Accept: {}\r\n", accept);

    stream.write(b"HTTP/1.1 101 Switching Protocols\r\n").unwrap();
    stream.write(b"Upgrade: websocket\r\n").unwrap();
    stream.write(b"Connection: Upgrade\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Version: 13\r\n").unwrap();
    stream.write(b"Sec-WebSocket-Protocol: protocolOne\r\n").unwrap();
    stream.write(sec_header.as_bytes().as_slice()).unwrap();
    stream.write(b"\r\n");

    ws_listen(stream, headers);
}

fn ws_listen(mut stream: BufferedStream<TcpStream>,
             headers: Vec<ClientHeader>) {
    //let msg = Message::send(b"hello world", stream, headers);

    let string_msg = "this is a message".to_string();
    let opcode = Opcode::TextOp;
    let payload: Payload = match opcode {
        Opcode::TextOp => Payload::Text(string_msg),
    };

    let msg2 = box Message {
        payload: payload,
        opcode: opcode
    };

    msg2.snd(stream, headers);
}

fn main () {

    for argument in os::args().iter() {
        println!("arg: {}", argument);
    }

    let addr = "127.0.0.1:8099";

    let listener = TcpListener::bind(addr).unwrap();
    let mut acceptor = listener.listen().unwrap();
    println!("Listening on {}", addr);

    fn handle_client(mut stream: BufferedStream<TcpStream>) {
        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;
        let mut req: RequestedRoute = RequestedRoute {
            pathname: String::new(),
            method: String::new()
        };

        let mut headers: Vec<ClientHeader> = Vec::new();
        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF {
                break;
            }

            if ii == 0u { // the Request-Line is always the first line
                req = parse_request_line(cur_line.as_slice());
                println!("{}", req.pathname);
                ii += 1;
            } else { // this should be  "normal" key-value type header
                headers.push(parse_normal_header(cur_line.as_slice()));
            }

        }

        println!("pathname {} method {}", req.pathname, req.method);

        if req.pathname.as_bytes() == b"/" {
            body = get_normal_body("../html/ws1.html");
        } else if req.pathname.as_bytes() == b"/ws1.js" {
            body = get_normal_body("../html/ws1.js");
        } else if req.pathname.as_bytes() == b"/ws" {
            ws_handshake(stream, headers);
            return;
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap();
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Done handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<|endoftext|>


<commit_before>

/// Tool to compare the block processing time of core with bitcrust
///
/// Will run in two phases
/// - Sync bitcrust from blk files to add_block with initial_sync=true until no more blocks are in
/// - Then poll the blk files every 5 sec to see if a block came in and add it with initial_sync=false
///
/// Then we wait for incoming blocks in core, add them to bitcrust and compare the result
/// from log

extern crate bitcrust_lib;
extern crate byteorder;
use std::io::BufReader;
use std::fs::File;
use std::fs;
use std::io::Seek;

mod blk_file;

/// can be used for fast startup in combination with the no_clear_data feature
const SKIP_FILES: usize = 0;

fn blk_file_name(file_number: usize) -> String {
    format!("/home/tomas/.bitcoin/blocks/blk{:05}.dat", file_number)
}

/// A reference to a position in a blk file
#[derive(Debug,Copy,Clone)]
struct ReadPos {
    pub file_number: usize,
    pub file_position: u64
}

/// Reads a block from the blk file position
/// This is used on live reading, as we need to reopen the file to come out of EOF position.
fn read_next(pos: ReadPos) -> Option<(ReadPos,Vec<u8>)> {

    // next file available?
    if fs::metadata(blk_file_name(pos.file_number + 1)).is_ok() {
        return read_next(ReadPos { file_number: pos.file_number +  1, file_position: 0 });
    }

    let name = blk_file_name(pos.file_number);

    let file = File::open(name).unwrap();
    let mut rdr = BufReader::new(file);

    let _ = rdr.seek(std::io::SeekFrom::Start(pos.file_position)).unwrap();

    let blk = blk_file::read_block(&mut rdr).unwrap();
    match blk {
        None => {
            println!("No block");
            None
        },
        Some(blk) => {
            Some( (ReadPos {
                file_number: pos.file_number,
                file_position: rdr.seek(std::io::SeekFrom::Current(0)).unwrap()

                }, blk))

        }

    }

}

#[test]
#[ignore]
fn compare_core() {

    let mut store = bitcrust_lib::init();
    let mut pos = sync_initial(&mut store);

    store.initial_sync = false;

    println!("No more initial sync; polling files");

    loop {
        match read_next(pos) {
            None => {
                std::thread::sleep(std::time::Duration::new(5,0));
                continue;
            },
            Some((p, blk)) => {
                pos = p;
                bitcrust_lib::add_block(&mut store, &blk);

            }
        }
    }

}

fn sync_initial(store: &mut bitcrust_lib::Store) -> ReadPos {

    // Step one; load existing data from blk files
    let mut read_pos = ReadPos {
        file_number: SKIP_FILES,
        file_position: 0
    };

    let mut name = blk_file_name(read_pos.file_number);

    let mut file = File::open(name).unwrap();
    let mut rdr = BufReader::new(file);

    let mut blocks = 0;
    loop {
        let blk = blk_file::read_block(&mut rdr).unwrap();

        if blk.is_none() {

            // next file?
            name = blk_file_name(read_pos.file_number + 1);
            let open_result = File::open(name.clone());

            match open_result {
                Ok(f) => {
                    println!("Processing file {}", name);
                    file = f
                },
                Err(_) => {

                    // no? then we're done initial syncing
                    return read_pos;

                }
            };
            // next file
            read_pos.file_number = read_pos.file_number + 1;
            read_pos.file_position  = 0;
            rdr = BufReader::new(file);

        } else {
            bitcrust_lib::add_block(store, &blk.unwrap());
            read_pos.file_position += rdr.seek(std::io::SeekFrom::Current(0)).unwrap();

            blocks += 1;
            println!("Processing block {}", blocks);
        }
    }

}<commit_msg>Fix in seek position for blk files<commit_after>

/// Tool to compare the block processing time of core with bitcrust
///
/// Will run in two phases
/// - Sync bitcrust from blk files to add_block with initial_sync=true until no more blocks are in
/// - Then poll the blk files every 5 sec to see if a block came in and add it with initial_sync=false
///
/// Then we wait for incoming blocks in core, add them to bitcrust and compare the result
/// from log

extern crate bitcrust_lib;
extern crate byteorder;
use std::io::BufReader;
use std::fs::File;
use std::fs;
use std::io::Seek;

mod blk_file;

/// can be used for fast startup in combination with the no_clear_data feature
const SKIP_FILES: usize = 0;

fn blk_file_name(file_number: usize) -> String {
    format!("/home/tomas/.bitcoin/blocks/blk{:05}.dat", file_number)
}

/// A reference to a position in a blk file
#[derive(Debug,Copy,Clone)]
struct ReadPos {
    pub file_number: usize,
    pub file_position: u64
}

/// Reads a block from the blk file position
/// This is used on live reading, as we need to reopen the file to come out of EOF position.
fn read_next(pos: ReadPos) -> Option<(ReadPos,Vec<u8>)> {

    // next file available?
    if fs::metadata(blk_file_name(pos.file_number + 1)).is_ok() {
        return read_next(ReadPos { file_number: pos.file_number +  1, file_position: 0 });
    }

    let name = blk_file_name(pos.file_number);

    let file = File::open(name).unwrap();
    let mut rdr = BufReader::new(file);

    let _ = rdr.seek(std::io::SeekFrom::Start(pos.file_position)).unwrap();

    let blk = blk_file::read_block(&mut rdr).unwrap();
    match blk {
        None => {
            None
        },
        Some(blk) => {
            Some( (ReadPos {
                file_number: pos.file_number,
                file_position: rdr.seek(std::io::SeekFrom::Current(0)).unwrap()

                }, blk))

        }

    }

}

#[test]
#[ignore]
fn compare_core() {

    let mut store = bitcrust_lib::init();
    let mut pos = sync_initial(&mut store);

    store.initial_sync = false;

    println!("No more initial sync; polling files");

    loop {
        match read_next(pos) {
            None => {
                std::thread::sleep(std::time::Duration::new(5,0));
                continue;
            },
            Some((p, blk)) => {
                pos = p;
                bitcrust_lib::add_block(&mut store, &blk);

            }
        }
    }

}

fn sync_initial(store: &mut bitcrust_lib::Store) -> ReadPos {

    // Step one; load existing data from blk files
    let mut read_pos = ReadPos {
        file_number: SKIP_FILES,
        file_position: 0
    };

    let mut name = blk_file_name(read_pos.file_number);

    let mut file = File::open(name).unwrap();
    let mut rdr = BufReader::new(file);

    let mut blocks = 0;
    loop {
        let blk = blk_file::read_block(&mut rdr).unwrap();

        if blk.is_none() {

            // next file?
            name = blk_file_name(read_pos.file_number + 1);
            let open_result = File::open(name.clone());

            match open_result {
                Ok(f) => {
                    println!("Processing file {}", name);
                    file = f
                },
                Err(_) => {

                    // no? then we're done initial syncing
                    return read_pos;

                }
            };
            // next file
            read_pos.file_number = read_pos.file_number + 1;
            read_pos.file_position  = 0;
            rdr = BufReader::new(file);

        } else {
            bitcrust_lib::add_block(store, &blk.unwrap());
            read_pos.file_position = rdr.seek(std::io::SeekFrom::Current(0)).unwrap();

            blocks += 1;
            println!("Processing block {}", blocks);
        }
    }

}<|endoftext|>


<commit_before>#![feature(test)]

use compiletest_rs as compiletest;
extern crate test;

use std::env::{set_var, var};
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

#[must_use]
fn clippy_driver_path() -> PathBuf {
    if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
        PathBuf::from(path)
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/clippy-driver"))
    }
}

#[must_use]
fn host_libs() -> PathBuf {
    if let Some(path) = option_env!("HOST_LIBS") {
        PathBuf::from(path)
    } else {
        Path::new("target").join(env!("PROFILE"))
    }
}

#[must_use]
fn target_libs() -> Option<PathBuf> {
    option_env!("TARGET_LIBS").map(PathBuf::from)
}

#[must_use]
fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

#[must_use]
fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn config(mode: &str, dir: PathBuf) -> compiletest::Config {
    let mut config = compiletest::Config::default();

    let cfg_mode = mode.parse().expect("Invalid mode");
    if let Ok(name) = var::<&str>("TESTNAME") {
        config.filter = Some(name)
    }

    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }

    // When we'll want to use `extern crate ..` for a dependency that is used
    // both by the crate and the compiler itself, we can't simply pass -L flags
    // as we'll get a duplicate matching versions. Instead, disambiguate with
    // `--extern dep=path`.
    // See https://github.com/rust-lang/rust-clippy/issues/4015.
    let needs_disambiguation = ["serde", "regex", "clippy_lints"];
    // This assumes that deps are compiled (they are for Cargo integration tests).
    let deps = fs::read_dir(host_libs().join("deps")).unwrap();
    let deps: Vec<_> = if let Some(target_libs) = target_libs() {
        deps.chain(fs::read_dir(target_libs.join("deps")).unwrap()).collect()
    } else {
        deps.collect()
    };
    let disambiguated = deps
        .into_iter()
        .filter_map(|dep| {
            let path = dep.ok()?.path();
            let name = path.file_name()?.to_string_lossy();
            // NOTE: This only handles a single dep
            // https://github.com/laumann/compiletest-rs/issues/101
            needs_disambiguation.iter().find_map(|dep| {
                if name.starts_with(&format!("lib{}-", dep)) && name.ends_with(".rlib") {
                    Some(format!("--extern {}={}", dep, path.display()))
                } else {
                    None
                }
            })
        })
        .collect::<Vec<_>>();

    config.target_rustcflags = Some(format!(
        "-L {0} -L {0}/deps {1} -Dwarnings -Zui-testing {2}",
        host_libs().display(),
        target_libs().map_or_else(String::new, |path| format!("-L {0} -L {0}/deps", path.display())),
        disambiguated.join(" ")
    ));

    config.mode = cfg_mode;
    config.build_base = if rustc_test_suite().is_some() {
        // we don't need access to the stderr files on travis
        let mut path = PathBuf::from(env!("OUT_DIR"));
        path.push("test_build_base");
        path
    } else {
        let mut path = std::env::current_dir().unwrap();
        path.push("target/debug/test_build_base");
        path
    };
    config.src_base = dir;
    config.rustc_path = clippy_driver_path();
    config
}

fn run_mode(mode: &str, dir: PathBuf) {
    let cfg = config(mode, dir);
    compiletest::run_tests(&cfg);
}

#[allow(clippy::identity_conversion)]
fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDescAndFn>) -> Result<bool, io::Error> {
    let mut result = true;
    let opts = compiletest::test_opts(config);
    for dir in fs::read_dir(&config.src_base)? {
        let dir = dir?;
        if !dir.file_type()?.is_dir() {
            continue;
        }
        let dir_path = dir.path();
        set_var("CARGO_MANIFEST_DIR", &dir_path);
        for file in fs::read_dir(&dir_path)? {
            let file = file?;
            let file_path = file.path();
            if !file.file_type()?.is_file() {
                continue;
            }
            if file_path.extension() != Some(OsStr::new("rs")) {
                continue;
            }
            let paths = compiletest::common::TestPaths {
                file: file_path,
                base: config.src_base.clone(),
                relative_dir: dir_path.file_name().unwrap().into(),
            };
            let test_name = compiletest::make_test_name(&config, &paths);
            let index = tests
                .iter()
                .position(|test| test.desc.name == test_name)
                .expect("The test should be in there");
            result &= test::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
        }
    }
    Ok(result)
}

fn run_ui_toml() {
    let path = PathBuf::from("tests/ui-toml").canonicalize().unwrap();
    let config = config("ui", path);
    let tests = compiletest::make_tests(&config);

    let res = run_ui_toml_tests(&config, tests);
    match res {
        Ok(true) => {},
        Ok(false) => panic!("Some tests failed"),
        Err(e) => {
            println!("I/O failure during tests: {:?}", e);
        },
    }
}

fn prepare_env() {
    set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
    set_var("CLIPPY_TESTS", "true");
    //set_var("RUST_BACKTRACE", "0");
}

#[test]
fn compile_test() {
    prepare_env();
    run_mode("ui", "tests/ui".into());
    run_ui_toml();
}
<commit_msg>Auto merge of #4800 - msizanoen1:target-libs2, r=Manishearth<commit_after>#![feature(test)]

use compiletest_rs as compiletest;
extern crate test;

use std::env::{set_var, var};
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

#[must_use]
fn clippy_driver_path() -> PathBuf {
    if let Some(path) = option_env!("CLIPPY_DRIVER_PATH") {
        PathBuf::from(path)
    } else {
        PathBuf::from(concat!("target/", env!("PROFILE"), "/clippy-driver"))
    }
}

#[must_use]
fn host_libs() -> PathBuf {
    if let Some(path) = option_env!("HOST_LIBS") {
        PathBuf::from(path)
    } else {
        Path::new("target").join(env!("PROFILE"))
    }
}

#[must_use]
fn target_libs() -> Option<PathBuf> {
    option_env!("TARGET_LIBS").map(PathBuf::from)
}

#[must_use]
fn rustc_test_suite() -> Option<PathBuf> {
    option_env!("RUSTC_TEST_SUITE").map(PathBuf::from)
}

#[must_use]
fn rustc_lib_path() -> PathBuf {
    option_env!("RUSTC_LIB_PATH").unwrap().into()
}

fn config(mode: &str, dir: PathBuf) -> compiletest::Config {
    let mut config = compiletest::Config::default();

    let cfg_mode = mode.parse().expect("Invalid mode");
    if let Ok(name) = var::<&str>("TESTNAME") {
        config.filter = Some(name)
    }

    if rustc_test_suite().is_some() {
        config.run_lib_path = rustc_lib_path();
        config.compile_lib_path = rustc_lib_path();
    }

    // When we'll want to use `extern crate ..` for a dependency that is used
    // both by the crate and the compiler itself, we can't simply pass -L flags
    // as we'll get a duplicate matching versions. Instead, disambiguate with
    // `--extern dep=path`.
    // See https://github.com/rust-lang/rust-clippy/issues/4015.
    let needs_disambiguation = ["serde", "regex", "clippy_lints"];
    // This assumes that deps are compiled (they are for Cargo integration tests).
    let deps = fs::read_dir(target_libs().unwrap_or_else(host_libs).join("deps")).unwrap();
    let disambiguated = deps
        .filter_map(|dep| {
            let path = dep.ok()?.path();
            let name = path.file_name()?.to_string_lossy();
            // NOTE: This only handles a single dep
            // https://github.com/laumann/compiletest-rs/issues/101
            needs_disambiguation.iter().find_map(|dep| {
                if name.starts_with(&format!("lib{}-", dep)) && name.ends_with(".rlib") {
                    Some(format!("--extern {}={}", dep, path.display()))
                } else {
                    None
                }
            })
        })
        .collect::<Vec<_>>();

    config.target_rustcflags = Some(format!(
        "-L {0} -L {0}/deps {1} -Dwarnings -Zui-testing {2}",
        host_libs().display(),
        target_libs().map_or_else(String::new, |path| format!("-L {0} -L {0}/deps", path.display())),
        disambiguated.join(" ")
    ));

    config.mode = cfg_mode;
    config.build_base = if rustc_test_suite().is_some() {
        // we don't need access to the stderr files on travis
        let mut path = PathBuf::from(env!("OUT_DIR"));
        path.push("test_build_base");
        path
    } else {
        let mut path = std::env::current_dir().unwrap();
        path.push("target/debug/test_build_base");
        path
    };
    config.src_base = dir;
    config.rustc_path = clippy_driver_path();
    config
}

fn run_mode(mode: &str, dir: PathBuf) {
    let cfg = config(mode, dir);
    compiletest::run_tests(&cfg);
}

#[allow(clippy::identity_conversion)]
fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec<test::TestDescAndFn>) -> Result<bool, io::Error> {
    let mut result = true;
    let opts = compiletest::test_opts(config);
    for dir in fs::read_dir(&config.src_base)? {
        let dir = dir?;
        if !dir.file_type()?.is_dir() {
            continue;
        }
        let dir_path = dir.path();
        set_var("CARGO_MANIFEST_DIR", &dir_path);
        for file in fs::read_dir(&dir_path)? {
            let file = file?;
            let file_path = file.path();
            if !file.file_type()?.is_file() {
                continue;
            }
            if file_path.extension() != Some(OsStr::new("rs")) {
                continue;
            }
            let paths = compiletest::common::TestPaths {
                file: file_path,
                base: config.src_base.clone(),
                relative_dir: dir_path.file_name().unwrap().into(),
            };
            let test_name = compiletest::make_test_name(&config, &paths);
            let index = tests
                .iter()
                .position(|test| test.desc.name == test_name)
                .expect("The test should be in there");
            result &= test::run_tests_console(&opts, vec![tests.swap_remove(index)])?;
        }
    }
    Ok(result)
}

fn run_ui_toml() {
    let path = PathBuf::from("tests/ui-toml").canonicalize().unwrap();
    let config = config("ui", path);
    let tests = compiletest::make_tests(&config);

    let res = run_ui_toml_tests(&config, tests);
    match res {
        Ok(true) => {},
        Ok(false) => panic!("Some tests failed"),
        Err(e) => {
            println!("I/O failure during tests: {:?}", e);
        },
    }
}

fn prepare_env() {
    set_var("CLIPPY_DISABLE_DOCS_LINKS", "true");
    set_var("CLIPPY_TESTS", "true");
    //set_var("RUST_BACKTRACE", "0");
}

#[test]
fn compile_test() {
    prepare_env();
    run_mode("ui", "tests/ui".into());
    run_ui_toml();
}
<|endoftext|>


<commit_before>use super::wasm;
use anyhow::Context;
use std::env;
use std::fs;
use std::net::TcpListener;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use tiny_http::{Header, Response, Server};
use webbrowser;

macro_rules! resource {
    ($name: tt, $path: tt) => {
        #[cfg(TREE_SITTER_EMBED_WASM_BINDING)]
        fn $name(tree_sitter_dir: &Option<PathBuf>) -> Vec<u8> {
            if let Some(tree_sitter_dir) = tree_sitter_dir {
                fs::read(tree_sitter_dir.join($path)).unwrap()
            } else {
                include_bytes!(concat!("../../", $path)).to_vec()
            }
        }

        #[cfg(not(TREE_SITTER_EMBED_WASM_BINDING))]
        fn $name(tree_sitter_dir: &Option<PathBuf>) -> Vec<u8> {
            if let Some(tree_sitter_dir) = tree_sitter_dir {
                fs::read(tree_sitter_dir.join($path)).unwrap()
            } else {
                include_bytes!(concat!("../../", $path)).to_vec()
            }
        }
    };
}

macro_rules! optional_resource {
    ($name: tt, $path: tt) => {
        #[cfg(TREE_SITTER_EMBED_WASM_BINDING)]
        fn $name(tree_sitter_dir: &Option<PathBuf>) -> Vec<u8> {
            if let Some(tree_sitter_dir) = tree_sitter_dir {
                fs::read(tree_sitter_dir.join($path)).unwrap()
            } else {
                include_bytes!(concat!("../../", $path)).to_vec()
            }
        }

        #[cfg(not(TREE_SITTER_EMBED_WASM_BINDING))]
        fn $name(tree_sitter_dir: &Option<PathBuf>) -> Vec<u8> {
            if let Some(tree_sitter_dir) = tree_sitter_dir {
                fs::read(tree_sitter_dir.join($path)).unwrap()
            } else {
                Vec::new()
            }
        }
    };
}

resource!(get_main_html, "cli/src/web_ui.html");
resource!(get_playground_js, "docs/assets/js/playground.js");
optional_resource!(get_lib_js, "lib/binding_web/tree-sitter.js");
optional_resource!(get_lib_wasm, "lib/binding_web/tree-sitter.wasm");

pub fn serve(grammar_path: &Path, open_in_browser: bool) {
    let port = get_available_port().expect("Couldn't find an available port");
    let url = format!("127.0.0.1:{}", port);
    let server = Server::http(&url).expect("Failed to start web server");
    let grammar_name = wasm::get_grammar_name(&grammar_path.join("src"))
        .with_context(|| "Failed to get wasm filename")
        .unwrap();
    let wasm_filename = format!("tree-sitter-{}.wasm", grammar_name);
    let language_wasm = fs::read(grammar_path.join(&wasm_filename))
        .with_context(|| {
            format!(
                "Failed to read {}. Run `tree-sitter build-wasm` first.",
                wasm_filename
            )
        })
        .unwrap();
    if open_in_browser {
        if let Err(_) = webbrowser::open(&format!("http://127.0.0.1:{}", port)) {
            eprintln!("Failed to open '{}' in a web browser", url);
        }
    }

    let tree_sitter_dir = env::var("TREE_SITTER_BASE_DIR").map(PathBuf::from).ok();
    let main_html = String::from_utf8(get_main_html(&tree_sitter_dir))
        .unwrap()
        .replace("THE_LANGUAGE_NAME", &grammar_name)
        .into_bytes();
    let playground_js = get_playground_js(&tree_sitter_dir);
    let lib_js = get_lib_js(&tree_sitter_dir);
    let lib_wasm = get_lib_wasm(&tree_sitter_dir);

    let html_header = Header::from_str("Content-Type: text/html").unwrap();
    let js_header = Header::from_str("Content-Type: application/javascript").unwrap();
    let wasm_header = Header::from_str("Content-Type: application/wasm").unwrap();

    for request in server.incoming_requests() {
        let res = match request.url() {
            "/" => response(&main_html, &html_header),
            "/playground.js" => response(&playground_js, &js_header),
            "/tree-sitter-parser.wasm" => response(&language_wasm, &wasm_header),
            "/tree-sitter.js" => {
                if cfg!(windows) {
                    redirect("https://tree-sitter.github.io/tree-sitter.js")
                } else {
                    response(&lib_js, &js_header)
                }
            }
            "/tree-sitter.wasm" => {
                if cfg!(windows) {
                    redirect("https://tree-sitter.github.io/tree-sitter.wasm")
                } else {
                    response(&lib_wasm, &wasm_header)
                }
            }
            _ => response(b"Not found", &html_header).with_status_code(404),
        };
        request.respond(res).expect("Failed to write HTTP response");
    }
}

fn redirect<'a>(url: &'a str) -> Response<&'a [u8]> {
    Response::empty(302)
        .with_data("".as_bytes(), Some(0))
        .with_header(Header::from_bytes("Location", url.as_bytes()).unwrap())
}

fn response<'a>(data: &'a [u8], header: &Header) -> Response<&'a [u8]> {
    Response::empty(200)
        .with_data(data, Some(data.len()))
        .with_header(header.clone())
}

fn get_available_port() -> Option<u16> {
    (8000..12000).find(port_is_available)
}

fn port_is_available(port: &u16) -> bool {
    TcpListener::bind(("127.0.0.1", *port)).is_ok()
}
<commit_msg>Always print where the playground is running<commit_after>use super::wasm;
use anyhow::Context;
use std::env;
use std::fs;
use std::net::TcpListener;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use tiny_http::{Header, Response, Server};
use webbrowser;

macro_rules! resource {
    ($name: tt, $path: tt) => {
        #[cfg(TREE_SITTER_EMBED_WASM_BINDING)]
        fn $name(tree_sitter_dir: &Option<PathBuf>) -> Vec<u8> {
            if let Some(tree_sitter_dir) = tree_sitter_dir {
                fs::read(tree_sitter_dir.join($path)).unwrap()
            } else {
                include_bytes!(concat!("../../", $path)).to_vec()
            }
        }

        #[cfg(not(TREE_SITTER_EMBED_WASM_BINDING))]
        fn $name(tree_sitter_dir: &Option<PathBuf>) -> Vec<u8> {
            if let Some(tree_sitter_dir) = tree_sitter_dir {
                fs::read(tree_sitter_dir.join($path)).unwrap()
            } else {
                include_bytes!(concat!("../../", $path)).to_vec()
            }
        }
    };
}

macro_rules! optional_resource {
    ($name: tt, $path: tt) => {
        #[cfg(TREE_SITTER_EMBED_WASM_BINDING)]
        fn $name(tree_sitter_dir: &Option<PathBuf>) -> Vec<u8> {
            if let Some(tree_sitter_dir) = tree_sitter_dir {
                fs::read(tree_sitter_dir.join($path)).unwrap()
            } else {
                include_bytes!(concat!("../../", $path)).to_vec()
            }
        }

        #[cfg(not(TREE_SITTER_EMBED_WASM_BINDING))]
        fn $name(tree_sitter_dir: &Option<PathBuf>) -> Vec<u8> {
            if let Some(tree_sitter_dir) = tree_sitter_dir {
                fs::read(tree_sitter_dir.join($path)).unwrap()
            } else {
                Vec::new()
            }
        }
    };
}

resource!(get_main_html, "cli/src/web_ui.html");
resource!(get_playground_js, "docs/assets/js/playground.js");
optional_resource!(get_lib_js, "lib/binding_web/tree-sitter.js");
optional_resource!(get_lib_wasm, "lib/binding_web/tree-sitter.wasm");

pub fn serve(grammar_path: &Path, open_in_browser: bool) {
    let port = get_available_port().expect("Couldn't find an available port");
    let url = format!("127.0.0.1:{}", port);
    let server = Server::http(&url).expect("Failed to start web server");
    let grammar_name = wasm::get_grammar_name(&grammar_path.join("src"))
        .with_context(|| "Failed to get wasm filename")
        .unwrap();
    let wasm_filename = format!("tree-sitter-{}.wasm", grammar_name);
    let language_wasm = fs::read(grammar_path.join(&wasm_filename))
        .with_context(|| {
            format!(
                "Failed to read {}. Run `tree-sitter build-wasm` first.",
                wasm_filename
            )
        })
        .unwrap();
    println!("Started playground on '{}'", url);
    if open_in_browser {
        if let Err(_) = webbrowser::open(&url) {
            eprintln!("Failed to open '{}' in a web browser", url);
        }
    }

    let tree_sitter_dir = env::var("TREE_SITTER_BASE_DIR").map(PathBuf::from).ok();
    let main_html = String::from_utf8(get_main_html(&tree_sitter_dir))
        .unwrap()
        .replace("THE_LANGUAGE_NAME", &grammar_name)
        .into_bytes();
    let playground_js = get_playground_js(&tree_sitter_dir);
    let lib_js = get_lib_js(&tree_sitter_dir);
    let lib_wasm = get_lib_wasm(&tree_sitter_dir);

    let html_header = Header::from_str("Content-Type: text/html").unwrap();
    let js_header = Header::from_str("Content-Type: application/javascript").unwrap();
    let wasm_header = Header::from_str("Content-Type: application/wasm").unwrap();

    for request in server.incoming_requests() {
        let res = match request.url() {
            "/" => response(&main_html, &html_header),
            "/playground.js" => response(&playground_js, &js_header),
            "/tree-sitter-parser.wasm" => response(&language_wasm, &wasm_header),
            "/tree-sitter.js" => {
                if cfg!(windows) {
                    redirect("https://tree-sitter.github.io/tree-sitter.js")
                } else {
                    response(&lib_js, &js_header)
                }
            }
            "/tree-sitter.wasm" => {
                if cfg!(windows) {
                    redirect("https://tree-sitter.github.io/tree-sitter.wasm")
                } else {
                    response(&lib_wasm, &wasm_header)
                }
            }
            _ => response(b"Not found", &html_header).with_status_code(404),
        };
        request.respond(res).expect("Failed to write HTTP response");
    }
}

fn redirect<'a>(url: &'a str) -> Response<&'a [u8]> {
    Response::empty(302)
        .with_data("".as_bytes(), Some(0))
        .with_header(Header::from_bytes("Location", url.as_bytes()).unwrap())
}

fn response<'a>(data: &'a [u8], header: &Header) -> Response<&'a [u8]> {
    Response::empty(200)
        .with_data(data, Some(data.len()))
        .with_header(header.clone())
}

fn get_available_port() -> Option<u16> {
    (8000..12000).find(port_is_available)
}

fn port_is_available(port: &u16) -> bool {
    TcpListener::bind(("127.0.0.1", *port)).is_ok()
}
<|endoftext|>


<commit_before><commit_msg>Use the correct serialize crate<commit_after><|endoftext|>


<commit_before><commit_msg>Add manufacturer/service data<commit_after><|endoftext|>


<commit_before>#[test]
fn it_works() {
}

mod SVM {
    /// Singly-linked cons list.
    ///
    /// This is used internally to represent list primitives in the machine.
    pub enum List<T> {
        Cons(T ~List<T>),
        Nil
    }

    /// Public implementation for List.
    pub impl List<T> {

        pub fn new() -> List<T> {
            Nil
        }

    }

    enum Exp {
        Number(int)
    }

    struct Engine {
        stack: Vec<Exp>
    }
}
<commit_msg>Use strict size for num expression<commit_after>#[test]
fn it_works() {
}

mod SVM {
    /// Singly-linked cons list.
    ///
    /// This is used internally to represent list primitives in the machine.
    pub enum List<T> {
        Nil,
        Cons(T, List<T>)
    }

    /// Public implementation for List.
    impl<T> List<T> {

        fn new() -> List<T> {
            Nil
        }

    }

    enum Exp {
        Number(i32)
    }

    struct Engine {
        stack: Vec<Exp>
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! This file implements Diem transaction metadata types to allow
//! easy parsing and introspection into metadata, whether the transaction
//! is using regular subaddressing, is subject to travel rule or corresponds
//! to an on-chain payment refund.

use serde::{Deserialize, Serialize};

/// List of all supported metadata types
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Metadata {
    Undefined,
    GeneralMetadata(GeneralMetadata),
    TravelRuleMetadata(TravelRuleMetadata),
    UnstructuredBytesMetadata(UnstructuredBytesMetadata),
    RefundMetadata(RefundMetadata),
    CoinTradeMetadata(CoinTradeMetadata),
}

/// List of supported transaction metadata format versions for regular
/// addressing with optional subaddressing or refund reference
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum GeneralMetadata {
    GeneralMetadataVersion0(GeneralMetadataV0),
}

/// Transaction metadata for regular addressing with optional subaddressing
/// or refunded transaction reference
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct GeneralMetadataV0 {
    /// Subaddress to which the funds are being sent
    #[serde(with = "serde_bytes")]
    to_subaddress: Option<Vec<u8>>,
    /// Subaddress from which the funds are being sent
    #[serde(with = "serde_bytes")]
    from_subaddress: Option<Vec<u8>>,
    /// In the case of refunds, referenced_event refers to the event sequence
    /// number of the sender’s original sent payment event.
    /// Since refunds are just another form of P2P transfer, the referenced
    /// event field allows a refunded payment to refer back to the original
    /// payment
    referenced_event: Option<u64>,
}

impl GeneralMetadataV0 {
    pub fn new(
        to_subaddress: Option<Vec<u8>>,
        from_subaddress: Option<Vec<u8>>,
        referenced_event: Option<u64>,
    ) -> Self {
        GeneralMetadataV0 {
            to_subaddress,
            from_subaddress,
            referenced_event,
        }
    }

    pub fn to_subaddress(&self) -> &Option<Vec<u8>> {
        &self.to_subaddress
    }

    pub fn from_subaddress(&self) -> &Option<Vec<u8>> {
        &self.from_subaddress
    }

    pub fn referenced_event(&self) -> &Option<u64> {
        &self.referenced_event
    }
}

/// List of supported transaction metadata format versions for transactions
/// subject to travel rule
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum TravelRuleMetadata {
    TravelRuleMetadataVersion0(TravelRuleMetadataV0),
}

/// Transaction metadata format for transactions subject to travel rule
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct TravelRuleMetadataV0 {
    /// Off-chain reference_id.  Used when off-chain APIs are used.
    /// Specifies the off-chain reference ID that was agreed upon in off-chain APIs.
    off_chain_reference_id: Option<String>,
}

/// Opaque binary transaction metadata
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct UnstructuredBytesMetadata {
    /// Unstructured byte vector metadata
    #[serde(with = "serde_bytes")]
    metadata: Option<Vec<u8>>,
}

/// List of supported transaction metadata format versions for refund transaction
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum RefundMetadata {
    RefundMetadataV0(RefundMetadataV0),
}

/// Transaction metadata format for transactions subject to refund transaction
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct RefundMetadataV0 {
    /// Transaction version that is refunded
    pub transaction_version: u64,
    /// The reason of the refund
    pub reason: RefundReason,
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum RefundReason {
    OtherReason,
    InvalidSubaddress,
    UserInitiatedPartialRefund,
    UserInitiatedFullRefund,
}

/// List of supported transaction metadata format versions for coin trade transaction
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum CoinTradeMetadata {
    CoinTradeMetadataV0(CoinTradeMetadataV0),
}

/// Transaction metadata format for coin trades (purchases/sells)
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct CoinTradeMetadataV0 {
    /// A list of trade_ids this transaction wants to settle
    pub trade_ids: Vec<String>,
}
<commit_msg>Add Payment Metadata<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! This file implements Diem transaction metadata types to allow
//! easy parsing and introspection into metadata, whether the transaction
//! is using regular subaddressing, is subject to travel rule or corresponds
//! to an on-chain payment refund.

use serde::{Deserialize, Serialize};

/// List of all supported metadata types
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Metadata {
    Undefined,
    GeneralMetadata(GeneralMetadata),
    TravelRuleMetadata(TravelRuleMetadata),
    UnstructuredBytesMetadata(UnstructuredBytesMetadata),
    RefundMetadata(RefundMetadata),
    CoinTradeMetadata(CoinTradeMetadata),
    PaymentMetadata(PaymentMetadata),
}

/// List of supported transaction metadata format versions for regular
/// addressing with optional subaddressing or refund reference
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum GeneralMetadata {
    GeneralMetadataVersion0(GeneralMetadataV0),
}

/// Transaction metadata for regular addressing with optional subaddressing
/// or refunded transaction reference
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct GeneralMetadataV0 {
    /// Subaddress to which the funds are being sent
    #[serde(with = "serde_bytes")]
    to_subaddress: Option<Vec<u8>>,
    /// Subaddress from which the funds are being sent
    #[serde(with = "serde_bytes")]
    from_subaddress: Option<Vec<u8>>,
    /// In the case of refunds, referenced_event refers to the event sequence
    /// number of the sender’s original sent payment event.
    /// Since refunds are just another form of P2P transfer, the referenced
    /// event field allows a refunded payment to refer back to the original
    /// payment
    referenced_event: Option<u64>,
}

impl GeneralMetadataV0 {
    pub fn new(
        to_subaddress: Option<Vec<u8>>,
        from_subaddress: Option<Vec<u8>>,
        referenced_event: Option<u64>,
    ) -> Self {
        GeneralMetadataV0 {
            to_subaddress,
            from_subaddress,
            referenced_event,
        }
    }

    pub fn to_subaddress(&self) -> &Option<Vec<u8>> {
        &self.to_subaddress
    }

    pub fn from_subaddress(&self) -> &Option<Vec<u8>> {
        &self.from_subaddress
    }

    pub fn referenced_event(&self) -> &Option<u64> {
        &self.referenced_event
    }
}

/// List of supported transaction metadata format versions for transactions
/// subject to travel rule
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum TravelRuleMetadata {
    TravelRuleMetadataVersion0(TravelRuleMetadataV0),
}

/// Transaction metadata format for transactions subject to travel rule
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct TravelRuleMetadataV0 {
    /// Off-chain reference_id.  Used when off-chain APIs are used.
    /// Specifies the off-chain reference ID that was agreed upon in off-chain APIs.
    off_chain_reference_id: Option<String>,
}

/// Opaque binary transaction metadata
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct UnstructuredBytesMetadata {
    /// Unstructured byte vector metadata
    #[serde(with = "serde_bytes")]
    metadata: Option<Vec<u8>>,
}

/// List of supported transaction metadata format versions for refund transaction
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum RefundMetadata {
    RefundMetadataV0(RefundMetadataV0),
}

/// Transaction metadata format for transactions subject to refund transaction
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct RefundMetadataV0 {
    /// Transaction version that is refunded
    pub transaction_version: u64,
    /// The reason of the refund
    pub reason: RefundReason,
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum RefundReason {
    OtherReason,
    InvalidSubaddress,
    UserInitiatedPartialRefund,
    UserInitiatedFullRefund,
}

/// List of supported transaction metadata format versions for coin trade transaction
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum CoinTradeMetadata {
    CoinTradeMetadataV0(CoinTradeMetadataV0),
}

/// Transaction metadata format for coin trades (purchases/sells)
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct CoinTradeMetadataV0 {
    /// A list of trade_ids this transaction wants to settle
    pub trade_ids: Vec<String>,
}

/// List of supported transaction metadata format versions for transactions for payments
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum PaymentMetadata {
    PaymentMetadataVersion0(PaymentMetadataV0),
}

/// Transaction metadata format for transactions for payments
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct PaymentMetadataV0 {
    /// Reference ID needed for off-chain reference ID exchange.
    reference_id: [u8; 16],
}
<|endoftext|>


<commit_before><commit_msg>Fixed distance clamping<commit_after><|endoftext|>


<commit_before>use algo::{AlgoInput, AlgoOutput, JsonValue};
use std::error::Error as StdError;
use error::{Error, ErrorKind};
use json;

#[cfg(feature="with-serde")]
use serde::Deserialize;
#[cfg(feature="with-rustc-serialize")]
use rustc_serialize::Decodable;

/// Alternate implementation for `EntryPoint`
///   that automatically decodes JSON input to the associate type
///
/// # Examples
/// ```no_run
/// # use algorithmia::prelude::*;
/// # use std::error::Error;
/// # #[derive(Default)]
/// # struct Algo;
/// impl DecodedEntryPoint for Algo {
///     // Expect input to be an array of 2 strings
///     type Input = (String, String);
///     fn apply_decoded(&self, input: Self::Input) -> Result<AlgoOutput, Box<Error>> {
///         let msg = format!("{} - {}", input.0, input.1);
///         Ok(msg.into())
///     }
/// }
/// ```
pub trait DecodedEntryPoint: Default {
    /// Specifies the type that the input will be automatically deserialized into
    #[cfg(feature="with-serde")]
    type Input: Deserialize;
    /// Specifies the type that the input will be automatically decoded into
    #[cfg(feature="with-rustc-serialize")]
    type Input: Decodable;

    /// This method is an apply variant that will receive the decoded form of JSON input.
    ///   If decoding failed, a `DecoderError` will be returned before this method is invoked.
    #[allow(unused_variables)]
    fn apply_decoded(&self, input: Self::Input) -> Result<AlgoOutput, Box<StdError>>;
}

impl<T> EntryPoint for T
    where T: DecodedEntryPoint
{
    fn apply(&self, input: AlgoInput) -> Result<AlgoOutput, Box<StdError>> {
        match input.as_json() {
            Some(obj) => {
                let decoded = json::decode_value(obj.into_owned())?;
                self.apply_decoded(decoded)
            }
            None => Err(Error::from(ErrorKind::UnsupportedInput).into()),
        }
    }
}

/// Implementing an algorithm involves overriding at least one of these methods
pub trait EntryPoint: Default {
    #[allow(unused_variables)]
    /// Override to handle string input
    fn apply_str(&self, text: &str) -> Result<AlgoOutput, Box<StdError>> {
        Err(Error::from(ErrorKind::UnsupportedInput).into())
    }

    #[allow(unused_variables)]
    /// Override to handle JSON input (see also [`DecodedEntryPoint`](trait.DecodedEntryPoint.html))
    fn apply_json(&self, json: &JsonValue) -> Result<AlgoOutput, Box<StdError>> {
        Err(Error::from(ErrorKind::UnsupportedInput).into())
    }

    #[allow(unused_variables)]
    /// Override to handle binary input
    fn apply_bytes(&self, bytes: &[u8]) -> Result<AlgoOutput, Box<StdError>> {
        Err(Error::from(ErrorKind::UnsupportedInput).into())
    }

    /// The default implementation of this method calls
    /// `apply_str`, `apply_json`, or `apply_bytes` based on the input type.
    ///
    /// - `AlgoInput::Text` results in call to  `apply_str`
    /// - `AlgoInput::Json` results in call to  `apply_json`
    /// - `AlgoInput::Binary` results in call to  `apply_bytes`
    ///
    /// If that call returns anKind `UnsupportedInput` error, then this method
    ///   method will may attempt to coerce the input into another type
    ///   and attempt one more call:
    ///
    /// - `AlgoInput::Text` input will be JSON-encoded to call `apply_json`
    /// - `AlgoInput::Json` input will be parse to see it can call `apply_str`
    fn apply(&self, input: AlgoInput) -> Result<AlgoOutput, Box<StdError>> {
        match input {
            AlgoInput::Text(ref text) => {
                match self.apply_str(text) {
                    Err(err) => {
                        match err.downcast::<Error>().map(|err| *err) {
                            Ok(Error(ErrorKind::UnsupportedInput, _)) => {
                                match input.as_json() {
                                    Some(json) => self.apply_json(&json),
                                    None => Err(Error::from(ErrorKind::UnsupportedInput).into()),
                                }
                            }
                            Ok(err) => Err(err.into()),
                            Err(err) => Err(err.into()),
                        }
                    }
                    ret => ret,
                }
            }
            AlgoInput::Json(ref json) => {
                match self.apply_json(json) {
                    Err(err) => {
                        match err.downcast::<Error>().map(|err| *err) {
                            Ok(Error(ErrorKind::UnsupportedInput, _)) => {
                                match input.as_string() {
                                    Some(text) => self.apply_str(text),
                                    None => {
                                        Err(Error::from(ErrorKind::UnsupportedInput).into()).into()
                                    }
                                }
                            }
                            Ok(err) => Err(err.into()),
                            Err(err) => Err(err.into()),
                        }
                    }
                    ret => ret,
                }
            }
            AlgoInput::Binary(ref bytes) => self.apply_bytes(bytes),
        }
    }
}
<commit_msg>Wrap decoding error in more helpful message<commit_after>use algo::{AlgoInput, AlgoOutput, JsonValue};
use std::error::Error as StdError;
use error::{Error, ErrorKind, ResultExt};
use json;

#[cfg(feature="with-serde")]
use serde::Deserialize;
#[cfg(feature="with-rustc-serialize")]
use rustc_serialize::Decodable;

/// Alternate implementation for `EntryPoint`
///   that automatically decodes JSON input to the associate type
///
/// # Examples
/// ```no_run
/// # use algorithmia::prelude::*;
/// # use std::error::Error;
/// # #[derive(Default)]
/// # struct Algo;
/// impl DecodedEntryPoint for Algo {
///     // Expect input to be an array of 2 strings
///     type Input = (String, String);
///     fn apply_decoded(&self, input: Self::Input) -> Result<AlgoOutput, Box<Error>> {
///         let msg = format!("{} - {}", input.0, input.1);
///         Ok(msg.into())
///     }
/// }
/// ```
pub trait DecodedEntryPoint: Default {
    /// Specifies the type that the input will be automatically deserialized into
    #[cfg(feature="with-serde")]
    type Input: Deserialize;
    /// Specifies the type that the input will be automatically decoded into
    #[cfg(feature="with-rustc-serialize")]
    type Input: Decodable;

    /// This method is an apply variant that will receive the decoded form of JSON input.
    ///   If decoding failed, a `DecoderError` will be returned before this method is invoked.
    #[allow(unused_variables)]
    fn apply_decoded(&self, input: Self::Input) -> Result<AlgoOutput, Box<StdError>>;
}

impl<T> EntryPoint for T
    where T: DecodedEntryPoint
{
    fn apply(&self, input: AlgoInput) -> Result<AlgoOutput, Box<StdError>> {
        match input.as_json() {
            Some(obj) => {
                let decoded = json::decode_value(obj.into_owned())
                    .chain_err(|| "failed to parse input as JSON into the expected type")?;
                self.apply_decoded(decoded)
            }
            None => Err(Error::from(ErrorKind::UnsupportedInput).into()),
        }
    }
}

/// Implementing an algorithm involves overriding at least one of these methods
pub trait EntryPoint: Default {
    #[allow(unused_variables)]
    /// Override to handle string input
    fn apply_str(&self, text: &str) -> Result<AlgoOutput, Box<StdError>> {
        Err(Error::from(ErrorKind::UnsupportedInput).into())
    }

    #[allow(unused_variables)]
    /// Override to handle JSON input (see also [`DecodedEntryPoint`](trait.DecodedEntryPoint.html))
    fn apply_json(&self, json: &JsonValue) -> Result<AlgoOutput, Box<StdError>> {
        Err(Error::from(ErrorKind::UnsupportedInput).into())
    }

    #[allow(unused_variables)]
    /// Override to handle binary input
    fn apply_bytes(&self, bytes: &[u8]) -> Result<AlgoOutput, Box<StdError>> {
        Err(Error::from(ErrorKind::UnsupportedInput).into())
    }

    /// The default implementation of this method calls
    /// `apply_str`, `apply_json`, or `apply_bytes` based on the input type.
    ///
    /// - `AlgoInput::Text` results in call to  `apply_str`
    /// - `AlgoInput::Json` results in call to  `apply_json`
    /// - `AlgoInput::Binary` results in call to  `apply_bytes`
    ///
    /// If that call returns anKind `UnsupportedInput` error, then this method
    ///   method will may attempt to coerce the input into another type
    ///   and attempt one more call:
    ///
    /// - `AlgoInput::Text` input will be JSON-encoded to call `apply_json`
    /// - `AlgoInput::Json` input will be parse to see it can call `apply_str`
    fn apply(&self, input: AlgoInput) -> Result<AlgoOutput, Box<StdError>> {
        match input {
            AlgoInput::Text(ref text) => {
                match self.apply_str(text) {
                    Err(err) => {
                        match err.downcast::<Error>().map(|err| *err) {
                            Ok(Error(ErrorKind::UnsupportedInput, _)) => {
                                match input.as_json() {
                                    Some(json) => self.apply_json(&json),
                                    None => Err(Error::from(ErrorKind::UnsupportedInput).into()),
                                }
                            }
                            Ok(err) => Err(err.into()),
                            Err(err) => Err(err.into()),
                        }
                    }
                    ret => ret,
                }
            }
            AlgoInput::Json(ref json) => {
                match self.apply_json(json) {
                    Err(err) => {
                        match err.downcast::<Error>().map(|err| *err) {
                            Ok(Error(ErrorKind::UnsupportedInput, _)) => {
                                match input.as_string() {
                                    Some(text) => self.apply_str(text),
                                    None => {
                                        Err(Error::from(ErrorKind::UnsupportedInput).into()).into()
                                    }
                                }
                            }
                            Ok(err) => Err(err.into()),
                            Err(err) => Err(err.into()),
                        }
                    }
                    ret => ret,
                }
            }
            AlgoInput::Binary(ref bytes) => self.apply_bytes(bytes),
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp::Reverse;
use std::collections::HashMap;

use once_cell::sync::Lazy;

use super::RawOutcome;
use crate::core::{FilterList, LowercaseText};
use crate::utils::is_stop_char;
use crate::{Lang, Script};

const AFR: &str = "abcdefghijklmnopqrstuvwxyzáèéêëíîïóôúû";
const AKA: &str = "abdefghiklmnoprstuwyɔɛ";
const AZE: &str = "abcdefghijklmnopqrstuvxyzçöüğışə̇";
const CAT: &str = "abcdefghijklmnopqrstuvwxyz·àçèéíïòóúü";
const CES: &str = "abcdefghijklmnopqrstuvwxyzáéóúýčďěňřšťůž";
const DAN: &str = "abcdefghijklmnopqrstuvwxyzåæø";
const DEU: &str = "abcdefghijklmnopqrstuvwxyzßäöü";
const ENG: &str = "abcdefghijklmnopqrstuvwxyz";
const EPO: &str = "abcdefghijklmnoprstuvzĉĝĥĵŝŭ";
const EST: &str = "abcdefghijklmnopqrstuvwxyzäõöü";
const FIN: &str = "abcdefghijklmnopqrstuvwxyzäöšž";
const FRA: &str = "abcdefghijklmnopqrstuvwxyzàâçèéêëîïôùûüÿœ";
const HRV: &str = "abcdefghijklmnopqrstuvwxyzćčđšž";
const HUN: &str = "abcdefghijklmnopqrstuvwxyzáéíóöúüőű";
const IND: &str = "abcdefghijklmnopqrstuvwxyz";
const ITA: &str = "abcdefghijklmnopqrstuvwxyzàèéìòù";
const JAV: &str = "abcdefghijklmnopqrstuvwxyzèé";
const LAT: &str = "abcdefghijklmnopqrstuvwxyz";
const LAV: &str = "abcdefghijklmnopqrstuvwxyzāčēģīķļņōŗšūž";
const LIT: &str = "abcdefghijklmnopqrstuvwxyząčėęįšūųž";
const NLD: &str = "abcdefghijklmnopqrstuvwxyzàèéëïĳ";
const NOB: &str = "abcdefghijklmnopqrstuvwxyzåæø";
const POL: &str = "abcdefghijklmnopqrstuvwxyzóąćęłńśźż";
const POR: &str = "abcdefghijklmnopqrstuvwxyzàáâãçéêíóôõú";
const RON: &str = "abcdefghijklmnopqrstuvwxyzâîăşţ";
const SLK: &str = "abcdefghijklmnopqrstuvwxyzáäéíóôúýčďĺľňŕšťž";
const SLV: &str = "abcdefghijklmnopqrstuvwxyzčšž";
const SNA: &str = "abcdefghijklmnopqrstuvwxyz";
const SPA: &str = "abcdefghijklmnopqrstuvwxyz¡¿áéíñóúü";
const SWE: &str = "abcdefghijklmnopqrstuvwxyzäåö";
const TGL: &str = "abcdefghijklmnopqrstuvwxyzáéíñóú";
const TUK: &str = "abdefghijklmnoprstuwyzäçöüýňşž";
const TUR: &str = "abcdefghijklmnopqrstuvwxyzçöüğış̇";
const UZB: &str = "abcdefghijklmnopqrstuvxyzʻ";
const VIE: &str =
    "abcdefghijklmnopqrstuvwxyzàáâãèéêìíòóôõùúýăđĩũơưạảấầẩẫậắằẳẵặẹẻẽếềểễệỉịọỏốồổỗộớờởỡợụủứừửữựỳỵỷỹ";
const ZUL: &str = "abcdefghijklmnopqrstuvwxyz";

const LATIN_ALPHABETS: &[(Lang, &str)] = &[
    (Lang::Afr, AFR),
    (Lang::Aka, AKA),
    (Lang::Aze, AZE),
    (Lang::Cat, CAT),
    (Lang::Ces, CES),
    (Lang::Dan, DAN),
    (Lang::Deu, DEU),
    (Lang::Eng, ENG),
    (Lang::Epo, EPO),
    (Lang::Est, EST),
    (Lang::Fin, FIN),
    (Lang::Fra, FRA),
    (Lang::Hrv, HRV),
    (Lang::Hun, HUN),
    (Lang::Ind, IND),
    (Lang::Ita, ITA),
    (Lang::Jav, JAV),
    (Lang::Lat, LAT),
    (Lang::Lav, LAV),
    (Lang::Lit, LIT),
    (Lang::Nld, NLD),
    (Lang::Nob, NOB),
    (Lang::Pol, POL),
    (Lang::Por, POR),
    (Lang::Ron, RON),
    (Lang::Slk, SLK),
    (Lang::Slv, SLV),
    (Lang::Sna, SNA),
    (Lang::Spa, SPA),
    (Lang::Swe, SWE),
    (Lang::Tgl, TGL),
    (Lang::Tuk, TUK),
    (Lang::Tur, TUR),
    (Lang::Uzb, UZB),
    (Lang::Vie, VIE),
    (Lang::Zul, ZUL),
];

/// Inverted map binding a character to a set of languages.
pub static ALPHABET_LANG_MAP: Lazy<(Vec<char>, Vec<Vec<Lang>>)> = Lazy::new(|| {
    let mut map = HashMap::new();

    for (lang, alphabet) in LATIN_ALPHABETS {
        for c in alphabet.chars() {
            let entry = map.entry(c).or_insert_with(Vec::new);
            entry.push(*lang);
        }
    }

    let mut char_lang: Vec<_> = map.into_iter().collect();

    char_lang.sort_unstable_by_key(|(c, _)| *c);

    let mut chars = Vec::with_capacity(char_lang.len());
    let mut langs = Vec::with_capacity(char_lang.len());
    for (ch, languages) in char_lang {
        chars.push(ch);
        langs.push(languages);
    }

    (chars, langs)
});

pub fn alphabet_calculate_scores(text: &LowercaseText, filter_list: &FilterList) -> RawOutcome {
    let (chars, langs) = &*ALPHABET_LANG_MAP;

    // score of each character.
    let mut char_scores = vec![0; chars.len()];
    let mut max_raw_score = 0;
    // iterate over the text and scores characters.
    for ch in text.chars() {
        if is_stop_char(ch) {
            continue;
        }

        max_raw_score += 1;

        if let Ok(position) = chars.binary_search(&ch) {
            // add 2 and remove max_raw_score at the end,
            // to keep the score interval of -max_raw_score..max_raw_score
            char_scores[position] += 2;
        }
    }

    // score of each lang.
    let mut lang_scores = vec![0; Lang::all().len()];
    let mut common_score: usize = 0;
    // iterate over scored characters to compute language's scores.
    for (position, char_score) in char_scores.into_iter().enumerate() {
        if char_score > 0 {
            let languages = &langs[position];
            // if current character is common to all Languages, increment a common score
            // instead of iterating over all Languages scores.
            if languages.len() == LATIN_ALPHABETS.len() {
                common_score += char_score;
            } else {
                for &lang in languages {
                    lang_scores[lang as usize] += char_score;
                }
            }
        }
    }

    // remap languages with theirs scores.
    let mut raw_scores: Vec<(Lang, usize)> = Script::Latin
        .langs()
        .iter()
        .filter(|&&l| filter_list.is_allowed(l))
        .map(|&l| {
            let score = (lang_scores[l as usize] + common_score).saturating_sub(max_raw_score);
            (l, score)
        })
        .collect();

    raw_scores.sort_unstable_by_key(|(_, score)| Reverse(*score));

    let mut normalized_scores = vec![];

    for &(lang, raw_score) in raw_scores.iter() {
        let normalized_score = raw_score as f64 / max_raw_score as f64;
        normalized_scores.push((lang, normalized_score));
    }

    RawOutcome {
        count: max_raw_score,
        raw_scores,
        scores: normalized_scores,
    }
}
<commit_msg>Add a unit test for latin::alphabet_calculate_scores<commit_after>use std::cmp::Reverse;
use std::collections::HashMap;

use once_cell::sync::Lazy;

use super::RawOutcome;
use crate::core::{FilterList, LowercaseText};
use crate::utils::is_stop_char;
use crate::{Lang, Script};

const AFR: &str = "abcdefghijklmnopqrstuvwxyzáèéêëíîïóôúû";
const AKA: &str = "abdefghiklmnoprstuwyɔɛ";
const AZE: &str = "abcdefghijklmnopqrstuvxyzçöüğışə̇";
const CAT: &str = "abcdefghijklmnopqrstuvwxyz·àçèéíïòóúü";
const CES: &str = "abcdefghijklmnopqrstuvwxyzáéóúýčďěňřšťůž";
const DAN: &str = "abcdefghijklmnopqrstuvwxyzåæø";
const DEU: &str = "abcdefghijklmnopqrstuvwxyzßäöü";
const ENG: &str = "abcdefghijklmnopqrstuvwxyz";
const EPO: &str = "abcdefghijklmnoprstuvzĉĝĥĵŝŭ";
const EST: &str = "abcdefghijklmnopqrstuvwxyzäõöü";
const FIN: &str = "abcdefghijklmnopqrstuvwxyzäöšž";
const FRA: &str = "abcdefghijklmnopqrstuvwxyzàâçèéêëîïôùûüÿœ";
const HRV: &str = "abcdefghijklmnopqrstuvwxyzćčđšž";
const HUN: &str = "abcdefghijklmnopqrstuvwxyzáéíóöúüőű";
const IND: &str = "abcdefghijklmnopqrstuvwxyz";
const ITA: &str = "abcdefghijklmnopqrstuvwxyzàèéìòù";
const JAV: &str = "abcdefghijklmnopqrstuvwxyzèé";
const LAT: &str = "abcdefghijklmnopqrstuvwxyz";
const LAV: &str = "abcdefghijklmnopqrstuvwxyzāčēģīķļņōŗšūž";
const LIT: &str = "abcdefghijklmnopqrstuvwxyząčėęįšūųž";
const NLD: &str = "abcdefghijklmnopqrstuvwxyzàèéëïĳ";
const NOB: &str = "abcdefghijklmnopqrstuvwxyzåæø";
const POL: &str = "abcdefghijklmnopqrstuvwxyzóąćęłńśźż";
const POR: &str = "abcdefghijklmnopqrstuvwxyzàáâãçéêíóôõú";
const RON: &str = "abcdefghijklmnopqrstuvwxyzâîăşţ";
const SLK: &str = "abcdefghijklmnopqrstuvwxyzáäéíóôúýčďĺľňŕšťž";
const SLV: &str = "abcdefghijklmnopqrstuvwxyzčšž";
const SNA: &str = "abcdefghijklmnopqrstuvwxyz";
const SPA: &str = "abcdefghijklmnopqrstuvwxyz¡¿áéíñóúü";
const SWE: &str = "abcdefghijklmnopqrstuvwxyzäåö";
const TGL: &str = "abcdefghijklmnopqrstuvwxyzáéíñóú";
const TUK: &str = "abdefghijklmnoprstuwyzäçöüýňşž";
const TUR: &str = "abcdefghijklmnopqrstuvwxyzçöüğış̇";
const UZB: &str = "abcdefghijklmnopqrstuvxyzʻ";
const VIE: &str =
    "abcdefghijklmnopqrstuvwxyzàáâãèéêìíòóôõùúýăđĩũơưạảấầẩẫậắằẳẵặẹẻẽếềểễệỉịọỏốồổỗộớờởỡợụủứừửữựỳỵỷỹ";
const ZUL: &str = "abcdefghijklmnopqrstuvwxyz";

const LATIN_ALPHABETS: &[(Lang, &str)] = &[
    (Lang::Afr, AFR),
    (Lang::Aka, AKA),
    (Lang::Aze, AZE),
    (Lang::Cat, CAT),
    (Lang::Ces, CES),
    (Lang::Dan, DAN),
    (Lang::Deu, DEU),
    (Lang::Eng, ENG),
    (Lang::Epo, EPO),
    (Lang::Est, EST),
    (Lang::Fin, FIN),
    (Lang::Fra, FRA),
    (Lang::Hrv, HRV),
    (Lang::Hun, HUN),
    (Lang::Ind, IND),
    (Lang::Ita, ITA),
    (Lang::Jav, JAV),
    (Lang::Lat, LAT),
    (Lang::Lav, LAV),
    (Lang::Lit, LIT),
    (Lang::Nld, NLD),
    (Lang::Nob, NOB),
    (Lang::Pol, POL),
    (Lang::Por, POR),
    (Lang::Ron, RON),
    (Lang::Slk, SLK),
    (Lang::Slv, SLV),
    (Lang::Sna, SNA),
    (Lang::Spa, SPA),
    (Lang::Swe, SWE),
    (Lang::Tgl, TGL),
    (Lang::Tuk, TUK),
    (Lang::Tur, TUR),
    (Lang::Uzb, UZB),
    (Lang::Vie, VIE),
    (Lang::Zul, ZUL),
];

/// Inverted map binding a character to a set of languages.
pub static ALPHABET_LANG_MAP: Lazy<(Vec<char>, Vec<Vec<Lang>>)> = Lazy::new(|| {
    let mut map = HashMap::new();

    for (lang, alphabet) in LATIN_ALPHABETS {
        for c in alphabet.chars() {
            let entry = map.entry(c).or_insert_with(Vec::new);
            entry.push(*lang);
        }
    }

    let mut char_lang: Vec<_> = map.into_iter().collect();

    char_lang.sort_unstable_by_key(|(c, _)| *c);

    let mut chars = Vec::with_capacity(char_lang.len());
    let mut langs = Vec::with_capacity(char_lang.len());
    for (ch, languages) in char_lang {
        chars.push(ch);
        langs.push(languages);
    }

    (chars, langs)
});

pub fn alphabet_calculate_scores(text: &LowercaseText, filter_list: &FilterList) -> RawOutcome {
    let (chars, langs) = &*ALPHABET_LANG_MAP;

    // score of each character.
    let mut char_scores = vec![0; chars.len()];
    let mut max_raw_score = 0;
    // iterate over the text and scores characters.
    for ch in text.chars() {
        if is_stop_char(ch) {
            continue;
        }

        max_raw_score += 1;

        if let Ok(position) = chars.binary_search(&ch) {
            // add 2 and remove max_raw_score at the end,
            // to keep the score interval of -max_raw_score..max_raw_score
            char_scores[position] += 2;
        }
    }

    // score of each lang.
    let mut lang_scores = vec![0; Lang::all().len()];
    let mut common_score: usize = 0;
    // iterate over scored characters to compute language's scores.
    for (position, char_score) in char_scores.into_iter().enumerate() {
        if char_score > 0 {
            let languages = &langs[position];
            // if current character is common to all Languages, increment a common score
            // instead of iterating over all Languages scores.
            if languages.len() == LATIN_ALPHABETS.len() {
                common_score += char_score;
            } else {
                for &lang in languages {
                    lang_scores[lang as usize] += char_score;
                }
            }
        }
    }

    // remap languages with theirs scores.
    let mut raw_scores: Vec<(Lang, usize)> = Script::Latin
        .langs()
        .iter()
        .filter(|&&l| filter_list.is_allowed(l))
        .map(|&l| {
            let score = (lang_scores[l as usize] + common_score).saturating_sub(max_raw_score);
            (l, score)
        })
        .collect();

    raw_scores.sort_unstable_by_key(|(_, score)| Reverse(*score));

    let mut normalized_scores = vec![];

    for &(lang, raw_score) in raw_scores.iter() {
        let normalized_score = raw_score as f64 / max_raw_score as f64;
        normalized_scores.push((lang, normalized_score));
    }

    RawOutcome {
        count: max_raw_score,
        raw_scores,
        scores: normalized_scores,
    }
}

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

    #[test]
    fn test_alphabet_calculate_scores_against_harmaja_hauras() {
        let text =
            LowercaseText::new("Ja kulkee kylmä hetki pariimme, Olet hauras kuin jää, Ja kulke");
        let filter = FilterList::All;

        let outcome = alphabet_calculate_scores(&text, &filter);
        assert_eq!(outcome.count, 50);
        assert_eq!(outcome.raw_scores.len(), 36);
        assert_eq!(outcome.scores.len(), 36);

        let raw_scores_for = |lang: Lang| {
            outcome
                .raw_scores
                .iter()
                .find(|(l, _)| *l == lang)
                .unwrap()
                .1
        };
        let scores_for = |lang: Lang| outcome.scores.iter().find(|(l, _)| *l == lang).unwrap().1;

        assert_eq!(raw_scores_for(Lang::Fin), 50);
        assert_eq!(raw_scores_for(Lang::Deu), 50);
        assert_eq!(raw_scores_for(Lang::Epo), 42);

        assert_eq!(scores_for(Lang::Fin), 1.0);
        assert_eq!(scores_for(Lang::Deu), 1.0);
        assert_eq!(scores_for(Lang::Epo), 0.84);
    }
}
<|endoftext|>


<commit_before>use events::VirtualKeyCode;
use winapi;

pub fn vkeycode_to_element(code: winapi::WPARAM) -> Option<VirtualKeyCode> {
    match code {
        //winapi::VK_LBUTTON => Some(VirtualKeyCode::Lbutton),
        //winapi::VK_RBUTTON => Some(VirtualKeyCode::Rbutton),
        //winapi::VK_CANCEL => Some(VirtualKeyCode::Cancel),
        //winapi::VK_MBUTTON => Some(VirtualKeyCode::Mbutton),
        //winapi::VK_XBUTTON1 => Some(VirtualKeyCode::Xbutton1),
        //winapi::VK_XBUTTON2 => Some(VirtualKeyCode::Xbutton2),
        winapi::VK_BACK => Some(VirtualKeyCode::Back),
        winapi::VK_TAB => Some(VirtualKeyCode::Tab),
        //winapi::VK_CLEAR => Some(VirtualKeyCode::Clear),
        winapi::VK_RETURN => Some(VirtualKeyCode::Return),
        //winapi::VK_SHIFT => Some(VirtualKeyCode::Shift),
        //winapi::VK_CONTROL => Some(VirtualKeyCode::Control),
        //winapi::VK_MENU => Some(VirtualKeyCode::Menu),
        winapi::VK_PAUSE => Some(VirtualKeyCode::Pause),
        winapi::VK_CAPITAL => Some(VirtualKeyCode::Capital),
        winapi::VK_KANA => Some(VirtualKeyCode::Kana),
        //winapi::VK_HANGUEL => Some(VirtualKeyCode::Hanguel),
        //winapi::VK_HANGUL => Some(VirtualKeyCode::Hangul),
        //winapi::VK_JUNJA => Some(VirtualKeyCode::Junja),
        //winapi::VK_FINAL => Some(VirtualKeyCode::Final),
        //winapi::VK_HANJA => Some(VirtualKeyCode::Hanja),
        winapi::VK_KANJI => Some(VirtualKeyCode::Kanji),
        winapi::VK_ESCAPE => Some(VirtualKeyCode::Escape),
        winapi::VK_CONVERT => Some(VirtualKeyCode::Convert),
        //winapi::VK_NONCONVERT => Some(VirtualKeyCode::Nonconvert),
        //winapi::VK_ACCEPT => Some(VirtualKeyCode::Accept),
        //winapi::VK_MODECHANGE => Some(VirtualKeyCode::Modechange),
        winapi::VK_SPACE => Some(VirtualKeyCode::Space),
        winapi::VK_PRIOR => Some(VirtualKeyCode::PageUp),
        winapi::VK_NEXT => Some(VirtualKeyCode::PageDown),
        winapi::VK_END => Some(VirtualKeyCode::End),
        winapi::VK_HOME => Some(VirtualKeyCode::Home),
        winapi::VK_LEFT => Some(VirtualKeyCode::Left),
        winapi::VK_UP => Some(VirtualKeyCode::Up),
        winapi::VK_RIGHT => Some(VirtualKeyCode::Right),
        winapi::VK_DOWN => Some(VirtualKeyCode::Down),
        //winapi::VK_SELECT => Some(VirtualKeyCode::Select),
        //winapi::VK_PRINT => Some(VirtualKeyCode::Print),
        //winapi::VK_EXECUTE => Some(VirtualKeyCode::Execute),
        winapi::VK_SNAPSHOT => Some(VirtualKeyCode::Snapshot),
        winapi::VK_INSERT => Some(VirtualKeyCode::Insert),
        winapi::VK_DELETE => Some(VirtualKeyCode::Delete),
        //winapi::VK_HELP => Some(VirtualKeyCode::Help),
        0x30 => Some(VirtualKeyCode::Key0),
        0x31 => Some(VirtualKeyCode::Key1),
        0x32 => Some(VirtualKeyCode::Key2),
        0x33 => Some(VirtualKeyCode::Key3),
        0x34 => Some(VirtualKeyCode::Key4),
        0x35 => Some(VirtualKeyCode::Key5),
        0x36 => Some(VirtualKeyCode::Key6),
        0x37 => Some(VirtualKeyCode::Key7),
        0x38 => Some(VirtualKeyCode::Key8),
        0x39 => Some(VirtualKeyCode::Key9),
        0x41 => Some(VirtualKeyCode::A),
        0x42 => Some(VirtualKeyCode::B),
        0x43 => Some(VirtualKeyCode::C),
        0x44 => Some(VirtualKeyCode::D),
        0x45 => Some(VirtualKeyCode::E),
        0x46 => Some(VirtualKeyCode::F),
        0x47 => Some(VirtualKeyCode::G),
        0x48 => Some(VirtualKeyCode::H),
        0x49 => Some(VirtualKeyCode::I),
        0x4A => Some(VirtualKeyCode::J),
        0x4B => Some(VirtualKeyCode::K),
        0x4C => Some(VirtualKeyCode::L),
        0x4D => Some(VirtualKeyCode::M),
        0x4E => Some(VirtualKeyCode::N),
        0x4F => Some(VirtualKeyCode::O),
        0x50 => Some(VirtualKeyCode::P),
        0x51 => Some(VirtualKeyCode::Q),
        0x52 => Some(VirtualKeyCode::R),
        0x53 => Some(VirtualKeyCode::S),
        0x54 => Some(VirtualKeyCode::T),
        0x55 => Some(VirtualKeyCode::U),
        0x56 => Some(VirtualKeyCode::V),
        0x57 => Some(VirtualKeyCode::W),
        0x58 => Some(VirtualKeyCode::X),
        0x59 => Some(VirtualKeyCode::Y),
        0x5A => Some(VirtualKeyCode::Z),
        //winapi::VK_LWIN => Some(VirtualKeyCode::Lwin),
        //winapi::VK_RWIN => Some(VirtualKeyCode::Rwin),
        winapi::VK_APPS => Some(VirtualKeyCode::Apps),
        winapi::VK_SLEEP => Some(VirtualKeyCode::Sleep),
        winapi::VK_NUMPAD0 => Some(VirtualKeyCode::Numpad0),
        winapi::VK_NUMPAD1 => Some(VirtualKeyCode::Numpad1),
        winapi::VK_NUMPAD2 => Some(VirtualKeyCode::Numpad2),
        winapi::VK_NUMPAD3 => Some(VirtualKeyCode::Numpad3),
        winapi::VK_NUMPAD4 => Some(VirtualKeyCode::Numpad4),
        winapi::VK_NUMPAD5 => Some(VirtualKeyCode::Numpad5),
        winapi::VK_NUMPAD6 => Some(VirtualKeyCode::Numpad6),
        winapi::VK_NUMPAD7 => Some(VirtualKeyCode::Numpad7),
        winapi::VK_NUMPAD8 => Some(VirtualKeyCode::Numpad8),
        winapi::VK_NUMPAD9 => Some(VirtualKeyCode::Numpad9),
        winapi::VK_MULTIPLY => Some(VirtualKeyCode::Multiply),
        winapi::VK_ADD => Some(VirtualKeyCode::Add),
        //winapi::VK_SEPARATOR => Some(VirtualKeyCode::Separator),
        winapi::VK_SUBTRACT => Some(VirtualKeyCode::Subtract),
        winapi::VK_DECIMAL => Some(VirtualKeyCode::Decimal),
        winapi::VK_DIVIDE => Some(VirtualKeyCode::Divide),
        winapi::VK_F1 => Some(VirtualKeyCode::F1),
        winapi::VK_F2 => Some(VirtualKeyCode::F2),
        winapi::VK_F3 => Some(VirtualKeyCode::F3),
        winapi::VK_F4 => Some(VirtualKeyCode::F4),
        winapi::VK_F5 => Some(VirtualKeyCode::F5),
        winapi::VK_F6 => Some(VirtualKeyCode::F6),
        winapi::VK_F7 => Some(VirtualKeyCode::F7),
        winapi::VK_F8 => Some(VirtualKeyCode::F8),
        winapi::VK_F9 => Some(VirtualKeyCode::F9),
        winapi::VK_F10 => Some(VirtualKeyCode::F10),
        winapi::VK_F11 => Some(VirtualKeyCode::F11),
        winapi::VK_F12 => Some(VirtualKeyCode::F12),
        winapi::VK_F13 => Some(VirtualKeyCode::F13),
        winapi::VK_F14 => Some(VirtualKeyCode::F14),
        winapi::VK_F15 => Some(VirtualKeyCode::F15),
        /*winapi::VK_F16 => Some(VirtualKeyCode::F16),
        winapi::VK_F17 => Some(VirtualKeyCode::F17),
        winapi::VK_F18 => Some(VirtualKeyCode::F18),
        winapi::VK_F19 => Some(VirtualKeyCode::F19),
        winapi::VK_F20 => Some(VirtualKeyCode::F20),
        winapi::VK_F21 => Some(VirtualKeyCode::F21),
        winapi::VK_F22 => Some(VirtualKeyCode::F22),
        winapi::VK_F23 => Some(VirtualKeyCode::F23),
        winapi::VK_F24 => Some(VirtualKeyCode::F24),*/
        winapi::VK_NUMLOCK => Some(VirtualKeyCode::Numlock),
        winapi::VK_SCROLL => Some(VirtualKeyCode::Scroll),
        /*winapi::VK_LSHIFT => Some(VirtualKeyCode::Lshift),
        winapi::VK_RSHIFT => Some(VirtualKeyCode::Rshift),
        winapi::VK_LCONTROL => Some(VirtualKeyCode::Lcontrol),
        winapi::VK_RCONTROL => Some(VirtualKeyCode::Rcontrol),
        winapi::VK_LMENU => Some(VirtualKeyCode::Lmenu),
        winapi::VK_RMENU => Some(VirtualKeyCode::Rmenu),
        winapi::VK_BROWSER_BACK => Some(VirtualKeyCode::Browser_back),
        winapi::VK_BROWSER_FORWARD => Some(VirtualKeyCode::Browser_forward),
        winapi::VK_BROWSER_REFRESH => Some(VirtualKeyCode::Browser_refresh),
        winapi::VK_BROWSER_STOP => Some(VirtualKeyCode::Browser_stop),
        winapi::VK_BROWSER_SEARCH => Some(VirtualKeyCode::Browser_search),
        winapi::VK_BROWSER_FAVORITES => Some(VirtualKeyCode::Browser_favorites),
        winapi::VK_BROWSER_HOME => Some(VirtualKeyCode::Browser_home),
        winapi::VK_VOLUME_MUTE => Some(VirtualKeyCode::Volume_mute),
        winapi::VK_VOLUME_DOWN => Some(VirtualKeyCode::Volume_down),
        winapi::VK_VOLUME_UP => Some(VirtualKeyCode::Volume_up),
        winapi::VK_MEDIA_NEXT_TRACK => Some(VirtualKeyCode::Media_next_track),
        winapi::VK_MEDIA_PREV_TRACK => Some(VirtualKeyCode::Media_prev_track),
        winapi::VK_MEDIA_STOP => Some(VirtualKeyCode::Media_stop),
        winapi::VK_MEDIA_PLAY_PAUSE => Some(VirtualKeyCode::Media_play_pause),
        winapi::VK_LAUNCH_MAIL => Some(VirtualKeyCode::Launch_mail),
        winapi::VK_LAUNCH_MEDIA_SELECT => Some(VirtualKeyCode::Launch_media_select),
        winapi::VK_LAUNCH_APP1 => Some(VirtualKeyCode::Launch_app1),
        winapi::VK_LAUNCH_APP2 => Some(VirtualKeyCode::Launch_app2),
        winapi::VK_OEM_1 => Some(VirtualKeyCode::Oem_1),
        winapi::VK_OEM_PLUS => Some(VirtualKeyCode::Oem_plus),
        winapi::VK_OEM_COMMA => Some(VirtualKeyCode::Oem_comma),
        winapi::VK_OEM_MINUS => Some(VirtualKeyCode::Oem_minus),
        winapi::VK_OEM_PERIOD => Some(VirtualKeyCode::Oem_period),
        winapi::VK_OEM_2 => Some(VirtualKeyCode::Oem_2),
        winapi::VK_OEM_3 => Some(VirtualKeyCode::Oem_3),
        winapi::VK_OEM_4 => Some(VirtualKeyCode::Oem_4),
        winapi::VK_OEM_5 => Some(VirtualKeyCode::Oem_5),
        winapi::VK_OEM_6 => Some(VirtualKeyCode::Oem_6),
        winapi::VK_OEM_7 => Some(VirtualKeyCode::Oem_7),
        winapi::VK_OEM_8 => Some(VirtualKeyCode::Oem_8),
        winapi::VK_OEM_102 => Some(VirtualKeyCode::Oem_102),
        winapi::VK_PROCESSKEY => Some(VirtualKeyCode::Processkey),
        winapi::VK_PACKET => Some(VirtualKeyCode::Packet),
        winapi::VK_ATTN => Some(VirtualKeyCode::Attn),
        winapi::VK_CRSEL => Some(VirtualKeyCode::Crsel),
        winapi::VK_EXSEL => Some(VirtualKeyCode::Exsel),
        winapi::VK_EREOF => Some(VirtualKeyCode::Ereof),
        winapi::VK_PLAY => Some(VirtualKeyCode::Play),
        winapi::VK_ZOOM => Some(VirtualKeyCode::Zoom),
        winapi::VK_NONAME => Some(VirtualKeyCode::Noname),
        winapi::VK_PA1 => Some(VirtualKeyCode::Pa1),
        winapi::VK_OEM_CLEAR => Some(VirtualKeyCode::Oem_clear),*/
        _ => None
    }
}
<commit_msg>Fix the windows build<commit_after>use events::VirtualKeyCode;
use winapi;

pub fn vkeycode_to_element(code: winapi::WPARAM) -> Option<VirtualKeyCode> {
    match code as i32 {
        //winapi::VK_LBUTTON => Some(VirtualKeyCode::Lbutton),
        //winapi::VK_RBUTTON => Some(VirtualKeyCode::Rbutton),
        //winapi::VK_CANCEL => Some(VirtualKeyCode::Cancel),
        //winapi::VK_MBUTTON => Some(VirtualKeyCode::Mbutton),
        //winapi::VK_XBUTTON1 => Some(VirtualKeyCode::Xbutton1),
        //winapi::VK_XBUTTON2 => Some(VirtualKeyCode::Xbutton2),
        winapi::VK_BACK => Some(VirtualKeyCode::Back),
        winapi::VK_TAB => Some(VirtualKeyCode::Tab),
        //winapi::VK_CLEAR => Some(VirtualKeyCode::Clear),
        winapi::VK_RETURN => Some(VirtualKeyCode::Return),
        //winapi::VK_SHIFT => Some(VirtualKeyCode::Shift),
        //winapi::VK_CONTROL => Some(VirtualKeyCode::Control),
        //winapi::VK_MENU => Some(VirtualKeyCode::Menu),
        winapi::VK_PAUSE => Some(VirtualKeyCode::Pause),
        winapi::VK_CAPITAL => Some(VirtualKeyCode::Capital),
        winapi::VK_KANA => Some(VirtualKeyCode::Kana),
        //winapi::VK_HANGUEL => Some(VirtualKeyCode::Hanguel),
        //winapi::VK_HANGUL => Some(VirtualKeyCode::Hangul),
        //winapi::VK_JUNJA => Some(VirtualKeyCode::Junja),
        //winapi::VK_FINAL => Some(VirtualKeyCode::Final),
        //winapi::VK_HANJA => Some(VirtualKeyCode::Hanja),
        winapi::VK_KANJI => Some(VirtualKeyCode::Kanji),
        winapi::VK_ESCAPE => Some(VirtualKeyCode::Escape),
        winapi::VK_CONVERT => Some(VirtualKeyCode::Convert),
        //winapi::VK_NONCONVERT => Some(VirtualKeyCode::Nonconvert),
        //winapi::VK_ACCEPT => Some(VirtualKeyCode::Accept),
        //winapi::VK_MODECHANGE => Some(VirtualKeyCode::Modechange),
        winapi::VK_SPACE => Some(VirtualKeyCode::Space),
        winapi::VK_PRIOR => Some(VirtualKeyCode::PageUp),
        winapi::VK_NEXT => Some(VirtualKeyCode::PageDown),
        winapi::VK_END => Some(VirtualKeyCode::End),
        winapi::VK_HOME => Some(VirtualKeyCode::Home),
        winapi::VK_LEFT => Some(VirtualKeyCode::Left),
        winapi::VK_UP => Some(VirtualKeyCode::Up),
        winapi::VK_RIGHT => Some(VirtualKeyCode::Right),
        winapi::VK_DOWN => Some(VirtualKeyCode::Down),
        //winapi::VK_SELECT => Some(VirtualKeyCode::Select),
        //winapi::VK_PRINT => Some(VirtualKeyCode::Print),
        //winapi::VK_EXECUTE => Some(VirtualKeyCode::Execute),
        winapi::VK_SNAPSHOT => Some(VirtualKeyCode::Snapshot),
        winapi::VK_INSERT => Some(VirtualKeyCode::Insert),
        winapi::VK_DELETE => Some(VirtualKeyCode::Delete),
        //winapi::VK_HELP => Some(VirtualKeyCode::Help),
        0x30 => Some(VirtualKeyCode::Key0),
        0x31 => Some(VirtualKeyCode::Key1),
        0x32 => Some(VirtualKeyCode::Key2),
        0x33 => Some(VirtualKeyCode::Key3),
        0x34 => Some(VirtualKeyCode::Key4),
        0x35 => Some(VirtualKeyCode::Key5),
        0x36 => Some(VirtualKeyCode::Key6),
        0x37 => Some(VirtualKeyCode::Key7),
        0x38 => Some(VirtualKeyCode::Key8),
        0x39 => Some(VirtualKeyCode::Key9),
        0x41 => Some(VirtualKeyCode::A),
        0x42 => Some(VirtualKeyCode::B),
        0x43 => Some(VirtualKeyCode::C),
        0x44 => Some(VirtualKeyCode::D),
        0x45 => Some(VirtualKeyCode::E),
        0x46 => Some(VirtualKeyCode::F),
        0x47 => Some(VirtualKeyCode::G),
        0x48 => Some(VirtualKeyCode::H),
        0x49 => Some(VirtualKeyCode::I),
        0x4A => Some(VirtualKeyCode::J),
        0x4B => Some(VirtualKeyCode::K),
        0x4C => Some(VirtualKeyCode::L),
        0x4D => Some(VirtualKeyCode::M),
        0x4E => Some(VirtualKeyCode::N),
        0x4F => Some(VirtualKeyCode::O),
        0x50 => Some(VirtualKeyCode::P),
        0x51 => Some(VirtualKeyCode::Q),
        0x52 => Some(VirtualKeyCode::R),
        0x53 => Some(VirtualKeyCode::S),
        0x54 => Some(VirtualKeyCode::T),
        0x55 => Some(VirtualKeyCode::U),
        0x56 => Some(VirtualKeyCode::V),
        0x57 => Some(VirtualKeyCode::W),
        0x58 => Some(VirtualKeyCode::X),
        0x59 => Some(VirtualKeyCode::Y),
        0x5A => Some(VirtualKeyCode::Z),
        //winapi::VK_LWIN => Some(VirtualKeyCode::Lwin),
        //winapi::VK_RWIN => Some(VirtualKeyCode::Rwin),
        winapi::VK_APPS => Some(VirtualKeyCode::Apps),
        winapi::VK_SLEEP => Some(VirtualKeyCode::Sleep),
        winapi::VK_NUMPAD0 => Some(VirtualKeyCode::Numpad0),
        winapi::VK_NUMPAD1 => Some(VirtualKeyCode::Numpad1),
        winapi::VK_NUMPAD2 => Some(VirtualKeyCode::Numpad2),
        winapi::VK_NUMPAD3 => Some(VirtualKeyCode::Numpad3),
        winapi::VK_NUMPAD4 => Some(VirtualKeyCode::Numpad4),
        winapi::VK_NUMPAD5 => Some(VirtualKeyCode::Numpad5),
        winapi::VK_NUMPAD6 => Some(VirtualKeyCode::Numpad6),
        winapi::VK_NUMPAD7 => Some(VirtualKeyCode::Numpad7),
        winapi::VK_NUMPAD8 => Some(VirtualKeyCode::Numpad8),
        winapi::VK_NUMPAD9 => Some(VirtualKeyCode::Numpad9),
        winapi::VK_MULTIPLY => Some(VirtualKeyCode::Multiply),
        winapi::VK_ADD => Some(VirtualKeyCode::Add),
        //winapi::VK_SEPARATOR => Some(VirtualKeyCode::Separator),
        winapi::VK_SUBTRACT => Some(VirtualKeyCode::Subtract),
        winapi::VK_DECIMAL => Some(VirtualKeyCode::Decimal),
        winapi::VK_DIVIDE => Some(VirtualKeyCode::Divide),
        winapi::VK_F1 => Some(VirtualKeyCode::F1),
        winapi::VK_F2 => Some(VirtualKeyCode::F2),
        winapi::VK_F3 => Some(VirtualKeyCode::F3),
        winapi::VK_F4 => Some(VirtualKeyCode::F4),
        winapi::VK_F5 => Some(VirtualKeyCode::F5),
        winapi::VK_F6 => Some(VirtualKeyCode::F6),
        winapi::VK_F7 => Some(VirtualKeyCode::F7),
        winapi::VK_F8 => Some(VirtualKeyCode::F8),
        winapi::VK_F9 => Some(VirtualKeyCode::F9),
        winapi::VK_F10 => Some(VirtualKeyCode::F10),
        winapi::VK_F11 => Some(VirtualKeyCode::F11),
        winapi::VK_F12 => Some(VirtualKeyCode::F12),
        winapi::VK_F13 => Some(VirtualKeyCode::F13),
        winapi::VK_F14 => Some(VirtualKeyCode::F14),
        winapi::VK_F15 => Some(VirtualKeyCode::F15),
        /*winapi::VK_F16 => Some(VirtualKeyCode::F16),
        winapi::VK_F17 => Some(VirtualKeyCode::F17),
        winapi::VK_F18 => Some(VirtualKeyCode::F18),
        winapi::VK_F19 => Some(VirtualKeyCode::F19),
        winapi::VK_F20 => Some(VirtualKeyCode::F20),
        winapi::VK_F21 => Some(VirtualKeyCode::F21),
        winapi::VK_F22 => Some(VirtualKeyCode::F22),
        winapi::VK_F23 => Some(VirtualKeyCode::F23),
        winapi::VK_F24 => Some(VirtualKeyCode::F24),*/
        winapi::VK_NUMLOCK => Some(VirtualKeyCode::Numlock),
        winapi::VK_SCROLL => Some(VirtualKeyCode::Scroll),
        /*winapi::VK_LSHIFT => Some(VirtualKeyCode::Lshift),
        winapi::VK_RSHIFT => Some(VirtualKeyCode::Rshift),
        winapi::VK_LCONTROL => Some(VirtualKeyCode::Lcontrol),
        winapi::VK_RCONTROL => Some(VirtualKeyCode::Rcontrol),
        winapi::VK_LMENU => Some(VirtualKeyCode::Lmenu),
        winapi::VK_RMENU => Some(VirtualKeyCode::Rmenu),
        winapi::VK_BROWSER_BACK => Some(VirtualKeyCode::Browser_back),
        winapi::VK_BROWSER_FORWARD => Some(VirtualKeyCode::Browser_forward),
        winapi::VK_BROWSER_REFRESH => Some(VirtualKeyCode::Browser_refresh),
        winapi::VK_BROWSER_STOP => Some(VirtualKeyCode::Browser_stop),
        winapi::VK_BROWSER_SEARCH => Some(VirtualKeyCode::Browser_search),
        winapi::VK_BROWSER_FAVORITES => Some(VirtualKeyCode::Browser_favorites),
        winapi::VK_BROWSER_HOME => Some(VirtualKeyCode::Browser_home),
        winapi::VK_VOLUME_MUTE => Some(VirtualKeyCode::Volume_mute),
        winapi::VK_VOLUME_DOWN => Some(VirtualKeyCode::Volume_down),
        winapi::VK_VOLUME_UP => Some(VirtualKeyCode::Volume_up),
        winapi::VK_MEDIA_NEXT_TRACK => Some(VirtualKeyCode::Media_next_track),
        winapi::VK_MEDIA_PREV_TRACK => Some(VirtualKeyCode::Media_prev_track),
        winapi::VK_MEDIA_STOP => Some(VirtualKeyCode::Media_stop),
        winapi::VK_MEDIA_PLAY_PAUSE => Some(VirtualKeyCode::Media_play_pause),
        winapi::VK_LAUNCH_MAIL => Some(VirtualKeyCode::Launch_mail),
        winapi::VK_LAUNCH_MEDIA_SELECT => Some(VirtualKeyCode::Launch_media_select),
        winapi::VK_LAUNCH_APP1 => Some(VirtualKeyCode::Launch_app1),
        winapi::VK_LAUNCH_APP2 => Some(VirtualKeyCode::Launch_app2),
        winapi::VK_OEM_1 => Some(VirtualKeyCode::Oem_1),
        winapi::VK_OEM_PLUS => Some(VirtualKeyCode::Oem_plus),
        winapi::VK_OEM_COMMA => Some(VirtualKeyCode::Oem_comma),
        winapi::VK_OEM_MINUS => Some(VirtualKeyCode::Oem_minus),
        winapi::VK_OEM_PERIOD => Some(VirtualKeyCode::Oem_period),
        winapi::VK_OEM_2 => Some(VirtualKeyCode::Oem_2),
        winapi::VK_OEM_3 => Some(VirtualKeyCode::Oem_3),
        winapi::VK_OEM_4 => Some(VirtualKeyCode::Oem_4),
        winapi::VK_OEM_5 => Some(VirtualKeyCode::Oem_5),
        winapi::VK_OEM_6 => Some(VirtualKeyCode::Oem_6),
        winapi::VK_OEM_7 => Some(VirtualKeyCode::Oem_7),
        winapi::VK_OEM_8 => Some(VirtualKeyCode::Oem_8),
        winapi::VK_OEM_102 => Some(VirtualKeyCode::Oem_102),
        winapi::VK_PROCESSKEY => Some(VirtualKeyCode::Processkey),
        winapi::VK_PACKET => Some(VirtualKeyCode::Packet),
        winapi::VK_ATTN => Some(VirtualKeyCode::Attn),
        winapi::VK_CRSEL => Some(VirtualKeyCode::Crsel),
        winapi::VK_EXSEL => Some(VirtualKeyCode::Exsel),
        winapi::VK_EREOF => Some(VirtualKeyCode::Ereof),
        winapi::VK_PLAY => Some(VirtualKeyCode::Play),
        winapi::VK_ZOOM => Some(VirtualKeyCode::Zoom),
        winapi::VK_NONAME => Some(VirtualKeyCode::Noname),
        winapi::VK_PA1 => Some(VirtualKeyCode::Pa1),
        winapi::VK_OEM_CLEAR => Some(VirtualKeyCode::Oem_clear),*/
        _ => None
    }
}
<|endoftext|>