<commit_before>//! Raw and high-level instruction abstractions

/// First register in an opcode
///
/// There are 16 registers, `V0`..`VF`
pub type Vx = u8;
/// Second register in an opcode
pub type Vy = u8;
/// Absolute memory address
///
/// Valid addresses are within `0x0` .. `0xFFF`.
pub type Addr = u16;
/// A byte
///
/// Valid values are within `0x0` .. `0xFF`.
pub type Byte = u8;
/// A nibble (hex digit)
///
/// Valid values are within `0x0` .. `0xF`.
pub type Nibble = u8;

/// Raw instruction
///
/// Helper around the raw bits, not necessarily a valid instruction.
#[derive(Copy)]
pub struct RawInstruction {
    bits: u16
}

impl RawInstruction {
    /// Creates a new raw instruction without any checks of the `bits`
    pub fn new(bits: u16) -> RawInstruction {
        RawInstruction{ bits: bits }
    }

    /// The *raw bits*
    #[allow(dead_code)]
    pub fn bits(&self) -> u16 {
        self.bits
    }

    /// The *address bits* part
    pub fn addr(&self) -> Addr {
        self.bits & 0x0FFF
    }

    /// The *index of the `Vx` register* part
    pub fn x(&self) -> Vx {
        ((self.bits & 0x0F00) >> 8) as u8
    }

    /// The *index of the `Vy` register* part
    pub fn y(&self) -> Vy {
        ((self.bits & 0x00F0) >> 4) as u8
    }

    /// The *high nibble* part
    pub fn n_high(&self) -> Nibble {
        ((self.bits & 0xF000) >> 12) as u8
    }

    /// The *low nibble* part
    pub fn n_low(&self) -> Nibble {
        (self.bits & 0x000F) as u8
    }

    /// The *`k` byte* part
    pub fn k(&self) -> Byte {
        (self.bits & 0x00FF) as u8
    }
}

/// High-level instruction
///
/// A valid instruction that can be executed as-is.
#[derive(Copy,Debug)]
pub enum Instruction {
    Sys(Addr),              // 0nnn - SYS addr
    Clear,                  // 00E0 - CLS
    Return,                 // 00EE - RET
    Jump(Addr),             // 1nnn - JP addr
    Call(Addr),             // 2nnn - CALL addr
    SkipEqualK(Vx, Byte),   // 3xkk - SE Vx, byte
    SkipNotEqualK(Vx, Byte),// 4xkk - SNE Vx, byte
    SkipEqual(Vx, Vy),      // 5xy0 - SE Vx, Vy
    SetK(Vx, Byte),         // 6xkk - LD Vx, byte
    AddK(Vx, Byte),         // 7xkk - ADD Vx, byte
    Set(Vx, Vy),            // 8xy0 - LD Vx, Vy
    Or(Vx, Vy),             // 8xy1 - OR Vx, Vy
    And(Vx, Vy),            // 8xy2 - AND Vx, Vy
    XOr(Vx, Vy),            // 8xy3 - XOR Vx, Vy
    Add(Vx, Vy),            // 8xy4 - ADD Vx, Vy
    Sub(Vx, Vy),            // 8xy5 - SUB Vx, Vy
    ShiftRight(Vx, Vy),     // 8xy6 - SHR Vx {, Vy}
    SubInv(Vx, Vy),         // 8xy7 - SUBN Vx, Vy
    ShiftLeft(Vx, Vy),      // 8xyE - SHL Vx {, Vy}
    SkipNotEqual(Vx, Vy),   // 9xy0 - SNE Vx, Vy
    LoadI(Addr),            // Annn - LD I, addr
    LongJump(Addr),         // Bnnn - JP V0, addr
    Rand(Vx, Byte),         // Cxkk - RND Vx, byte
    Draw(Vx, Vy, Nibble),   // Dxyn - DRW Vx, Vy, nibble
    SkipPressed(Vx),        // Ex9E - SKP Vx
    SkipNotPressed(Vx),     // ExA1 - SKNP Vx
    GetTimer(Vx),           // Fx07 - LD Vx, DT
    WaitKey(Vx),            // Fx0A - LD Vx, K
    SetTimer(Vx),           // Fx15 - LD DT, Vx
    SetSoundTimer(Vx),      // Fx18 - LD ST, Vx
    AddToI(Vx),             // Fx1E - ADD I, Vx
    LoadHexGlyph(Vx),       // Fx29 - LD F, Vx
    StoreBCD(Vx),           // Fx33 - LD B, Vx
    StoreRegisters(Vx),     // Fx55 - LD [I], Vx
    LoadRegisters(Vx),      // Fx65 - LD Vx, [I]
    Unknown,
}

impl Instruction {
    /// Creates a new instruction from raw bits,
    /// or `Instruction::Unknown` if no valid match could be found
    pub fn from_raw(raw: &RawInstruction) -> Instruction {
        use self::Instruction::*;

        match raw.n_high() {
            0x0 => {
                match raw.k() {
                    0xE0 => Clear,
                    0xEE => Return,
                    _ => Sys(raw.addr())
                }
            },
            0x1 => Jump(raw.addr()),
            0x2 => Call(raw.addr()),
            0x3 => SkipEqualK(raw.x(), raw.k()),
            0x4 => SkipNotEqualK(raw.x(), raw.k()),
            0x5 => SkipEqual(raw.x(), raw.y()),
            0x6 => SetK(raw.x(), raw.k()),
            0x7 => AddK(raw.x(), raw.k()),
            0x8 => {
                match raw.n_low() {
                    0x0 => Set(raw.x(), raw.y()),
                    0x1 => Or(raw.x(), raw.y()),
                    0x2 => And(raw.x(), raw.y()),
                    0x3 => XOr(raw.x(), raw.y()),
                    0x4 => Add(raw.x(), raw.y()),
                    0x5 => Sub(raw.x(), raw.y()),
                    0x6 => ShiftRight(raw.x(), raw.y()),
                    0x7 => SubInv(raw.x(), raw.y()),
                    0xE => ShiftLeft(raw.x(), raw.y()),
                    _ => Unknown
                }
            },
            0x9 => SkipNotEqual(raw.x(), raw.y()),
            0xA => LoadI(raw.addr()),
            0xB => LongJump(raw.addr()),
            0xC => Rand(raw.x(), raw.k()),
            0xD => Draw(raw.x(), raw.y(), raw.n_low()),
            0xE => {
                match raw.k() {
                    0x9E => SkipPressed(raw.x()),
                    0xA1 => SkipNotPressed(raw.x()),
                    _ => Unknown,
                }
            },
            0xF => {
                match raw.k() {
                    0x07 => GetTimer(raw.x()),
                    0x0A => WaitKey(raw.x()),
                    0x15 => SetTimer(raw.x()),
                    0x18 => SetSoundTimer(raw.x()),
                    0x1E => AddToI(raw.x()),
                    0x29 => LoadHexGlyph(raw.x()),
                    0x33 => StoreBCD(raw.x()),
                    0x55 => StoreRegisters(raw.x()),
                    0x65 => LoadRegisters(raw.x()),
                    _ => Unknown,
                }
            }
            _ => Unknown
        }
    }
}
<commit_msg>Clarify rustdoc of `RawInstruction::x()` and `::y()`<commit_after>//! Raw and high-level instruction abstractions

/// First register in an opcode
///
/// There are 16 registers, `V0`..`VF`
pub type Vx = u8;
/// Second register in an opcode
pub type Vy = u8;
/// Absolute memory address
///
/// Valid addresses are within `0x0` .. `0xFFF`.
pub type Addr = u16;
/// A byte
///
/// Valid values are within `0x0` .. `0xFF`.
pub type Byte = u8;
/// A nibble (hex digit)
///
/// Valid values are within `0x0` .. `0xF`.
pub type Nibble = u8;

/// Raw instruction
///
/// Helper around the raw bits, not necessarily a valid instruction.
#[derive(Copy)]
pub struct RawInstruction {
    bits: u16
}

impl RawInstruction {
    /// Creates a new raw instruction without any checks of the `bits`
    pub fn new(bits: u16) -> RawInstruction {
        RawInstruction{ bits: bits }
    }

    /// The *raw bits*
    #[allow(dead_code)]
    pub fn bits(&self) -> u16 {
        self.bits
    }

    /// The *address bits* part
    pub fn addr(&self) -> Addr {
        self.bits & 0x0FFF
    }

    /// The *`Vx` register-index* part, i.e. `0xE` is `VE`
    pub fn x(&self) -> Vx {
        ((self.bits & 0x0F00) >> 8) as u8
    }

    /// The *`Vy` register-index* part, i.e. `0xE` is `VE`
    pub fn y(&self) -> Vy {
        ((self.bits & 0x00F0) >> 4) as u8
    }

    /// The *high nibble* part
    pub fn n_high(&self) -> Nibble {
        ((self.bits & 0xF000) >> 12) as u8
    }

    /// The *low nibble* part
    pub fn n_low(&self) -> Nibble {
        (self.bits & 0x000F) as u8
    }

    /// The *`k` byte* part
    pub fn k(&self) -> Byte {
        (self.bits & 0x00FF) as u8
    }
}

/// High-level instruction
///
/// A valid instruction that can be executed as-is.
#[derive(Copy,Debug)]
pub enum Instruction {
    Sys(Addr),              // 0nnn - SYS addr
    Clear,                  // 00E0 - CLS
    Return,                 // 00EE - RET
    Jump(Addr),             // 1nnn - JP addr
    Call(Addr),             // 2nnn - CALL addr
    SkipEqualK(Vx, Byte),   // 3xkk - SE Vx, byte
    SkipNotEqualK(Vx, Byte),// 4xkk - SNE Vx, byte
    SkipEqual(Vx, Vy),      // 5xy0 - SE Vx, Vy
    SetK(Vx, Byte),         // 6xkk - LD Vx, byte
    AddK(Vx, Byte),         // 7xkk - ADD Vx, byte
    Set(Vx, Vy),            // 8xy0 - LD Vx, Vy
    Or(Vx, Vy),             // 8xy1 - OR Vx, Vy
    And(Vx, Vy),            // 8xy2 - AND Vx, Vy
    XOr(Vx, Vy),            // 8xy3 - XOR Vx, Vy
    Add(Vx, Vy),            // 8xy4 - ADD Vx, Vy
    Sub(Vx, Vy),            // 8xy5 - SUB Vx, Vy
    ShiftRight(Vx, Vy),     // 8xy6 - SHR Vx {, Vy}
    SubInv(Vx, Vy),         // 8xy7 - SUBN Vx, Vy
    ShiftLeft(Vx, Vy),      // 8xyE - SHL Vx {, Vy}
    SkipNotEqual(Vx, Vy),   // 9xy0 - SNE Vx, Vy
    LoadI(Addr),            // Annn - LD I, addr
    LongJump(Addr),         // Bnnn - JP V0, addr
    Rand(Vx, Byte),         // Cxkk - RND Vx, byte
    Draw(Vx, Vy, Nibble),   // Dxyn - DRW Vx, Vy, nibble
    SkipPressed(Vx),        // Ex9E - SKP Vx
    SkipNotPressed(Vx),     // ExA1 - SKNP Vx
    GetTimer(Vx),           // Fx07 - LD Vx, DT
    WaitKey(Vx),            // Fx0A - LD Vx, K
    SetTimer(Vx),           // Fx15 - LD DT, Vx
    SetSoundTimer(Vx),      // Fx18 - LD ST, Vx
    AddToI(Vx),             // Fx1E - ADD I, Vx
    LoadHexGlyph(Vx),       // Fx29 - LD F, Vx
    StoreBCD(Vx),           // Fx33 - LD B, Vx
    StoreRegisters(Vx),     // Fx55 - LD [I], Vx
    LoadRegisters(Vx),      // Fx65 - LD Vx, [I]
    Unknown,
}

impl Instruction {
    /// Creates a new instruction from raw bits,
    /// or `Instruction::Unknown` if no valid match could be found
    pub fn from_raw(raw: &RawInstruction) -> Instruction {
        use self::Instruction::*;

        match raw.n_high() {
            0x0 => {
                match raw.k() {
                    0xE0 => Clear,
                    0xEE => Return,
                    _ => Sys(raw.addr())
                }
            },
            0x1 => Jump(raw.addr()),
            0x2 => Call(raw.addr()),
            0x3 => SkipEqualK(raw.x(), raw.k()),
            0x4 => SkipNotEqualK(raw.x(), raw.k()),
            0x5 => SkipEqual(raw.x(), raw.y()),
            0x6 => SetK(raw.x(), raw.k()),
            0x7 => AddK(raw.x(), raw.k()),
            0x8 => {
                match raw.n_low() {
                    0x0 => Set(raw.x(), raw.y()),
                    0x1 => Or(raw.x(), raw.y()),
                    0x2 => And(raw.x(), raw.y()),
                    0x3 => XOr(raw.x(), raw.y()),
                    0x4 => Add(raw.x(), raw.y()),
                    0x5 => Sub(raw.x(), raw.y()),
                    0x6 => ShiftRight(raw.x(), raw.y()),
                    0x7 => SubInv(raw.x(), raw.y()),
                    0xE => ShiftLeft(raw.x(), raw.y()),
                    _ => Unknown
                }
            },
            0x9 => SkipNotEqual(raw.x(), raw.y()),
            0xA => LoadI(raw.addr()),
            0xB => LongJump(raw.addr()),
            0xC => Rand(raw.x(), raw.k()),
            0xD => Draw(raw.x(), raw.y(), raw.n_low()),
            0xE => {
                match raw.k() {
                    0x9E => SkipPressed(raw.x()),
                    0xA1 => SkipNotPressed(raw.x()),
                    _ => Unknown,
                }
            },
            0xF => {
                match raw.k() {
                    0x07 => GetTimer(raw.x()),
                    0x0A => WaitKey(raw.x()),
                    0x15 => SetTimer(raw.x()),
                    0x18 => SetSoundTimer(raw.x()),
                    0x1E => AddToI(raw.x()),
                    0x29 => LoadHexGlyph(raw.x()),
                    0x33 => StoreBCD(raw.x()),
                    0x55 => StoreRegisters(raw.x()),
                    0x65 => LoadRegisters(raw.x()),
                    _ => Unknown,
                }
            }
            _ => Unknown
        }
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate wasm_ast;

use byteorder::{ByteOrder, LittleEndian};

use std::iter::repeat;

use wasm_ast::{BinOp, Expr, UnaryOp};
use wasm_ast::BinOp::{Add, And, DivS, DivU, Eq, GeS, GeU, GtS, GtU, LeS, LeU, LtS, LtU};
use wasm_ast::BinOp::{Mul, Ne, Or, RemS, RemU, RotL, RotR, Shl, ShrS, ShrU, Sub, Xor};
use wasm_ast::Const::{F32Const, F64Const, I32Const, I64Const};
use wasm_ast::Expr::{BinOpExpr, ConstExpr, GetLocalExpr, GrowMemoryExpr, IfThenExpr, IfThenElseExpr, LoadExpr, NopExpr, SetLocalExpr, StoreExpr, UnaryOpExpr};
use wasm_ast::Typ::{F32, F64, I32, I64};
use wasm_ast::UnaryOp::{Clz, Ctz, Popcnt, Eqz};

trait Interpreter<T> {

    fn interpret_binop(&self, op: &BinOp, lhs: T, rhs: T) -> T;

    fn interpret_unop(&self, op: &UnaryOp, arg: T) -> T;

    fn interpret_f32(&self, _: f32) -> T {
        panic!("Type error.")
    }

    fn interpret_f64(&self, _: f64) -> T {
        panic!("Type error.")
    }

    fn interpret_i32(&self, _: u32) -> T {
        panic!("Type error.")
    }

    fn interpret_i64(&self, _: u64) -> T {
        panic!("Type error.")
    }

    fn from_u64(&self, _: u64) -> T;

    fn to_u64(&self, _: T) -> u64;

    fn interpret_expr(&mut self, expr: &Expr, locals: &mut[u64], heap: &mut Vec<u8>) -> T
        where Self: Interpreter<f32> + Interpreter<f64> + Interpreter<u32> + Interpreter<u64>,
              T: Copy,
    {
        // NOTE: currently only handling the control flow that can be dealt with in direct style.
        // More sophisticated control flow will require a technique for handling a CFG,
        // e.g. functional SSA.
        match expr {
            &BinOpExpr(_, ref op, ref lhs, ref rhs) => {
                let lhs = self.interpret_expr(lhs, locals, heap);
                let rhs = self.interpret_expr(rhs, locals, heap);
                self.interpret_binop(op, lhs, rhs)
            },
            &ConstExpr(F32Const(value)) => self.interpret_f32(value),
            &ConstExpr(F64Const(value)) => self.interpret_f64(value),
            &ConstExpr(I32Const(value)) => self.interpret_i32(value),
            &ConstExpr(I64Const(value)) => self.interpret_i64(value),
            &GetLocalExpr(ref var) => self.from_u64(locals[var.position]),
            &GrowMemoryExpr(ref ext) => {
                let result: u32 = heap.len() as u32;
                let ext: u32 = self.interpret_expr(ext, locals, heap);
                heap.extend(repeat(0).take(ext as usize));
                self.interpret_i32(result)
            },
            &IfThenExpr(ref cond, ref true_branch) => {
                let cond: u32 = self.interpret_expr(cond, locals, heap);
                if cond == 0 {
                    self.from_u64(0)
                } else {
                    self.interpret_expr(true_branch, locals, heap)
                }
            },
            &IfThenElseExpr(ref cond, ref true_branch, ref false_branch) => {
                let cond: u32 = self.interpret_expr(cond, locals, heap);
                if cond == 0 {
                    self.interpret_expr(false_branch, locals, heap)
                } else {
                    self.interpret_expr(true_branch, locals, heap)
                }
            },
            &LoadExpr(F32, ref addr) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: f32 = LittleEndian::read_f32(&heap[addr as usize..]);
                self.interpret_f32(value)
            },
            &LoadExpr(F64, ref addr) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: f64 = LittleEndian::read_f64(&heap[addr as usize..]);
                self.interpret_f64(value)
            },
            &LoadExpr(I32, ref addr) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: u32 = LittleEndian::read_u32(&heap[addr as usize..]);
                self.interpret_i32(value)
            },
            &LoadExpr(I64, ref addr) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: u64 = LittleEndian::read_u64(&heap[addr as usize..]);
                self.interpret_i64(value)
            },
            &NopExpr => self.from_u64(0),
            &SetLocalExpr(ref var, ref value) => {
                let value: T = self.interpret_expr(value, locals, heap);
                locals[var.position] = self.to_u64(value);
                value
            },
            &StoreExpr(F32, ref addr, ref value) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: f32 = self.interpret_expr(value, locals, heap);
                LittleEndian::write_f32(&mut heap[addr as usize..], value);
                self.interpret_f32(value)
            },
            &StoreExpr(F64, ref addr, ref value) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: f64 = self.interpret_expr(value, locals, heap);
                LittleEndian::write_f64(&mut heap[addr as usize..], value);
                self.interpret_f64(value)
            },
            &StoreExpr(I32, ref addr, ref value) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: u32 = self.interpret_expr(value, locals, heap);
                LittleEndian::write_u32(&mut heap[addr as usize..], value);
                self.interpret_i32(value)
            },
            &StoreExpr(I64, ref addr, ref value) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: u64 = self.interpret_expr(value, locals, heap);
                LittleEndian::write_u64(&mut heap[addr as usize..], value);
                self.interpret_i64(value)
            },
            &UnaryOpExpr(_, ref op, ref arg) => {
                let arg = self.interpret_expr(arg, locals, heap);
                self.interpret_unop(op, arg)
            },
       }
    }

}

pub struct Program;

impl Interpreter<u32> for Program {

    fn interpret_binop(&self, op: &BinOp, lhs: u32, rhs: u32) -> u32 {
        match op {
            &Add => (lhs.wrapping_add(rhs)),
            &And => (lhs & rhs),
            &DivU => (lhs / rhs),
            &DivS => ((lhs as i32) / (rhs as i32)) as u32,
            &Eq => (lhs == rhs) as u32,
            &GeS => ((lhs as i32) >= (rhs as i32)) as u32,
            &GeU => (lhs >= rhs) as u32,
            &GtS => ((lhs as i32) > (rhs as i32)) as u32,
            &GtU => (lhs > rhs) as u32,
            &LeS => ((lhs as i32) <= (rhs as i32)) as u32,
            &LeU => (lhs <= rhs) as u32,
            &LtS => ((lhs as i32) < (rhs as i32)) as u32,
            &LtU => (lhs < rhs) as u32,
            &Mul => (lhs.wrapping_mul(rhs)),
            &Ne => (lhs != rhs) as u32,
            &Or => (lhs | rhs),
            &RemS => ((lhs as i32) % (rhs as i32)) as u32,
            &RemU => (lhs % rhs),
            &RotL => (lhs.rotate_left(rhs)),
            &RotR => (lhs.rotate_right(rhs)),
            &Shl => (lhs.wrapping_shl(rhs)),
            &ShrS => ((lhs as i32).wrapping_shr(rhs)) as u32,
            &ShrU => (lhs.wrapping_shr(rhs)),
            &Sub => (lhs.wrapping_sub(rhs)),
            &Xor => (lhs ^ rhs),
        }
    }

    fn interpret_unop(&self, op: &UnaryOp, arg: u32) -> u32 {
        match op {
            &Clz => arg.leading_zeros(),
            &Ctz => arg.trailing_zeros(),
            &Popcnt => arg.count_ones(),
            &Eqz => (arg == 0) as u32,
        }
    }

    fn interpret_i32(&self, value: u32) -> u32 {
        value
    }

    fn from_u64(&self, value: u64) -> u32 {
        value as u32
    }

    fn to_u64(&self, value: u32) -> u64 {
        value as u64
    }

}
<commit_msg>Renaming functions.<commit_after>extern crate byteorder;
extern crate wasm_ast;

use byteorder::{ByteOrder, LittleEndian};

use std::iter::repeat;
use std::default::Default;

use wasm_ast::{BinOp, Expr, UnaryOp};
use wasm_ast::BinOp::{Add, And, DivS, DivU, Eq, GeS, GeU, GtS, GtU, LeS, LeU, LtS, LtU};
use wasm_ast::BinOp::{Mul, Ne, Or, RemS, RemU, RotL, RotR, Shl, ShrS, ShrU, Sub, Xor};
use wasm_ast::Const::{F32Const, F64Const, I32Const, I64Const};
use wasm_ast::Expr::{BinOpExpr, ConstExpr, GetLocalExpr, GrowMemoryExpr, IfThenExpr, IfThenElseExpr, LoadExpr, NopExpr, SetLocalExpr, StoreExpr, UnaryOpExpr};
use wasm_ast::Typ::{F32, F64, I32, I64};
use wasm_ast::UnaryOp::{Clz, Ctz, Popcnt, Eqz};

trait Interpreter<T> {

    fn interpret_binop(&self, op: &BinOp, lhs: T, rhs: T) -> T;

    fn interpret_unop(&self, op: &UnaryOp, arg: T) -> T;

    fn from_f32(&self, _: f32) -> T {
        panic!("Type error.")
    }

    fn from_f64(&self, _: f64) -> T {
        panic!("Type error.")
    }

    fn from_i32(&self, _: u32) -> T {
        panic!("Type error.")
    }

    fn from_i64(&self, _: u64) -> T {
        panic!("Type error.")
    }

    fn from_raw(&self, _: u64) -> T;

    fn to_raw(&self, _: T) -> u64;

    fn interpret_expr(&mut self, expr: &Expr, locals: &mut[u64], heap: &mut Vec<u8>) -> T
        where Self: Interpreter<f32> + Interpreter<f64> + Interpreter<u32> + Interpreter<u64>,
              T: Copy + Default,
    {
        // NOTE: currently only handling the control flow that can be dealt with in direct style.
        // More sophisticated control flow will require a technique for handling a CFG,
        // e.g. functional SSA.
        match expr {
            &BinOpExpr(_, ref op, ref lhs, ref rhs) => {
                let lhs = self.interpret_expr(lhs, locals, heap);
                let rhs = self.interpret_expr(rhs, locals, heap);
                self.interpret_binop(op, lhs, rhs)
            },
            &ConstExpr(F32Const(value)) => self.from_f32(value),
            &ConstExpr(F64Const(value)) => self.from_f64(value),
            &ConstExpr(I32Const(value)) => self.from_i32(value),
            &ConstExpr(I64Const(value)) => self.from_i64(value),
            &GetLocalExpr(ref var) => self.from_raw(locals[var.position]),
            &GrowMemoryExpr(ref ext) => {
                let result: u32 = heap.len() as u32;
                let ext: u32 = self.interpret_expr(ext, locals, heap);
                heap.extend(repeat(0).take(ext as usize));
                self.from_i32(result)
            },
            &IfThenExpr(ref cond, ref true_branch) => {
                let cond: u32 = self.interpret_expr(cond, locals, heap);
                if cond == 0 {
                    T::default()
                } else {
                    self.interpret_expr(true_branch, locals, heap)
                }
            },
            &IfThenElseExpr(ref cond, ref true_branch, ref false_branch) => {
                let cond: u32 = self.interpret_expr(cond, locals, heap);
                if cond == 0 {
                    self.interpret_expr(false_branch, locals, heap)
                } else {
                    self.interpret_expr(true_branch, locals, heap)
                }
            },
            &LoadExpr(F32, ref addr) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: f32 = LittleEndian::read_f32(&heap[addr as usize..]);
                self.from_f32(value)
            },
            &LoadExpr(F64, ref addr) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: f64 = LittleEndian::read_f64(&heap[addr as usize..]);
                self.from_f64(value)
            },
            &LoadExpr(I32, ref addr) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: u32 = LittleEndian::read_u32(&heap[addr as usize..]);
                self.from_i32(value)
            },
            &LoadExpr(I64, ref addr) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: u64 = LittleEndian::read_u64(&heap[addr as usize..]);
                self.from_i64(value)
            },
            &NopExpr => T::default(),
            &SetLocalExpr(ref var, ref value) => {
                let value: T = self.interpret_expr(value, locals, heap);
                locals[var.position] = self.to_raw(value);
                value
            },
            &StoreExpr(F32, ref addr, ref value) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: f32 = self.interpret_expr(value, locals, heap);
                LittleEndian::write_f32(&mut heap[addr as usize..], value);
                self.from_f32(value)
            },
            &StoreExpr(F64, ref addr, ref value) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: f64 = self.interpret_expr(value, locals, heap);
                LittleEndian::write_f64(&mut heap[addr as usize..], value);
                self.from_f64(value)
            },
            &StoreExpr(I32, ref addr, ref value) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: u32 = self.interpret_expr(value, locals, heap);
                LittleEndian::write_u32(&mut heap[addr as usize..], value);
                self.from_i32(value)
            },
            &StoreExpr(I64, ref addr, ref value) => {
                let addr: u32 = self.interpret_expr(addr, locals, heap);
                let value: u64 = self.interpret_expr(value, locals, heap);
                LittleEndian::write_u64(&mut heap[addr as usize..], value);
                self.from_i64(value)
            },
            &UnaryOpExpr(_, ref op, ref arg) => {
                let arg = self.interpret_expr(arg, locals, heap);
                self.interpret_unop(op, arg)
            },
       }
    }

}

pub struct Program;

impl Interpreter<u32> for Program {

    fn interpret_binop(&self, op: &BinOp, lhs: u32, rhs: u32) -> u32 {
        match op {
            &Add => (lhs.wrapping_add(rhs)),
            &And => (lhs & rhs),
            &DivU => (lhs / rhs),
            &DivS => ((lhs as i32) / (rhs as i32)) as u32,
            &Eq => (lhs == rhs) as u32,
            &GeS => ((lhs as i32) >= (rhs as i32)) as u32,
            &GeU => (lhs >= rhs) as u32,
            &GtS => ((lhs as i32) > (rhs as i32)) as u32,
            &GtU => (lhs > rhs) as u32,
            &LeS => ((lhs as i32) <= (rhs as i32)) as u32,
            &LeU => (lhs <= rhs) as u32,
            &LtS => ((lhs as i32) < (rhs as i32)) as u32,
            &LtU => (lhs < rhs) as u32,
            &Mul => (lhs.wrapping_mul(rhs)),
            &Ne => (lhs != rhs) as u32,
            &Or => (lhs | rhs),
            &RemS => ((lhs as i32) % (rhs as i32)) as u32,
            &RemU => (lhs % rhs),
            &RotL => (lhs.rotate_left(rhs)),
            &RotR => (lhs.rotate_right(rhs)),
            &Shl => (lhs.wrapping_shl(rhs)),
            &ShrS => ((lhs as i32).wrapping_shr(rhs)) as u32,
            &ShrU => (lhs.wrapping_shr(rhs)),
            &Sub => (lhs.wrapping_sub(rhs)),
            &Xor => (lhs ^ rhs),
        }
    }

    fn interpret_unop(&self, op: &UnaryOp, arg: u32) -> u32 {
        match op {
            &Clz => arg.leading_zeros(),
            &Ctz => arg.trailing_zeros(),
            &Popcnt => arg.count_ones(),
            &Eqz => (arg == 0) as u32,
        }
    }

    fn from_i32(&self, value: u32) -> u32 {
        value
    }

    fn from_raw(&self, value: u64) -> u32 {
        value as u32
    }

    fn to_raw(&self, value: u32) -> u64 {
        value as u64
    }

}
<|endoftext|>


<commit_before>extern crate libloading;
extern crate rand;
extern crate test_server;

use libloading::{Library, Symbol};
use std::{env, str};
use std::u16::MAX;
use test_server::hyper;

#[cfg(target_os = "windows")]
const LIB_PATH: &str = "../../target/debug/ctehxk2.dll";
#[cfg(target_os = "linux")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.so";
#[cfg(target_os = "macos")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.dylib";

#[test]
fn has_ct_api_functions() {
    let server = test_server::serve(Some(String::from("127.0.0.1:65432")));
    env::set_var("K2_BASE_URL", "http://127.0.0.1:65432");

    match Library::new(LIB_PATH) {
        Ok(lib) => {
            let init: Symbol<unsafe extern "system" fn(u16, u16) -> i8> =
                unsafe { lib.get(b"CT_init").unwrap() };

            let data: Symbol<
                unsafe extern "system" fn(u16, *mut u8, *mut u8, u16, *const u8, *mut u16, *mut u8)
                    -> i8,
            > = unsafe { lib.get(b"CT_data").unwrap() };

            let close: Symbol<unsafe extern "system" fn(u16) -> i8> =
                unsafe { lib.get(b"CT_close").unwrap() };

            let ctn = rand::random::<u16>();
            let pn = rand::random::<u16>();
            let mut dad = rand::random::<u8>();
            let mut sad = rand::random::<u8>();

            let commands: [u8; 1] = [rand::random::<u8>(); 1];
            let commands_ptr: *const u8 = &commands[0];
            let lenc: u16 = commands.len() as u16;

            let mut response: [u8; MAX as usize] = [rand::random::<u8>(); MAX as usize];
            let response_ptr: *mut u8 = &mut response[0];
            let mut lenr: u16 = response.len() as u16;

            unsafe {
                server.reply().status(hyper::Ok).body("0");

                assert_eq!(0, init(ctn, pn));

                server.reply().status(hyper::Ok).body(
                    "{\"dad\":1,\"sad\":1,\"lenr\":5,\"response\":\"AQIDBAU=\",\"responseCode\":0}",
                );

                assert_eq!(
                    0,
                    data(
                        ctn,
                        &mut dad,
                        &mut sad,
                        lenc,
                        commands_ptr,
                        &mut lenr,
                        response_ptr,
                    )
                );

                server.reply().status(hyper::Ok).body("0");

                assert_eq!(0, close(ctn));
            }
        }
        _ => assert!(false, format!("loading library from {}", LIB_PATH)),
    }
}
<commit_msg>use unsafe block only to call lib functions<commit_after>extern crate libloading;
extern crate rand;
extern crate test_server;

use libloading::{Library, Symbol};
use std::{env, str};
use std::u16::MAX;
use test_server::hyper;

#[cfg(target_os = "windows")]
const LIB_PATH: &str = "../../target/debug/ctehxk2.dll";
#[cfg(target_os = "linux")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.so";
#[cfg(target_os = "macos")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.dylib";

#[test]
fn has_ct_api_functions() {
    let server = test_server::serve(Some(String::from("127.0.0.1:65432")));
    env::set_var("K2_BASE_URL", "http://127.0.0.1:65432");

    match Library::new(LIB_PATH) {
        Ok(lib) => {
            let init: Symbol<unsafe extern "system" fn(u16, u16) -> i8> =
                unsafe { lib.get(b"CT_init").unwrap() };

            let data: Symbol<
                unsafe extern "system" fn(u16, *mut u8, *mut u8, u16, *const u8, *mut u16, *mut u8)
                    -> i8,
            > = unsafe { lib.get(b"CT_data").unwrap() };

            let close: Symbol<unsafe extern "system" fn(u16) -> i8> =
                unsafe { lib.get(b"CT_close").unwrap() };

            let ctn = rand::random::<u16>();
            let pn = rand::random::<u16>();
            let mut dad = rand::random::<u8>();
            let mut sad = rand::random::<u8>();

            let commands: [u8; 1] = [rand::random::<u8>(); 1];
            let commands_ptr: *const u8 = &commands[0];
            let lenc: u16 = commands.len() as u16;

            let mut response: [u8; MAX as usize] = [rand::random::<u8>(); MAX as usize];
            let response_ptr: *mut u8 = &mut response[0];
            let mut lenr: u16 = response.len() as u16;

            server.reply().status(hyper::Ok).body("0");
            let init_response = unsafe { init(ctn, pn) };
            assert_eq!(0, init_response);

            // response for data
            server.reply().status(hyper::Ok).body(
                "{\"dad\":1,\"sad\":1,\"lenr\":5,\"response\":\"AQIDBAU=\",\"responseCode\":0}",
            );
            let data_response = unsafe {
                data(
                    ctn,
                    &mut dad,
                    &mut sad,
                    lenc,
                    commands_ptr,
                    &mut lenr,
                    response_ptr,
                )
            };
            assert_eq!(0, data_response);

            server.reply().status(hyper::Ok).body("0");
            let close_response = unsafe { close(ctn) };
            assert_eq!(0, close_response);
        }
        _ => assert!(false, format!("loading library from {}", LIB_PATH)),
    }
}
<|endoftext|>


<commit_before>// option1.rs
// Make me compile! Execute `rustlings hint option1` for hints

// I AM NOT DONE

// you can modify anything EXCEPT for this function's sig
fn print_number(maybe_number: Option<u16>) {
    println!("printing: {}", maybe_number.unwrap());
}

fn main() {
    print_number(13);
    print_number(99);

    let mut numbers: [Option<u16>; 5];
    for iter in 0..5 {
        let number_to_add: u16 = {
            ((iter * 5) + 2) / (4 * 16)
        };

        numbers[iter as usize] = number_to_add;
    }
}
<commit_msg>fix(option1): Don't add only zeros to the numbers array<commit_after>// option1.rs
// Make me compile! Execute `rustlings hint option1` for hints

// I AM NOT DONE

// you can modify anything EXCEPT for this function's sig
fn print_number(maybe_number: Option<u16>) {
    println!("printing: {}", maybe_number.unwrap());
}

fn main() {
    print_number(13);
    print_number(99);

    let mut numbers: [Option<u16>; 5];
    for iter in 0..5 {
        let number_to_add: u16 = {
            ((iter * 1235) + 2) / (4 * 16)
        };

        numbers[iter as usize] = number_to_add;
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// `message!` implement structure that could be sent in exonum network.
///
/// Each message is a piece of data that is signed by creators key.
/// For now it's required to set service id as `const TYPE`, message id as `const ID`, and
/// message fixed part size as `const SIZE`.
///
/// - service id should be unique inside whole exonum.
/// - message id should be unique inside each service.
///
/// For each field, it's required to set exact position in message.
/// # Usage Example:
/// ```
/// #[macro_use] extern crate exonum;
/// # extern crate serde;
///
/// const MY_SERVICE_ID: u16 = 777;
/// const MY_NEW_MESSAGE_ID: u16 = 1;
///
/// message! {
///     struct SendTwoInteger {
///         const TYPE = MY_NEW_MESSAGE_ID;
///         const ID   = MY_SERVICE_ID;
///         const SIZE = 16;
///
///         field first: u64 [0 => 8]
///         field second: u64 [8 => 16]
///     }
/// }
///
/// # fn main() {
///     let (_, creators_key) = ::exonum::crypto::gen_keypair();
/// #    let structure = create_message(&creators_key);
/// #    println!("Debug structure = {:?}", structure);
/// # }
///
/// # fn create_message(creators_key: &::exonum::crypto::SecretKey) -> SendTwoInteger {
///     let first = 1u64;
///     let second = 2u64;
///     SendTwoInteger::new(first, second, creators_key)
/// # }
/// ```
///
/// For additionall reference about data layout see also
/// *[ `encoding` documentation](./encoding/index.html).*
///
/// `message!` internaly use `ident_count!`, be sure to add this macro to namespace.
#[macro_export]
macro_rules! message {
    (
    $(#[$attr:meta])*
    struct $name:ident {
        const TYPE = $extension:expr;
        const ID = $id:expr;
        const SIZE = $body:expr;

        $(
        $(#[$field_attr:meta])*
        field $field_name:ident : $field_type:ty [$from:expr => $to:expr]
        )*
    }) => (
        #[derive(Clone, PartialEq)]
        $(#[$attr])*
        pub struct $name {
            raw: $crate::messages::RawMessage
        }

        impl $crate::messages::Message for $name {
            fn raw(&self) -> &$crate::messages::RawMessage {
                &self.raw
            }
        }

        impl<'a> $crate::encoding::SegmentField<'a> for $name {

            fn item_size() -> $crate::encoding::Offset {
                1
            }

            fn count(&self) -> $crate::encoding::Offset {
                self.raw.len() as $crate::encoding::Offset
            }

            fn extend_buffer(&self, buffer: &mut Vec<u8>) {
                buffer.extend_from_slice(self.raw.as_ref().as_ref())
            }

            unsafe fn from_buffer(buffer: &'a [u8],
                                    from: $crate::encoding::Offset,
                                    count: $crate::encoding::Offset) -> Self {
                let raw_message: $crate::messages::RawMessage =
                                    $crate::encoding::SegmentField::from_buffer(buffer,
                                                                from,
                                                                count);
                $crate::messages::FromRaw::from_raw(raw_message).unwrap()
            }

            fn check_data(buffer: &'a [u8],
                    from: $crate::encoding::CheckedOffset,
                    count: $crate::encoding::CheckedOffset,
                    latest_segment: $crate::encoding::CheckedOffset)
              -> $crate::encoding::Result {
                let latest_segment_origin = <$crate::messages::RawMessage as
                                $crate::encoding::SegmentField>::check_data(buffer,
                                                                from,
                                                                count,
                                                                latest_segment)?;
                // TODO: remove this allication,
                // by allowing creating message from borrowed data
                let raw_message: $crate::messages::RawMessage =
                                    unsafe { $crate::encoding::SegmentField::from_buffer(buffer,
                                                                from.unchecked_offset(),
                                                                count.unchecked_offset())};
                let _: $name = $crate::messages::FromRaw::from_raw(raw_message)?;
                Ok(latest_segment_origin)
            }
        }

        impl $crate::messages::FromRaw for $name {
            fn from_raw(raw: $crate::messages::RawMessage)
                -> Result<$name, $crate::encoding::Error> {
                let min_message_size = $body as usize
                            + $crate::messages::HEADER_LENGTH as usize
                            + $crate::crypto::SIGNATURE_LENGTH as usize;
                if raw.len() < min_message_size {
                    return Err($crate::encoding::Error::UnexpectedlyShortPayload {
                        actual_size: raw.len() as $crate::encoding::Offset,
                        minimum_size: min_message_size as $crate::encoding::Offset,
                    });
                }

                let body_len = <Self>::check_fields(&raw)?;

                if body_len.unchecked_offset() as usize +
                    $crate::crypto::SIGNATURE_LENGTH as usize != raw.len()  {
                   return Err("Incorrect raw message length.".into())
                }

                Ok($name { raw: raw })
            }
        }
        impl $name {
            #[cfg_attr(feature="cargo-clippy", allow(too_many_arguments))]
            /// Creates messsage and sign it.
            #[allow(unused_mut)]
            pub fn new($($field_name: $field_type,)*
                       secret_key: &$crate::crypto::SecretKey) -> $name {
                use $crate::messages::{RawMessage, MessageWriter};
                check_bounds!($body, $($field_name : $field_type [$from => $to],)*);
                let mut writer = MessageWriter::new($crate::messages::PROTOCOL_MAJOR_VERSION,
                                                    $crate::messages::TEST_NETWORK_ID,
                                                    $extension, $id, $body);
                $(writer.write($field_name, $from, $to);)*
                $name { raw: RawMessage::new(writer.sign(secret_key)) }
            }

            /// Creates message and appends existing signature.
            #[cfg_attr(feature="cargo-clippy", allow(too_many_arguments))]
            #[allow(dead_code, unused_mut)]
            pub fn new_with_signature($($field_name: $field_type,)*
                       signature: &$crate::crypto::Signature) -> $name {
                use $crate::messages::{RawMessage, MessageWriter};
                check_bounds!($body, $($field_name : $field_type [$from => $to],)*);
                let mut writer = MessageWriter::new($crate::messages::PROTOCOL_MAJOR_VERSION,
                                                    $crate::messages::TEST_NETWORK_ID,
                                                    $extension, $id, $body);
                $(writer.write($field_name, $from, $to);)*
                $name { raw: RawMessage::new(writer.append_signature(signature)) }

            }

            #[allow(unused_variables)]
            fn check_fields(raw_message: &$crate::messages::RawMessage)
            -> $crate::encoding::Result {
                let latest_segment = (($body + $crate::messages::HEADER_LENGTH)
                                        as $crate::encoding::Offset).into();
                $(
                    let field_from: $crate::encoding::Offset = $from;
                    let field_to: $crate::encoding::Offset = $to;
                    let latest_segment = raw_message.check::<$field_type>(field_from.into(),
                                                    field_to.into(),
                                                    latest_segment)?;
                )*
                Ok(latest_segment)
            }

            /// Returns `message_id` useable for matching.
            #[allow(dead_code)]
            pub fn message_id() -> u16 {
                $id
            }

            /// Returns `service_id` useable for matching.
            #[allow(dead_code)]
            pub fn service_id() -> u16 {
                $extension
            }

            $(
            $(#[$field_attr])*
            pub fn $field_name(&self) -> $field_type {
                unsafe{ self.raw.read::<$field_type>($from, $to)}
            })*
        }

        impl $crate::storage::StorageValue for $name {
            fn hash(&self) -> $crate::crypto::Hash {
                $crate::messages::Message::hash(self)
            }

            fn into_bytes(self) -> Vec<u8> {
                self.raw.as_ref().as_ref().to_vec()
            }

            fn from_bytes(value: ::std::borrow::Cow<[u8]>) -> Self {
                $name {
                    raw: ::std::sync::Arc::new($crate::messages::MessageBuffer::from_vec(
                        value.into_owned()))
                }
            }
        }

        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                -> Result<(), ::std::fmt::Error> {
                fmt.debug_struct(stringify!($name))
                 $(.field(stringify!($field_name), &self.$field_name()))*
                   .finish()
            }
        }

        impl $crate::encoding::serialize::json::ExonumJson for $name {
            fn deserialize_field<B> (value: &$crate::encoding::serialize::json::reexport::Value,
                                        buffer: & mut B,
                                        from: $crate::encoding::Offset,
                                        to: $crate::encoding::Offset )
                -> Result<(), Box<::std::error::Error>>
            where B: $crate::encoding::serialize::WriteBufferWrapper
            {
                use $crate::encoding::serialize::json::ExonumJsonDeserialize;
                // deserialize full field
                let structure = <Self as ExonumJsonDeserialize>::deserialize(value)?;
                // then write it
                buffer.write(from, to, structure);
                Ok(())
            }

            #[allow(unused_mut)]
            fn serialize_field(&self)
                -> Result<$crate::encoding::serialize::json::reexport::Value,
                            Box<::std::error::Error>>
            {
                use $crate::encoding::serialize::json::reexport::Value;
                use $crate::encoding::serialize::json::reexport::Map;
                let mut body = Map::new();
                $(
                    body.insert(stringify!($field_name).to_string(),
                        self.$field_name().serialize_field()?);
                )*
                let mut structure = Map::new();
                structure.insert("body".to_string(), Value::Object(body));
                structure.insert("signature".to_string(),
                                    self.raw.signature().serialize_field()?);
                structure.insert("message_id".to_string(),
                                    self.raw.message_type().serialize_field()?);
                structure.insert("service_id".to_string(),
                                    self.raw.service_id().serialize_field()?);
                structure.insert("network_id".to_string(),
                                    self.raw.network_id().serialize_field()?);
                structure.insert("protocol_version".to_string(),
                                    self.raw.version().serialize_field()?);
                Ok(Value::Object(structure))
            }
        }

        impl $crate::encoding::serialize::json::ExonumJsonDeserialize for $name {
            #[allow(unused_imports, unused_variables, unused_mut)]
            fn deserialize(value: &$crate::encoding::serialize::json::reexport::Value)
                -> Result<Self, Box<::std::error::Error>>
            {
                use $crate::encoding::serialize::json::ExonumJson;
                use $crate::encoding::serialize::json::reexport::from_value;
                use $crate::messages::{RawMessage, MessageWriter};

                // if we could deserialize values, try append signature
                let obj = value.as_object().ok_or("Can't cast json as object.")?;

                let body = obj.get("body").ok_or("Can't get body from json.")?;

                let signature = from_value(obj.get("signature")
                                    .ok_or("Can't get signature from json")?.clone())?;
                let message_type = from_value(obj.get("message_id")
                                    .ok_or("Can't get message_type from json")?.clone())?;
                let service_id = from_value(obj.get("service_id")
                                    .ok_or("Can't get service_id from json")?.clone())?;

                let network_id = from_value(obj.get("network_id")
                                    .ok_or("Can't get network_id from json")?.clone())?;
                let protocol_version = from_value(obj.get("protocol_version")
                                        .ok_or("Can't get protocol_version from json")?.clone())?;

                if service_id != $extension {
                    return Err("service_id didn't equal real service_id.".into())
                }

                if message_type != $id {
                    return Err("message_id didn't equal real message_id.".into())
                }

                let mut writer = MessageWriter::new(protocol_version, network_id,
                                                        service_id, message_type, $body);
                let obj = body.as_object().ok_or("Can't cast body as object.")?;
                $(
                    let val = obj.get(stringify!($field_name))
                                    .ok_or("Can't get object from json.")?;
                    <$field_type as ExonumJson>::deserialize_field(val,
                                                                    &mut writer, $from, $to )?;
                )*

                Ok($name { raw: RawMessage::new(writer.append_signature(&signature)) })
            }
        }

        // TODO: Rewrite Deserialize and Serialize implementation
        impl<'de> $crate::encoding::serialize::reexport::Deserialize<'de> for $name {
            #[allow(unused_mut)]
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
                where D: $crate::encoding::serialize::reexport::Deserializer<'de>
            {
                use $crate::encoding::serialize::json::reexport::Value;
                use $crate::encoding::serialize::reexport::{DeError, Deserialize};
                let value = <Value as Deserialize>::deserialize(deserializer)?;
                <Self as $crate::encoding::serialize::json::ExonumJsonDeserialize>::deserialize(
                    &value).map_err(|_| D::Error::custom("Can not deserialize value."))
            }
        }

        impl $crate::encoding::serialize::reexport::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: $crate::encoding::serialize::reexport::Serializer
           {
               use $crate::encoding::serialize::reexport::SerError;
                use $crate::encoding::serialize::json::ExonumJson;
                self.serialize_field()
                    .map_err(|_| S::Error::custom(
                                concat!("Can not serialize structure: ", stringify!($name))))?
                    .serialize(serializer)
            }
        }

    );
}
<commit_msg>Add description of deserialization error<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// `message!` implement structure that could be sent in exonum network.
///
/// Each message is a piece of data that is signed by creators key.
/// For now it's required to set service id as `const TYPE`, message id as `const ID`, and
/// message fixed part size as `const SIZE`.
///
/// - service id should be unique inside whole exonum.
/// - message id should be unique inside each service.
///
/// For each field, it's required to set exact position in message.
/// # Usage Example:
/// ```
/// #[macro_use] extern crate exonum;
/// # extern crate serde;
///
/// const MY_SERVICE_ID: u16 = 777;
/// const MY_NEW_MESSAGE_ID: u16 = 1;
///
/// message! {
///     struct SendTwoInteger {
///         const TYPE = MY_NEW_MESSAGE_ID;
///         const ID   = MY_SERVICE_ID;
///         const SIZE = 16;
///
///         field first: u64 [0 => 8]
///         field second: u64 [8 => 16]
///     }
/// }
///
/// # fn main() {
///     let (_, creators_key) = ::exonum::crypto::gen_keypair();
/// #    let structure = create_message(&creators_key);
/// #    println!("Debug structure = {:?}", structure);
/// # }
///
/// # fn create_message(creators_key: &::exonum::crypto::SecretKey) -> SendTwoInteger {
///     let first = 1u64;
///     let second = 2u64;
///     SendTwoInteger::new(first, second, creators_key)
/// # }
/// ```
///
/// For additionall reference about data layout see also
/// *[ `encoding` documentation](./encoding/index.html).*
///
/// `message!` internaly use `ident_count!`, be sure to add this macro to namespace.
#[macro_export]
macro_rules! message {
    (
    $(#[$attr:meta])*
    struct $name:ident {
        const TYPE = $extension:expr;
        const ID = $id:expr;
        const SIZE = $body:expr;

        $(
        $(#[$field_attr:meta])*
        field $field_name:ident : $field_type:ty [$from:expr => $to:expr]
        )*
    }) => (
        #[derive(Clone, PartialEq)]
        $(#[$attr])*
        pub struct $name {
            raw: $crate::messages::RawMessage
        }

        impl $crate::messages::Message for $name {
            fn raw(&self) -> &$crate::messages::RawMessage {
                &self.raw
            }
        }

        impl<'a> $crate::encoding::SegmentField<'a> for $name {

            fn item_size() -> $crate::encoding::Offset {
                1
            }

            fn count(&self) -> $crate::encoding::Offset {
                self.raw.len() as $crate::encoding::Offset
            }

            fn extend_buffer(&self, buffer: &mut Vec<u8>) {
                buffer.extend_from_slice(self.raw.as_ref().as_ref())
            }

            unsafe fn from_buffer(buffer: &'a [u8],
                                    from: $crate::encoding::Offset,
                                    count: $crate::encoding::Offset) -> Self {
                let raw_message: $crate::messages::RawMessage =
                                    $crate::encoding::SegmentField::from_buffer(buffer,
                                                                from,
                                                                count);
                $crate::messages::FromRaw::from_raw(raw_message).unwrap()
            }

            fn check_data(buffer: &'a [u8],
                    from: $crate::encoding::CheckedOffset,
                    count: $crate::encoding::CheckedOffset,
                    latest_segment: $crate::encoding::CheckedOffset)
              -> $crate::encoding::Result {
                let latest_segment_origin = <$crate::messages::RawMessage as
                                $crate::encoding::SegmentField>::check_data(buffer,
                                                                from,
                                                                count,
                                                                latest_segment)?;
                // TODO: remove this allication,
                // by allowing creating message from borrowed data
                let raw_message: $crate::messages::RawMessage =
                                    unsafe { $crate::encoding::SegmentField::from_buffer(buffer,
                                                                from.unchecked_offset(),
                                                                count.unchecked_offset())};
                let _: $name = $crate::messages::FromRaw::from_raw(raw_message)?;
                Ok(latest_segment_origin)
            }
        }

        impl $crate::messages::FromRaw for $name {
            fn from_raw(raw: $crate::messages::RawMessage)
                -> Result<$name, $crate::encoding::Error> {
                let min_message_size = $body as usize
                            + $crate::messages::HEADER_LENGTH as usize
                            + $crate::crypto::SIGNATURE_LENGTH as usize;
                if raw.len() < min_message_size {
                    return Err($crate::encoding::Error::UnexpectedlyShortPayload {
                        actual_size: raw.len() as $crate::encoding::Offset,
                        minimum_size: min_message_size as $crate::encoding::Offset,
                    });
                }

                let body_len = <Self>::check_fields(&raw)?;

                if body_len.unchecked_offset() as usize +
                    $crate::crypto::SIGNATURE_LENGTH as usize != raw.len()  {
                   return Err("Incorrect raw message length.".into())
                }

                Ok($name { raw: raw })
            }
        }
        impl $name {
            #[cfg_attr(feature="cargo-clippy", allow(too_many_arguments))]
            /// Creates messsage and sign it.
            #[allow(unused_mut)]
            pub fn new($($field_name: $field_type,)*
                       secret_key: &$crate::crypto::SecretKey) -> $name {
                use $crate::messages::{RawMessage, MessageWriter};
                check_bounds!($body, $($field_name : $field_type [$from => $to],)*);
                let mut writer = MessageWriter::new($crate::messages::PROTOCOL_MAJOR_VERSION,
                                                    $crate::messages::TEST_NETWORK_ID,
                                                    $extension, $id, $body);
                $(writer.write($field_name, $from, $to);)*
                $name { raw: RawMessage::new(writer.sign(secret_key)) }
            }

            /// Creates message and appends existing signature.
            #[cfg_attr(feature="cargo-clippy", allow(too_many_arguments))]
            #[allow(dead_code, unused_mut)]
            pub fn new_with_signature($($field_name: $field_type,)*
                       signature: &$crate::crypto::Signature) -> $name {
                use $crate::messages::{RawMessage, MessageWriter};
                check_bounds!($body, $($field_name : $field_type [$from => $to],)*);
                let mut writer = MessageWriter::new($crate::messages::PROTOCOL_MAJOR_VERSION,
                                                    $crate::messages::TEST_NETWORK_ID,
                                                    $extension, $id, $body);
                $(writer.write($field_name, $from, $to);)*
                $name { raw: RawMessage::new(writer.append_signature(signature)) }

            }

            #[allow(unused_variables)]
            fn check_fields(raw_message: &$crate::messages::RawMessage)
            -> $crate::encoding::Result {
                let latest_segment = (($body + $crate::messages::HEADER_LENGTH)
                                        as $crate::encoding::Offset).into();
                $(
                    let field_from: $crate::encoding::Offset = $from;
                    let field_to: $crate::encoding::Offset = $to;
                    let latest_segment = raw_message.check::<$field_type>(field_from.into(),
                                                    field_to.into(),
                                                    latest_segment)?;
                )*
                Ok(latest_segment)
            }

            /// Returns `message_id` useable for matching.
            #[allow(dead_code)]
            pub fn message_id() -> u16 {
                $id
            }

            /// Returns `service_id` useable for matching.
            #[allow(dead_code)]
            pub fn service_id() -> u16 {
                $extension
            }

            $(
            $(#[$field_attr])*
            pub fn $field_name(&self) -> $field_type {
                unsafe{ self.raw.read::<$field_type>($from, $to)}
            })*
        }

        impl $crate::storage::StorageValue for $name {
            fn hash(&self) -> $crate::crypto::Hash {
                $crate::messages::Message::hash(self)
            }

            fn into_bytes(self) -> Vec<u8> {
                self.raw.as_ref().as_ref().to_vec()
            }

            fn from_bytes(value: ::std::borrow::Cow<[u8]>) -> Self {
                $name {
                    raw: ::std::sync::Arc::new($crate::messages::MessageBuffer::from_vec(
                        value.into_owned()))
                }
            }
        }

        impl ::std::fmt::Debug for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                -> Result<(), ::std::fmt::Error> {
                fmt.debug_struct(stringify!($name))
                 $(.field(stringify!($field_name), &self.$field_name()))*
                   .finish()
            }
        }

        impl $crate::encoding::serialize::json::ExonumJson for $name {
            fn deserialize_field<B> (value: &$crate::encoding::serialize::json::reexport::Value,
                                        buffer: & mut B,
                                        from: $crate::encoding::Offset,
                                        to: $crate::encoding::Offset )
                -> Result<(), Box<::std::error::Error>>
            where B: $crate::encoding::serialize::WriteBufferWrapper
            {
                use $crate::encoding::serialize::json::ExonumJsonDeserialize;
                // deserialize full field
                let structure = <Self as ExonumJsonDeserialize>::deserialize(value)?;
                // then write it
                buffer.write(from, to, structure);
                Ok(())
            }

            #[allow(unused_mut)]
            fn serialize_field(&self)
                -> Result<$crate::encoding::serialize::json::reexport::Value,
                            Box<::std::error::Error>>
            {
                use $crate::encoding::serialize::json::reexport::Value;
                use $crate::encoding::serialize::json::reexport::Map;
                let mut body = Map::new();
                $(
                    body.insert(stringify!($field_name).to_string(),
                        self.$field_name().serialize_field()?);
                )*
                let mut structure = Map::new();
                structure.insert("body".to_string(), Value::Object(body));
                structure.insert("signature".to_string(),
                                    self.raw.signature().serialize_field()?);
                structure.insert("message_id".to_string(),
                                    self.raw.message_type().serialize_field()?);
                structure.insert("service_id".to_string(),
                                    self.raw.service_id().serialize_field()?);
                structure.insert("network_id".to_string(),
                                    self.raw.network_id().serialize_field()?);
                structure.insert("protocol_version".to_string(),
                                    self.raw.version().serialize_field()?);
                Ok(Value::Object(structure))
            }
        }

        impl $crate::encoding::serialize::json::ExonumJsonDeserialize for $name {
            #[allow(unused_imports, unused_variables, unused_mut)]
            fn deserialize(value: &$crate::encoding::serialize::json::reexport::Value)
                -> Result<Self, Box<::std::error::Error>>
            {
                use $crate::encoding::serialize::json::ExonumJson;
                use $crate::encoding::serialize::json::reexport::from_value;
                use $crate::messages::{RawMessage, MessageWriter};

                // if we could deserialize values, try append signature
                let obj = value.as_object().ok_or("Can't cast json as object.")?;

                let body = obj.get("body").ok_or("Can't get body from json.")?;

                let signature = from_value(obj.get("signature")
                                    .ok_or("Can't get signature from json")?.clone())?;
                let message_type = from_value(obj.get("message_id")
                                    .ok_or("Can't get message_type from json")?.clone())?;
                let service_id = from_value(obj.get("service_id")
                                    .ok_or("Can't get service_id from json")?.clone())?;

                let network_id = from_value(obj.get("network_id")
                                    .ok_or("Can't get network_id from json")?.clone())?;
                let protocol_version = from_value(obj.get("protocol_version")
                                        .ok_or("Can't get protocol_version from json")?.clone())?;

                if service_id != $extension {
                    return Err("service_id didn't equal real service_id.".into())
                }

                if message_type != $id {
                    return Err("message_id didn't equal real message_id.".into())
                }

                let mut writer = MessageWriter::new(protocol_version, network_id,
                                                        service_id, message_type, $body);
                let obj = body.as_object().ok_or("Can't cast body as object.")?;
                $(
                    let val = obj.get(stringify!($field_name))
                                    .ok_or("Can't get object from json.")?;
                    <$field_type as ExonumJson>::deserialize_field(val,
                                                                    &mut writer, $from, $to )?;
                )*

                Ok($name { raw: RawMessage::new(writer.append_signature(&signature)) })
            }
        }

        // TODO: Rewrite Deserialize and Serialize implementation
        impl<'de> $crate::encoding::serialize::reexport::Deserialize<'de> for $name {
            #[allow(unused_mut)]
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
                where D: $crate::encoding::serialize::reexport::Deserializer<'de>
            {
                use $crate::encoding::serialize::json::reexport::Value;
                use $crate::encoding::serialize::reexport::{DeError, Deserialize};
                let value = <Value as Deserialize>::deserialize(deserializer)?;
                <Self as $crate::encoding::serialize::json::ExonumJsonDeserialize>::deserialize(
                    &value).map_err(|e| D::Error::custom(
                            format!("Can't deserialize a value: {}", e.description())))
            }
        }

        impl $crate::encoding::serialize::reexport::Serialize for $name {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: $crate::encoding::serialize::reexport::Serializer
           {
               use $crate::encoding::serialize::reexport::SerError;
                use $crate::encoding::serialize::json::ExonumJson;
                self.serialize_field()
                    .map_err(|_| S::Error::custom(
                                concat!("Can not serialize structure: ", stringify!($name))))?
                    .serialize(serializer)
            }
        }

    );
}
<|endoftext|>


<commit_before>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
pub mod metadata;
pub mod frame;
pub mod subframe;
pub mod stream;
<commit_msg>Re-export type and parser names<commit_after>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
pub mod metadata;
pub mod frame;
pub mod subframe;
pub mod stream;

pub use frame::{frame_parser, Frame};
pub use subframe::{subframe_parser, SubFrame};
<|endoftext|>


<commit_before>#[macro_use]
extern crate string_cache;
extern crate html5ever;

use std::io;
use html5ever::{Parser,parse_document};
use html5ever::driver::ParseOpts;
use html5ever::tree_builder::TreeBuilderOpts;
use html5ever::rcdom::{RcDom,Handle,Text,Element,Document};
use html5ever::tendril::TendrilSink;

fn get_text(handle: Handle) -> String {
    let node = handle.borrow();
    let mut result = String::new();
    if let Text(ref tstr) = node.node {
        result.push_str(&tstr);
    } else {
        for child in node.children.iter() {
            result.push_str(&get_text(child.clone()));
        }
    }
    result
}

fn dom_to_string(handle: Handle) -> String {
    let node = handle.borrow();
    let mut result = String::new();
    match node.node {
        Document => {},
        Element(ref name, _, ref attrs) => {
            match *name {
                qualname!(html, "html") |
                qualname!(html, "div") |
                qualname!(html, "body") => {
                    /* process children, but don't add anything */
                },
                qualname!(html, "link") |
                qualname!(html, "meta") |
                qualname!(html, "hr") |
                qualname!(html, "head") => {
                    /* Ignore the head and its children */
                    return result;
                },
                qualname!(html, "h4") |
                qualname!(html, "p") => {
                    return get_text(handle.clone());
                }
                _ => {
                    result.push_str(&format!("Unhandled element: {:?}\n", name.local));
                },
            }
          },
        Text(ref tstr) => {
            return tstr.to_string();
        }
        _ => { result.push_str(&format!("Unhandled: {:?}\n", node)); },
    }
    for child in node.children.iter() {
        result.push_str(&dom_to_string(child.clone()));
    }
    result
}

pub fn from_read<R>(mut input: R) -> String where R: io::Read {
    let opts = ParseOpts {
        tree_builder: TreeBuilderOpts {
            drop_doctype: true,
            ..Default::default()
        },
        ..Default::default()
    };
    let dom = parse_document(RcDom::default(), opts)
                   .from_utf8()
                   .read_from(&mut input)
                   .unwrap();

    dom_to_string(dom.document)
}

#[cfg(test)]
mod tests {
}
<commit_msg>WIP on simple table layout.<commit_after>#[macro_use]
extern crate string_cache;
extern crate html5ever;

use std::io;
use std::io::Write;
use html5ever::{Parser,parse_document};
use html5ever::driver::ParseOpts;
use html5ever::tree_builder::TreeBuilderOpts;
use html5ever::rcdom::{RcDom,Handle,Text,Element,Document,Comment};
use html5ever::tendril::TendrilSink;

fn get_text(handle: Handle) -> String {
    let node = handle.borrow();
    let mut result = String::new();
    if let Text(ref tstr) = node.node {
        result.push_str(&tstr);
    } else {
        for child in node.children.iter() {
            result.push_str(&get_text(child.clone()));
        }
    }
    result
}

fn dom_to_string<T:Write>(handle: Handle, err_out: &mut T, width: usize) -> String {
    let node = handle.borrow();
    let mut result = String::new();
    match node.node {
        Document => {},
        Element(ref name, _, ref attrs) => {
            match *name {
                qualname!(html, "html") |
                qualname!(html, "div") |
                qualname!(html, "span") |
                qualname!(html, "body") => {
                    /* process children, but don't add anything */
                },
                qualname!(html, "link") |
                qualname!(html, "meta") |
                qualname!(html, "hr") |
                qualname!(html, "head") => {
                    /* Ignore the head and its children */
                    return result;
                },
                qualname!(html, "h4") |
                qualname!(html, "p") => {
                    return get_text(handle.clone()) + "\n\n";
                },
                qualname!(html, "br") => {
                    result.push('\n');
                }
                qualname!(html, "table") => return table_to_string(handle.clone(), err_out, width),
                _ => {
                    write!(err_out, "Unhandled element: {:?}\n", name.local);
                },
            }
          },
        Text(ref tstr) => {
            return tstr.to_string();
        }
        Comment(_) => {},
        _ => { write!(err_out, "Unhandled: {:?}\n", node); },
    }
    for child in node.children.iter() {
        result.push_str(&dom_to_string(child.clone(), err_out, width));
    }
    result
}

#[derive(Debug)]
struct TableCell {
    content: Handle,
}

#[derive(Debug)]
struct TableRow {
    cells: Vec<TableCell>,
}

#[derive(Debug)]
struct Table {
    rows: Vec<TableRow>,
}

impl Table {
    pub fn new() -> Table {
        Table{ rows: Vec::new() }
    }
    pub fn push(&mut self, row: TableRow) {
        self.rows.push(row);
    }
    pub fn rows(&self) -> std::slice::Iter<TableRow> {
        self.rows.iter()
    }
}

impl TableRow {
    pub fn new() -> TableRow {
        TableRow{ cells: Vec::new() }
    }
    pub fn push(&mut self, cell: TableCell) {
        self.cells.push(cell);
    }
    pub fn cells(&self) -> std::slice::Iter<TableCell> {
        self.cells.iter()
    }
    pub fn num_cells(&self) -> usize {
        self.cells.len()
    }
}

impl TableCell {
    pub fn new(s: Handle) -> TableCell {
        TableCell{ content: s }
    }
    pub fn render<T:Write>(&self, width: usize, err_out: &mut T) -> String
    {
        dom_to_string(self.content.clone(), err_out, width)
    }
}

fn handle_td(handle: Handle) -> TableCell {
    TableCell::new(handle)
}

fn handle_tr<T:Write>(handle: Handle, err_out: &mut T) -> TableRow {
    let node = handle.borrow();

    let mut row = TableRow::new();

    for child in node.children.iter() {
        match child.borrow().node {
            Element(ref name, _, ref attrs) => {
                match *name {
                    qualname!(html, "td") => {
                        row.push(handle_td(child.clone()));
                    },
                    _ => println!("  [[tr child: {:?}]]", name),
                }
            },
            Comment(_) => {},
            _ => { /*result.push_str(&format!("Unhandled in table: {:?}\n", node));*/ },
        }
    }

    row
}

fn handle_tbody<T:Write>(handle: Handle, err_out: &mut T, width: usize) -> String {
    let node = handle.borrow();

    let mut table = Table::new();

    for child in node.children.iter() {
        match child.borrow().node {
            Element(ref name, _, ref attrs) => {
                match *name {
                    qualname!(html, "tr") => {
                        table.push(handle_tr(child.clone(), err_out));
                    },
                    _ => println!("  [[tbody child: {:?}]]", name),
                }
            },
            Comment(_) => {},
            _ => { /*result.push_str(&format!("Unhandled in table: {:?}\n", node));*/ },
        }
    }

    /* Now lay out the table.  Use the simple option of giving each column
     * same width.  TODO: be cleverer, and handle multi-width cells, etc. */
    let num_columns = table.rows().map(|r| r.num_cells()).max().unwrap();

    // Allow for | between columns.
    let col_width = (width - (num_columns-1))/num_columns;

    let cell_bottom: String = (0..col_width).map(|_| '-').collect::<String>() + "+";
    let rowline: String = (0..num_columns).map(|_| &cell_bottom[..]).collect::<String>() + &cell_bottom[..col_width];

    let mut result = rowline.clone();
    result.push('\n');

    for row in table.rows() {
        let formatted_cells: Vec<String> = row.cells()
                                              .map(|cell| cell.render(col_width, err_out))
                                              .collect();
        let line_sets: Vec<Vec<&str>> = formatted_cells.iter()
                                                       .map(|s| s.lines()
                                                                 .map(|line| line.trim_right())
                                                                 .collect())
                                                       .collect();
        let cell_height = line_sets.iter()
                                   .map(|v| v.len())
                                   .max().unwrap();
        for i in 0..cell_height {
            for ls in &line_sets {
                result.push_str(&format!("{: <width$}", ls.get(i).cloned().unwrap_or(""), width = col_width));
                result.push('|')
            }
        }
        result.push_str(&rowline);
        result.push('\n');
    }

    result
}

fn table_to_string<T:Write>(handle: Handle, err_out: &mut T, width: usize) -> String {
    let node = handle.borrow();
    let mut result = String::new();

    for child in node.children.iter() {
        match child.borrow().node {
            Element(ref name, _, ref attrs) => {
                match *name {
                    qualname!(html, "tbody") => return handle_tbody(child.clone(), err_out, width),
                    _ => { writeln!(err_out, "  [[table child: {:?}]]", name);},
                }
            },
            Comment(_) => {},
            _ => { /*result.push_str(&format!("Unhandled in table: {:?}\n", node));*/ },
        }
    }

    result
}

pub fn from_read<R>(mut input: R) -> String where R: io::Read {
    let opts = ParseOpts {
        tree_builder: TreeBuilderOpts {
            drop_doctype: true,
            ..Default::default()
        },
        ..Default::default()
    };
    let dom = parse_document(RcDom::default(), opts)
                   .from_utf8()
                   .read_from(&mut input)
                   .unwrap();

    dom_to_string(dom.document, &mut io::stderr(), 80)
}

#[cfg(test)]
mod tests {
}
<|endoftext|>


<commit_before>//! Native library for reading and writing the [ASPRS
//! LAS](https://www.asprs.org/committee-general/laser-las-file-format-exchange-activities.html)
//! data exchange format.
//!
//! The LAS data exchange format is designed for transmitting and storing
//! [LiDAR](https://en.wikipedia.org/wiki/Lidar) data.
//!
//! # Reading points
//!
//! Use a `Reader` to read one or more points:
//!
//! ```
//! use las::Reader;
//! let mut reader = Reader::from_path("data/1.0_0.las").unwrap();
//! // Points from `Reader::read` are provided as a `Result<Option<Point>>`
//! let point = reader.read().unwrap().unwrap();
//! // Use `.iter_mut` to iterate over points, provided as `Result<Point>`.
//! for point in reader.iter_mut() {
//!     let point = point.unwrap();
//!     let x = point.x;
//!     // etc.
//! }
//! ```
//!
//! # Writing points
//!
//! A `Writer` writes points to a `Read`. If you're comfortable with reasonable default settings,
//! use a `Writer` directly:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Point, Writer};
//! let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
//! let mut point: Point = Default::default();
//! point.x = 1.;
//! // etc.
//! writer.write(&point).unwrap();
//! ```
//!
//! In order to configure the `Writer`, i.e. by setting the LAS version or point format, use a
//! `Builder`:
//!
//! ```
//! # use std::io::Cursor;
//! use las::Builder;
//! let mut builder = Builder::new();
//! builder.point_format = 1.into();
//! builder.version = (1, 2).into();
//! let writer = builder.writer(Cursor::new(Vec::new())).unwrap();
//! ```
//!
//! Convenience methods are provided for writing LAS data to a file:
//!
//! ```
//! # use las::{Writer, Builder};
//! // Use the default writer:
//! let writer = Writer::from_path("/dev/null").unwrap();
//! // Allows configuration before open:
//! let writer = Builder::new().writer_from_path("/dev/null").unwrap();
//! ```
//!
//! A `Writer` implements `Drop`, which it uses to re-write the header with the point count and
//! other metadata when the `Writer` goes out of scope. If this header re-write fails, an error
//! will be printed to the logs but the thread will not panic. If is unacceptable, you can close
//! the `Writer` yourself and prevent any re-writing on drop:
//!
//! ```
//! # use std::io::Cursor;
//! # use las::Writer;
//! {
//!     let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
//!     writer.close().unwrap();
//! } // `close` is not called
//! ```

#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unstable_features,
        unused_import_braces, unused_qualifications)]

extern crate byteorder;
extern crate chrono;
#[macro_use]
extern crate log;

pub mod global_encoding;
pub mod point;
pub mod utils;

mod builder;
mod error;
mod header;
mod reader;
mod version;
mod vlr;
mod writer;

pub use builder::Builder;
pub use error::Error;
pub use header::Header;
pub use point::Point;
pub use reader::Reader;
pub use writer::Writer;
pub use version::Version;
pub use vlr::Vlr;

/// Crate-specific result type.
pub type Result<T> = std::result::Result<T, Error>;
<commit_msg>Update some library-level documentation<commit_after>//! Native library for reading and writing the [ASPRS
//! LAS](https://www.asprs.org/committee-general/laser-las-file-format-exchange-activities.html)
//! data exchange format.
//!
//! The LAS data exchange format is designed for transmitting and storing
//! [LiDAR](https://en.wikipedia.org/wiki/Lidar) data.
//!
//! # Reading points
//!
//! Use a `Reader` to read one or more points:
//!
//! ```
//! use las::Reader;
//! let mut reader = Reader::from_path("data/1.0_0.las").unwrap();
//!
//! // Points from `Reader::read` are provided as a `Result<Option<Point>>`
//! let point = reader.read().unwrap().unwrap();
//!
//! // Use `.iter_mut` to iterate over points, provided as `Result<Point>`.
//! for point in reader.iter_mut() {
//!     let point = point.unwrap();
//!     let x = point.x;
//!     // etc.
//! }
//! ```
//!
//! # Writing points
//!
//! A `Writer` writes points to a `Read`. If you're comfortable with reasonable default settings,
//! use a `Writer` directly:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Point, Writer};
//! let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
//! let mut point: Point = Default::default();
//! point.x = 1.;
//! writer.write(&point).unwrap();
//! ```
//!
//! In order to configure the `Writer`, e.g. to set the LAS version or point format, use a
//! `Builder`:
//!
//! ```
//! # use std::io::Cursor;
//! use las::Builder;
//! let mut builder = Builder::new();
//! builder.point_format = 1.into();
//! builder.version = (1, 2).into();
//! let writer = builder.writer(Cursor::new(Vec::new())).unwrap();
//! ```
//!
//! Convenience methods are provided for writing LAS data to a file:
//!
//! ```
//! # use las::{Writer, Builder};
//! // Uses the default writer:
//! let writer = Writer::from_path("/dev/null").unwrap();
//!
//! // Allows configuration before open:
//! let writer = Builder::new().writer_from_path("/dev/null").unwrap();
//! ```
//!
//! A `Writer` implements `Drop`, which it uses to re-write the header with the point count and
//! other metadata when the `Writer` goes out of scope. If this header re-write fails, an error
//! will be printed to the logs but the thread will not panic. If is unacceptable, you can close
//! the `Writer` yourself and prevent any re-writing on drop:
//!
//! ```
//! # use std::io::Cursor;
//! # use las::Writer;
//! {
//!     let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
//!     writer.close().unwrap();
//! } // `close` is not called
//! ```

#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unstable_features,
        unused_import_braces, unused_qualifications)]

extern crate byteorder;
extern crate chrono;
#[macro_use]
extern crate log;

pub mod global_encoding;
pub mod point;
pub mod utils;

mod builder;
mod error;
mod header;
mod reader;
mod version;
mod vlr;
mod writer;

pub use builder::Builder;
pub use error::Error;
pub use header::Header;
pub use point::Point;
pub use reader::Reader;
pub use writer::Writer;
pub use version::Version;
pub use vlr::Vlr;

/// Crate-specific result type.
pub type Result<T> = std::result::Result<T, Error>;
<|endoftext|>


<commit_before>//! Rust friendly bindings to the various *nix system functions.
//!
//! Modules are structured according to the C header file that they would be
//! defined in.
#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
// warnings even though the macro expands into something with allow(dead_code)
#![allow(dead_code)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
#![deny(unused)]
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]

// External crates
extern crate bytes;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate cfg_if;
extern crate void;

// Re-exported external crates
pub extern crate libc;

// Private internal modules
#[macro_use] mod macros;

// Public crates
pub mod errno;
#[deny(missing_docs)]
pub mod features;
pub mod fcntl;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod mount;
#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "fushsia",
          target_os = "linux",
          target_os = "netbsd"))]
pub mod mqueue;
#[deny(missing_docs)]
pub mod net;
#[deny(missing_docs)]
pub mod poll;
#[deny(missing_docs)]
pub mod pty;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod sched;
pub mod sys;
// This can be implemented for other platforms as soon as libc
// provides bindings for them.
#[cfg(all(target_os = "linux",
          any(target_arch = "x86", target_arch = "x86_64")))]
pub mod ucontext;
pub mod unistd;

/*
 *
 * ===== Result / Error =====
 *
 */

use libc::{c_char, PATH_MAX};

use std::{error, fmt, ptr, result};
use std::ffi::{CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

use errno::Errno;

/// Nix Result Type
pub type Result<T> = result::Result<T, Error>;

/// Nix Error Type
///
/// The nix error type provides a common way of dealing with
/// various system system/libc calls that might fail.  Each
/// error has a corresponding errno (usually the one from the
/// underlying OS) to which it can be mapped in addition to
/// implementing other common traits.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
    Sys(Errno),
    InvalidPath,
    /// The operation involved a conversion to Rust's native String type, which failed because the
    /// string did not contain all valid UTF-8.
    InvalidUtf8,
    /// The operation is not supported by Nix, in this instance either use the libc bindings or
    /// consult the module documentation to see if there is a more appropriate interface available.
    UnsupportedOperation,
}

impl Error {

    /// Create a nix Error from a given errno
    pub fn from_errno(errno: Errno) -> Error {
        Error::Sys(errno)
    }

    /// Get the current errno and convert it to a nix Error
    pub fn last() -> Error {
        Error::Sys(Errno::last())
    }

    /// Create a new invalid argument error (`EINVAL`)
    pub fn invalid_argument() -> Error {
        Error::Sys(Errno::EINVAL)
    }

}

impl From<Errno> for Error {
    fn from(errno: Errno) -> Error { Error::from_errno(errno) }
}

impl From<std::string::FromUtf8Error> for Error {
    fn from(_: std::string::FromUtf8Error) -> Error { Error::InvalidUtf8 }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidPath => "Invalid path",
            Error::InvalidUtf8 => "Invalid UTF-8 string",
            Error::UnsupportedOperation => "Unsupported Operation",
            Error::Sys(ref errno) => errno.desc(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::InvalidPath => write!(f, "Invalid path"),
            Error::InvalidUtf8 => write!(f, "Invalid UTF-8 string"),
            Error::UnsupportedOperation => write!(f, "Unsupported Operation"),
            Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
        }
    }
}

pub trait NixPath {
    fn len(&self) -> usize;

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T;
}

impl NixPath for str {
    fn len(&self) -> usize {
        NixPath::len(OsStr::new(self))
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            OsStr::new(self).with_nix_path(f)
        }
}

impl NixPath for OsStr {
    fn len(&self) -> usize {
        self.as_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            self.as_bytes().with_nix_path(f)
        }
}

impl NixPath for CStr {
    fn len(&self) -> usize {
        self.to_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        // Equivalence with the [u8] impl.
        if self.len() >= PATH_MAX as usize {
            return Err(Error::InvalidPath);
        }

        Ok(f(self))
    }
}

impl NixPath for [u8] {
    fn len(&self) -> usize {
        self.len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        let mut buf = [0u8; PATH_MAX as usize];

        if self.len() >= PATH_MAX as usize {
            return Err(Error::InvalidPath);
        }

        match self.iter().position(|b| *b == 0) {
            Some(_) => Err(Error::InvalidPath),
            None => {
                unsafe {
                    // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
                    ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
                    Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
                }

            }
        }
    }
}

impl NixPath for Path {
    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

impl NixPath for PathBuf {
    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

/// Treats `None` as an empty string.
impl<'a, NP: ?Sized + NixPath>  NixPath for Option<&'a NP> {
    fn len(&self) -> usize {
        self.map_or(0, NixPath::len)
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        if let Some(nix_path) = *self {
            nix_path.with_nix_path(f)
        } else {
            unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
        }
    }
}
<commit_msg>Re-add ifaddrs module<commit_after>//! Rust friendly bindings to the various *nix system functions.
//!
//! Modules are structured according to the C header file that they would be
//! defined in.
#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
// warnings even though the macro expands into something with allow(dead_code)
#![allow(dead_code)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit = "500"]
#![deny(unused)]
#![deny(unstable_features)]
#![deny(missing_copy_implementations)]
#![deny(missing_debug_implementations)]

// External crates
extern crate bytes;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate cfg_if;
extern crate void;

// Re-exported external crates
pub extern crate libc;

// Private internal modules
#[macro_use] mod macros;

// Public crates
pub mod errno;
#[deny(missing_docs)]
pub mod features;
pub mod fcntl;
#[deny(missing_docs)]
#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "ios",
          target_os = "linux",
          target_os = "macos",
          target_os = "netbsd",
          target_os = "openbsd"))]
pub mod ifaddrs;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod mount;
#[cfg(any(target_os = "dragonfly",
          target_os = "freebsd",
          target_os = "fushsia",
          target_os = "linux",
          target_os = "netbsd"))]
pub mod mqueue;
#[deny(missing_docs)]
pub mod net;
#[deny(missing_docs)]
pub mod poll;
#[deny(missing_docs)]
pub mod pty;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod sched;
pub mod sys;
// This can be implemented for other platforms as soon as libc
// provides bindings for them.
#[cfg(all(target_os = "linux",
          any(target_arch = "x86", target_arch = "x86_64")))]
pub mod ucontext;
pub mod unistd;

/*
 *
 * ===== Result / Error =====
 *
 */

use libc::{c_char, PATH_MAX};

use std::{error, fmt, ptr, result};
use std::ffi::{CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};

use errno::Errno;

/// Nix Result Type
pub type Result<T> = result::Result<T, Error>;

/// Nix Error Type
///
/// The nix error type provides a common way of dealing with
/// various system system/libc calls that might fail.  Each
/// error has a corresponding errno (usually the one from the
/// underlying OS) to which it can be mapped in addition to
/// implementing other common traits.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
    Sys(Errno),
    InvalidPath,
    /// The operation involved a conversion to Rust's native String type, which failed because the
    /// string did not contain all valid UTF-8.
    InvalidUtf8,
    /// The operation is not supported by Nix, in this instance either use the libc bindings or
    /// consult the module documentation to see if there is a more appropriate interface available.
    UnsupportedOperation,
}

impl Error {

    /// Create a nix Error from a given errno
    pub fn from_errno(errno: Errno) -> Error {
        Error::Sys(errno)
    }

    /// Get the current errno and convert it to a nix Error
    pub fn last() -> Error {
        Error::Sys(Errno::last())
    }

    /// Create a new invalid argument error (`EINVAL`)
    pub fn invalid_argument() -> Error {
        Error::Sys(Errno::EINVAL)
    }

}

impl From<Errno> for Error {
    fn from(errno: Errno) -> Error { Error::from_errno(errno) }
}

impl From<std::string::FromUtf8Error> for Error {
    fn from(_: std::string::FromUtf8Error) -> Error { Error::InvalidUtf8 }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidPath => "Invalid path",
            Error::InvalidUtf8 => "Invalid UTF-8 string",
            Error::UnsupportedOperation => "Unsupported Operation",
            Error::Sys(ref errno) => errno.desc(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::InvalidPath => write!(f, "Invalid path"),
            Error::InvalidUtf8 => write!(f, "Invalid UTF-8 string"),
            Error::UnsupportedOperation => write!(f, "Unsupported Operation"),
            Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
        }
    }
}

pub trait NixPath {
    fn len(&self) -> usize;

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T;
}

impl NixPath for str {
    fn len(&self) -> usize {
        NixPath::len(OsStr::new(self))
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            OsStr::new(self).with_nix_path(f)
        }
}

impl NixPath for OsStr {
    fn len(&self) -> usize {
        self.as_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            self.as_bytes().with_nix_path(f)
        }
}

impl NixPath for CStr {
    fn len(&self) -> usize {
        self.to_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        // Equivalence with the [u8] impl.
        if self.len() >= PATH_MAX as usize {
            return Err(Error::InvalidPath);
        }

        Ok(f(self))
    }
}

impl NixPath for [u8] {
    fn len(&self) -> usize {
        self.len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        let mut buf = [0u8; PATH_MAX as usize];

        if self.len() >= PATH_MAX as usize {
            return Err(Error::InvalidPath);
        }

        match self.iter().position(|b| *b == 0) {
            Some(_) => Err(Error::InvalidPath),
            None => {
                unsafe {
                    // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
                    ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
                    Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
                }

            }
        }
    }
}

impl NixPath for Path {
    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

impl NixPath for PathBuf {
    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

/// Treats `None` as an empty string.
impl<'a, NP: ?Sized + NixPath>  NixPath for Option<&'a NP> {
    fn len(&self) -> usize {
        self.map_or(0, NixPath::len)
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        if let Some(nix_path) = *self {
            nix_path.with_nix_path(f)
        } else {
            unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
        }
    }
}
<|endoftext|>