<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use libc::consts::os::posix88::*;
use libc::funcs::posix88::mman::mmap;
use libc::funcs::posix88::mman::munmap;
use libc::funcs::posix88::mman::mprotect;
use libc::types::common::c95::c_void;
use libc::types::os::arch::c95::size_t;
use std::ptr;
use std::mem;
use asm::Reg::*;

enum Reg {
    rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
    r8, r9, r10, r11, r12, r13, r14, r15,
}

impl Reg {
    // most significant bit
    fn msb(&self) -> u8 {
        match *self {
            rax | rcx | rdx | rbx | rsp | rbp | rsi | rdi => 0,
            r8 | r9 | r10 | r11 | r12 | r13 | r14 | r15 => 1,
        }
    }

    // least 3 significant bit
    fn lsb3(&self) -> u8 {
        match *self {
            rax => 0,
            rcx => 1,
            rdx => 2,
            rbx => 3,
            rsp => 4,
            rbp => 5,
            rsi => 6,
            rdi => 7,
            r8 => 0,
            r9 => 1,
            r10 => 2,
            r11 => 3,
            r12 => 4,
            r13 => 5,
            r14 => 6,
            r15 => 7,
        }
    }

    // index of enum
    fn idx(&self) -> u8 {
        match *self {
            rax => 0,
            rcx => 1,
            rdx => 2,
            rbx => 3,
            rsp => 4,
            rbp => 5,
            rsi => 6,
            rdi => 7,
            r8 => 8,
            r9 => 9,
            r10 => 10,
            r11 => 11,
            r12 => 12,
            r13 => 13,
            r14 => 14,
            r15 => 15,
        }
    }
}

// Memory-Address: Register with positive or negative offset
struct Mem(Reg, i32);

impl Mem {
    fn fits8(&self) -> bool {
        self.1 == (self.1 as i8) as i32
    }

    fn fits16(&self) -> bool {
        self.1 == (self.1 as i16) as i32
    }
}

#[test]
fn test_fits8() {
    assert!(Mem(rax, 0).fits8());
    assert!(Mem(rax, 127).fits8());
    assert!(Mem(rax, -128).fits8());
    assert!(!Mem(rax, 128).fits8());
    assert!(!Mem(rax, -129).fits8());
}

#[test]
fn test_fits16() {
    assert!(Mem(rax, 0).fits16());
    assert!(Mem(rax, 127).fits16());
    assert!(Mem(rax, -128).fits16());
    assert!(Mem(rax, 128).fits16());
    assert!(Mem(rax, -129).fits16());

    assert!(Mem(rax, 32767).fits16());
    assert!(Mem(rax, -32768).fits16());
    assert!(!Mem(rax, 32768).fits16());
    assert!(!Mem(rax, -32769).fits16());
}

// Machine instruction without any operands, just emits the given
// opcode
macro_rules! i0p {
   ($i:ident, $w:expr) => {pub fn $i(&mut self) { self.opcode($w); }}
}

// Machine Instruction with 1 register operand, register
// index is added to opcode
macro_rules! q1p_rpo {
    ($i:ident, $w:expr) => {pub fn $i(&mut self, dest: Reg) {
        if dest.msb() != 0 {
            self.rex_prefix(0, 0, 0, 1);
        }

        self.opcode($w + dest.lsb3());
    }}
}

// Machine instruction with 2 register operands, operands are
// saved in mod_rm-Byte. MSB is saved in rex-Prefix
macro_rules! q2p_r2r {
    ($i:ident, $w:expr) => {pub fn $i(&mut self, src: Reg, dest: Reg) {
        self.rex_prefix(1, src.msb(), 0, dest.msb());
        self.opcode($w);
        self.mod_rm(0b11, src.lsb3(), dest.lsb3());
    }}
}

macro_rules! q2p_m2r {
    ($i:ident, $w: expr) => {pub fn $i(&mut self, src: Mem, dest: Reg) {
        self.rex_prefix(1, dest.msb(), 0, src.0.msb());
        self.opcode($w);

        if(src.fits8()) {
            self.mod_rm(0b01, dest.lsb3(), src.0.lsb3());
            self.emitb(src.1 as u8);
        } else {
            self.mod_rm(0b10, dest.lsb3(), src.0.lsb3());
            self.emitd(src.1 as u32);
        }
    }}
}

macro_rules! q2p_r2m {
    ($i:ident, $w: expr) => {pub fn $i(&mut self, src: Reg, dest: Mem) {
        self.rex_prefix(1, src.msb(), 0, dest.0.msb());
        self.opcode($w);

        if(dest.fits8()) {
            self.mod_rm(0b01, src.lsb3(), dest.0.lsb3());
            self.emitb(dest.1 as u8);
        } else {
            self.mod_rm(0b10, src.lsb3(), dest.0.lsb3());
            self.emitd(dest.1 as u32);
        }
    }}
}

pub struct Assembler {
    code: Vec<u8>
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { code: Vec::new() }
    }

    i0p!(nop, 0x90);
    i0p!(ret, 0xC3);

    q1p_rpo!(pushq, 0x50);
    q1p_rpo!(popq, 0x58);

    q2p_r2r!(addq_r2r, 0x01);

    q2p_r2r!(movq_r2r, 0x89);
    q2p_r2m!(movq_r2m, 0x89);
    q2p_m2r!(movq_m2r, 0x8B);

    fn opcode(&mut self, c: u8) { self.code.push(c); }
    fn emitb(&mut self, c: u8) { self.code.push(c); }
    fn emitw(&mut self, w: u16) { self.code.write_u16::<LittleEndian>(w).unwrap(); }
    fn emitd(&mut self, d: u32) { self.code.write_u32::<LittleEndian>(d).unwrap(); }
    fn emitq(&mut self, q: u64) { self.code.write_u64::<LittleEndian>(q).unwrap(); }

    fn mod_rm(&mut self, mode: u8, reg: u8, rm: u8) {
        self.emitb(mode << 6 | reg << 3 | rm );
    }

    fn rex_prefix(&mut self, w: u8, r: u8, x: u8, b: u8) {
        let v = 0x40 | w << 3 | r << 2 | x << 1 | b;

        self.code.push(v);
    }
}

static CODE : [u8;8] = [ 0x48, 0x89, 0xf8, 0x48, 0x83, 0xc0, 0x04, 0xc3 ];

pub struct JitFunction {
    pub size: size_t,
    pub ptr: extern fn (u64) -> u64
}

impl JitFunction {
    pub fn new(code: &[u8]) -> JitFunction {
        let size = code.len() as u64;

        unsafe {
            let fct = mmap(0 as *mut c_void, size, PROT_READ | PROT_WRITE,
                MAP_PRIVATE | MAP_ANON, -1, 0);

            if fct == MAP_FAILED {
                panic!("mmap failed");
            }

            ptr::copy_nonoverlapping(code.as_ptr() as *const c_void, fct, code.len());

            if mprotect(fct, size, PROT_READ | PROT_EXEC) == -1 {
                panic!("mprotect failed");
            }

            JitFunction {
                size: size,
                ptr: mem::transmute(fct)
            }
        }
    }
}

impl Drop for JitFunction {
    fn drop(&mut self) {
        unsafe {
            munmap(mem::transmute(self.ptr), self.size);
        }
    }
}

#[test]
fn test_create_function() {
    let fct = JitFunction::new(&CODE);

    assert_eq!(5, (fct.ptr)(1));
}
<commit_msg>added tests for nop, ret, push and pop<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use libc::consts::os::posix88::*;
use libc::funcs::posix88::mman::mmap;
use libc::funcs::posix88::mman::munmap;
use libc::funcs::posix88::mman::mprotect;
use libc::types::common::c95::c_void;
use libc::types::os::arch::c95::size_t;
use std::ptr;
use std::mem;
use asm::Reg::*;

enum Reg {
    rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
    r8, r9, r10, r11, r12, r13, r14, r15,
}

impl Reg {
    // most significant bit
    fn msb(&self) -> u8 {
        match *self {
            rax | rcx | rdx | rbx | rsp | rbp | rsi | rdi => 0,
            r8 | r9 | r10 | r11 | r12 | r13 | r14 | r15 => 1,
        }
    }

    // least 3 significant bit
    fn lsb3(&self) -> u8 {
        match *self {
            rax => 0,
            rcx => 1,
            rdx => 2,
            rbx => 3,
            rsp => 4,
            rbp => 5,
            rsi => 6,
            rdi => 7,
            r8 => 0,
            r9 => 1,
            r10 => 2,
            r11 => 3,
            r12 => 4,
            r13 => 5,
            r14 => 6,
            r15 => 7,
        }
    }

    // index of enum
    fn idx(&self) -> u8 {
        match *self {
            rax => 0,
            rcx => 1,
            rdx => 2,
            rbx => 3,
            rsp => 4,
            rbp => 5,
            rsi => 6,
            rdi => 7,
            r8 => 8,
            r9 => 9,
            r10 => 10,
            r11 => 11,
            r12 => 12,
            r13 => 13,
            r14 => 14,
            r15 => 15,
        }
    }
}

// Memory-Address: Register with positive or negative offset
struct Mem(Reg, i32);

fn fits8(v: i64) -> bool {
    v == (v as i8) as i64
}

fn fits16(v: i64) -> bool {
    v == (v as i16) as i64
}

fn fits32(v: i64) -> bool {
    v == (v as i32) as i64
}

#[test]
fn test_fits8() {
    assert!(fits8(0));
    assert!(fits8(127));
    assert!(fits8(-128));
    assert!(!fits8(128));
    assert!(!fits8(-129));
}

#[test]
fn test_fits16() {
    assert!(fits16(8));
    assert!(fits16(32767));
    assert!(fits16(-32768));
    assert!(!fits16(32768));
    assert!(!fits16(-32769));
}

// Machine instruction without any operands, just emits the given
// opcode
macro_rules! i0p {
   ($i:ident, $w:expr) => {pub fn $i(&mut self) { self.opcode($w); }}
}

// Machine Instruction with 1 register operand, register
// index is added to opcode
macro_rules! q1p_r_rpo {
    ($i:ident, $w:expr) => {pub fn $i(&mut self, dest: Reg) {
        if dest.msb() != 0 {
            self.rex_prefix(0, 0, 0, 1);
        }

        self.opcode($w + dest.lsb3());
    }}
}

// Machine instruction with 2 register operands, operands are
// saved in mod_rm-Byte. MSB is saved in rex-Prefix
macro_rules! q2p_rtr {
    ($i:ident, $w:expr) => {pub fn $i(&mut self, src: Reg, dest: Reg) {
        self.rex_prefix(1, src.msb(), 0, dest.msb());
        self.opcode($w);
        self.mod_rm(0b11, src.lsb3(), dest.lsb3());
    }}
}

macro_rules! q2p_mtr {
    ($i:ident, $w: expr) => {pub fn $i(&mut self, src: Mem, dest: Reg) {
        self.rex_prefix(1, dest.msb(), 0, src.0.msb());
        self.opcode($w);

        if(fits8(src.1 as i64)) {
            self.mod_rm(0b01, dest.lsb3(), src.0.lsb3());
            self.emitb(src.1 as u8);
        } else {
            self.mod_rm(0b10, dest.lsb3(), src.0.lsb3());
            self.emitd(src.1 as u32);
        }
    }}
}

macro_rules! q2p_rtm {
    ($i:ident, $w: expr) => {pub fn $i(&mut self, src: Reg, dest: Mem) {
        self.rex_prefix(1, src.msb(), 0, dest.0.msb());
        self.opcode($w);

        if(fits8(dest.1 as i64)) {
            self.mod_rm(0b01, src.lsb3(), dest.0.lsb3());
            self.emitb(dest.1 as u8);
        } else {
            self.mod_rm(0b10, src.lsb3(), dest.0.lsb3());
            self.emitd(dest.1 as u32);
        }
    }}
}

// machine operand with 2 operands. 64 bit immediate and destination register
// register is added to opcode
macro_rules! q2p_i64tr {
    ($i:ident, $w: expr) => {pub fn $i(&mut self, src: u64, dest: Reg) {
        self.rex_prefix(1, 0, 0, dest.msb());
        self.opcode($w + dest.lsb3());
        self.emitq(src);
    }}
}

// machine operand with 2 operands. 64 bit immediate and destination register
macro_rules! q2p_i32tr {
    ($i:ident, $w: expr) => {pub fn $i(&mut self, src: u32, dest: Reg) {
        self.rex_prefix(1, 0, 0, dest.msb());
        self.opcode($w);
        self.mod_rm(0b11, dest.lsb3(), 0);
        self.emitd(src);
    }}
}

// machine operand with 2 operands. 64 bit immediate and destination memory
macro_rules! q2p_i32tm {
    ($i:ident, $w: expr) => {pub fn $i(&mut self, src: u32, dest: Mem) {
        self.rex_prefix(1, 0, 0, dest.0.msb());
        self.opcode($w);

        if(fits8(dest.1 as i64)) {
            self.mod_rm(0b01, src.lsb3(), dest.0.lsb3());
            self.emitb(dest.1 as u8);
        } else {
            self.mod_rm(0b10, src.lsb3(), dest.0.lsb3());
            self.emitd(dest.1 as u32);
        }

        self.emitd(src);
    }}
}

pub struct Assembler {
    code: Vec<u8>
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { code: Vec::new() }
    }

    i0p!(nop, 0x90);
    i0p!(ret, 0xC3);

    q1p_r_rpo!(pushq, 0x50);
    q1p_r_rpo!(popq, 0x58);

    q2p_rtr!(addq_rtr, 0x01);
    q2p_rtm!(addq_rtm, 0x01);
    q2p_mtr!(addq_mtr, 0x03);
    q2p_i64tr!(addq_i32tm, 0x81);
    q2p_i64tr!(addq_i32tr, 0x81);

    q2p_rtr!(subq_rtr, 0x28);
    q2p_rtm!(subq_rtm, 0x29);
    q2p_mtr!(subq_mtr, 0x2B);
    q2p_i64tr!(subq_i32tm, 0x81); // /5 ?
    q2p_i64tr!(subq_i32tr, 0x81); // /5 ?

    q2p_rtr!(movq_rtr, 0x89);
    q2p_rtm!(movq_rtm, 0x89);
    q2p_mtr!(movq_mtr, 0x8B);
    q2p_i64tr!(movq_i64tr, 0xB8);
    q2p_i64tr!(movq_i32tr, 0xC7);
    q2p_i64tr!(movq_i32tm, 0xC7);

    fn opcode(&mut self, c: u8) { self.code.push(c); }
    fn emitb(&mut self, c: u8) { self.code.push(c); }
    fn emitw(&mut self, w: u16) { self.code.write_u16::<LittleEndian>(w).unwrap(); }
    fn emitd(&mut self, d: u32) { self.code.write_u32::<LittleEndian>(d).unwrap(); }
    fn emitq(&mut self, q: u64) { self.code.write_u64::<LittleEndian>(q).unwrap(); }

    fn mod_rm(&mut self, mode: u8, reg: u8, rm: u8) {
        self.emitb(mode << 6 | reg << 3 | rm );
    }

    fn rex_prefix(&mut self, w: u8, r: u8, x: u8, b: u8) {
        let v = 0x40 | w << 3 | r << 2 | x << 1 | b;

        self.code.push(v);
    }
}

#[test]
fn test_nop() {
    let mut asm = Assembler::new();
    asm.nop();

    assert_eq!(vec![0x90], asm.code);
}

#[test]
fn test_ret() {
    let mut asm = Assembler::new();
    asm.ret();

    assert_eq!(vec![0xc3], asm.code);
}

#[test]
fn test_push() {
    let mut asm = Assembler::new();
    asm.pushq(rax);
    asm.pushq(r8);
    asm.pushq(rcx);

    assert_eq!(vec![0x50, 0x41, 0x50, 0x51], asm.code);
}

#[test]
fn test_pop() {
    let mut asm = Assembler::new();
    asm.popq(rax);
    asm.popq(r8);
    asm.popq(rcx);

    assert_eq!(vec![0x58, 0x41, 0x58, 0x59], asm.code);
}

static CODE : [u8;8] = [ 0x48, 0x89, 0xf8, 0x48, 0x83, 0xc0, 0x04, 0xc3 ];

pub struct JitFunction {
    pub size: size_t,
    pub ptr: extern fn (u64) -> u64
}

impl JitFunction {
    pub fn new(code: &[u8]) -> JitFunction {
        let size = code.len() as u64;

        unsafe {
            let fct = mmap(0 as *mut c_void, size, PROT_READ | PROT_WRITE,
                MAP_PRIVATE | MAP_ANON, -1, 0);

            if fct == MAP_FAILED {
                panic!("mmap failed");
            }

            ptr::copy_nonoverlapping(code.as_ptr() as *const c_void, fct, code.len());

            if mprotect(fct, size, PROT_READ | PROT_EXEC) == -1 {
                panic!("mprotect failed");
            }

            JitFunction {
                size: size,
                ptr: mem::transmute(fct)
            }
        }
    }
}

impl Drop for JitFunction {
    fn drop(&mut self) {
        unsafe {
            munmap(mem::transmute(self.ptr), self.size);
        }
    }
}

#[test]
fn test_create_function() {
    let fct = JitFunction::new(&CODE);

    assert_eq!(5, (fct.ptr)(1));
}
<|endoftext|>


<commit_before>use std::fmt;
use std::rc::Rc;
use token::Literal;

#[derive(Clone, Debug)]
pub enum Expr {
    Func(Function),
    Atom(Atom),
    List(List),
    Quote(Quote),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Atom {
    Bool(bool),
    Int(i64),
    Flt(f64),
    Str(String),
    Symbol(Symbol),
}

#[derive(Clone, Debug)]
pub struct List(Vec<Expr>);

#[derive(Clone, Debug)]
pub struct Quote(Vec<Expr>);

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Symbol(String);

#[derive(Clone)]
pub struct Function {
    name: Option<String>,
    func: Rc<Fn(&[Expr]) -> Expr>,
}

impl Function {
    fn new<S, F>(name: Option<S>, func: F) -> Self
        where S: Into<String>,
              F: 'static + Fn(&[Expr]) -> Expr
    {
        Function { name: name.map(Into::into), func: Rc::new(func) }
    }

    fn call<'a>(&self, args: &'a [Expr]) -> Expr {
        (self.func)(args)
    }
}

impl fmt::Debug for Function {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ref name) = self.name {
            write!(f, "#[{}]", name)
        } else {
            write!(f, "#\u{03BB}")
        }
    }
}

impl From<Literal> for Atom {
    fn from(x: Literal) -> Self {
        match x {
            Literal::Bool(y) => Atom::Bool(y),
            Literal::Int(y) => Atom::Int(y),
            Literal::Flt(y) => Atom::Flt(y),
            Literal::Str(y) => Atom::Str(y),
        }
    }
}

impl From<Quote> for List {
    fn from(x: Quote) -> Self {
        List(x.0)
    }
}

impl From<List> for Quote {
    fn from(x: List) -> Self {
        Quote(x.0)
    }
}

impl From<Symbol> for Atom {
    fn from(x: Symbol) -> Self {
        Atom::Symbol(x)
    }
}

fn lift<F, G>(func: Box<Fn(&[Atom]) -> Atom>) -> Box<Fn(&[Expr]) -> Expr>
{
    Box::new(move |args| Expr::Atom(
        func(args.iter()
            .map(|arg| { if let &Expr::Atom(ref atom) = arg { atom.clone() } else { panic!() } })
            .collect::<Vec<_>>()
            .as_slice())
    ))
}

#[cfg(test)]
mod test {
    use super::*;
    fn add_fn(x: &[Expr]) -> Expr {
        Expr::Atom(Atom::Int(
            x.iter().map(|x| match x {
                &Expr::Atom(Atom::Int(y)) => y,
                _ => panic!()
            }).sum()))
    }
    #[test]
    fn print_debug() {
        let func = move |atoms: &[Atom]| Atom::Int(atoms.iter().map(|x| if let &Atom::Int(y) = x {y} else { panic!() }).sum());
        let add = Function::new(Some("add"), lift(Box::new(func)));
        add.call(vec![Expr::Atom(Atom::Int(1)), Expr::Atom(Atom::Int(2))].as_slice());
    }
}
<commit_msg>Throw Rc at the problem and hope it goes away<commit_after>use std::fmt;
use std::rc::Rc;
use token::Literal;

#[derive(Clone, Debug)]
pub enum Expr {
    Func(Function),
    Atom(Atom),
    List(List),
    Quote(Quote),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Atom {
    Bool(bool),
    Int(i64),
    Flt(f64),
    Str(String),
    Symbol(Symbol),
}

#[derive(Clone, Debug)]
pub struct List(Vec<Expr>);

#[derive(Clone, Debug)]
pub struct Quote(Vec<Expr>);

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Symbol(String);

#[derive(Clone)]
pub struct Function{
    name: Option<String>,
    func: Rc<Fn(&[Expr]) -> Expr>,
}

impl Function {
    fn new<S>(name: Option<S>, func: Rc<Fn(&[Expr]) -> Expr>) -> Self
        where S: Into<String>,
    {
        Function { name: name.map(Into::into), func: func }
    }

    fn call<'a>(&self, args: &'a [Expr]) -> Expr {
        (self.func)(args)
    }
}

impl fmt::Debug for Function {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ref name) = self.name {
            write!(f, "#[{}]", name)
        } else {
            write!(f, "#\u{03BB}")
        }
    }
}

impl From<Literal> for Atom {
    fn from(x: Literal) -> Self {
        match x {
            Literal::Bool(y) => Atom::Bool(y),
            Literal::Int(y) => Atom::Int(y),
            Literal::Flt(y) => Atom::Flt(y),
            Literal::Str(y) => Atom::Str(y),
        }
    }
}

impl From<Quote> for List {
    fn from(x: Quote) -> Self {
        List(x.0)
    }
}

impl From<List> for Quote {
    fn from(x: List) -> Self {
        Quote(x.0)
    }
}

impl From<Symbol> for Atom {
    fn from(x: Symbol) -> Self {
        Atom::Symbol(x)
    }
}

fn lift(func: Rc<Fn(&[Atom]) -> Atom>) -> Rc<Fn(&[Expr]) -> Expr>
{
    Rc::new(move |args| Expr::Atom(
        func(args.iter()
            .map(|arg| { if let &Expr::Atom(ref atom) = arg { atom.clone() } else { panic!() } })
            .collect::<Vec<_>>()
            .as_slice())
    ))
}

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

    /*
    fn add_fn(x: &[Expr]) -> Expr {
        Expr::Atom(Atom::Int(
            x.iter().map(|x| match x {
                &Expr::Atom(Atom::Int(y)) => y,
                _ => panic!()
            }).sum()))
    }
    */
    #[test]
    fn print_debug() {
        let func = Rc::new(move |atoms: &[Atom]|
            Atom::Int(atoms.iter().map(|x| if let &Atom::Int(y) = x {y} else { panic!() }).sum()));
        let add = Function::new(Some("add"), lift(func));
        add.call(vec![Expr::Atom(Atom::Int(1)), Expr::Atom(Atom::Int(2))].as_slice());
    }
}
<|endoftext|>


<commit_before>use item_state::ItemState;
use bar_builder::UpdateStream;
use std::rc::Rc;
use xcb::{Connection, Rectangle, Window};
use futures::stream::{Merge, MergedItem};
use futures::{Future, Stream};
use xcb_event_stream::XcbEventStream;
use error::*;
use std::error::Error;
use xcb;
use component::Slot;

type UpdateAndEventStream = Merge<UpdateStream, XcbEventStream>;

/// Struct that contains everything needed to run the bar.
pub struct Bar {
    pub center_items: Vec<ItemState>,
    pub conn: Rc<Connection>,
    pub foreground: u32,
    pub geometry: Rectangle,
    pub item_positions: Vec<(u16, u16)>,
    pub left_items: Vec<ItemState>,
    pub right_items: Vec<ItemState>,
    pub stream: Option<UpdateAndEventStream>,
    pub window: Window,
}

impl Bar {
    /// Returns `self.stream` without borrowing or consuming `self`.
    /// Panics if called twice.
    fn get_stream(&mut self) -> UpdateAndEventStream {
        ::std::mem::replace(&mut self.stream, None).unwrap()
    }

    /// Launch and run the bar.
    pub fn run(mut self) -> Box<Future<Item = (), Error = ()>> {
        let future = self.get_stream()
            .map_err(|e| ::error::Error::with_chain(e, ErrorKind::ItemError))
            .for_each(move |item| -> Result<()> {
                let (_, update) = match item {
                    MergedItem::First(update) => (None, Some(update)),
                    MergedItem::Second(event) => (Some(event), None),
                    MergedItem::Both(update, event) => (Some(event), Some(update)),
                };

                if let Some(update) = update {
                    let size_changed;

                    // Figure out if the component has chanaged
                    // it's size since the last update.
                    // TODO: Move to a function
                    {
                        let slot_items = match update.slot {
                            Slot::Left => &mut self.left_items,
                            Slot::Center => &mut self.center_items,
                            Slot::Right => &mut self.right_items,
                        };
                        slot_items[update.index].update(update.value)?;

                        let width = slot_items[update.index].get_content_width();
                        size_changed = self.item_positions[update.id].1 != width;
                    }

                    // Redraw only neccessary stuff
                    match update.slot {
                        Slot::Center => self.redraw_center()?,
                        Slot::Left => self.redraw_left(size_changed, update.index)?,
                        Slot::Right => self.redraw_right(size_changed, update.index)?,
                    }
                }
                Ok(())
            })
            .map_err(|err| {
                println!("Error occurred: {}", err);
                let mut cause = err.cause();
                while let Some(err) = cause {
                    println!("  Caused by: {}", err);
                    cause = err.cause();
                }
            });

        Box::new(future)
    }

    /// Redraws components in the center slot.
    /// Unforunately centering means that all components
    /// must be redrawn if even one of them changes size.
    fn redraw_center(&mut self) -> Result<()> {
        let width_all: u16 = self.center_items
            .iter()
            .map(|item| item.get_content_width())
            .sum();

        let mut pos = (self.geometry.width()) / 2 - width_all / 2;

        for item in self.center_items.iter() {
            self.item_positions[item.get_id()].0 = pos;
            self.draw_item(item, pos)?;
            self.item_positions[item.get_id()].1 = item.get_content_width();
            pos += item.get_content_width();
        }

        Ok(())
    }

    /// Pretty much the same as `self.redraw_left` but with `left` replaced with `right`.
    /// The order in which the items are gone through is reversed.
    fn redraw_right(&mut self, size_changed: bool, index: usize) -> Result<()> {
        let mut pos = self.geometry.width();

        for n in 0..self.right_items.len() {
            let item = &self.right_items[self.right_items.len() - n - 1];

            pos -= item.get_content_width();

            if n < self.right_items.len() - index - 1 {
                continue;
            }

            if size_changed {
                let mut bg_start = pos;
                let bg_end = pos + item.get_content_width();

                if n == self.right_items.len() - 1 {
                    let old_start = self.item_positions[item.get_id()].0 as u16;
                    if old_start < bg_start {
                        bg_start = old_start;
                    }
                }

                self.paint_bg(bg_start, bg_end)?;
            }

            self.item_positions[item.get_id()].0 = pos;
            self.item_positions[item.get_id()].1 = item.get_content_width();
            self.draw_item(item, pos)?;

            if !size_changed {
                break;
            }
        }

        Ok(())
    }

    /// Redraw only needed items in the right slot.
    /// Symmetric to `self.redraw_left`.
    ///
    /// If the component hasn't changed it's size, it doesn't affect
    /// any other components and we can get away with just painting
    /// the one component.
    ///
    /// However if the component has changed it's size, we must also
    /// redraw every component on the right of it. If the item has shrunk
    /// we must also repaint the exposed background.
    fn redraw_left(&mut self, size_changed: bool, index: usize) -> Result<()> {
        let pos = 0;

        for n in 0..self.left_items.len() {
            let item = &self.left_items[n];

            if n < index {
                continue;
            }

            if size_changed {
                let bg_start = pos;
                let mut bg_end = pos + item.get_content_width();

                if n == self.left_items.len() - 1 {
                    let old_end = self.item_positions[item.get_id()].0 +
                        self.item_positions[item.get_id()].1;
                    if bg_end < old_end {
                        bg_end = old_end;
                    }
                }

                self.paint_bg(bg_start, bg_end)?;
            }

            self.item_positions[item.get_id()].0 = pos;
            self.item_positions[item.get_id()].1 = item.get_content_width();
            self.draw_item(item, pos)?;

            if !size_changed {
                break;
            }
        }

        Ok(())
    }

    /// Copies the item's pixmap to the window.
    fn draw_item(&self, item: &ItemState, pos: u16) -> Result<()> {
        if !item.is_ready() {
            return Ok(());
        }

        try_xcb!(
            xcb::copy_area_checked,
            "failed to copy pixmap",
            &self.conn,
            item.get_pixmap(),
            self.window,
            self.foreground,
            0,
            0,
            pos as i16,
            0,
            item.get_content_width() as u16,
            self.geometry.height()
        );

        Ok(())
    }

    /// Draws the background starting at point a on the x-axis until point b.
    fn paint_bg(&self, a: u16, b: u16) -> Result<()> {
        try_xcb!(
            xcb::poly_fill_rectangle,
            "failed to draw background",
            &self.conn,
            self.window,
            self.foreground,
            &[Rectangle::new(a as i16, 0, b - a, self.geometry.height())]
        );

        Ok(())
    }
}
<commit_msg>Ingrement `pos` in `redraw_left`<commit_after>use item_state::ItemState;
use bar_builder::UpdateStream;
use std::rc::Rc;
use xcb::{Connection, Rectangle, Window};
use futures::stream::{Merge, MergedItem};
use futures::{Future, Stream};
use xcb_event_stream::XcbEventStream;
use error::*;
use std::error::Error;
use xcb;
use component::Slot;

type UpdateAndEventStream = Merge<UpdateStream, XcbEventStream>;

/// Struct that contains everything needed to run the bar.
pub struct Bar {
    pub center_items: Vec<ItemState>,
    pub conn: Rc<Connection>,
    pub foreground: u32,
    pub geometry: Rectangle,
    pub item_positions: Vec<(u16, u16)>,
    pub left_items: Vec<ItemState>,
    pub right_items: Vec<ItemState>,
    pub stream: Option<UpdateAndEventStream>,
    pub window: Window,
}

impl Bar {
    /// Returns `self.stream` without borrowing or consuming `self`.
    /// Panics if called twice.
    fn get_stream(&mut self) -> UpdateAndEventStream {
        ::std::mem::replace(&mut self.stream, None).unwrap()
    }

    /// Launch and run the bar.
    pub fn run(mut self) -> Box<Future<Item = (), Error = ()>> {
        let future = self.get_stream()
            .map_err(|e| ::error::Error::with_chain(e, ErrorKind::ItemError))
            .for_each(move |item| -> Result<()> {
                let (_, update) = match item {
                    MergedItem::First(update) => (None, Some(update)),
                    MergedItem::Second(event) => (Some(event), None),
                    MergedItem::Both(update, event) => (Some(event), Some(update)),
                };

                if let Some(update) = update {
                    let size_changed;

                    // Figure out if the component has chanaged
                    // it's size since the last update.
                    // TODO: Move to a function
                    {
                        let slot_items = match update.slot {
                            Slot::Left => &mut self.left_items,
                            Slot::Center => &mut self.center_items,
                            Slot::Right => &mut self.right_items,
                        };
                        slot_items[update.index].update(update.value)?;

                        let width = slot_items[update.index].get_content_width();
                        size_changed = self.item_positions[update.id].1 != width;
                    }

                    // Redraw only neccessary stuff
                    match update.slot {
                        Slot::Center => self.redraw_center()?,
                        Slot::Left => self.redraw_left(size_changed, update.index)?,
                        Slot::Right => self.redraw_right(size_changed, update.index)?,
                    }
                }
                Ok(())
            })
            .map_err(|err| {
                println!("Error occurred: {}", err);
                let mut cause = err.cause();
                while let Some(err) = cause {
                    println!("  Caused by: {}", err);
                    cause = err.cause();
                }
            });

        Box::new(future)
    }

    /// Redraws components in the center slot.
    /// Unforunately centering means that all components
    /// must be redrawn if even one of them changes size.
    fn redraw_center(&mut self) -> Result<()> {
        let width_all: u16 = self.center_items
            .iter()
            .map(|item| item.get_content_width())
            .sum();

        let mut pos = (self.geometry.width()) / 2 - width_all / 2;

        for item in self.center_items.iter() {
            self.item_positions[item.get_id()].0 = pos;
            self.draw_item(item, pos)?;
            self.item_positions[item.get_id()].1 = item.get_content_width();
            pos += item.get_content_width();
        }

        Ok(())
    }

    /// Pretty much the same as `self.redraw_left` but with `left` replaced with `right`.
    /// The order in which the items are gone through is reversed.
    fn redraw_right(&mut self, size_changed: bool, index: usize) -> Result<()> {
        let mut pos = self.geometry.width();

        for n in 0..self.right_items.len() {
            let item = &self.right_items[self.right_items.len() - n - 1];

            pos -= item.get_content_width();

            if n < self.right_items.len() - index - 1 {
                continue;
            }

            if size_changed {
                let mut bg_start = pos;
                let bg_end = pos + item.get_content_width();

                if n == self.right_items.len() - 1 {
                    let old_start = self.item_positions[item.get_id()].0 as u16;
                    if old_start < bg_start {
                        bg_start = old_start;
                    }
                }

                self.paint_bg(bg_start, bg_end)?;
            }

            self.item_positions[item.get_id()].0 = pos;
            self.item_positions[item.get_id()].1 = item.get_content_width();
            self.draw_item(item, pos)?;

            if !size_changed {
                break;
            }
        }

        Ok(())
    }

    /// Redraw only needed items in the right slot.
    /// Symmetric to `self.redraw_left`.
    ///
    /// If the component hasn't changed it's size, it doesn't affect
    /// any other components and we can get away with just painting
    /// the one component.
    ///
    /// However if the component has changed it's size, we must also
    /// redraw every component on the right of it. If the item has shrunk
    /// we must also repaint the exposed background.
    fn redraw_left(&mut self, size_changed: bool, index: usize) -> Result<()> {
        let mut pos = 0;

        for n in 0..self.left_items.len() {
            let item = &self.left_items[n];

            if n < index {
                pos += item.get_content_width();
                continue;
            }

            if size_changed {
                let bg_start = pos;
                let mut bg_end = pos + item.get_content_width();

                if n == self.left_items.len() - 1 {
                    let old_end = self.item_positions[item.get_id()].0 +
                        self.item_positions[item.get_id()].1;
                    if bg_end < old_end {
                        bg_end = old_end;
                    }
                }

                self.paint_bg(bg_start, bg_end)?;
            }

            self.item_positions[item.get_id()].0 = pos;
            self.item_positions[item.get_id()].1 = item.get_content_width();
            println!("Drawing {} pos {}", n, pos);
            self.draw_item(item, pos)?;

            if !size_changed {
                break;
            }

            pos += item.get_content_width();
        }

        Ok(())
    }

    /// Copies the item's pixmap to the window.
    fn draw_item(&self, item: &ItemState, pos: u16) -> Result<()> {
        if !item.is_ready() {
            return Ok(());
        }

        try_xcb!(
            xcb::copy_area_checked,
            "failed to copy pixmap",
            &self.conn,
            item.get_pixmap(),
            self.window,
            self.foreground,
            0,
            0,
            pos as i16,
            0,
            item.get_content_width() as u16,
            self.geometry.height()
        );

        Ok(())
    }

    /// Draws the background starting at point a on the x-axis until point b.
    fn paint_bg(&self, a: u16, b: u16) -> Result<()> {
        try_xcb!(
            xcb::poly_fill_rectangle,
            "failed to draw background",
            &self.conn,
            self.window,
            self.foreground,
            &[Rectangle::new(a as i16, 0, b - a, self.geometry.height())]
        );

        Ok(())
    }
}
<|endoftext|>


<commit_before><commit_msg>feat: error mask support<commit_after><|endoftext|>


<commit_before><commit_msg>Added is_linetouched(), is_touched(), touch(), touchline(), touchln() and untouch()<commit_after><|endoftext|>


<commit_before>// Copyright 2016 oauth-client-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! OAuth 1.0 client library for Rust.
//!
//! Dependent on libcurl.
//!
//! [Repository](https://github.com/charlag/oauth-client-rs)
//!
//!# Examples
//!
//! Send request for request token.
//!
//! ```
//!let consumer = Token::new("key", "secret")
//!let bytes = oauth::get(api::REQUEST_TOKEN, consumer, None, None).unwrap();
//! ```
#![warn(bad_style)]
#![warn(missing_docs)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate crypto;
extern crate curl;
#[macro_use]
extern crate log;
extern crate rand;
extern crate rustc_serialize;
extern crate time;
extern crate url;

use std::borrow::Cow;
use std::collections::HashMap;
use std::{error, fmt};
use rand::Rng;
use rustc_serialize::base64::{self, ToBase64};
use crypto::hmac::Hmac;
use crypto::mac::{Mac, MacResult};
use crypto::sha1::Sha1;
use curl::http::{self, Response};
use curl::http::handle::Method;
use url::percent_encoding;

/// The `Error` type
#[derive(Debug)]
pub enum Error {
    /// Curl error
    Curl(curl::ErrCode),
    /// Http status
    HttpStatus(Response),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Curl(ref err) => write!(f, "Curl error: {}", err),
            Error::HttpStatus(ref resp) => write!(f, "HTTP status error: {}", resp),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Curl(ref err) => err.description(),
            Error::HttpStatus(_) => "HTTP status error",
        }
    }

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

impl From<curl::ErrCode> for Error {
    fn from(err: curl::ErrCode) -> Error {
        Error::Curl(err)
    }
}

/// Token structure for the OAuth
#[derive(Clone, Debug)]
pub struct Token<'a> {
    pub key: Cow<'a, str>,
    pub secret: Cow<'a, str>,
}

impl<'a> Token<'a> {
    /// Create new token from `key` and `secret`
    ///
    ///# Examples
    ///
    /// ```
    ///let consumer = Token::new("key", "secret");
    /// ```
    pub fn new<K, S>(key: K, secret: S) -> Token<'a>
        where K: Into<Cow<'a, str>>,
              S: Into<Cow<'a, str>>
    {
        Token {
            key: key.into(),
            secret: secret.into(),
        }
    }
}

/// Alias for `HashMap<Cow<'a, str>, Cow<'a, str>>`
pub type ParamList<'a> = HashMap<Cow<'a, str>, Cow<'a, str>>;

fn insert_param<'a, K, V>(param: &mut ParamList<'a>, key: K, value: V) -> Option<Cow<'a, str>>
    where K: Into<Cow<'a, str>>,
          V: Into<Cow<'a, str>>
{
    param.insert(key.into(), value.into())
}

fn join_query<'a>(param: &ParamList<'a>) -> String {
    let mut pairs = param.iter()
                         .map(|(k, v)| format!("{}={}", encode(&k), encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    pairs.join("&")
}

/// Percent encode string
fn encode(s: &str) -> String {
    percent_encoding::utf8_percent_encode(s, percent_encoding::FORM_URLENCODED_ENCODE_SET)
}

/// Wrapper function around 'crypto::Hmac'
fn hmac_sha1(key: &[u8], data: &[u8]) -> MacResult {
    let mut hmac = Hmac::new(Sha1::new(), key);
    hmac.input(data);
    hmac.result()
}

/// Create signature. See https://dev.twitter.com/oauth/overview/creating-signatures
fn signature(method: &str,
             uri: &str,
             query: &str,
             consumer_secret: &str,
             token_secret: Option<&str>)
             -> String {
    let base = format!("{}&{}&{}", encode(method), encode(uri), encode(query));
    let key = format!("{}&{}",
                      encode(consumer_secret),
                      encode(token_secret.unwrap_or("")));
    let conf = base64::Config {
        char_set: base64::CharacterSet::Standard,
        newline: base64::Newline::LF,
        pad: true,
        line_length: None,
    };
    debug!("Signature base string: {}", base);
    debug!("Authorization header: Authorization: {}", base);
    hmac_sha1(key.as_bytes(), base.as_bytes()).code().to_base64(conf)
}

/// Constuct plain-text header
fn header(param: &ParamList) -> String {
    let mut pairs = param.iter()
                         .filter(|&(k, _)| k.starts_with("oauth_"))
                         .map(|(k, v)| format!("{}=\"{}\"", k, encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    format!("OAuth {}", pairs.join(", "))
}

/// Construct plain-text body from 'PaaramList'
fn body(param: &ParamList) -> String {
    let mut pairs = param.iter()
                         .filter(|&(k, _)| !k.starts_with("oauth_"))
                         .map(|(k, v)| format!("{}={}", k, encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    format!("{}", pairs.join("&"))
}

/// Create header and body
fn get_header(method: Method,
              uri: &str,
              consumer: &Token,
              token: Option<&Token>,
              other_param: Option<&ParamList>)
              -> (String, String) {
    let mut param = HashMap::new();
    let timestamp = format!("{}", time::now_utc().to_timespec().sec);
    let nonce = rand::thread_rng().gen_ascii_chars().take(32).collect::<String>();

    let _ = insert_param(&mut param, "oauth_consumer_key", consumer.key.to_string());
    let _ = insert_param(&mut param, "oauth_nonce", nonce);
    let _ = insert_param(&mut param, "oauth_signature_method", "HMAC-SHA1");
    let _ = insert_param(&mut param, "oauth_timestamp", timestamp);
    let _ = insert_param(&mut param, "oauth_version", "1.0");
    if let Some(tk) = token {
        let _ = insert_param(&mut param, "oauth_token", tk.key.as_ref());
    }

    if let Some(ps) = other_param {
        for (k, v) in ps.iter() {
            let _ = insert_param(&mut param, k.as_ref(), v.as_ref());
        }
    }

    let method_str = match method {
        Method::Options => "OPTIONS",
        Method::Get => "GET",
        Method::Head => "HEAD",
        Method::Post => "POST",
        Method::Put => "PUT",
        Method::Patch => "PATCH",
        Method::Delete => "DELETE",
        Method::Trace => "TRACE",
        Method::Connect => "CONNECT",
    };

    let sign = signature(method_str,
                         uri,
                         join_query(&param).as_ref(),
                         consumer.secret.as_ref(),
                         token.map(|t| t.secret.as_ref()));
    let _ = insert_param(&mut param, "oauth_signature", sign);

    (header(&param), body(&param))
}

/// Create an authorization header.
/// See https://dev.twitter.com/oauth/overview/authorizing-requests
///
///# Examples
///
///```
///let header = oauth::authorization_header(Method::Get, api::REQUEST_TOKEN, consumer, None, None);
///```
pub fn authorization_header(method: Method,
                            uri: &str,
                            consumer: &Token,
                            token: Option<&Token>,
                            other_param: Option<&ParamList>)
                            -> String {
    get_header(method, uri, consumer, token, other_param).0
}

/// Send authorized GET request to the specified URL.
/// `consumer` is a consumer token.
///
///# Examples
///
///```
///let REQUEST_TOKEN: &'static str = "http://oauthbin.com/v1/request-token"
///let bytes = oauth::get(REQUEST_TOKEN, consumer, None, None).unwrap();
///let resp = String::from_utf8(bytes).unwrap();
///```
pub fn get(uri: &str,
           consumer: &Token,
           token: Option<&Token>,
           other_param: Option<&ParamList>)
           -> Result<Vec<u8>, Error> {
    let (header, body) = get_header(Method::Get, uri, consumer, token, other_param);
    let req_uri = if body.len() > 0 {
        format!("{}?{}", uri, body)
    } else {
        format!("{}", uri)
    };
    let resp = try!(http::handle()
                        .get(req_uri)
                        .header("Authorization", header.as_ref())
                        .exec());
    debug!("{}", resp);
    if resp.get_code() != 200 {
        return Err(Error::HttpStatus(resp));
    }
    Ok(resp.move_body())
}

/// Send authorized POST request to the specified URL.
/// `consumer` is a consumer token.
///
///# Examples
///
///```
///let ACCESS_TOKEN: &'static str = "http://oauthbin.com/v1/access-token"
///let bytes = oauth::post(ACCESS_TOKEN, consumer, Some(request), None).unwrap();
///let resp = String::from_utf8(bytes).unwrap();
///```
pub fn post(uri: &str,
            consumer: &Token,
            token: Option<&Token>,
            other_param: Option<&ParamList>)
            -> Result<Vec<u8>, Error> {
    let (header, body) = get_header(Method::Post, uri, consumer, token, other_param);
    let resp = try!(http::handle()
                        .post(uri, &body)
                        .header("Authorization", header.as_ref())
                        .content_type("application/x-www-form-urlencoded")
                        .exec());
    debug!("{}", resp);
    if resp.get_code() != 200 {
        return Err(Error::HttpStatus(resp));
    }
    Ok(resp.move_body())
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;

    #[test]
    fn query() {
        let mut map = HashMap::new();
        let _ = map.insert("aaa".into(), "AAA".into());
        let _ = map.insert("bbbb".into(), "BBBB".into());
        let query = super::join_query(&map);
        assert_eq!("aaa=AAA&bbbb=BBBB", query);
    }
}
<commit_msg>Add docs<commit_after>// Copyright 2016 oauth-client-rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! OAuth 1.0 client library for Rust.
//!
//! Dependent on libcurl.
//!
//! [Repository](https://github.com/charlag/oauth-client-rs)
//!
//!# Examples
//!
//! Send request for request token.
//!
//! ```
//!let consumer = Token::new("key", "secret")
//!let bytes = oauth::get(api::REQUEST_TOKEN, consumer, None, None).unwrap();
//! ```

#![warn(bad_style)]
#![warn(missing_docs)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate crypto;
extern crate curl;
#[macro_use]
extern crate log;
extern crate rand;
extern crate rustc_serialize;
extern crate time;
extern crate url;

use std::borrow::Cow;
use std::collections::HashMap;
use std::{error, fmt};
use rand::Rng;
use rustc_serialize::base64::{self, ToBase64};
use crypto::hmac::Hmac;
use crypto::mac::{Mac, MacResult};
use crypto::sha1::Sha1;
use curl::http::{self, Response};
use curl::http::handle::Method;
use url::percent_encoding;

/// The `Error` type
#[derive(Debug)]
pub enum Error {
    /// Curl error
    Curl(curl::ErrCode),
    /// Http status
    HttpStatus(Response),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Curl(ref err) => write!(f, "Curl error: {}", err),
            Error::HttpStatus(ref resp) => write!(f, "HTTP status error: {}", resp),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Curl(ref err) => err.description(),
            Error::HttpStatus(_) => "HTTP status error",
        }
    }

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

impl From<curl::ErrCode> for Error {
    fn from(err: curl::ErrCode) -> Error {
        Error::Curl(err)
    }
}

/// Token structure for the OAuth
#[derive(Clone, Debug)]
pub struct Token<'a> {
    pub key: Cow<'a, str>,
    pub secret: Cow<'a, str>,
}

impl<'a> Token<'a> {
    /// Create new token from `key` and `secret`
    ///
    ///# Examples
    ///
    /// ```
    ///let consumer = Token::new("key", "secret");
    /// ```
    pub fn new<K, S>(key: K, secret: S) -> Token<'a>
        where K: Into<Cow<'a, str>>,
              S: Into<Cow<'a, str>>
    {
        Token {
            key: key.into(),
            secret: secret.into(),
        }
    }
}

/// Alias for `HashMap<Cow<'a, str>, Cow<'a, str>>`
pub type ParamList<'a> = HashMap<Cow<'a, str>, Cow<'a, str>>;

fn insert_param<'a, K, V>(param: &mut ParamList<'a>, key: K, value: V) -> Option<Cow<'a, str>>
    where K: Into<Cow<'a, str>>,
          V: Into<Cow<'a, str>>
{
    param.insert(key.into(), value.into())
}

fn join_query<'a>(param: &ParamList<'a>) -> String {
    let mut pairs = param.iter()
                         .map(|(k, v)| format!("{}={}", encode(&k), encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    pairs.join("&")
}

/// Percent encode string
fn encode(s: &str) -> String {
    percent_encoding::utf8_percent_encode(s, percent_encoding::FORM_URLENCODED_ENCODE_SET)
}

/// Wrapper function around 'crypto::Hmac'
fn hmac_sha1(key: &[u8], data: &[u8]) -> MacResult {
    let mut hmac = Hmac::new(Sha1::new(), key);
    hmac.input(data);
    hmac.result()
}

/// Create signature. See https://dev.twitter.com/oauth/overview/creating-signatures
fn signature(method: &str,
             uri: &str,
             query: &str,
             consumer_secret: &str,
             token_secret: Option<&str>)
             -> String {
    let base = format!("{}&{}&{}", encode(method), encode(uri), encode(query));
    let key = format!("{}&{}",
                      encode(consumer_secret),
                      encode(token_secret.unwrap_or("")));
    let conf = base64::Config {
        char_set: base64::CharacterSet::Standard,
        newline: base64::Newline::LF,
        pad: true,
        line_length: None,
    };
    debug!("Signature base string: {}", base);
    debug!("Authorization header: Authorization: {}", base);
    hmac_sha1(key.as_bytes(), base.as_bytes()).code().to_base64(conf)
}

/// Constuct plain-text header
fn header(param: &ParamList) -> String {
    let mut pairs = param.iter()
                         .filter(|&(k, _)| k.starts_with("oauth_"))
                         .map(|(k, v)| format!("{}=\"{}\"", k, encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    format!("OAuth {}", pairs.join(", "))
}

/// Construct plain-text body from 'PaaramList'
fn body(param: &ParamList) -> String {
    let mut pairs = param.iter()
                         .filter(|&(k, _)| !k.starts_with("oauth_"))
                         .map(|(k, v)| format!("{}={}", k, encode(&v)))
                         .collect::<Vec<_>>();
    pairs.sort();
    format!("{}", pairs.join("&"))
}

/// Create header and body
fn get_header(method: Method,
              uri: &str,
              consumer: &Token,
              token: Option<&Token>,
              other_param: Option<&ParamList>)
              -> (String, String) {
    let mut param = HashMap::new();
    let timestamp = format!("{}", time::now_utc().to_timespec().sec);
    let nonce = rand::thread_rng().gen_ascii_chars().take(32).collect::<String>();

    let _ = insert_param(&mut param, "oauth_consumer_key", consumer.key.to_string());
    let _ = insert_param(&mut param, "oauth_nonce", nonce);
    let _ = insert_param(&mut param, "oauth_signature_method", "HMAC-SHA1");
    let _ = insert_param(&mut param, "oauth_timestamp", timestamp);
    let _ = insert_param(&mut param, "oauth_version", "1.0");
    if let Some(tk) = token {
        let _ = insert_param(&mut param, "oauth_token", tk.key.as_ref());
    }

    if let Some(ps) = other_param {
        for (k, v) in ps.iter() {
            let _ = insert_param(&mut param, k.as_ref(), v.as_ref());
        }
    }

    let method_str = match method {
        Method::Options => "OPTIONS",
        Method::Get => "GET",
        Method::Head => "HEAD",
        Method::Post => "POST",
        Method::Put => "PUT",
        Method::Patch => "PATCH",
        Method::Delete => "DELETE",
        Method::Trace => "TRACE",
        Method::Connect => "CONNECT",
    };

    let sign = signature(method_str,
                         uri,
                         join_query(&param).as_ref(),
                         consumer.secret.as_ref(),
                         token.map(|t| t.secret.as_ref()));
    let _ = insert_param(&mut param, "oauth_signature", sign);

    (header(&param), body(&param))
}

/// Create an authorization header.
/// See https://dev.twitter.com/oauth/overview/authorizing-requests
///
///# Examples
///
///```
///let header = oauth::authorization_header(Method::Get, api::REQUEST_TOKEN, consumer, None, None);
///```
pub fn authorization_header(method: Method,
                            uri: &str,
                            consumer: &Token,
                            token: Option<&Token>,
                            other_param: Option<&ParamList>)
                            -> String {
    get_header(method, uri, consumer, token, other_param).0
}

/// Send authorized GET request to the specified URL.
/// `consumer` is a consumer token.
///
///# Examples
///
///```
///let REQUEST_TOKEN: &'static str = "http://oauthbin.com/v1/request-token"
///let bytes = oauth::get(REQUEST_TOKEN, consumer, None, None).unwrap();
///let resp = String::from_utf8(bytes).unwrap();
///```
pub fn get(uri: &str,
           consumer: &Token,
           token: Option<&Token>,
           other_param: Option<&ParamList>)
           -> Result<Vec<u8>, Error> {
    let (header, body) = get_header(Method::Get, uri, consumer, token, other_param);
    let req_uri = if body.len() > 0 {
        format!("{}?{}", uri, body)
    } else {
        format!("{}", uri)
    };
    let resp = try!(http::handle()
                        .get(req_uri)
                        .header("Authorization", header.as_ref())
                        .exec());
    debug!("{}", resp);
    if resp.get_code() != 200 {
        return Err(Error::HttpStatus(resp));
    }
    Ok(resp.move_body())
}

/// Send authorized POST request to the specified URL.
/// `consumer` is a consumer token.
///
///# Examples
///
///```
///let ACCESS_TOKEN: &'static str = "http://oauthbin.com/v1/access-token"
///let bytes = oauth::post(ACCESS_TOKEN, consumer, Some(request), None).unwrap();
///let resp = String::from_utf8(bytes).unwrap();
///```
pub fn post(uri: &str,
            consumer: &Token,
            token: Option<&Token>,
            other_param: Option<&ParamList>)
            -> Result<Vec<u8>, Error> {
    let (header, body) = get_header(Method::Post, uri, consumer, token, other_param);
    let resp = try!(http::handle()
                        .post(uri, &body)
                        .header("Authorization", header.as_ref())
                        .content_type("application/x-www-form-urlencoded")
                        .exec());
    debug!("{}", resp);
    if resp.get_code() != 200 {
        return Err(Error::HttpStatus(resp));
    }
    Ok(resp.move_body())
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;

    #[test]
    fn query() {
        let mut map = HashMap::new();
        let _ = map.insert("aaa".into(), "AAA".into());
        let _ = map.insert("bbbb".into(), "BBBB".into());
        let query = super::join_query(&map);
        assert_eq!("aaa=AAA&bbbb=BBBB", query);
    }
}
<|endoftext|>


<commit_before>extern crate num;

mod vector;
mod matrix;

pub use vector::Vector;
pub use matrix::Matrix;

#[test]
fn it_works() {
}
<commit_msg>Remove default test<commit_after>extern crate num;

mod vector;
mod matrix;

pub use vector::Vector;
pub use matrix::Matrix;
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A Glutin window back-end for the Piston game engine.

extern crate glutin;
extern crate gl;
extern crate input;
extern crate window;
extern crate shader_version;

// External crates.
use input::{
    keyboard,
    MouseButton,
    Button,
    Input,
};
use window::{
    OpenGLWindow,
    Window,
    AdvancedWindow,
    ProcAddress,
    WindowSettings,
    Size,
};

pub use shader_version::OpenGL;

/// Contains stuff for game window.
pub struct GlutinWindow {
    /// The window.
    pub window: glutin::Window,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
    should_close: bool,
}

impl GlutinWindow {
    /// Creates a new game window for Glutin.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlutinWindow {
        let (major, minor) = opengl.get_major_minor();
        let size = settings.get_size();
        let mut builder = glutin::WindowBuilder::new()
            .with_dimensions(size.width, size.height)
            .with_gl_version((major as u32, minor as u32))
            .with_title(settings.get_title());
        let samples = settings.get_samples();
        if samples != 0 {
            builder = builder.with_multisampling(samples as u16);
        }
        if settings.get_fullscreen() {
            builder = builder.with_fullscreen(glutin::get_primary_monitor());
        }
        let window = builder
            .build().unwrap();
        unsafe { window.make_current(); }

        // Load the OpenGL function pointers.
        gl::load_with(|s| window.get_proc_address(s));

        GlutinWindow {
            window: window,
            last_mouse_pos: None,
            title: settings.get_title(),
            exit_on_esc: settings.get_exit_on_esc(),
            should_close: false,
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        use glutin::Event as E;
        use input::{ Key, Input, Motion };

        if let Some((x, y)) = self.last_mouse_pos {
            self.last_mouse_pos = None;
            return Some(Input::Move(Motion::MouseRelative(x, y)));
        }

        match self.window.poll_events().next() {
            None => None,
            Some(E::Resized(w, h)) =>
                Some(Input::Resize(w, h)),
            Some(E::ReceivedCharacter(ch)) => {
                let string = match ch {
                    // Ignore control characters and return ascii for Text event (like sdl2).
                    '\u{7f}' | // Delete
                    '\u{1b}' | // Escape
                    '\u{8}'  | // Backspace
                    '\r' | '\n' | '\t' => "".to_string(),
                    _ => ch.to_string()
                };
                Some(Input::Text(string))
            },
            Some(E::Focused(focused)) =>
                Some(Input::Focus(focused)),
            Some(E::KeyboardInput(glutin::ElementState::Pressed, _, Some(key))) => {
                let piston_key = map_key(key);
                if let (true, Key::Escape) = (self.exit_on_esc, piston_key) {
                    self.should_close = true;
                }
                Some(Input::Press(Button::Keyboard(piston_key)))
            },
            Some(E::KeyboardInput(glutin::ElementState::Released, _, Some(key))) =>
                Some(Input::Release(Button::Keyboard(map_key(key)))),
            Some(E::MouseMoved((x, y))) => {
                self.last_mouse_pos = Some((x as f64, y as f64));
                Some(Input::Move(
                    Motion::MouseCursor(x as f64, y as f64)))
            }
            Some(E::MouseWheel(y)) =>
                Some(Input::Move(
                    Motion::MouseScroll(0.0, y as f64))),
            Some(E::MouseInput(glutin::ElementState::Pressed, button)) =>
                Some(Input::Press(Button::Mouse(map_mouse(button)))),
            Some(E::MouseInput(glutin::ElementState::Released, button)) =>
                Some(Input::Release(Button::Mouse(map_mouse(button)))),
            _ => None,
        }
    }
}

impl Window for GlutinWindow {
    type Event = Input;

    fn size(&self) -> Size {
        let f = self.window.hidpi_factor();
        if let Some((w, h)) = self.window.get_inner_size() {
            Size { width: (w as f32 / f) as u32, height: (h as f32 / f) as u32 }
        } else {
            Size { width: 0, height: 0 }
        }
    }
    fn should_close(&self) -> bool {
        self.window.should_close() || self.should_close
    }
    fn swap_buffers(&mut self) { self.window.swap_buffers(); }
    fn poll_event(&mut self) -> Option<Input> { self.poll_event() }
}

impl AdvancedWindow for GlutinWindow {
    fn draw_size(&self) -> Size {
        if let Some((w, h)) = self.window.get_inner_size() {
            Size { width: w, height: h }
        } else {
            Size { width: 0, height: 0 }
        }
    }
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) {
        self.title = value;
        self.window.set_title(&self.title);
    }
    fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }
    fn set_exit_on_esc(&mut self, value: bool) { self.exit_on_esc = value; }
    fn set_capture_cursor(&mut self, value: bool) {
        use glutin::CursorState;
        if value {
            let _ = self.window.set_cursor_state(CursorState::Grab);
        } else {
            let _ = self.window.set_cursor_state(CursorState::Normal);
        }
    }
}

impl OpenGLWindow for GlutinWindow {
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress {
        self.window.get_proc_address(proc_name)
    }

    fn is_current(&self) -> bool {
        self.window.is_current()
    }

    fn make_current(&mut self) {
        unsafe {
            self.window.make_current()
        }
    }
}

/// Maps Glutin's key to Piston's key.
pub fn map_key(keycode: glutin::VirtualKeyCode) -> keyboard::Key {
    use input::keyboard::Key;
    use glutin::VirtualKeyCode as K;

    match keycode {
        K::Key0 => Key::D0,
        K::Key1 => Key::D1,
        K::Key2 => Key::D2,
        K::Key3 => Key::D3,
        K::Key4 => Key::D4,
        K::Key5 => Key::D5,
        K::Key6 => Key::D6,
        K::Key7 => Key::D7,
        K::Key8 => Key::D8,
        K::Key9 => Key::D9,
        K::A => Key::A,
        K::B => Key::B,
        K::C => Key::C,
        K::D => Key::D,
        K::E => Key::E,
        K::F => Key::F,
        K::G => Key::G,
        K::H => Key::H,
        K::I => Key::I,
        K::J => Key::J,
        K::K => Key::K,
        K::L => Key::L,
        K::M => Key::M,
        K::N => Key::N,
        K::O => Key::O,
        K::P => Key::P,
        K::Q => Key::Q,
        K::R => Key::R,
        K::S => Key::S,
        K::T => Key::T,
        K::U => Key::U,
        K::V => Key::V,
        K::W => Key::W,
        K::X => Key::X,
        K::Y => Key::Y,
        K::Z => Key::Z,
        K::Apostrophe => Key::Unknown,
        K::Backslash => Key::Backslash,
        K::Back => Key::Backspace,
        // K::CapsLock => Key::CapsLock,
        K::Delete => Key::Delete,
        K::Comma => Key::Comma,
        K::Down => Key::Down,
        K::End => Key::End,
        K::Return => Key::Return,
        K::Equals => Key::Equals,
        K::Escape => Key::Escape,
        K::F1 => Key::F1,
        K::F2 => Key::F2,
        K::F3 => Key::F3,
        K::F4 => Key::F4,
        K::F5 => Key::F5,
        K::F6 => Key::F6,
        K::F7 => Key::F7,
        K::F8 => Key::F8,
        K::F9 => Key::F9,
        K::F10 => Key::F10,
        K::F11 => Key::F11,
        K::F12 => Key::F12,
        K::F13 => Key::F13,
        K::F14 => Key::F14,
        K::F15 => Key::F15,
        // K::F16 => Key::F16,
        // K::F17 => Key::F17,
        // K::F18 => Key::F18,
        // K::F19 => Key::F19,
        // K::F20 => Key::F20,
        // K::F21 => Key::F21,
        // K::F22 => Key::F22,
        // K::F23 => Key::F23,
        // K::F24 => Key::F24,
        // Possibly next code.
        // K::F25 => Key::Unknown,
        K::Numpad0 => Key::NumPad0,
        K::Numpad1 => Key::NumPad1,
        K::Numpad2 => Key::NumPad2,
        K::Numpad3 => Key::NumPad3,
        K::Numpad4 => Key::NumPad4,
        K::Numpad5 => Key::NumPad5,
        K::Numpad6 => Key::NumPad6,
        K::Numpad7 => Key::NumPad7,
        K::Numpad8 => Key::NumPad8,
        K::Numpad9 => Key::NumPad9,
        K::NumpadComma => Key::NumPadDecimal,
        K::Divide => Key::NumPadDivide,
        K::Multiply => Key::NumPadMultiply,
        K::Subtract => Key::NumPadMinus,
        K::Add => Key::NumPadPlus,
        K::NumpadEnter => Key::NumPadEnter,
        K::NumpadEquals => Key::NumPadEquals,
        K::LShift => Key::LShift,
        K::LControl => Key::LCtrl,
        K::LAlt => Key::LAlt,
        K::LMenu => Key::LGui,
        K::RShift => Key::RShift,
        K::RControl => Key::RCtrl,
        K::RAlt => Key::RAlt,
        K::RMenu => Key::RGui,
        // Map to backslash?
        // K::GraveAccent => Key::Unknown,
        K::Home => Key::Home,
        K::Insert => Key::Insert,
        K::Left => Key::Left,
        K::LBracket => Key::LeftBracket,
        // K::Menu => Key::Menu,
        K::Minus => Key::Minus,
        K::Numlock => Key::NumLockClear,
        K::PageDown => Key::PageDown,
        K::PageUp => Key::PageUp,
        K::Pause => Key::Pause,
        K::Period => Key::Period,
        // K::PrintScreen => Key::PrintScreen,
        K::Right => Key::Right,
        K::RBracket => Key::RightBracket,
        // K::ScrollLock => Key::ScrollLock,
        K::Semicolon => Key::Semicolon,
        K::Slash => Key::Slash,
        K::Space => Key::Space,
        K::Tab => Key::Tab,
        K::Up => Key::Up,
        // K::World1 => Key::Unknown,
        // K::World2 => Key::Unknown,
        _ => Key::Unknown,
    }
}

/// Maps Glutin's mouse button to Piston's mouse button.
pub fn map_mouse(mouse_button: glutin::MouseButton) -> MouseButton {
    use glutin::MouseButton as M;

    match mouse_button {
        M::Left => MouseButton::Left,
        M::Right => MouseButton::Right,
        M::Middle => MouseButton::Middle,
        M::Other(0) => MouseButton::X1,
        M::Other(1) => MouseButton::X2,
        M::Other(2) => MouseButton::Button6,
        M::Other(3) => MouseButton::Button7,
        M::Other(4) => MouseButton::Button8,
        _ => MouseButton::Unknown
    }
}
<commit_msg>Upgrade to latest window<commit_after>#![deny(missing_docs)]

//! A Glutin window back-end for the Piston game engine.

extern crate glutin;
extern crate gl;
extern crate input;
extern crate window;
extern crate shader_version;

// External crates.
use input::{
    keyboard,
    MouseButton,
    Button,
    Input,
};
use window::{
    OpenGLWindow,
    Window,
    AdvancedWindow,
    ProcAddress,
    WindowSettings,
    Size,
};

pub use shader_version::OpenGL;

/// Contains stuff for game window.
pub struct GlutinWindow {
    /// The window.
    pub window: glutin::Window,
    // Used to compute relative mouse movement.
    last_mouse_pos: Option<(f64, f64)>,
    // The back-end does not remember the title.
    title: String,
    exit_on_esc: bool,
    should_close: bool,
}

impl GlutinWindow {
    /// Creates a new game window for Glutin.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> GlutinWindow {
        let (major, minor) = opengl.get_major_minor();
        let size = settings.get_size();
        let mut builder = glutin::WindowBuilder::new()
            .with_dimensions(size.width, size.height)
            .with_gl_version((major as u32, minor as u32))
            .with_title(settings.get_title());
        let samples = settings.get_samples();
        if samples != 0 {
            builder = builder.with_multisampling(samples as u16);
        }
        if settings.get_fullscreen() {
            builder = builder.with_fullscreen(glutin::get_primary_monitor());
        }
        let window = builder
            .build().unwrap();
        unsafe { window.make_current(); }

        // Load the OpenGL function pointers.
        gl::load_with(|s| window.get_proc_address(s));

        GlutinWindow {
            window: window,
            last_mouse_pos: None,
            title: settings.get_title(),
            exit_on_esc: settings.get_exit_on_esc(),
            should_close: false,
        }
    }

    fn poll_event(&mut self) -> Option<Input> {
        use glutin::Event as E;
        use input::{ Key, Input, Motion };

        if let Some((x, y)) = self.last_mouse_pos {
            self.last_mouse_pos = None;
            return Some(Input::Move(Motion::MouseRelative(x, y)));
        }

        match self.window.poll_events().next() {
            None => None,
            Some(E::Resized(w, h)) =>
                Some(Input::Resize(w, h)),
            Some(E::ReceivedCharacter(ch)) => {
                let string = match ch {
                    // Ignore control characters and return ascii for Text event (like sdl2).
                    '\u{7f}' | // Delete
                    '\u{1b}' | // Escape
                    '\u{8}'  | // Backspace
                    '\r' | '\n' | '\t' => "".to_string(),
                    _ => ch.to_string()
                };
                Some(Input::Text(string))
            },
            Some(E::Focused(focused)) =>
                Some(Input::Focus(focused)),
            Some(E::KeyboardInput(glutin::ElementState::Pressed, _, Some(key))) => {
                let piston_key = map_key(key);
                if let (true, Key::Escape) = (self.exit_on_esc, piston_key) {
                    self.should_close = true;
                }
                Some(Input::Press(Button::Keyboard(piston_key)))
            },
            Some(E::KeyboardInput(glutin::ElementState::Released, _, Some(key))) =>
                Some(Input::Release(Button::Keyboard(map_key(key)))),
            Some(E::MouseMoved((x, y))) => {
                self.last_mouse_pos = Some((x as f64, y as f64));
                Some(Input::Move(
                    Motion::MouseCursor(x as f64, y as f64)))
            }
            Some(E::MouseWheel(y)) =>
                Some(Input::Move(
                    Motion::MouseScroll(0.0, y as f64))),
            Some(E::MouseInput(glutin::ElementState::Pressed, button)) =>
                Some(Input::Press(Button::Mouse(map_mouse(button)))),
            Some(E::MouseInput(glutin::ElementState::Released, button)) =>
                Some(Input::Release(Button::Mouse(map_mouse(button)))),
            _ => None,
        }
    }
}

impl Window for GlutinWindow {
    type Event = Input;

    fn size(&self) -> Size {
        let f = self.window.hidpi_factor();
        if let Some((w, h)) = self.window.get_inner_size() {
            Size { width: (w as f32 / f) as u32, height: (h as f32 / f) as u32 }
        } else {
            Size { width: 0, height: 0 }
        }
    }
    fn draw_size(&self) -> Size {
        if let Some((w, h)) = self.window.get_inner_size() {
            Size { width: w, height: h }
        } else {
            Size { width: 0, height: 0 }
        }
    }
    fn should_close(&self) -> bool {
        self.window.should_close() || self.should_close
    }
    fn swap_buffers(&mut self) { self.window.swap_buffers(); }
    fn poll_event(&mut self) -> Option<Input> { self.poll_event() }
}

impl AdvancedWindow for GlutinWindow {
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) {
        self.title = value;
        self.window.set_title(&self.title);
    }
    fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }
    fn set_exit_on_esc(&mut self, value: bool) { self.exit_on_esc = value; }
    fn set_capture_cursor(&mut self, value: bool) {
        use glutin::CursorState;
        if value {
            let _ = self.window.set_cursor_state(CursorState::Grab);
        } else {
            let _ = self.window.set_cursor_state(CursorState::Normal);
        }
    }
}

impl OpenGLWindow for GlutinWindow {
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress {
        self.window.get_proc_address(proc_name)
    }

    fn is_current(&self) -> bool {
        self.window.is_current()
    }

    fn make_current(&mut self) {
        unsafe {
            self.window.make_current()
        }
    }
}

/// Maps Glutin's key to Piston's key.
pub fn map_key(keycode: glutin::VirtualKeyCode) -> keyboard::Key {
    use input::keyboard::Key;
    use glutin::VirtualKeyCode as K;

    match keycode {
        K::Key0 => Key::D0,
        K::Key1 => Key::D1,
        K::Key2 => Key::D2,
        K::Key3 => Key::D3,
        K::Key4 => Key::D4,
        K::Key5 => Key::D5,
        K::Key6 => Key::D6,
        K::Key7 => Key::D7,
        K::Key8 => Key::D8,
        K::Key9 => Key::D9,
        K::A => Key::A,
        K::B => Key::B,
        K::C => Key::C,
        K::D => Key::D,
        K::E => Key::E,
        K::F => Key::F,
        K::G => Key::G,
        K::H => Key::H,
        K::I => Key::I,
        K::J => Key::J,
        K::K => Key::K,
        K::L => Key::L,
        K::M => Key::M,
        K::N => Key::N,
        K::O => Key::O,
        K::P => Key::P,
        K::Q => Key::Q,
        K::R => Key::R,
        K::S => Key::S,
        K::T => Key::T,
        K::U => Key::U,
        K::V => Key::V,
        K::W => Key::W,
        K::X => Key::X,
        K::Y => Key::Y,
        K::Z => Key::Z,
        K::Apostrophe => Key::Unknown,
        K::Backslash => Key::Backslash,
        K::Back => Key::Backspace,
        // K::CapsLock => Key::CapsLock,
        K::Delete => Key::Delete,
        K::Comma => Key::Comma,
        K::Down => Key::Down,
        K::End => Key::End,
        K::Return => Key::Return,
        K::Equals => Key::Equals,
        K::Escape => Key::Escape,
        K::F1 => Key::F1,
        K::F2 => Key::F2,
        K::F3 => Key::F3,
        K::F4 => Key::F4,
        K::F5 => Key::F5,
        K::F6 => Key::F6,
        K::F7 => Key::F7,
        K::F8 => Key::F8,
        K::F9 => Key::F9,
        K::F10 => Key::F10,
        K::F11 => Key::F11,
        K::F12 => Key::F12,
        K::F13 => Key::F13,
        K::F14 => Key::F14,
        K::F15 => Key::F15,
        // K::F16 => Key::F16,
        // K::F17 => Key::F17,
        // K::F18 => Key::F18,
        // K::F19 => Key::F19,
        // K::F20 => Key::F20,
        // K::F21 => Key::F21,
        // K::F22 => Key::F22,
        // K::F23 => Key::F23,
        // K::F24 => Key::F24,
        // Possibly next code.
        // K::F25 => Key::Unknown,
        K::Numpad0 => Key::NumPad0,
        K::Numpad1 => Key::NumPad1,
        K::Numpad2 => Key::NumPad2,
        K::Numpad3 => Key::NumPad3,
        K::Numpad4 => Key::NumPad4,
        K::Numpad5 => Key::NumPad5,
        K::Numpad6 => Key::NumPad6,
        K::Numpad7 => Key::NumPad7,
        K::Numpad8 => Key::NumPad8,
        K::Numpad9 => Key::NumPad9,
        K::NumpadComma => Key::NumPadDecimal,
        K::Divide => Key::NumPadDivide,
        K::Multiply => Key::NumPadMultiply,
        K::Subtract => Key::NumPadMinus,
        K::Add => Key::NumPadPlus,
        K::NumpadEnter => Key::NumPadEnter,
        K::NumpadEquals => Key::NumPadEquals,
        K::LShift => Key::LShift,
        K::LControl => Key::LCtrl,
        K::LAlt => Key::LAlt,
        K::LMenu => Key::LGui,
        K::RShift => Key::RShift,
        K::RControl => Key::RCtrl,
        K::RAlt => Key::RAlt,
        K::RMenu => Key::RGui,
        // Map to backslash?
        // K::GraveAccent => Key::Unknown,
        K::Home => Key::Home,
        K::Insert => Key::Insert,
        K::Left => Key::Left,
        K::LBracket => Key::LeftBracket,
        // K::Menu => Key::Menu,
        K::Minus => Key::Minus,
        K::Numlock => Key::NumLockClear,
        K::PageDown => Key::PageDown,
        K::PageUp => Key::PageUp,
        K::Pause => Key::Pause,
        K::Period => Key::Period,
        // K::PrintScreen => Key::PrintScreen,
        K::Right => Key::Right,
        K::RBracket => Key::RightBracket,
        // K::ScrollLock => Key::ScrollLock,
        K::Semicolon => Key::Semicolon,
        K::Slash => Key::Slash,
        K::Space => Key::Space,
        K::Tab => Key::Tab,
        K::Up => Key::Up,
        // K::World1 => Key::Unknown,
        // K::World2 => Key::Unknown,
        _ => Key::Unknown,
    }
}

/// Maps Glutin's mouse button to Piston's mouse button.
pub fn map_mouse(mouse_button: glutin::MouseButton) -> MouseButton {
    use glutin::MouseButton as M;

    match mouse_button {
        M::Left => MouseButton::Left,
        M::Right => MouseButton::Right,
        M::Middle => MouseButton::Middle,
        M::Other(0) => MouseButton::X1,
        M::Other(1) => MouseButton::X2,
        M::Other(2) => MouseButton::Button6,
        M::Other(3) => MouseButton::Button7,
        M::Other(4) => MouseButton::Button8,
        _ => MouseButton::Unknown
    }
}
<|endoftext|>


<commit_before>#[derive(Debug)]
pub struct DictEntry<'a> {
    traditional: &'a str,
    simplified: &'a str,
    pinyin: &'a str,
    definitions: Vec<&'a str>
}

pub fn parse_line(line: &str) -> Result<DictEntry, ()> {
    let line = line.trim();

    let (traditional, line) = {
        let mut parts = line.splitn(2, " ");
        ( parts.next().ok_or(())?, parts.next().ok_or(())? )
    };

    let (simplified, line) = {
        let mut parts = line.splitn(2, " ");
        ( parts.next().ok_or(())?, parts.next().ok_or(())? )
    };

    let (pinyin, line) = {
        let pinyin_begin = line.find('[').ok_or(())? + 1;
        let pinyin_end = line.find(']').ok_or(())?;
        ( &line[pinyin_begin..pinyin_end], &line[pinyin_end+1..] )
    };

    let definitions = {
        let mut defs = Vec::new();
        let mut line = line.trim();
        while !line.is_empty() {
            let def_end = line.find('/').ok_or(())?;
            if !line[..def_end].is_empty() {
                defs.push(&line[..def_end]);
            }
            line = &line[def_end + 1..]
        }
        defs
    };

    Ok(DictEntry {
        traditional: traditional,
        simplified: simplified,
        pinyin: pinyin,
        definitions: definitions
    })
}

#[test]
fn test_parse_pinyin() {
    let line = "你好 你好 [ni3 hao3] /Hello!/Hi!/How are you?/";
    let parsed = parse_line(line).unwrap();

    assert_eq!(parsed.pinyin, "ni3 hao3");
}

#[test]
fn test_parse_simplified() {
    let line = "你好 你好 [ni3 hao3] /Hello!/Hi!/How are you?/";
    let parsed = parse_line(line).unwrap();

    assert_eq!(parsed.simplified, "你好");
}

#[test]
fn test_parse_traditional() {
    let line = "愛 爱 [ai4] /to love/to be fond of/to like/";
    let parsed = parse_line(line).unwrap();

    assert_eq!(parsed.traditional, "愛");
    assert_eq!(parsed.simplified, "爱");
}
<commit_msg>Made struct fields public<commit_after>#[derive(Debug)]
pub struct DictEntry<'a> {
    pub traditional: &'a str,
    pub simplified: &'a str,
    pub pinyin: &'a str,
    pub definitions: Vec<&'a str>
}

pub fn parse_line(line: &str) -> Result<DictEntry, ()> {
    let line = line.trim();

    let (traditional, line) = {
        let mut parts = line.splitn(2, " ");
        ( parts.next().ok_or(())?, parts.next().ok_or(())? )
    };

    let (simplified, line) = {
        let mut parts = line.splitn(2, " ");
        ( parts.next().ok_or(())?, parts.next().ok_or(())? )
    };

    let (pinyin, line) = {
        let pinyin_begin = line.find('[').ok_or(())? + 1;
        let pinyin_end = line.find(']').ok_or(())?;
        ( &line[pinyin_begin..pinyin_end], &line[pinyin_end+1..] )
    };

    let definitions = {
        let mut defs = Vec::new();
        let mut line = line.trim();
        while !line.is_empty() {
            let def_end = line.find('/').ok_or(())?;
            if !line[..def_end].is_empty() {
                defs.push(&line[..def_end]);
            }
            line = &line[def_end + 1..]
        }
        defs
    };

    Ok(DictEntry {
        traditional: traditional,
        simplified: simplified,
        pinyin: pinyin,
        definitions: definitions
    })
}

#[test]
fn test_parse_pinyin() {
    let line = "你好 你好 [ni3 hao3] /Hello!/Hi!/How are you?/";
    let parsed = parse_line(line).unwrap();

    assert_eq!(parsed.pinyin, "ni3 hao3");
}

#[test]
fn test_parse_simplified() {
    let line = "你好 你好 [ni3 hao3] /Hello!/Hi!/How are you?/";
    let parsed = parse_line(line).unwrap();

    assert_eq!(parsed.simplified, "你好");
}

#[test]
fn test_parse_traditional() {
    let line = "愛 爱 [ai4] /to love/to be fond of/to like/";
    let parsed = parse_line(line).unwrap();

    assert_eq!(parsed.traditional, "愛");
    assert_eq!(parsed.simplified, "爱");
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "cargo-clippy", allow(large_enum_variant))]

#[cfg(feature = "printing")]
extern crate quote;

#[cfg(feature = "parsing")]
extern crate unicode_xid;

#[cfg(feature = "parsing")]
#[macro_use]
extern crate synom;

#[cfg(feature = "aster")]
pub mod aster;

mod attr;
pub use attr::{Attribute, AttrStyle, MetaItem, NestedMetaItem};

mod constant;
pub use constant::ConstExpr;

mod data;
pub use data::{Field, Variant, VariantData, Visibility};

#[cfg(feature = "parsing")]
mod escape;

#[cfg(feature = "full")]
mod expr;
#[cfg(feature = "full")]
pub use expr::{Arm, BindingMode, Block, CaptureBy, Expr, ExprKind, FieldPat, FieldValue,
               Local, MacStmtStyle, Pat, RangeLimits, Stmt};

mod generics;
pub use generics::{Generics, Lifetime, LifetimeDef, TraitBoundModifier, TyParam, TyParamBound,
                   WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate,
                   WhereRegionPredicate};
#[cfg(feature = "printing")]
pub use generics::{ImplGenerics, Turbofish, TyGenerics};

mod ident;
pub use ident::Ident;

#[cfg(feature = "full")]
mod item;
#[cfg(feature = "full")]
pub use item::{Constness, Defaultness, FnArg, FnDecl, ForeignItemKind, ForeignItem, ForeignMod,
               ImplItem, ImplItemKind, ImplPolarity, Item, ItemKind, MethodSig, PathListItem,
               TraitItem, TraitItemKind, ViewPath};

#[cfg(feature = "full")]
mod krate;
#[cfg(feature = "full")]
pub use krate::Crate;

mod lit;
pub use lit::{FloatTy, IntTy, Lit, StrStyle};
#[cfg(feature = "parsing")]
pub use lit::{ByteStrLit, FloatLit, IntLit, StrLit};

mod mac;
pub use mac::{BinOpToken, DelimToken, Delimited, Mac, Token, TokenTree};

mod derive;
pub use derive::{Body, DeriveInput};
// Deprecated. Use `DeriveInput` instead.
#[doc(hidden)]
pub type MacroInput = DeriveInput;

mod op;
pub use op::{BinOp, UnOp};

mod ty;
pub use ty::{Abi, AngleBracketedParameterData, BareFnArg, BareFnTy, FunctionRetTy, MutTy,
             Mutability, ParenthesizedParameterData, Path, PathParameters, PathSegment,
             PolyTraitRef, QSelf, Ty, TypeBinding, Unsafety};

#[cfg(feature = "visit")]
pub mod visit;

#[cfg(feature = "fold")]
pub mod fold;

#[cfg(feature = "parsing")]
pub use parsing::*;

#[cfg(feature = "parsing")]
mod parsing {
    use super::*;
    use {derive, generics, ident, mac, ty};
    use synom::{space, IResult};

    #[cfg(feature = "full")]
    use {expr, item, krate};

    pub fn parse_derive_input(input: &str) -> Result<DeriveInput, String> {
        unwrap("derive input", derive::parsing::derive_input, input)
    }

    #[cfg(feature = "full")]
    pub fn parse_crate(input: &str) -> Result<Crate, String> {
        unwrap("crate", krate::parsing::krate, input)
    }

    #[cfg(feature = "full")]
    pub fn parse_item(input: &str) -> Result<Item, String> {
        unwrap("item", item::parsing::item, input)
    }

    #[cfg(feature = "full")]
    pub fn parse_items(input: &str) -> Result<Vec<Item>, String> {
        unwrap("items", item::parsing::items, input)
    }

    #[cfg(feature = "full")]
    pub fn parse_expr(input: &str) -> Result<Expr, String> {
        unwrap("expression", expr::parsing::expr, input)
    }

    pub fn parse_type(input: &str) -> Result<Ty, String> {
        unwrap("type", ty::parsing::ty, input)
    }

    pub fn parse_path(input: &str) -> Result<Path, String> {
        unwrap("path", ty::parsing::path, input)
    }

    pub fn parse_where_clause(input: &str) -> Result<WhereClause, String> {
        unwrap("where clause", generics::parsing::where_clause, input)
    }

    pub fn parse_token_trees(input: &str) -> Result<Vec<TokenTree>, String> {
        unwrap("token trees", mac::parsing::token_trees, input)
    }

    pub fn parse_ident(input: &str) -> Result<Ident, String> {
        unwrap("identifier", ident::parsing::ident, input)
    }

    pub fn parse_ty_param_bound(input: &str) -> Result<TyParamBound, String> {
        unwrap("type parameter bound", generics::parsing::ty_param_bound, input)
    }

    // Deprecated. Use `parse_derive_input` instead.
    #[doc(hidden)]
    pub fn parse_macro_input(input: &str) -> Result<MacroInput, String> {
        parse_derive_input(input)
    }

    fn unwrap<T>(name: &'static str,
                 f: fn(&str) -> IResult<&str, T>,
                 input: &str)
                 -> Result<T, String> {
        match f(input) {
            IResult::Done(mut rest, t) => {
                rest = space::skip_whitespace(rest);
                if rest.is_empty() {
                    Ok(t)
                } else if rest.len() == input.len() {
                    // parsed nothing
                    Err(format!("failed to parse {}: {:?}", name, rest))
                } else {
                    Err(format!("unparsed tokens after {}: {:?}", name, rest))
                }
            }
            IResult::Error => Err(format!("failed to parse {}: {:?}", name, input)),
        }
    }
}

#[cfg(feature = "parsing")]
pub mod parse {
    //! This module contains a set of exported nom parsers which can be used to
    //! parse custom grammars when used alongside the `synom` crate.
    //!
    //! Internally, `syn` uses a fork of `nom` called `synom` which resolves a
    //! persistent pitfall of using `nom` to parse Rust by eliminating the
    //! `IResult::Incomplete` variant. The `synom` crate should be used instead
    //! of `nom` when working with the parsers in this module.

    #[cfg(feature = "full")]
    pub use item::parsing::item;

    #[cfg(feature = "full")]
    pub use expr::parsing::{expr, pat, block, stmt};

    pub use lit::parsing::{lit, string, byte_string, byte, character, float, int, boolean};

    pub use ty::parsing::{ty, path};

    pub use mac::parsing::token_tree as tt;

    pub use ident::parsing::ident;

    pub use generics::parsing::lifetime;
}
<commit_msg>Re-export IResult<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(large_enum_variant))]

#[cfg(feature = "printing")]
extern crate quote;

#[cfg(feature = "parsing")]
extern crate unicode_xid;

#[cfg(feature = "parsing")]
#[macro_use]
extern crate synom;

#[cfg(feature = "aster")]
pub mod aster;

mod attr;
pub use attr::{Attribute, AttrStyle, MetaItem, NestedMetaItem};

mod constant;
pub use constant::ConstExpr;

mod data;
pub use data::{Field, Variant, VariantData, Visibility};

#[cfg(feature = "parsing")]
mod escape;

#[cfg(feature = "full")]
mod expr;
#[cfg(feature = "full")]
pub use expr::{Arm, BindingMode, Block, CaptureBy, Expr, ExprKind, FieldPat, FieldValue,
               Local, MacStmtStyle, Pat, RangeLimits, Stmt};

mod generics;
pub use generics::{Generics, Lifetime, LifetimeDef, TraitBoundModifier, TyParam, TyParamBound,
                   WhereBoundPredicate, WhereClause, WhereEqPredicate, WherePredicate,
                   WhereRegionPredicate};
#[cfg(feature = "printing")]
pub use generics::{ImplGenerics, Turbofish, TyGenerics};

mod ident;
pub use ident::Ident;

#[cfg(feature = "full")]
mod item;
#[cfg(feature = "full")]
pub use item::{Constness, Defaultness, FnArg, FnDecl, ForeignItemKind, ForeignItem, ForeignMod,
               ImplItem, ImplItemKind, ImplPolarity, Item, ItemKind, MethodSig, PathListItem,
               TraitItem, TraitItemKind, ViewPath};

#[cfg(feature = "full")]
mod krate;
#[cfg(feature = "full")]
pub use krate::Crate;

mod lit;
pub use lit::{FloatTy, IntTy, Lit, StrStyle};
#[cfg(feature = "parsing")]
pub use lit::{ByteStrLit, FloatLit, IntLit, StrLit};

mod mac;
pub use mac::{BinOpToken, DelimToken, Delimited, Mac, Token, TokenTree};

mod derive;
pub use derive::{Body, DeriveInput};
// Deprecated. Use `DeriveInput` instead.
#[doc(hidden)]
pub type MacroInput = DeriveInput;

mod op;
pub use op::{BinOp, UnOp};

mod ty;
pub use ty::{Abi, AngleBracketedParameterData, BareFnArg, BareFnTy, FunctionRetTy, MutTy,
             Mutability, ParenthesizedParameterData, Path, PathParameters, PathSegment,
             PolyTraitRef, QSelf, Ty, TypeBinding, Unsafety};

#[cfg(feature = "visit")]
pub mod visit;

#[cfg(feature = "fold")]
pub mod fold;

#[cfg(feature = "parsing")]
pub use parsing::*;

#[cfg(feature = "parsing")]
mod parsing {
    use super::*;
    use {derive, generics, ident, mac, ty};
    use synom::{space, IResult};

    #[cfg(feature = "full")]
    use {expr, item, krate};

    pub fn parse_derive_input(input: &str) -> Result<DeriveInput, String> {
        unwrap("derive input", derive::parsing::derive_input, input)
    }

    #[cfg(feature = "full")]
    pub fn parse_crate(input: &str) -> Result<Crate, String> {
        unwrap("crate", krate::parsing::krate, input)
    }

    #[cfg(feature = "full")]
    pub fn parse_item(input: &str) -> Result<Item, String> {
        unwrap("item", item::parsing::item, input)
    }

    #[cfg(feature = "full")]
    pub fn parse_items(input: &str) -> Result<Vec<Item>, String> {
        unwrap("items", item::parsing::items, input)
    }

    #[cfg(feature = "full")]
    pub fn parse_expr(input: &str) -> Result<Expr, String> {
        unwrap("expression", expr::parsing::expr, input)
    }

    pub fn parse_type(input: &str) -> Result<Ty, String> {
        unwrap("type", ty::parsing::ty, input)
    }

    pub fn parse_path(input: &str) -> Result<Path, String> {
        unwrap("path", ty::parsing::path, input)
    }

    pub fn parse_where_clause(input: &str) -> Result<WhereClause, String> {
        unwrap("where clause", generics::parsing::where_clause, input)
    }

    pub fn parse_token_trees(input: &str) -> Result<Vec<TokenTree>, String> {
        unwrap("token trees", mac::parsing::token_trees, input)
    }

    pub fn parse_ident(input: &str) -> Result<Ident, String> {
        unwrap("identifier", ident::parsing::ident, input)
    }

    pub fn parse_ty_param_bound(input: &str) -> Result<TyParamBound, String> {
        unwrap("type parameter bound", generics::parsing::ty_param_bound, input)
    }

    // Deprecated. Use `parse_derive_input` instead.
    #[doc(hidden)]
    pub fn parse_macro_input(input: &str) -> Result<MacroInput, String> {
        parse_derive_input(input)
    }

    fn unwrap<T>(name: &'static str,
                 f: fn(&str) -> IResult<&str, T>,
                 input: &str)
                 -> Result<T, String> {
        match f(input) {
            IResult::Done(mut rest, t) => {
                rest = space::skip_whitespace(rest);
                if rest.is_empty() {
                    Ok(t)
                } else if rest.len() == input.len() {
                    // parsed nothing
                    Err(format!("failed to parse {}: {:?}", name, rest))
                } else {
                    Err(format!("unparsed tokens after {}: {:?}", name, rest))
                }
            }
            IResult::Error => Err(format!("failed to parse {}: {:?}", name, input)),
        }
    }
}

#[cfg(feature = "parsing")]
pub mod parse {
    //! This module contains a set of exported nom parsers which can be used to
    //! parse custom grammars when used alongside the `synom` crate.
    //!
    //! Internally, `syn` uses a fork of `nom` called `synom` which resolves a
    //! persistent pitfall of using `nom` to parse Rust by eliminating the
    //! `IResult::Incomplete` variant. The `synom` crate should be used instead
    //! of `nom` when working with the parsers in this module.

    pub use synom::IResult;

    #[cfg(feature = "full")]
    pub use item::parsing::item;

    #[cfg(feature = "full")]
    pub use expr::parsing::{expr, pat, block, stmt};

    pub use lit::parsing::{lit, string, byte_string, byte, character, float, int, boolean};

    pub use ty::parsing::{ty, path};

    pub use mac::parsing::token_tree as tt;

    pub use ident::parsing::ident;

    pub use generics::parsing::lifetime;
}
<|endoftext|>