<commit_before>use ::piston_window::*;

use ::gfx_device_gl::{Resources, CommandBuffer};
use ::gfx_graphics::GfxGraphics;

use ::na::Vector2;

type Vec2 = Vector2<f64>;

pub struct Tetromino {
    pos: Vec2,
    blocks: [SquareBlock; 4]
}

impl Tetromino {
    pub fn new_s() -> Tetromino {
        // TODO this will depend on the rotation direction.
        let logical_center = Vec2::new(60.0, 40.0);
        Tetromino {
            pos: Vec2::new(0.0, 0.0),
            blocks: [
                SquareBlock::new(Vec2::new(0.0, 0.0) - logical_center),
                SquareBlock::new(Vec2::new(40.0, 0.0) - logical_center),
                SquareBlock::new(Vec2::new(40.0, 40.0) - logical_center),
                SquareBlock::new(Vec2::new(80.0, 40.0) - logical_center)
            ]
        }
    }
}

pub struct SquareBlock {
    offset: Vec2,
    trans: Transform,
    curr_trans: Transform,
    sprite: Option<Texture<Resources>>
}

impl SquareBlock {
    fn new(offset: Vec2) -> SquareBlock {
        SquareBlock {
            offset,
            trans: Transform::new(),
            curr_trans: Transform::new(),
            sprite: Option::None
        }
    }

}

#[derive(Copy, Clone)]
pub struct Transform {
    pos: Vec2,
    rot: f64
}

impl Transform {
    pub fn new() -> Transform {
        Transform {
            pos: Vec2::new(0.0, 0.0),
            rot: 0.0
        }
    }

    pub fn mov(&mut self, v: Vec2) {
        self.pos = self.pos + v;
    }

    pub fn mov_to(&mut self, v: Vec2) {
        self.pos = v;
    }

    pub fn rot(&mut self, d: f64) {
        self.rot += d;
    }

    pub fn rot_to(&mut self, d: f64) {
        self.rot = d;
    }
}

impl PartialEq for Transform {
    fn eq(&self, other: &Transform) -> bool {
        &self.pos == &other.pos && &self.rot == &other.rot
    }
}

pub trait Movable {
    fn mov(&mut self, pos: Vec2);
    fn mov_to(&mut self, pos: Vec2);
    fn rot(&mut self, r: f64);
    fn rot_to(&mut self, r: f64);
    fn update(&mut self, dt: f64);
}

impl Movable for SquareBlock {
    fn mov(&mut self, pos: Vec2) {
        self.trans.mov(pos);
    }

    fn mov_to(&mut self, pos: Vec2) {
        self.trans.mov_to(pos);
    }

    fn rot(&mut self, r: f64) {
        self.trans.rot(r);
    }

    fn rot_to(&mut self, r: f64) {
        self.trans.rot_to(r);
    }

    fn update(&mut self, dt: f64) {
        let pos_d = self.trans.pos - self.curr_trans.pos;
        if (pos_d.abs().y >= 0.5) {
            self.curr_trans.mov(pos_d / 5.0);
        } else if (self.curr_trans.pos != self.trans.pos) {
            self.curr_trans.mov_to(self.trans.pos);
        }

        let rot_d = self.trans.rot - self.curr_trans.rot;
        if (rot_d.abs() >= 0.5) {
            self.curr_trans.rot(rot_d / 5.0);
        } else if (self.curr_trans.rot != self.trans.rot) {
            self.curr_trans.rot_to(self.trans.rot);
        }
    }
}

impl Movable for Tetromino {
    fn mov(&mut self, pos: Vec2) {
        for block in &mut self.blocks {
            block.mov(pos);
        }
    }

    fn mov_to(&mut self, pos: Vec2) {
        for block in &mut self.blocks {
            block.mov_to(pos);
        }
    }
    fn rot(&mut self, r: f64) {
        for block in &mut self.blocks {
            block.rot(r);
        }
    }
    fn rot_to(&mut self, r: f64) {
        for block in &mut self.blocks {
            block.rot_to(r);
        }
    }

    fn update(&mut self, dt: f64) {
        for block in &mut self.blocks {
            block.update(dt);
        }
    }
}

pub trait Renderable {
    fn render(&self, g: &mut GfxGraphics<Resources, CommandBuffer>, view: math::Matrix2d);
}

impl Renderable for SquareBlock {
    fn render(&self, g: &mut GfxGraphics<Resources, CommandBuffer>, view: math::Matrix2d) {
        let t: Transform = self.curr_trans;
        let o = self.offset;
        let tile_size = 40.0;
        let square = rectangle::square(0.0, 0.0, tile_size);
        let transition = view.trans(t.pos.x, t.pos.y)
                             .rot_deg(t.rot)
                             .trans(o.x, o.y);
        rectangle(
            [1.0, 0.0, 0.0, 1.0],
            square,
            transition,
            g);
    }
}

impl Renderable for Tetromino {
    fn render(&self, g: &mut GfxGraphics<Resources, CommandBuffer>, view: math::Matrix2d) {
        for block in &self.blocks {
            block.render(g, view);
        }
    }
}<commit_msg>Reorganize Transform struct<commit_after>use ::piston_window::*;

use ::gfx_device_gl::{Resources, CommandBuffer};
use ::gfx_graphics::GfxGraphics;

use ::na::{Vector2, Vector3};

type Vec2 = Vector2<f64>;
type Vec3 = Vector3<f64>;

pub struct Tetromino {
    pos: Vec2,
    blocks: [SquareBlock; 4]
}

impl Tetromino {
    pub fn new_s() -> Tetromino {
        // TODO this will depend on the rotation direction.
        let logical_center = Vec2::new(60.0, 40.0);
        Tetromino {
            pos: Vec2::new(0.0, 0.0),
            blocks: [
                SquareBlock::new(Vec2::new(0.0, 0.0) - logical_center),
                SquareBlock::new(Vec2::new(40.0, 0.0) - logical_center),
                SquareBlock::new(Vec2::new(40.0, 40.0) - logical_center),
                SquareBlock::new(Vec2::new(80.0, 40.0) - logical_center)
            ]
        }
    }
}

pub struct SquareBlock {
    offset: Vec2,
    trans: Transform,
    sprite: Option<Texture<Resources>>
}

impl SquareBlock {
    fn new(offset: Vec2) -> SquareBlock {
        SquareBlock {
            offset,
            trans: Transform::new(),
            sprite: Option::None
        }
    }

}

#[derive(Copy, Clone)]
pub struct Transform {
    pos_rot: Vec3,
    target: Vec3,
    step: Vec3
}

impl Transform {
    pub fn new() -> Transform {
        Transform {
            pos_rot: Vec3::zeros(),
            target: Vec3::zeros(),
            step: Vec3::zeros()
        }
    }

    fn update_step(&mut self) {
        self.step = (self.target - self.pos_rot) / 10.0;
        println!("new step = {}", self.step);
    }

}

pub trait Movable {
    fn mov(&mut self, pos: Vec2);
    fn rot(&mut self, r: f64);
    fn update(&mut self, dt: f64);
}

impl Movable for Transform {
    fn mov(&mut self, v: Vec2) {
        let x: Vec3 = Vec3::new(v.x, v.y, 0.0);
        self.target = self.target + x;
        self.update_step();
    }

    fn rot(&mut self, d: f64) {
        let mut x = Vec3::zeros();
        x.z = d;
        self.target = self.target + x;
        self.update_step();
    }

    fn update(&mut self, dt: f64) {
        if self.step != Vec3::zeros() && (self.pos_rot - self.target).abs() <= Vec3::new(1.0, 1.0, 1.0) {
            self.step = Vec3::zeros();
            self.pos_rot = self.target;
        } else {
            self.pos_rot = self.pos_rot + self.step;
        }
    }
}

impl Movable for SquareBlock {

    fn mov(&mut self, pos: Vec2) {
        self.trans.mov(pos);
    }

    fn rot(&mut self, r: f64) {
        self.trans.rot(r);
    }

    fn update(&mut self, dt: f64) {
        self.trans.update(dt);
    }
}

impl Movable for Tetromino {

    fn mov(&mut self, pos: Vec2) {
        for block in &mut self.blocks {
            block.mov(pos);
        }
    }

    fn rot(&mut self, r: f64) {
        for block in &mut self.blocks {
            block.rot(r);
        }
    }

    fn update(&mut self, dt: f64) {
        for block in &mut self.blocks {
            block.update(dt);
        }
    }
}

pub trait Renderable {
    fn render(&self, g: &mut GfxGraphics<Resources, CommandBuffer>, view: math::Matrix2d);
}

impl Renderable for SquareBlock {
    fn render(&self, g: &mut GfxGraphics<Resources, CommandBuffer>, view: math::Matrix2d) {
        let t: Transform = self.trans;
        let o = self.offset;
        let tile_size = 40.0;
        let square = rectangle::square(0.0, 0.0, tile_size);
        let transition = view.trans(t.pos_rot.x, t.pos_rot.y)
                             .rot_deg(t.pos_rot.z)
                             .trans(o.x, o.y);
        rectangle(
            [1.0, 0.0, 0.0, 1.0],
            square,
            transition,
            g);
    }
}

impl Renderable for Tetromino {
    fn render(&self, g: &mut GfxGraphics<Resources, CommandBuffer>, view: math::Matrix2d) {
        for block in &self.blocks {
            block.render(g, view);
        }
    }
}<|endoftext|>


<commit_before>//
// Copyright 2018 The Project Oak Authors
//
// 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.
//

extern crate fmt;
#[macro_use]
extern crate log;
extern crate protobuf;

use std::cell::RefCell;
use std::io;
use std::io::Write;

mod proto;
#[cfg(test)]
mod tests;

#[cfg(test)]
#[macro_use]
extern crate assert_matches;

pub type GrpcResult<T> = Result<T, proto::status::Status>;

type Handle = u64;

// Keep in sync with /oak/server/oak_node.h.
pub const LOGGING_CHANNEL_HANDLE: Handle = 1;
pub const GRPC_METHOD_NAME_CHANNEL_HANDLE: Handle = 2;
pub const GRPC_IN_CHANNEL_HANDLE: Handle = 3;
pub const GRPC_OUT_CHANNEL_HANDLE: Handle = 4;

// Status values returned across the host function interface
#[derive(Debug, PartialEq)]
pub enum Status {
    Ok,
    BadHandle,
    InvalidArgs,
    ChannelClosed,
    BufferTooSmall,
    OutOfRange,
    Unknown(i32),
}

fn status_from_i32(raw: i32) -> Status {
    // Keep in sync with /oak/server/status.h
    match raw {
        0 => Status::Ok,
        1 => Status::BadHandle,
        2 => Status::InvalidArgs,
        3 => Status::ChannelClosed,
        4 => Status::BufferTooSmall,
        5 => Status::OutOfRange,
        _ => Status::Unknown(raw),
    }
}

/// Map a host function status to the nearest available std::io::Result.
fn result_from_status<T>(status: Status, val: T) -> std::io::Result<T> {
    match status {
        Status::Ok => Ok(val),
        Status::BadHandle => Err(io::Error::new(io::ErrorKind::NotConnected, "Bad handle")),
        Status::InvalidArgs => Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "Invalid arguments",
        )),
        Status::ChannelClosed => Err(io::Error::new(
            io::ErrorKind::ConnectionReset,
            "Channel closed",
        )),
        Status::BufferTooSmall => Err(io::Error::new(
            io::ErrorKind::UnexpectedEof,
            "Buffer too small",
        )),
        Status::OutOfRange => Err(io::Error::new(io::ErrorKind::NotConnected, "Out of range")),
        Status::Unknown(raw) => Err(io::Error::new(
            io::ErrorKind::Other,
            format!("Unknown Oak status value {}", raw),
        )),
    }
}

// TODO: Implement panic handler.

mod wasm {
    // See https://rustwasm.github.io/book/reference/js-ffi.html
    #[link(wasm_import_module = "oak")]
    extern "C" {
        pub fn channel_read(handle: u64, buf: *mut u8, size: usize, actual_size: *mut u32) -> i32;
        pub fn channel_write(handle: u64, buf: *const u8, size: usize) -> i32;
    }
}

pub struct SendChannelHalf {
    handle: Handle,
}

impl SendChannelHalf {
    pub fn new(handle: Handle) -> SendChannelHalf {
        SendChannelHalf { handle }
    }
}

impl SendChannelHalf {
    pub fn write_message(&mut self, buf: &[u8]) -> std::io::Result<()> {
        result_from_status(
            status_from_i32(unsafe { wasm::channel_write(self.handle, buf.as_ptr(), buf.len()) }),
            (),
        )
    }
}

// Implement the Write trait on a send channel for convenience, particularly for
// the logging channel.
impl Write for SendChannelHalf {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        match self.write_message(buf) {
            Ok(_) => Ok(buf.len()),
            Err(e) => Err(e),
        }
    }
    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

pub fn logging_channel() -> impl Write {
    let logging_channel = SendChannelHalf::new(LOGGING_CHANNEL_HANDLE);
    // Only flush logging channel on newlines.
    std::io::LineWriter::new(logging_channel)
}

pub struct ReceiveChannelHalf {
    handle: Handle,
}

impl ReceiveChannelHalf {
    pub fn new(handle: Handle) -> ReceiveChannelHalf {
        ReceiveChannelHalf { handle }
    }
}

impl ReceiveChannelHalf {
    pub fn read_message(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
        // Try reading from the channel twice: first with provided vector,
        // then with a vector that's been resized to meet size requirements.
        for resized in &[false, true] {
            let mut actual_size: u32 = 0;
            let status = status_from_i32(unsafe {
                wasm::channel_read(
                    self.handle,
                    buf.as_mut_ptr(),
                    buf.capacity(),
                    &mut actual_size,
                )
            });
            match status {
                Status::Ok => {
                    unsafe {
                        buf.set_len(actual_size as usize);
                    };
                    return Ok(actual_size as usize);
                }
                Status::BufferTooSmall => {
                    if *resized {
                        return result_from_status(status, 0);
                    }
                    // Can escape the match if buffer is too small and !resized.
                }
                _ => return result_from_status(status, 0),
            }

            // Extend the vector to be large enough for the message
            debug!("Got {}, need {}", buf.capacity(), actual_size);
            if (actual_size as usize) < buf.len() {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!(
                        "Internal error: provided {} bytes for receive, asked for {}",
                        buf.len(),
                        actual_size
                    ),
                ));
            }
            let extra = (actual_size as usize) - buf.len();
            buf.reserve(extra);
        }
        Err(io::Error::new(io::ErrorKind::Other, "Unreachable reached!"))
    }
}

/// Convenience wrapper for a send/receive pair of channels.
pub struct ChannelPair {
    pub receive: ReceiveChannelHalf,
    pub send: SendChannelHalf,
}

impl ChannelPair {
    pub fn new(in_handle: Handle, out_handle: Handle) -> ChannelPair {
        ChannelPair {
            receive: ReceiveChannelHalf::new(in_handle),
            send: SendChannelHalf::new(out_handle),
        }
    }
}

/// Trait encapsulating the operations required for an Oak Node.
pub trait Node {
    fn new() -> Self
    where
        Self: Sized;
    fn invoke(&mut self, grpc_method_name: &str, grpc_pair: &mut ChannelPair);
}

thread_local! {
    static NODE: RefCell<Option<Box<dyn Node>>> = RefCell::new(None);
}

/// Sets the Oak Node to execute in the current instance.
///
/// This function may only be called once, and only from an exported `oak_initialize` function:
///
/// ```rust
/// struct Node;
///
/// impl oak::Node for Node {
///     fn new() -> Self { Node }
///     fn invoke(&mut self, grpc_method_name: &str, grpc_pair: &mut oak::ChannelPair) { /* ... */ }
/// }
///
/// #[no_mangle]
/// pub extern "C" fn oak_initialize() {
///     oak::set_node::<Node>();
/// }
/// ```
pub fn set_node<T: Node + 'static>() {
    NODE.with(|node| {
        match *node.borrow_mut() {
            Some(_) => {
                writeln!(logging_channel(), "attempt to set_node() when already set!").unwrap();
                panic!("attempt to set_node when already set");
            }
            None => {
                writeln!(logging_channel(), "setting current node instance").unwrap();
            }
        }
        *node.borrow_mut() = Some(Box::new(T::new()));
    });
}

#[no_mangle]
pub extern "C" fn oak_handle_grpc_call() {
    NODE.with(|node| match *node.borrow_mut() {
        Some(ref mut node) => {
            let mut grpc_method_channel = ReceiveChannelHalf::new(GRPC_METHOD_NAME_CHANNEL_HANDLE);
            let mut buf = Vec::<u8>::with_capacity(256);
            grpc_method_channel.read_message(&mut buf).unwrap();
            let grpc_method_name = String::from_utf8_lossy(&buf);
            let mut grpc_pair = ChannelPair::new(GRPC_IN_CHANNEL_HANDLE, GRPC_OUT_CHANNEL_HANDLE);
            node.invoke(&grpc_method_name, &mut grpc_pair);
        }
        None => {
            writeln!(logging_channel(), "gRPC call with no loaded Node").unwrap();
            panic!("gRPC call with no loaded Node");
        }
    });
}

/// Return whether an Oak Node is currently available.
pub fn have_node() -> bool {
    NODE.with(|node| (*node.borrow()).is_some())
}

#[test]
fn reset_node() {
    NODE.with(|node| {
        *node.borrow_mut() = None;
    })
}
<commit_msg>Install panic hook (#158)<commit_after>//
// Copyright 2018 The Project Oak Authors
//
// 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.
//

extern crate fmt;
#[macro_use]
extern crate log;
extern crate protobuf;

use std::cell::RefCell;
use std::io;
use std::io::Write;

mod proto;
#[cfg(test)]
mod tests;

#[cfg(test)]
#[macro_use]
extern crate assert_matches;

pub type GrpcResult<T> = Result<T, proto::status::Status>;

type Handle = u64;

// Keep in sync with /oak/server/oak_node.h.
pub const LOGGING_CHANNEL_HANDLE: Handle = 1;
pub const GRPC_METHOD_NAME_CHANNEL_HANDLE: Handle = 2;
pub const GRPC_IN_CHANNEL_HANDLE: Handle = 3;
pub const GRPC_OUT_CHANNEL_HANDLE: Handle = 4;

// Status values returned across the host function interface
#[derive(Debug, PartialEq)]
pub enum Status {
    Ok,
    BadHandle,
    InvalidArgs,
    ChannelClosed,
    BufferTooSmall,
    OutOfRange,
    Unknown(i32),
}

fn status_from_i32(raw: i32) -> Status {
    // Keep in sync with /oak/server/status.h
    match raw {
        0 => Status::Ok,
        1 => Status::BadHandle,
        2 => Status::InvalidArgs,
        3 => Status::ChannelClosed,
        4 => Status::BufferTooSmall,
        5 => Status::OutOfRange,
        _ => Status::Unknown(raw),
    }
}

/// Map a host function status to the nearest available std::io::Result.
fn result_from_status<T>(status: Status, val: T) -> std::io::Result<T> {
    match status {
        Status::Ok => Ok(val),
        Status::BadHandle => Err(io::Error::new(io::ErrorKind::NotConnected, "Bad handle")),
        Status::InvalidArgs => Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            "Invalid arguments",
        )),
        Status::ChannelClosed => Err(io::Error::new(
            io::ErrorKind::ConnectionReset,
            "Channel closed",
        )),
        Status::BufferTooSmall => Err(io::Error::new(
            io::ErrorKind::UnexpectedEof,
            "Buffer too small",
        )),
        Status::OutOfRange => Err(io::Error::new(io::ErrorKind::NotConnected, "Out of range")),
        Status::Unknown(raw) => Err(io::Error::new(
            io::ErrorKind::Other,
            format!("Unknown Oak status value {}", raw),
        )),
    }
}

// TODO: Implement panic handler.

mod wasm {
    // See https://rustwasm.github.io/book/reference/js-ffi.html
    #[link(wasm_import_module = "oak")]
    extern "C" {
        pub fn channel_read(handle: u64, buf: *mut u8, size: usize, actual_size: *mut u32) -> i32;
        pub fn channel_write(handle: u64, buf: *const u8, size: usize) -> i32;
    }
}

pub struct SendChannelHalf {
    handle: Handle,
}

impl SendChannelHalf {
    pub fn new(handle: Handle) -> SendChannelHalf {
        SendChannelHalf { handle }
    }
}

impl SendChannelHalf {
    pub fn write_message(&mut self, buf: &[u8]) -> std::io::Result<()> {
        result_from_status(
            status_from_i32(unsafe { wasm::channel_write(self.handle, buf.as_ptr(), buf.len()) }),
            (),
        )
    }
}

// Implement the Write trait on a send channel for convenience, particularly for
// the logging channel.
impl Write for SendChannelHalf {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        match self.write_message(buf) {
            Ok(_) => Ok(buf.len()),
            Err(e) => Err(e),
        }
    }
    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

pub fn logging_channel() -> impl Write {
    let logging_channel = SendChannelHalf::new(LOGGING_CHANNEL_HANDLE);
    // Only flush logging channel on newlines.
    std::io::LineWriter::new(logging_channel)
}

pub struct ReceiveChannelHalf {
    handle: Handle,
}

impl ReceiveChannelHalf {
    pub fn new(handle: Handle) -> ReceiveChannelHalf {
        ReceiveChannelHalf { handle }
    }
}

impl ReceiveChannelHalf {
    pub fn read_message(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
        // Try reading from the channel twice: first with provided vector,
        // then with a vector that's been resized to meet size requirements.
        for resized in &[false, true] {
            let mut actual_size: u32 = 0;
            let status = status_from_i32(unsafe {
                wasm::channel_read(
                    self.handle,
                    buf.as_mut_ptr(),
                    buf.capacity(),
                    &mut actual_size,
                )
            });
            match status {
                Status::Ok => {
                    unsafe {
                        buf.set_len(actual_size as usize);
                    };
                    return Ok(actual_size as usize);
                }
                Status::BufferTooSmall => {
                    if *resized {
                        return result_from_status(status, 0);
                    }
                    // Can escape the match if buffer is too small and !resized.
                }
                _ => return result_from_status(status, 0),
            }

            // Extend the vector to be large enough for the message
            debug!("Got {}, need {}", buf.capacity(), actual_size);
            if (actual_size as usize) < buf.len() {
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!(
                        "Internal error: provided {} bytes for receive, asked for {}",
                        buf.len(),
                        actual_size
                    ),
                ));
            }
            let extra = (actual_size as usize) - buf.len();
            buf.reserve(extra);
        }
        Err(io::Error::new(io::ErrorKind::Other, "Unreachable reached!"))
    }
}

/// Convenience wrapper for a send/receive pair of channels.
pub struct ChannelPair {
    pub receive: ReceiveChannelHalf,
    pub send: SendChannelHalf,
}

impl ChannelPair {
    pub fn new(in_handle: Handle, out_handle: Handle) -> ChannelPair {
        ChannelPair {
            receive: ReceiveChannelHalf::new(in_handle),
            send: SendChannelHalf::new(out_handle),
        }
    }
}

/// Trait encapsulating the operations required for an Oak Node.
pub trait Node {
    fn new() -> Self
    where
        Self: Sized;
    fn invoke(&mut self, grpc_method_name: &str, grpc_pair: &mut ChannelPair);
}

thread_local! {
    static NODE: RefCell<Option<Box<dyn Node>>> = RefCell::new(None);
}

/// Sets the Oak Node to execute in the current instance.
///
/// This function may only be called once, and only from an exported `oak_initialize` function:
///
/// ```rust
/// struct Node;
///
/// impl oak::Node for Node {
///     fn new() -> Self { Node }
///     fn invoke(&mut self, grpc_method_name: &str, grpc_pair: &mut oak::ChannelPair) { /* ... */ }
/// }
///
/// #[no_mangle]
/// pub extern "C" fn oak_initialize() {
///     oak::set_node::<Node>();
/// }
/// ```
pub fn set_node<T: Node + 'static>() {
    set_panic_hook();
    NODE.with(|node| {
        match *node.borrow_mut() {
            Some(_) => {
                writeln!(logging_channel(), "attempt to set_node() when already set!").unwrap();
                panic!("attempt to set_node when already set");
            }
            None => {
                writeln!(logging_channel(), "setting current node instance").unwrap();
            }
        }
        *node.borrow_mut() = Some(Box::new(T::new()));
    });
}

/// Install a panic hook so that panics are logged to the logging channel, if one is set.
/// See https://doc.rust-lang.org/std/panic/struct.PanicInfo.html.
fn set_panic_hook() {
    std::panic::set_hook(Box::new(|panic_info| {
        let msg = panic_info
            .payload()
            .downcast_ref::<&str>()
            .unwrap_or(&"<UNKWOWN MESSAGE>");
        let (file, line) = match panic_info.location() {
            Some(location) => (location.file(), location.line()),
            None => ("<UNKNOWN FILE>", 0),
        };
        error!(
            "panic occurred in file '{}' at line {}: {}",
            file, line, msg
        );
    }));
}

#[no_mangle]
pub extern "C" fn oak_handle_grpc_call() {
    NODE.with(|node| match *node.borrow_mut() {
        Some(ref mut node) => {
            let mut grpc_method_channel = ReceiveChannelHalf::new(GRPC_METHOD_NAME_CHANNEL_HANDLE);
            let mut buf = Vec::<u8>::with_capacity(256);
            grpc_method_channel.read_message(&mut buf).unwrap();
            let grpc_method_name = String::from_utf8_lossy(&buf);
            let mut grpc_pair = ChannelPair::new(GRPC_IN_CHANNEL_HANDLE, GRPC_OUT_CHANNEL_HANDLE);
            node.invoke(&grpc_method_name, &mut grpc_pair);
        }
        None => {
            writeln!(logging_channel(), "gRPC call with no loaded Node").unwrap();
            panic!("gRPC call with no loaded Node");
        }
    });
}

/// Return whether an Oak Node is currently available.
pub fn have_node() -> bool {
    NODE.with(|node| (*node.borrow()).is_some())
}

#[test]
fn reset_node() {
    NODE.with(|node| {
        *node.borrow_mut() = None;
    })
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;
use std::io;
use std::io::prelude::*;
use std::io::Cursor;
use std::io::SeekFrom;

use bv::BitSlice;
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
use rect_packer;
use rect_packer::Packer;

use crate::lz77;
use crate::piv::Colour;
use crate::rect::Rect;

#[derive(Debug)]
struct Header {
    image_count: usize,
    file_length: u16,
}

#[derive(Debug)]
pub struct ObjectsFile {
    pub images: Vec<Image>,
}

#[derive(Debug, Clone)]
pub struct TextureAtlas {
    pub image: Image,
    pub rects: Vec<Rect>,
    pub visible_widths: Vec<u32>,
}

#[derive(Debug, Copy, Clone)]
struct ImageHeader {
    data_address: usize,
    width: usize,
    height: usize,
    bit_plane_count: usize,
    blit_type: u8,
}

#[derive(Debug, Clone)]
pub struct TextureSizeTooSmall {
    pub texture_size: i32,
}

impl Error for TextureSizeTooSmall {}
impl fmt::Display for TextureSizeTooSmall {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Increase texture size {} to the next power of 2",
            self.texture_size
        )
    }
}

impl ObjectsFile {
    pub fn from_reader<T: Read>(reader: &mut T) -> Result<ObjectsFile, io::Error> {
        let mut data: Vec<u8> = Vec::new();
        reader.read_to_end(&mut data)?;

        let header = ObjectsFile::read_header(&data[..6]);
        let image_header_len = header.image_count * 10;
        let image_headers =
            ObjectsFile::read_image_headers(&header, &data[10..image_header_len + 10])?;

        let extracted = lz77::decompress(
            u32::from(header.file_length),
            &data[image_header_len + 10..],
        )?;
        let mut images: Vec<Image> = Vec::new();
        for image_header in image_headers {
            images.push(Image::from_data(image_header, &extracted));
        }
        Ok(ObjectsFile { images })
    }

    pub fn to_texture_atlas(&self, texture_size: i32) -> Result<TextureAtlas, TextureSizeTooSmall> {
        let config = rect_packer::Config {
            width: texture_size,
            height: texture_size,
            border_padding: 0,
            rectangle_padding: 0,
        };
        let mut atlas: Vec<usize> = vec![0; config.width as usize * config.height as usize];
        let mut packer = Packer::new(config);
        let mut rects: Vec<Rect> = Vec::new();
        let mut visible_widths: Vec<u32> = Vec::new();
        for image in self.images.iter() {
            if let Some(rect) = packer.pack(image.width as i32, image.height as i32, false) {
                let rgba_image = &image.pixels;
                for (y, image_row) in (0..rect.height).zip(rgba_image.chunks(image.width)) {
                    let row = (y + rect.y) as usize * config.width as usize;
                    let col = rect.x as usize;
                    let start = row + col;
                    let end = start + (rect.width as usize);
                    for (i, pixel) in (start..end).zip(image_row) {
                        atlas[i] = *pixel;
                    }
                }
                rects.push(Rect {
                    x: rect.x,
                    y: rect.y,
                    w: rect.width as u32,
                    h: rect.height as u32,
                });
                visible_widths.push(image.visible_width);
            } else {
                return Err(TextureSizeTooSmall { texture_size });
            }
        }
        Ok(TextureAtlas {
            image: Image {
                width: config.width as usize,
                visible_width: config.width as u32,
                height: config.height as usize,
                pixels: atlas,
            },
            rects,
            visible_widths,
        })
    }

    fn read_header(data: &[u8]) -> Header {
        Header {
            image_count: BigEndian::read_u16(&data[..2]) as usize,
            file_length: BigEndian::read_u16(&data[4..6]),
        }
    }

    fn read_image_headers(header: &Header, data: &[u8]) -> Result<Vec<ImageHeader>, io::Error> {
        let mut rdr = Cursor::new(data);
        let mut headers: Vec<ImageHeader> = Vec::with_capacity(header.image_count);
        for _ in 0..header.image_count {
            rdr.seek(SeekFrom::Current(2))?;
            headers.push(ImageHeader {
                data_address: rdr.read_u16::<BigEndian>()? as usize,
                width: rdr.read_u16::<BigEndian>()? as usize,
                height: rdr.read_u16::<BigEndian>()? as usize,
                bit_plane_count: rdr.read_u8()? as usize,
                blit_type: rdr.read_u8()?,
            })
        }
        Ok(headers)
    }
}

#[derive(Debug, Clone)]
pub struct Image {
    pub width: usize,
    pub visible_width: u32,
    pub height: usize,
    pub pixels: Vec<usize>,
}

impl Image {
    fn from_data(header: ImageHeader, extracted: &[u8]) -> Image {
        let packed_image_width = (header.width + 15) / 16 * 2;
        let num_bit_planes = if header.blit_type == 32 {
            2
        } else {
            (8 - header.blit_type.leading_zeros()) as usize
        };
        let bit_plane_size = packed_image_width * header.height;
        let unpacked_image_width = packed_image_width * 8;

        let image_data =
            &extracted[header.data_address..header.data_address + bit_plane_size * num_bit_planes];
        let planes: Vec<BitSlice<u8>> = image_data
            .chunks(bit_plane_size)
            .map(|p| BitSlice::from_slice(p))
            .collect();

        let mut pixels: Vec<usize> = Vec::with_capacity(unpacked_image_width * header.height);
        for i in (0..bit_plane_size * 8).map(|x| 7 - (x % 8) + x / 8 * 8) {
            let mut sum = 0;
            for (j, plane) in planes.iter().enumerate() {
                sum += (plane[i as u64] as usize) << j;
            }
            pixels.push(sum);
        }

        Image {
            width: unpacked_image_width,
            visible_width: header.width as u32,
            height: header.height,
            pixels,
        }
    }

    pub fn to_rgba8(&self, palette: &[Colour]) -> Vec<u8> {
        let mut pixels: Vec<u8> = Vec::with_capacity(self.width * self.height * 4);
        for pel in self.pixels.iter() {
            match palette.get(*pel) {
                Some(colour) => pixels.extend([colour.r, colour.g, colour.b, colour.a].iter()),
                None => panic!("Palette doesn't contain enough colours {}", pel),
            }
        }
        pixels
    }
}
<commit_msg>count bits instead of leading zeros to calculate bit planes.<commit_after>use std::error::Error;
use std::fmt;
use std::io;
use std::io::prelude::*;
use std::io::Cursor;
use std::io::SeekFrom;

use bv::BitSlice;
use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
use rect_packer;
use rect_packer::Packer;

use crate::lz77;
use crate::piv::Colour;
use crate::rect::Rect;

#[derive(Debug)]
struct Header {
    image_count: usize,
    file_length: u16,
}

#[derive(Debug)]
pub struct ObjectsFile {
    pub images: Vec<Image>,
}

#[derive(Debug, Clone)]
pub struct TextureAtlas {
    pub image: Image,
    pub rects: Vec<Rect>,
    pub visible_widths: Vec<u32>,
}

#[derive(Debug, Copy, Clone)]
struct ImageHeader {
    data_address: usize,
    width: usize,
    height: usize,
    bit_plane_count: usize,
    blit_type: u8,
}

#[derive(Debug, Clone)]
pub struct TextureSizeTooSmall {
    pub texture_size: i32,
}

impl Error for TextureSizeTooSmall {}
impl fmt::Display for TextureSizeTooSmall {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "Increase texture size {} to the next power of 2",
            self.texture_size
        )
    }
}

impl ObjectsFile {
    pub fn from_reader<T: Read>(reader: &mut T) -> Result<ObjectsFile, io::Error> {
        let mut data: Vec<u8> = Vec::new();
        reader.read_to_end(&mut data)?;

        let header = ObjectsFile::read_header(&data[..6]);
        let image_header_len = header.image_count * 10;
        let image_headers =
            ObjectsFile::read_image_headers(&header, &data[10..image_header_len + 10])?;

        let extracted = lz77::decompress(
            u32::from(header.file_length),
            &data[image_header_len + 10..],
        )?;
        let mut images: Vec<Image> = Vec::new();
        for image_header in image_headers {
            images.push(Image::from_data(image_header, &extracted));
        }
        Ok(ObjectsFile { images })
    }

    pub fn to_texture_atlas(&self, texture_size: i32) -> Result<TextureAtlas, TextureSizeTooSmall> {
        let config = rect_packer::Config {
            width: texture_size,
            height: texture_size,
            border_padding: 0,
            rectangle_padding: 0,
        };
        let mut atlas: Vec<usize> = vec![0; config.width as usize * config.height as usize];
        let mut packer = Packer::new(config);
        let mut rects: Vec<Rect> = Vec::new();
        let mut visible_widths: Vec<u32> = Vec::new();
        for image in self.images.iter() {
            if let Some(rect) = packer.pack(image.width as i32, image.height as i32, false) {
                let rgba_image = &image.pixels;
                for (y, image_row) in (0..rect.height).zip(rgba_image.chunks(image.width)) {
                    let row = (y + rect.y) as usize * config.width as usize;
                    let col = rect.x as usize;
                    let start = row + col;
                    let end = start + (rect.width as usize);
                    for (i, pixel) in (start..end).zip(image_row) {
                        atlas[i] = *pixel;
                    }
                }
                rects.push(Rect {
                    x: rect.x,
                    y: rect.y,
                    w: rect.width as u32,
                    h: rect.height as u32,
                });
                visible_widths.push(image.visible_width);
            } else {
                return Err(TextureSizeTooSmall { texture_size });
            }
        }
        Ok(TextureAtlas {
            image: Image {
                width: config.width as usize,
                visible_width: config.width as u32,
                height: config.height as usize,
                pixels: atlas,
            },
            rects,
            visible_widths,
        })
    }

    fn read_header(data: &[u8]) -> Header {
        Header {
            image_count: BigEndian::read_u16(&data[..2]) as usize,
            file_length: BigEndian::read_u16(&data[4..6]),
        }
    }

    fn read_image_headers(header: &Header, data: &[u8]) -> Result<Vec<ImageHeader>, io::Error> {
        let mut rdr = Cursor::new(data);
        let mut headers: Vec<ImageHeader> = Vec::with_capacity(header.image_count);
        for _ in 0..header.image_count {
            rdr.seek(SeekFrom::Current(2))?;
            headers.push(ImageHeader {
                data_address: rdr.read_u16::<BigEndian>()? as usize,
                width: rdr.read_u16::<BigEndian>()? as usize,
                height: rdr.read_u16::<BigEndian>()? as usize,
                bit_plane_count: rdr.read_u8()? as usize,
                blit_type: rdr.read_u8()?,
            })
        }
        Ok(headers)
    }
}

#[derive(Debug, Clone)]
pub struct Image {
    pub width: usize,
    pub visible_width: u32,
    pub height: usize,
    pub pixels: Vec<usize>,
}

impl Image {
    fn from_data(header: ImageHeader, extracted: &[u8]) -> Image {
        let packed_image_width = (header.width + 15) / 16 * 2;
        let num_bit_planes = if header.blit_type == 32 {
            2
        } else {
            header.blit_type.count_ones() as usize
        };
        let bit_plane_size = packed_image_width * header.height;
        let unpacked_image_width = packed_image_width * 8;

        let image_data =
            &extracted[header.data_address..header.data_address + bit_plane_size * num_bit_planes];
        let planes: Vec<BitSlice<u8>> = image_data
            .chunks(bit_plane_size)
            .map(|p| BitSlice::from_slice(p))
            .collect();

        let mut pixels: Vec<usize> = Vec::with_capacity(unpacked_image_width * header.height);
        for i in (0..bit_plane_size * 8).map(|x| 7 - (x % 8) + x / 8 * 8) {
            let mut sum = 0;
            for (j, plane) in planes.iter().enumerate() {
                sum += (plane[i as u64] as usize) << j;
            }
            pixels.push(sum);
        }

        Image {
            width: unpacked_image_width,
            visible_width: header.width as u32,
            height: header.height,
            pixels,
        }
    }

    pub fn to_rgba8(&self, palette: &[Colour]) -> Vec<u8> {
        let mut pixels: Vec<u8> = Vec::with_capacity(self.width * self.height * 4);
        for pel in self.pixels.iter() {
            match palette.get(*pel) {
                Some(colour) => pixels.extend([colour.r, colour.g, colour.b, colour.a].iter()),
                None => panic!("Palette doesn't contain enough colours {}", pel),
            }
        }
        pixels
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate cfg_if;
extern crate gcc;

use std::cmp::Ordering;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::iter;
use std::path::{Path, PathBuf};
use std::process::{self, Child, Command, Stdio};
use std::str;

cfg_if! {
    if #[cfg(feature = "v1_7_0")] {
        const TARGET_VERSION: &'static str = "1.7.0";
    } else if #[cfg(feature = "v1_6_0")] {
        const TARGET_VERSION: &'static str = "1.6.0";
    } else {
        const TARGET_VERSION: &'static str = "1.5.0";
    }
}

fn main() {
    let mut include_dirs = Vec::new();
    if let Ok(lib) = env::var("LIBGCRYPT_LIB") {
        if let Some(include) = env::var_os("LIBGCRYPT_INCLUDE_DIR") {
            include_dirs.push(include);
        }

        let mode = match env::var_os("LIBGCRYPT_STATIC") {
            Some(_) => "static",
            _ => "dylib",
        };

        build_shim(&include_dirs);
        println!("cargo:rustc-link-lib={0}={1}", mode, lib);
        return;
    } else if let Some(path) = env::var_os("LIBGCRYPT_CONFIG") {
        if !try_config(path) {
            process::exit(1);
        }
        return;
    }

    if !Path::new("libgcrypt/.git").exists() {
        run(Command::new("git").args(&["submodule", "update", "--init"]));
    }

    if try_build() || try_config("libgcrypt-config") {
        return;
    }
    process::exit(1);
}

fn try_config<S: AsRef<OsStr>>(path: S) -> bool {
    let path = path.as_ref();

    if let Some(output) = output(Command::new(&path).arg("--version")) {
        test_version(&output);
    } else {
        return false;
    }

    if let Some(output) = output(Command::new(&path).arg("--prefix")) {
        println!("cargo:root={}", output);
    }

    let mut command = Command::new(&path);
    command.args(&["--cflags", "--libs"]);
    if let Some(output) = output(&mut command) {
        let mut include_dirs = Vec::new();
        parse_config_output(&output, &mut include_dirs);
        build_shim(&include_dirs);
        return true;
    }
    false
}

fn try_build() -> bool {
    let src = PathBuf::from(env::current_dir().unwrap()).join("libgcrypt");
    let dst = env::var("OUT_DIR").unwrap();
    let build = PathBuf::from(&dst).join("build");
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let gpgerror_root = env::var("DEP_GPG_ERROR_ROOT").unwrap();
    let compiler = gcc::Config::new().get_compiler();
    let cflags = compiler.args().iter().fold(OsString::new(), |mut c, a| {
        c.push(a);
        c.push(" ");
        c
    });

    let _ = fs::create_dir_all(&build);

    if !run(Command::new("sh").current_dir(&src).arg("autogen.sh")) {
        return false;
    }
    if !run(Command::new("sh")
        .current_dir(&build)
        .env("CC", compiler.path())
        .env("CFLAGS", &cflags)
        .arg(msys_compatible(src.join("configure")))
        .args(&["--build", &gnu_target(&host),
                "--host", &gnu_target(&target),
                "--enable-static",
                "--disable-shared",
                "--disable-doc",
                &format!("--with-libgpg-error-prefix={}", &msys_compatible(&gpgerror_root)),
                &format!("--prefix={}", &dst)])) {
        return false;
    }
    if !run(Command::new("make")
        .current_dir(&build)
        .arg("-j").arg(env::var("NUM_JOBS").unwrap())) {
        return false;
    }
    if !run(Command::new("make").current_dir(&build).arg("install")) {
        return false;
    }

    build_shim(&[
       PathBuf::from(gpgerror_root).join("include"),
       PathBuf::from(dst.clone()).join("include"),
    ]);

    println!("cargo:rustc-link-search=native={}",
             PathBuf::from(dst.clone()).join("lib").display());
    println!("cargo:rustc-link-lib=static=gcrypt");
    println!("cargo:root={}", &dst);
    true
}

#[cfg(feature = "shim")]
fn build_shim<P: AsRef<Path>>(include_dirs: &[P]) {
    let mut config = gcc::Config::new();
    for path in include_dirs.iter() {
        config.include(msys_compatible(path));
    }
    config.flag("-Wno-deprecated-declarations").file("shim.c").compile("libgcrypt_shim.a");
}

#[cfg(not(feature = "shim"))]
fn build_shim<P: AsRef<Path>>(_include_dirs: &[P]) {}

fn test_version(version: &str) {
    let version = version.trim();
    for (x, y) in TARGET_VERSION.split('.').zip(version.split('.').chain(iter::repeat("0"))) {
        let (x, y): (u8, u8) = (x.parse().unwrap(), y.parse().unwrap());
        match x.cmp(&y) {
            Ordering::Less => break,
            Ordering::Greater => {
                panic!("gcrypt version `{}` is less than requested `{}`",
                       version, TARGET_VERSION)
            }
            _ => (),
        }
    }
}

fn parse_config_output(output: &str, include_dirs: &mut Vec<OsString>) {
    let parts = output.split(|c: char| c.is_whitespace()).filter_map(|p| if p.len() > 2 {
        Some(p.split_at(2))
    } else {
        None
    });

    for (flag, val) in parts {
        match flag {
            "-I" => include_dirs.push(val.into()),
            "-L" => {
                println!("cargo:rustc-link-search=native={}", val);
            }
            "-F" => {
                println!("cargo:rustc-link-search=framework={}", val);
            }
            "-l" => {
                println!("cargo:rustc-link-lib={}", val);
            }
            _ => (),
        }
    }
}

fn spawn(cmd: &mut Command) -> Option<Child> {
    println!("running: {:?}", cmd);
    match cmd.stdin(Stdio::null()).spawn() {
        Ok(child) => Some(child),
        Err(e) => {
            println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            None
        }
    }
}

fn run(cmd: &mut Command) -> bool {
    if let Some(mut child) = spawn(cmd) {
        match child.wait() {
            Ok(status) => {
                if !status.success() {
                    println!("command did not execute successfully: {:?}\n\
                       expected success, got: {}", cmd, status);
                } else {
                    return true;
                }
            }
            Err(e) => {
                println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            }
        }
    }
    false
}

fn output(cmd: &mut Command) -> Option<String> {
    if let Some(child) = spawn(cmd.stdout(Stdio::piped())) {
        match child.wait_with_output() {
            Ok(output) => {
                if !output.status.success() {
                    println!("command did not execute successfully: {:?}\n\
                       expected success, got: {}", cmd, output.status);
                } else {
                    return String::from_utf8(output.stdout).ok();
                }
            }
            Err(e) => {
                println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            }
        }
    }
    None
}

fn msys_compatible<P: AsRef<Path>>(path: P) -> String {
    let path = path.as_ref().to_str().unwrap();
    if !cfg!(windows) {
        return path.to_string();
    }
    path.replace("C:\\", "/c/").replace("\\", "/")
}

fn gnu_target(target: &str) -> String {
    match target {
        "i686-pc-windows-gnu" => "i686-w64-mingw32".to_string(),
        "x86_64-pc-windows-gnu" => "x86_64-w64-mingw32".to_string(),
        s => s.to_string(),
    }
}
<commit_msg>Fix msys incompatible path<commit_after>#[macro_use]
extern crate cfg_if;
extern crate gcc;

use std::cmp::Ordering;
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::iter;
use std::path::{Path, PathBuf};
use std::process::{self, Child, Command, Stdio};
use std::str;

cfg_if! {
    if #[cfg(feature = "v1_7_0")] {
        const TARGET_VERSION: &'static str = "1.7.0";
    } else if #[cfg(feature = "v1_6_0")] {
        const TARGET_VERSION: &'static str = "1.6.0";
    } else {
        const TARGET_VERSION: &'static str = "1.5.0";
    }
}

fn main() {
    let mut include_dirs = Vec::new();
    if let Ok(lib) = env::var("LIBGCRYPT_LIB") {
        if let Some(include) = env::var_os("LIBGCRYPT_INCLUDE_DIR") {
            include_dirs.push(include);
        }

        let mode = match env::var_os("LIBGCRYPT_STATIC") {
            Some(_) => "static",
            _ => "dylib",
        };

        build_shim(&include_dirs);
        println!("cargo:rustc-link-lib={0}={1}", mode, lib);
        return;
    } else if let Some(path) = env::var_os("LIBGCRYPT_CONFIG") {
        if !try_config(path) {
            process::exit(1);
        }
        return;
    }

    if !Path::new("libgcrypt/.git").exists() {
        run(Command::new("git").args(&["submodule", "update", "--init"]));
    }

    if try_build() || try_config("libgcrypt-config") {
        return;
    }
    process::exit(1);
}

fn try_config<S: AsRef<OsStr>>(path: S) -> bool {
    let path = path.as_ref();

    if let Some(output) = output(Command::new(&path).arg("--version")) {
        test_version(&output);
    } else {
        return false;
    }

    if let Some(output) = output(Command::new(&path).arg("--prefix")) {
        println!("cargo:root={}", output);
    }

    let mut command = Command::new(&path);
    command.args(&["--cflags", "--libs"]);
    if let Some(output) = output(&mut command) {
        let mut include_dirs = Vec::new();
        parse_config_output(&output, &mut include_dirs);
        build_shim(&include_dirs);
        return true;
    }
    false
}

fn try_build() -> bool {
    let src = PathBuf::from(env::current_dir().unwrap()).join("libgcrypt");
    let dst = env::var("OUT_DIR").unwrap();
    let build = PathBuf::from(&dst).join("build");
    let target = env::var("TARGET").unwrap();
    let host = env::var("HOST").unwrap();
    let gpgerror_root = env::var("DEP_GPG_ERROR_ROOT").unwrap();
    let compiler = gcc::Config::new().get_compiler();
    let cflags = compiler.args().iter().fold(OsString::new(), |mut c, a| {
        c.push(a);
        c.push(" ");
        c
    });

    let _ = fs::create_dir_all(&build);

    if !run(Command::new("sh").current_dir(&src).arg("autogen.sh")) {
        return false;
    }
    if !run(Command::new("sh")
        .current_dir(&build)
        .env("CC", compiler.path())
        .env("CFLAGS", &cflags)
        .arg(msys_compatible(src.join("configure")))
        .args(&["--build", &gnu_target(&host),
                "--host", &gnu_target(&target),
                "--enable-static",
                "--disable-shared",
                "--disable-doc",
                &format!("--with-libgpg-error-prefix={}", &msys_compatible(&gpgerror_root)),
                &format!("--prefix={}", msys_compatible(&dst))])) {
        return false;
    }
    if !run(Command::new("make")
        .current_dir(&build)
        .arg("-j").arg(env::var("NUM_JOBS").unwrap())) {
        return false;
    }
    if !run(Command::new("make").current_dir(&build).arg("install")) {
        return false;
    }

    build_shim(&[
       PathBuf::from(gpgerror_root).join("include"),
       PathBuf::from(dst.clone()).join("include"),
    ]);

    println!("cargo:rustc-link-search=native={}",
             PathBuf::from(dst.clone()).join("lib").display());
    println!("cargo:rustc-link-lib=static=gcrypt");
    println!("cargo:root={}", &dst);
    true
}

#[cfg(feature = "shim")]
fn build_shim<P: AsRef<Path>>(include_dirs: &[P]) {
    let mut config = gcc::Config::new();
    for path in include_dirs.iter() {
        config.include(msys_compatible(path));
    }
    config.flag("-Wno-deprecated-declarations").file("shim.c").compile("libgcrypt_shim.a");
}

#[cfg(not(feature = "shim"))]
fn build_shim<P: AsRef<Path>>(_include_dirs: &[P]) {}

fn test_version(version: &str) {
    let version = version.trim();
    for (x, y) in TARGET_VERSION.split('.').zip(version.split('.').chain(iter::repeat("0"))) {
        let (x, y): (u8, u8) = (x.parse().unwrap(), y.parse().unwrap());
        match x.cmp(&y) {
            Ordering::Less => break,
            Ordering::Greater => {
                panic!("gcrypt version `{}` is less than requested `{}`",
                       version, TARGET_VERSION)
            }
            _ => (),
        }
    }
}

fn parse_config_output(output: &str, include_dirs: &mut Vec<OsString>) {
    let parts = output.split(|c: char| c.is_whitespace()).filter_map(|p| if p.len() > 2 {
        Some(p.split_at(2))
    } else {
        None
    });

    for (flag, val) in parts {
        match flag {
            "-I" => include_dirs.push(val.into()),
            "-L" => {
                println!("cargo:rustc-link-search=native={}", val);
            }
            "-F" => {
                println!("cargo:rustc-link-search=framework={}", val);
            }
            "-l" => {
                println!("cargo:rustc-link-lib={}", val);
            }
            _ => (),
        }
    }
}

fn spawn(cmd: &mut Command) -> Option<Child> {
    println!("running: {:?}", cmd);
    match cmd.stdin(Stdio::null()).spawn() {
        Ok(child) => Some(child),
        Err(e) => {
            println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            None
        }
    }
}

fn run(cmd: &mut Command) -> bool {
    if let Some(mut child) = spawn(cmd) {
        match child.wait() {
            Ok(status) => {
                if !status.success() {
                    println!("command did not execute successfully: {:?}\n\
                       expected success, got: {}", cmd, status);
                } else {
                    return true;
                }
            }
            Err(e) => {
                println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            }
        }
    }
    false
}

fn output(cmd: &mut Command) -> Option<String> {
    if let Some(child) = spawn(cmd.stdout(Stdio::piped())) {
        match child.wait_with_output() {
            Ok(output) => {
                if !output.status.success() {
                    println!("command did not execute successfully: {:?}\n\
                       expected success, got: {}", cmd, output.status);
                } else {
                    return String::from_utf8(output.stdout).ok();
                }
            }
            Err(e) => {
                println!("failed to execute command: {:?}\nerror: {}", cmd, e);
            }
        }
    }
    None
}

fn msys_compatible<P: AsRef<Path>>(path: P) -> String {
    let path = path.as_ref().to_str().unwrap();
    if !cfg!(windows) {
        return path.to_string();
    }
    path.replace("C:\\", "/c/").replace("\\", "/")
}

fn gnu_target(target: &str) -> String {
    match target {
        "i686-pc-windows-gnu" => "i686-w64-mingw32".to_string(),
        "x86_64-pc-windows-gnu" => "x86_64-w64-mingw32".to_string(),
        s => s.to_string(),
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io;
use openssl::hash::{Hasher, MessageDigest};

pub struct HashingReader<R> {
    inner: R,
    hasher: Hasher,
}

impl<R: Read> HashingReader<R> {
    pub fn new(r: R) -> HashingReader<R> {
        HashingReader {
            inner: r,
            hasher: Hasher::new(MessageDigest::sha256()).unwrap(),
        }
    }

    pub fn finalize(mut self) -> Vec<u8> {
        #[allow(deprecated)]
#[allow(deprecated)]        #[allow(deprecated)]
        #[allow(deprecated)] self.hasher.finish().unwrap()
    }
}

impl<R: Read> Read for HashingReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let amt = self.inner.read(buf)?;
        self.hasher.update(&buf[..amt]).unwrap();
        Ok(amt)
    }
}
<commit_msg>cargo fmt<commit_after>use std::io::prelude::*;
use std::io;
use openssl::hash::{Hasher, MessageDigest};

pub struct HashingReader<R> {
    inner: R,
    hasher: Hasher,
}

impl<R: Read> HashingReader<R> {
    pub fn new(r: R) -> HashingReader<R> {
        HashingReader {
            inner: r,
            hasher: Hasher::new(MessageDigest::sha256()).unwrap(),
        }
    }

    pub fn finalize(mut self) -> Vec<u8> {
        #[allow(deprecated)]
#[allow(deprecated)]        #[allow(deprecated)]
#[allow(deprecated)]        #[allow(deprecated)]
        #[allow(deprecated)]
        #[allow(deprecated)]
        #[allow(deprecated)] self.hasher.finish().unwrap()
    }
}

impl<R: Read> Read for HashingReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let amt = self.inner.read(buf)?;
        self.hasher.update(&buf[..amt]).unwrap();
        Ok(amt)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nicholas Bishop
//
// 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.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    /// Create a Vec3f from three components
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    /// Create a Vec3f with all components set to the same scalar
    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    /// Squared length of the vector
    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    /// Length of the vector
    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

/// Convert a numeric type to an f32
pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two points
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

/// Linearly interpolate between two points by the factor `t`. When
/// `t` is zero the result is `p0`, and when `t` is one the result is
/// `p1`. The range of `t` is not clamped.
pub fn lerp3(p0: &Vec3f, p1: &Vec3f, t: f32) -> Vec3f {
    let n = 1.0 - t;
    Vec3f::new(p0.x * n + p1.x * t,
               p0.y * n + p1.y * t,
               p0.z * n + p1.z * t)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}

#[test]
fn test_vec3f_lerp() {
    let p0 = vec3f(1.0, 2.0, 3.0);
    let p1 = vec3f(-1.0, -2.0, -3.0);
    assert!(lerp3(&p0, &p1, 0.0) == p0);
    assert!(lerp3(&p0, &p1, 0.25) == vec3f(0.5, 1.0, 1.5));
    assert!(lerp3(&p0, &p1, 0.5) == vec3f(0.0, 0.0, 0.0));
    assert!(lerp3(&p0, &p1, 1.0) == p1);
}
<commit_msg>Add Vec3f::normalized() and test<commit_after>// Copyright 2015 Nicholas Bishop
//
// 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.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    /// Create a Vec3f from three components
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    /// Create a Vec3f with all components set to the same scalar
    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    /// Squared length of the vector
    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    /// Length of the vector
    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }

    /// Create a normalized copy, or None if the magnitude is zero
    pub fn normalized(&self) -> Option<Vec3f> {
        let m = self.magnitude();
        if m == 0.0 {
            None
        }
        else {
            let f = 1.0 / m;
            Some((*self) * f)
        }
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

/// Convert a numeric type to an f32
pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two points
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

/// Linearly interpolate between two points by the factor `t`. When
/// `t` is zero the result is `p0`, and when `t` is one the result is
/// `p1`. The range of `t` is not clamped.
pub fn lerp3(p0: &Vec3f, p1: &Vec3f, t: f32) -> Vec3f {
    let n = 1.0 - t;
    Vec3f::new(p0.x * n + p1.x * t,
               p0.y * n + p1.y * t,
               p0.z * n + p1.z * t)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_normalized() {
    assert_eq!(vec3f(0, 0, 0).normalized(), None);
    assert_eq!(vec3f(0.5, 0, 0).normalized(), Some(vec3f(1, 0, 0)));
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}

#[test]
fn test_vec3f_lerp() {
    let p0 = vec3f(1.0, 2.0, 3.0);
    let p1 = vec3f(-1.0, -2.0, -3.0);
    assert!(lerp3(&p0, &p1, 0.0) == p0);
    assert!(lerp3(&p0, &p1, 0.25) == vec3f(0.5, 1.0, 1.5));
    assert!(lerp3(&p0, &p1, 0.5) == vec3f(0.0, 0.0, 0.0));
    assert!(lerp3(&p0, &p1, 1.0) == p1);
}
<|endoftext|>


<commit_before>use noise::{Seed, Brownian2, Brownian3, perlin2, perlin3};

use field::Field;

pub struct HeightMap {
  pub height: Brownian2<f64, fn (&Seed, &[f64; 2]) -> f64>,
  pub features: Brownian3<f64, fn (&Seed, &[f64; 3]) -> f64>,
  pub seed: Seed,
}

impl HeightMap {
  pub fn new(seed: Seed) -> HeightMap {
    let perlin2: fn(&Seed, &[f64; 2]) -> f64 = perlin2;
    let perlin3: fn(&Seed, &[f64; 3]) -> f64 = perlin3;
    HeightMap {
      seed: seed,
      height:
        Brownian2::new(perlin2, 5)
        .frequency(1.0 / 8.0)
        .persistence(4.0)
        .lacunarity(1.0 / 3.0)
      ,
      features:
        Brownian3::new(perlin3, 2)
        .frequency(1.0 / 32.0)
        .persistence(8.0)
        .lacunarity(1.0 / 4.0)
      ,
    }
  }
}

impl Field for HeightMap {
  /// The height of the field at a given x,y,z.
  fn density_at(&self, x: f32, y: f32, z: f32) -> f32 {
    let height = self.height.apply(&self.seed, &[x as f64, z as f64]);
    let height = height as f32;
    let heightmap_density = height - y;

    let feature_density = self.features.apply(&self.seed, &[x as f64, y as f64, z as f64]) * 8.0;
    let feature_density = feature_density as f32;

    heightmap_density + feature_density
  }
}
<commit_msg>tweak hilliness more<commit_after>use noise::{Seed, Brownian2, Brownian3, perlin2, perlin3};

use field::Field;

pub struct HeightMap {
  pub height: Brownian2<f64, fn (&Seed, &[f64; 2]) -> f64>,
  pub features: Brownian3<f64, fn (&Seed, &[f64; 3]) -> f64>,
  pub seed: Seed,
}

impl HeightMap {
  pub fn new(seed: Seed) -> HeightMap {
    let perlin2: fn(&Seed, &[f64; 2]) -> f64 = perlin2;
    let perlin3: fn(&Seed, &[f64; 3]) -> f64 = perlin3;
    HeightMap {
      seed: seed,
      height:
        Brownian2::new(perlin2, 4)
        .frequency(1.0 / 8.0)
        .persistence(8.0)
        .lacunarity(1.0 / 4.0)
      ,
      features:
        Brownian3::new(perlin3, 2)
        .frequency(1.0 / 32.0)
        .persistence(8.0)
        .lacunarity(1.0 / 4.0)
      ,
    }
  }
}

impl Field for HeightMap {
  /// The height of the field at a given x,y,z.
  fn density_at(&self, x: f32, y: f32, z: f32) -> f32 {
    let height = self.height.apply(&self.seed, &[x as f64, z as f64]);
    let height = height as f32;
    let heightmap_density = height - y;

    let feature_density = self.features.apply(&self.seed, &[x as f64, y as f64, z as f64]) * 8.0;
    let feature_density = feature_density as f32;

    heightmap_density + feature_density
  }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2016-2017 Ivan Dejanovic
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use std::io::stdin;
use std::collections::HashMap;
use std::mem::transmute;

use common::INSTRUCTIONS;

// Bit Masks
const INST_MASK: u64 = 0xFF;

// Opcodes
const HALT: u64 = 0x00;
const IN_N: u64 = 0x01;
const OUT_N: u64 = 0x02;
const IN_S: u64 = 0x03;
const OUT_S: u64 = 0x04;
const ADD: u64 = 0x05;
const SUB: u64 = 0x06;
const MUL: u64 = 0x07;
const DIV: u64 = 0x08;
const CON: u64 = 0x09;
const PUSH: u64 = 0x0A;
const POP: u64 = 0x0B;
const LD: u64 = 0x0C;
const ST: u64 = 0x0D;
const JMP: u64 = 0x0E;
const JGR: u64 = 0x0F;
const JGE: u64 = 0x10;
const JEQ: u64 = 0x11;
const JNE: u64 = 0x12;
const JLE: u64 = 0x13;
const JLS: u64 = 0x14;

const REG_NUM: usize = 8;
const INS_MEM_CAP: usize = 50000;

pub struct Vm {
    ip: usize,
    sp: usize,
    acc: u64,
    reg: [u64; REG_NUM],
    ins_mem: [u64; INS_MEM_CAP],
}

impl Vm {
    pub fn new() -> Box<Vm> {
        Box::new(Vm {
                     ip: 0,
                     sp: 0,
                     acc: 0,
                     reg: [0; REG_NUM],
                     ins_mem: [0; INS_MEM_CAP],
                 })
    }

    pub fn load_code(&mut self, code: Vec<String>) {
        println!("{}", code.len());

        let mut opcode_map: HashMap<&'static str, u64> = HashMap::new();

        opcode_map.insert(INSTRUCTIONS.halt, HALT);
        opcode_map.insert(INSTRUCTIONS.in_n, IN_N);
        opcode_map.insert(INSTRUCTIONS.out_n, OUT_N);
        opcode_map.insert(INSTRUCTIONS.in_s, IN_S);
        opcode_map.insert(INSTRUCTIONS.out_s, OUT_S);
        opcode_map.insert(INSTRUCTIONS.add, ADD);
        opcode_map.insert(INSTRUCTIONS.sub, SUB);
        opcode_map.insert(INSTRUCTIONS.mul, MUL);
        opcode_map.insert(INSTRUCTIONS.div, DIV);
        opcode_map.insert(INSTRUCTIONS.con, CON);
        opcode_map.insert(INSTRUCTIONS.push, PUSH);
        opcode_map.insert(INSTRUCTIONS.pop, POP);
        opcode_map.insert(INSTRUCTIONS.ld, LD);
        opcode_map.insert(INSTRUCTIONS.st, ST);
        opcode_map.insert(INSTRUCTIONS.jmp, JMP);
        opcode_map.insert(INSTRUCTIONS.jgr, JGR);
        opcode_map.insert(INSTRUCTIONS.jge, JGE);
        opcode_map.insert(INSTRUCTIONS.jeq, JEQ);
        opcode_map.insert(INSTRUCTIONS.jne, JNE);
        opcode_map.insert(INSTRUCTIONS.jle, JLE);
        opcode_map.insert(INSTRUCTIONS.jls, JLS);

        for instruction in code {
            println!("{}", instruction);
        }
    }

    pub fn execute(&mut self) {
        loop {
            let inst = self.ins_mem[self.ip];
            let opcode = inst.rotate_left(8) & INST_MASK;

            match opcode {
                HALT => break,
                IN_N => self.process_in_n(),
                OUT_N => self.process_out_n(),
                IN_S => self.process_in_s(),
                OUT_S => self.process_out_s(),
                ADD => self.process_add(),
                SUB => self.process_sub(),
                MUL => self.process_mul(),
                DIV => self.process_div(),
                CON => self.process_con(),
                PUSH => self.process_push(),
                POP => self.process_pop(),
                LD => self.process_ld(),
                ST => self.process_st(),
                JMP => self.process_jmp(),
                JGR => self.process_jgr(),
                JGE => self.process_jge(),
                JEQ => self.process_jeq(),
                JNE => self.process_jne(),
                JLE => self.process_jle(),
                JLS => self.process_jls(),
                _ => {
                    println!("Unknow instruction. Aborting.");
                    break;
                }

            }

            if self.has_errors() {
                self.throw_exception();
                break;
            }
        }
    }

    fn process_in_n(&mut self) {
        let mut input_text = String::new();
        stdin().read_line(&mut input_text).expect("failed to read from stdin");

        let trimmed = input_text.trim();
        match trimmed.parse::<f64>() {
            Ok(i) => {
                self.acc = unsafe { transmute::<f64, u64>(i) };
                self.ip = self.ip + 1;
            }
            Err(..) => self.set_io_error_flag(),
        };
    }

    fn process_out_n(&mut self) {}

    fn process_in_s(&mut self) {}

    fn process_out_s(&mut self) {}

    fn process_add(&mut self) {}

    fn process_sub(&mut self) {}

    fn process_mul(&mut self) {}

    fn process_div(&mut self) {}

    fn process_con(&mut self) {}

    fn process_push(&mut self) {}

    fn process_pop(&mut self) {}

    fn process_ld(&mut self) {}

    fn process_st(&mut self) {}

    fn process_jmp(&mut self) {}

    fn process_jgr(&mut self) {}

    fn process_jge(&mut self) {}

    fn process_jeq(&mut self) {}

    fn process_jne(&mut self) {}

    fn process_jle(&mut self) {}

    fn process_jls(&mut self) {}

    fn set_io_error_flag(&mut self) {
        println!("IO error flag set!")
    }

    fn has_errors(&mut self) -> bool {
        false
    }

    fn throw_exception(&mut self) {
        println!("Exception thrown!")
    }
}
<commit_msg>Implemented process_out_n method.<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2016-2017 Ivan Dejanovic
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use std::io::stdin;
use std::collections::HashMap;
use std::mem::transmute;

use common::INSTRUCTIONS;

// Bit Masks
const INST_MASK: u64 = 0xFF;

// Opcodes
const HALT: u64 = 0x00;
const IN_N: u64 = 0x01;
const OUT_N: u64 = 0x02;
const IN_S: u64 = 0x03;
const OUT_S: u64 = 0x04;
const ADD: u64 = 0x05;
const SUB: u64 = 0x06;
const MUL: u64 = 0x07;
const DIV: u64 = 0x08;
const CON: u64 = 0x09;
const PUSH: u64 = 0x0A;
const POP: u64 = 0x0B;
const LD: u64 = 0x0C;
const ST: u64 = 0x0D;
const JMP: u64 = 0x0E;
const JGR: u64 = 0x0F;
const JGE: u64 = 0x10;
const JEQ: u64 = 0x11;
const JNE: u64 = 0x12;
const JLE: u64 = 0x13;
const JLS: u64 = 0x14;

const REG_NUM: usize = 8;
const INS_MEM_CAP: usize = 50000;

pub struct Vm {
    ip: usize,
    sp: usize,
    acc: u64,
    reg: [u64; REG_NUM],
    ins_mem: [u64; INS_MEM_CAP],
}

impl Vm {
    pub fn new() -> Box<Vm> {
        Box::new(Vm {
                     ip: 0,
                     sp: 0,
                     acc: 0,
                     reg: [0; REG_NUM],
                     ins_mem: [0; INS_MEM_CAP],
                 })
    }

    pub fn load_code(&mut self, code: Vec<String>) {
        println!("{}", code.len());

        let mut opcode_map: HashMap<&'static str, u64> = HashMap::new();

        opcode_map.insert(INSTRUCTIONS.halt, HALT);
        opcode_map.insert(INSTRUCTIONS.in_n, IN_N);
        opcode_map.insert(INSTRUCTIONS.out_n, OUT_N);
        opcode_map.insert(INSTRUCTIONS.in_s, IN_S);
        opcode_map.insert(INSTRUCTIONS.out_s, OUT_S);
        opcode_map.insert(INSTRUCTIONS.add, ADD);
        opcode_map.insert(INSTRUCTIONS.sub, SUB);
        opcode_map.insert(INSTRUCTIONS.mul, MUL);
        opcode_map.insert(INSTRUCTIONS.div, DIV);
        opcode_map.insert(INSTRUCTIONS.con, CON);
        opcode_map.insert(INSTRUCTIONS.push, PUSH);
        opcode_map.insert(INSTRUCTIONS.pop, POP);
        opcode_map.insert(INSTRUCTIONS.ld, LD);
        opcode_map.insert(INSTRUCTIONS.st, ST);
        opcode_map.insert(INSTRUCTIONS.jmp, JMP);
        opcode_map.insert(INSTRUCTIONS.jgr, JGR);
        opcode_map.insert(INSTRUCTIONS.jge, JGE);
        opcode_map.insert(INSTRUCTIONS.jeq, JEQ);
        opcode_map.insert(INSTRUCTIONS.jne, JNE);
        opcode_map.insert(INSTRUCTIONS.jle, JLE);
        opcode_map.insert(INSTRUCTIONS.jls, JLS);

        for instruction in code {
            println!("{}", instruction);
        }
    }

    pub fn execute(&mut self) {
        loop {
            let inst = self.ins_mem[self.ip];
            let opcode = inst.rotate_left(8) & INST_MASK;

            match opcode {
                HALT => break,
                IN_N => self.process_in_n(),
                OUT_N => self.process_out_n(),
                IN_S => self.process_in_s(),
                OUT_S => self.process_out_s(),
                ADD => self.process_add(),
                SUB => self.process_sub(),
                MUL => self.process_mul(),
                DIV => self.process_div(),
                CON => self.process_con(),
                PUSH => self.process_push(),
                POP => self.process_pop(),
                LD => self.process_ld(),
                ST => self.process_st(),
                JMP => self.process_jmp(),
                JGR => self.process_jgr(),
                JGE => self.process_jge(),
                JEQ => self.process_jeq(),
                JNE => self.process_jne(),
                JLE => self.process_jle(),
                JLS => self.process_jls(),
                _ => {
                    println!("Unknow instruction. Aborting.");
                    break;
                }

            }

            if self.has_errors() {
                self.throw_exception();
                break;
            }
        }
    }

    fn process_in_n(&mut self) {
        let mut input_text = String::new();
        stdin().read_line(&mut input_text).expect("failed to read from stdin");

        let trimmed = input_text.trim();
        match trimmed.parse::<f64>() {
            Ok(i) => {
                self.acc = unsafe { transmute::<f64, u64>(i) };
                self.ip = self.ip + 1;
            }
            Err(..) => self.set_io_error_flag(),
        };
    }

    fn process_out_n(&mut self) {
        let output = unsafe { transmute::<u64, f64>(self.acc) };
        println!("{}", output)
    }

    fn process_in_s(&mut self) {}

    fn process_out_s(&mut self) {}

    fn process_add(&mut self) {}

    fn process_sub(&mut self) {}

    fn process_mul(&mut self) {}

    fn process_div(&mut self) {}

    fn process_con(&mut self) {}

    fn process_push(&mut self) {}

    fn process_pop(&mut self) {}

    fn process_ld(&mut self) {}

    fn process_st(&mut self) {}

    fn process_jmp(&mut self) {}

    fn process_jgr(&mut self) {}

    fn process_jge(&mut self) {}

    fn process_jeq(&mut self) {}

    fn process_jne(&mut self) {}

    fn process_jle(&mut self) {}

    fn process_jls(&mut self) {}

    fn set_io_error_flag(&mut self) {
        println!("IO error flag set!")
    }

    fn has_errors(&mut self) -> bool {
        false
    }

    fn throw_exception(&mut self) {
        println!("Exception thrown!")
    }
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate glutin_window;

use std::rc::Rc;
use std::cell::RefCell;
use std::os::raw::c_void;
use glium::backend::{ Backend, Context, Facade };
use glium::{ GliumCreationError, Frame, SwapBuffersError };
use self::piston::event_loop::{ EventLoop, WindowEvents };
use self::piston::window::{ BuildFromWindowSettings, OpenGLWindow, Window, WindowSettings };
use self::piston::input::{ Event, GenericEvent };
use self::glutin_window::GlutinWindow;

#[derive(Clone)]
struct Wrapper<W>(Rc<RefCell<W>>);

/// A window struct for glium.
pub struct GliumWindow<W = GlutinWindow> {
    /// Window.
    pub window: Rc<RefCell<W>>,
    /// Glium context.
    pub context: Rc<Context>,
    /// Event loop state.
    pub events: WindowEvents
}

impl<W> Clone for GliumWindow<W> {
    fn clone(&self) -> GliumWindow<W> {
        GliumWindow {
            window: self.window.clone(),
            context: self.context.clone(),
            events: self.events.clone()
        }
    }
}

impl<W> BuildFromWindowSettings for GliumWindow<W>
    where W: 'static + Window + OpenGLWindow + BuildFromWindowSettings,
          W::Event: GenericEvent
{
    fn build_from_window_settings(mut settings: WindowSettings)
    -> Result<GliumWindow<W>, String> {
        // Turn on sRGB.
        settings = settings.srgb(true);
        GliumWindow::new(&Rc::new(RefCell::new(try!(settings.build()))))
            .map_err(|err| match err {
                GliumCreationError::BackendCreationError(..) =>
                    "Error while creating the backend",
                GliumCreationError::IncompatibleOpenGl(..) =>
                    "The OpenGL implementation is too old to work with glium",
            }.into())
    }
}

impl<W> GliumWindow<W>
    where W: OpenGLWindow + 'static
{
    /// Creates new GliumWindow.
    pub fn new(window: &Rc<RefCell<W>>) -> Result<Self, GliumCreationError<()>> {
        unsafe {
            Context::new(Wrapper(window.clone()), true, Default::default())
        }.map(|context| GliumWindow {
            window: window.clone(),
            context: context,
            events: WindowEvents::new().swap_buffers(false)
        })
    }

    /// Returns new frame.
    pub fn draw(&self) -> Frame {
        Frame::new(self.context.clone(), self.context.get_framebuffer_dimensions())
    }

    /// Returns next event.
    pub fn next(&mut self) -> Option<Event<<W as Window>::Event>> {
        self.events.next(&mut *self.window.borrow_mut())
    }
}

impl<W> Facade for GliumWindow<W> {
    fn get_context(&self) -> &Rc<Context> {
        &self.context
    }
}

unsafe impl<W> Backend for Wrapper<W> where W: OpenGLWindow {
    fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
        self.0.borrow_mut().swap_buffers();
        Ok(())
    }

    unsafe fn get_proc_address(&self, proc_name: &str) -> *const c_void {
        self.0.borrow_mut().get_proc_address(proc_name) as *const c_void
    }

    fn get_framebuffer_dimensions(&self) -> (u32, u32) {
        let size = self.0.borrow().size();
        (size.width, size.height)
    }

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

    unsafe fn make_current(&self) {
        self.0.borrow_mut().make_current()
    }
}
<commit_msg>Added wrapper implies for `GliumWindow`<commit_after>extern crate piston;
extern crate glutin_window;

use std::rc::Rc;
use std::cell::RefCell;
use std::os::raw::c_void;
use glium::backend::{ Backend, Context, Facade };
use glium::{ GliumCreationError, Frame, SwapBuffersError };
use self::piston::event_loop::{ EventLoop, WindowEvents };
use self::piston::window::{
    AdvancedWindow, BuildFromWindowSettings, OpenGLWindow, Size, Window, WindowSettings
};
use self::piston::input::{ Event, GenericEvent };
use self::glutin_window::GlutinWindow;

#[derive(Clone)]
struct Wrapper<W>(Rc<RefCell<W>>);

/// A window struct for glium.
pub struct GliumWindow<W = GlutinWindow> {
    /// Window.
    pub window: Rc<RefCell<W>>,
    /// Glium context.
    pub context: Rc<Context>,
    /// Event loop state.
    pub events: WindowEvents
}

impl<W> Clone for GliumWindow<W> {
    fn clone(&self) -> GliumWindow<W> {
        GliumWindow {
            window: self.window.clone(),
            context: self.context.clone(),
            events: self.events.clone()
        }
    }
}

impl<W> BuildFromWindowSettings for GliumWindow<W>
    where W: 'static + Window + OpenGLWindow + BuildFromWindowSettings,
          W::Event: GenericEvent
{
    fn build_from_window_settings(mut settings: WindowSettings)
    -> Result<GliumWindow<W>, String> {
        // Turn on sRGB.
        settings = settings.srgb(true);
        GliumWindow::new(&Rc::new(RefCell::new(try!(settings.build()))))
            .map_err(|err| match err {
                GliumCreationError::BackendCreationError(..) =>
                    "Error while creating the backend",
                GliumCreationError::IncompatibleOpenGl(..) =>
                    "The OpenGL implementation is too old to work with glium",
            }.into())
    }
}

impl<W> GliumWindow<W>
    where W: OpenGLWindow + 'static
{
    /// Creates new GliumWindow.
    pub fn new(window: &Rc<RefCell<W>>) -> Result<Self, GliumCreationError<()>> {
        unsafe {
            Context::new(Wrapper(window.clone()), true, Default::default())
        }.map(|context| GliumWindow {
            window: window.clone(),
            context: context,
            events: WindowEvents::new().swap_buffers(false)
        })
    }

    /// Returns new frame.
    pub fn draw(&self) -> Frame {
        Frame::new(self.context.clone(), self.context.get_framebuffer_dimensions())
    }

    /// Returns next event.
    pub fn next(&mut self) -> Option<Event<<W as Window>::Event>> {
        self.events.next(&mut *self.window.borrow_mut())
    }
}

impl<W> Facade for GliumWindow<W> {
    fn get_context(&self) -> &Rc<Context> {
        &self.context
    }
}

unsafe impl<W> Backend for Wrapper<W> where W: OpenGLWindow {
    fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
        self.0.borrow_mut().swap_buffers();
        Ok(())
    }

    unsafe fn get_proc_address(&self, proc_name: &str) -> *const c_void {
        self.0.borrow_mut().get_proc_address(proc_name) as *const c_void
    }

    fn get_framebuffer_dimensions(&self) -> (u32, u32) {
        let size = self.0.borrow().size();
        (size.width, size.height)
    }

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

    unsafe fn make_current(&self) {
        self.0.borrow_mut().make_current()
    }
}

impl<W> Window for GliumWindow<W>
    where W: Window
{
    type Event = <W as Window>::Event;

    fn should_close(&self) -> bool { self.window.borrow().should_close() }
    fn set_should_close(&mut self, value: bool) {
        self.window.borrow_mut().set_should_close(value)
    }
    fn size(&self) -> Size { self.window.borrow().size() }
    fn draw_size(&self) -> Size { self.window.borrow().draw_size() }
    fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
    fn poll_event(&mut self) -> Option<Self::Event> {
        Window::poll_event(&mut *self.window.borrow_mut())
    }
}

impl<W> AdvancedWindow for GliumWindow<W>
    where W: AdvancedWindow
{
    fn get_title(&self) -> String { self.window.borrow().get_title() }
    fn set_title(&mut self, title: String) {
        self.window.borrow_mut().set_title(title)
    }
    fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
    fn set_exit_on_esc(&mut self, value: bool) {
        self.window.borrow_mut().set_exit_on_esc(value)
    }
    fn set_capture_cursor(&mut self, value: bool) {
        self.window.borrow_mut().set_capture_cursor(value)
    }
}

impl<W> EventLoop for GliumWindow<W> {
    fn set_ups(&mut self, frames: u64) {
        self.events.set_ups(frames);
    }

    fn set_max_fps(&mut self, frames: u64) {
        self.events.set_max_fps(frames);
    }

    fn set_swap_buffers(&mut self, enable: bool) {
        self.events.set_swap_buffers(enable);
    }

    fn set_bench_mode(&mut self, enable: bool) {
        self.events.set_bench_mode(enable);
    }
}
<|endoftext|>