<commit_before>extern crate minifb;
extern crate bgfx_rs;
extern crate viewdock;

use bgfx_rs::Bgfx;
use libc::{c_void, c_int};
use minifb::{Scale, WindowOptions, MouseMode, MouseButton};
use core::view_plugins::{ViewHandle, ViewPlugins, ViewInstance};
use core::session::{Sessions, Session, SessionHandle};
use self::viewdock::{Workspace, Rect};
use imgui_sys::Imgui;
use prodbg_api::ui_ffi::{PDVec2};
use prodbg_api::view::CViewCallbacks;

const WIDTH: usize = 1280;
const HEIGHT: usize = 800;

pub struct Window {
    /// minifb window
    pub win: minifb::Window,

    /// Views in this window
    pub views: Vec<ViewHandle>,

    ///
    pub ws: Workspace,
}

///! Windows keeps track of all different windows that are present with in the application
///! There are several ways windows can be created:
///!
///! 1. User opens a new window using a shortcut or menu selection.
///! 2. User "undocks" a view from an existing window giving it it's own floating window.
///! 3. etc

pub struct Windows {
    /// All the windows being tracked
    windows: Vec<Window>,
    current: usize,
}

impl Windows {
    pub fn new() -> Windows {
        Windows {
            windows: Vec::new(),
            current: 0,
        }
    }

    /// Create a default window which will only be created if there are no other
    pub fn create_default(&mut self) {
        if self.windows.len() > 0 {
            return;
        }

        let window = Self::create_window(WIDTH, HEIGHT).expect("Unable to create window");

        self.windows.push(window)
   }

    pub fn create_window(width: usize, height: usize) -> minifb::Result<Window> {
        let res = minifb::Window::new("ProDBG",
                                      width,
                                      height,
                                      WindowOptions {
                                          resize: true,
                                          scale: Scale::X1,
                                          ..WindowOptions::default()
                                      });
        match res {
            Ok(win) => {
                Bgfx::create_window(win.get_window_handle() as *const c_void,
                                    width as c_int,
                                    height as c_int);
                Ok(Window {
                    win: win,
                    views: Vec::new(),
                    ws: Workspace::new(Rect::new(0.0, 0.0, WIDTH as f32, HEIGHT as f32)).unwrap(),
                })
            }
            Err(err) => Err(err),
        }
    }

    pub fn create_window_with_menus(&mut self) -> minifb::Result<Window> {
        const WIDTH: usize = 1280;
        const HEIGHT: usize = 1024;

        let window = try!(Self::create_window(WIDTH, HEIGHT));

        // for menu in &menus {
        // window.add_menu(m.name, m.menu);
        // }
        //

        Ok(window)
    }

    pub fn update(&mut self, sessions: &mut Sessions, view_plugins: &mut ViewPlugins) {
        for i in (0..self.windows.len()).rev() {
            self.windows[i].update(sessions, view_plugins);

            if !self.windows[i].win.is_open() {
                self.windows.swap_remove(i);
            }
        }
    }

    pub fn get_current(&mut self) -> &mut Window {
        let current = self.current;
        &mut self.windows[current]
    }

    /// Checks if application should exit (all window instances closed)
    pub fn should_exit(&self) -> bool {
        self.windows.len() == 0
    }

    /// Save the state of the windows (usually done when exiting the application)
    pub fn save(_filename: &str) {}

    /// Load the state of all the views from a previous run
    pub fn load(_filename: &str) {}
}

impl Window {
    fn is_inside(v: (f32, f32), pos: PDVec2, size: PDVec2) -> bool {
        let x0 = pos.x;
        let y0 = pos.y;
        let x1 = pos.x + size.x;
        let y1 = pos.y + size.y;

        if (v.0 >= x0 && v.0 < x1) && (v.1 >= y0 && v.1 < y1) {
            true
        } else {
            false
        }
    }

    fn update_view(instance: &mut ViewInstance, session: &mut Session, show_context_menu: bool, mouse: (f32, f32)) -> u32 {
        let ui = instance.ui;

        //bgfx_imgui_set_window_pos(0.0, 0.0);
        //bgfx_imgui_set_window_size(500.0, 500.0);

        Imgui::begin_window(&instance.name, true);
        Imgui::init_state(ui.api);

        let pos = ui.get_window_pos();
        let size = ui.get_window_size();

        if Self::is_inside(mouse, pos, size) && show_context_menu {
            Imgui::mark_show_popup(ui.api, true);
        } else {
            Imgui::mark_show_popup(ui.api, false);
        }

        unsafe {
            let plugin_funcs = instance.plugin_type.plugin_funcs as *mut CViewCallbacks;
            ((*plugin_funcs).update.unwrap())(instance.plugin_data,
                                                ui.api as *mut c_void,
                                                session.reader.api as *mut c_void,
                                                session.get_current_writer().api as *mut c_void);
        }

        let has_shown_menu = Imgui::has_showed_popup(ui.api);

        Imgui::end_window();

        has_shown_menu
    }

    pub fn update(&mut self, sessions: &mut Sessions, view_plugins: &mut ViewPlugins) {
        self.win.update();

        let mut has_shown_menu = 0u32;

        let mouse = self.win.get_mouse_pos(MouseMode::Clamp).unwrap_or((0.0, 0.0));

        Bgfx::set_mouse_pos(mouse);
        Bgfx::set_mouse_state(0, self.win.get_mouse_down(MouseButton::Left));

        let show_context_menu = self.win.get_mouse_down(MouseButton::Right);

        for view in &self.views {
            if let Some(ref mut v) = view_plugins.get_view(*view) {
                if let Some(ref mut s) = sessions.get_session(v.session_handle) {
                    has_shown_menu |= Self::update_view(v, s, show_context_menu, mouse);
                }
            }
        }

        // if now plugin has showed a menu we do it here
        // TODO: Handle diffrent cases when attach menu on to plugin menu or not

        if has_shown_menu == 0 && show_context_menu {
            Self::show_popup(self, true, view_plugins);
        } else {
            Self::show_popup(self, false, view_plugins);
        }
    }

    fn add_view(&mut self, name: &String, view_plugins: &mut ViewPlugins) {
        let ui = Imgui::create_ui_instance();
        if let Some(handle) = view_plugins.create_instance(ui, name, SessionHandle(0)) {
            self.views.push(handle);
        }
    }

    fn show_popup(&mut self, show: bool, view_plugins: &mut ViewPlugins) {
        let ui = Imgui::get_ui();

        if show {
            ui.open_popup("plugins");
        }

        if ui.begin_popup("plugins") {
            let plugin_names = view_plugins.get_plugin_names();

            if ui.begin_menu("Split Horizontally", true) {
                for name in &plugin_names {
                    if ui.menu_item(name, false, true) {
                        Self::add_view(self, &name, view_plugins);
                    }
                }
                ui.end_menu();
            }

            if ui.begin_menu("Split Vertically", true) {
                for name in &plugin_names {
                    ui.menu_item(name, false, true);
                }
                ui.end_menu();
            }

            ui.end_popup();
        }
    }

    /*
    pub fn add_view(&mut self, view: ViewHandle) {
        self.views.push(view);
    }
    */
}
<commit_msg>Now using docking system<commit_after>extern crate minifb;
extern crate bgfx_rs;
extern crate viewdock;

use bgfx_rs::Bgfx;
use libc::{c_void, c_int};
use minifb::{Scale, WindowOptions, MouseMode, MouseButton};
use core::view_plugins::{ViewHandle, ViewPlugins, ViewInstance};
use core::session::{Sessions, Session, SessionHandle};
use self::viewdock::{Workspace, Rect, Direction, DockHandle};
use imgui_sys::Imgui;
use prodbg_api::ui_ffi::{PDVec2};
use prodbg_api::view::CViewCallbacks;

const WIDTH: usize = 1280;
const HEIGHT: usize = 800;

pub struct Window {
    /// minifb window
    pub win: minifb::Window,

    /// Views in this window
    pub views: Vec<ViewHandle>,

    ///
    pub ws: Workspace,
}

///! Windows keeps track of all different windows that are present with in the application
///! There are several ways windows can be created:
///!
///! 1. User opens a new window using a shortcut or menu selection.
///! 2. User "undocks" a view from an existing window giving it it's own floating window.
///! 3. etc

pub struct Windows {
    /// All the windows being tracked
    windows: Vec<Window>,
    current: usize,
}

impl Windows {
    pub fn new() -> Windows {
        Windows {
            windows: Vec::new(),
            current: 0,
        }
    }

    /// Create a default window which will only be created if there are no other
    pub fn create_default(&mut self) {
        if self.windows.len() > 0 {
            return;
        }

        let window = Self::create_window(WIDTH, HEIGHT).expect("Unable to create window");

        self.windows.push(window)
   }

    pub fn create_window(width: usize, height: usize) -> minifb::Result<Window> {
        let res = minifb::Window::new("ProDBG",
                                      width,
                                      height,
                                      WindowOptions {
                                          resize: true,
                                          scale: Scale::X1,
                                          ..WindowOptions::default()
                                      });
        match res {
            Ok(win) => {
                Bgfx::create_window(win.get_window_handle() as *const c_void,
                                    width as c_int,
                                    height as c_int);
                Ok(Window {
                    win: win,
                    views: Vec::new(),
                    ws: Workspace::new(Rect::new(0.0, 0.0, width as f32, height as f32)).unwrap(),
                })
            }
            Err(err) => Err(err),
        }
    }

    pub fn create_window_with_menus(&mut self) -> minifb::Result<Window> {
        //const WIDTH: usize = 1280;
        //const HEIGHT: usize = 1024;

        let window = try!(Self::create_window(WIDTH, HEIGHT));

        // for menu in &menus {
        // window.add_menu(m.name, m.menu);
        // }
        //

        Ok(window)
    }

    pub fn update(&mut self, sessions: &mut Sessions, view_plugins: &mut ViewPlugins) {
        for i in (0..self.windows.len()).rev() {
            self.windows[i].update(sessions, view_plugins);

            if !self.windows[i].win.is_open() {
                self.windows.swap_remove(i);
            }
        }
    }

    pub fn get_current(&mut self) -> &mut Window {
        let current = self.current;
        &mut self.windows[current]
    }

    /// Checks if application should exit (all window instances closed)
    pub fn should_exit(&self) -> bool {
        self.windows.len() == 0
    }

    /// Save the state of the windows (usually done when exiting the application)
    pub fn save(_filename: &str) {}

    /// Load the state of all the views from a previous run
    pub fn load(_filename: &str) {}
}

impl Window {
    fn is_inside(v: (f32, f32), pos: PDVec2, size: PDVec2) -> bool {
        let x0 = pos.x;
        let y0 = pos.y;
        let x1 = pos.x + size.x;
        let y1 = pos.y + size.y;

        if (v.0 >= x0 && v.0 < x1) && (v.1 >= y0 && v.1 < y1) {
            true
        } else {
            false
        }
    }

    fn update_view(&self, instance: &mut ViewInstance, session: &mut Session, show_context_menu: bool, mouse: (f32, f32)) -> u32 {
        let ui = instance.ui;

        if let Some(rect) = self.ws.get_rect_by_handle(DockHandle(instance.handle.0)) {
            Imgui::set_window_pos(rect.x, rect.y);
            Imgui::set_window_size(rect.width, rect.height);
        }

        Imgui::begin_window(&instance.name, true);
        Imgui::init_state(ui.api);

        let pos = ui.get_window_pos();
        let size = ui.get_window_size();

        if Self::is_inside(mouse, pos, size) && show_context_menu {
            Imgui::mark_show_popup(ui.api, true);
        } else {
            Imgui::mark_show_popup(ui.api, false);
        }

        unsafe {
            let plugin_funcs = instance.plugin_type.plugin_funcs as *mut CViewCallbacks;
            ((*plugin_funcs).update.unwrap())(instance.plugin_data,
                                                ui.api as *mut c_void,
                                                session.reader.api as *mut c_void,
                                                session.get_current_writer().api as *mut c_void);
        }

        let has_shown_menu = Imgui::has_showed_popup(ui.api);

        Imgui::end_window();

        has_shown_menu
    }

    pub fn update(&mut self, sessions: &mut Sessions, view_plugins: &mut ViewPlugins) {
        self.win.update();

        let mut has_shown_menu = 0u32;

        self.ws.update();

        let mouse = self.win.get_mouse_pos(MouseMode::Clamp).unwrap_or((0.0, 0.0));

        Bgfx::set_mouse_pos(mouse);
        Bgfx::set_mouse_state(0, self.win.get_mouse_down(MouseButton::Left));

        let show_context_menu = self.win.get_mouse_down(MouseButton::Right);

        for view in &self.views {
            if let Some(ref mut v) = view_plugins.get_view(*view) {
                if let Some(ref mut s) = sessions.get_session(v.session_handle) {
                    has_shown_menu |= Self::update_view(self, v, s, show_context_menu, mouse);
                }
            }
        }

        // if now plugin has showed a menu we do it here
        // TODO: Handle diffrent cases when attach menu on to plugin menu or not

        if has_shown_menu == 0 && show_context_menu {
            Self::show_popup(self, true, mouse, view_plugins);
        } else {
            Self::show_popup(self, false, mouse, view_plugins);
        }
    }

    /*
    fn add_view(&mut self, name: &String, view_plugins: &mut ViewPlugins) {
        let ui = Imgui::create_ui_instance();
        if let Some(handle) = view_plugins.create_instance(ui, name, SessionHandle(0)) {
            self.views.push(handle);
        }
    }
    */

    fn split_view(&mut self, name: &String, view_plugins: &mut ViewPlugins, pos: (f32, f32), direction: Direction) {
        let ui = Imgui::create_ui_instance();
        if let Some(handle) = view_plugins.create_instance(ui, name, SessionHandle(0)) {
            if let Some(dock_handle) = self.ws.is_hovering_dock(pos) {
                self.ws.split_by_dock_handle(direction, dock_handle, DockHandle(handle.0));
            } else {
                self.ws.split_top(DockHandle(handle.0), direction);
            }

            self.views.push(handle);
        }
    }

    fn show_popup(&mut self, show: bool, mouse_pos: (f32, f32), view_plugins: &mut ViewPlugins) {
        let ui = Imgui::get_ui();

        if show {
            ui.open_popup("plugins");
        }

        if ui.begin_popup("plugins") {
            let plugin_names = view_plugins.get_plugin_names();

            if ui.begin_menu("Split Horizontally", true) {
                for name in &plugin_names {
                    if ui.menu_item(name, false, true) {
                        Self::split_view(self, &name, view_plugins, mouse_pos, Direction::Horizontal);
                    }
                }
                ui.end_menu();
            }

            if ui.begin_menu("Split Vertically", true) {
                for name in &plugin_names {
                    if ui.menu_item(name, false, true) {
                        Self::split_view(self, &name, view_plugins, mouse_pos, Direction::Vertical);
                    }
                }
                ui.end_menu();
            }

            ui.end_popup();
        }
    }
}
<|endoftext|>


<commit_before>// Rust Bitcoin Library
// Written in 2014 by
//   Andrew Poelstra <apoelstra@wpsoftware.net>
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Hash functions
//!
//! Utility functions related to hashing data, including merkleization

use collections::bitv::{Bitv, from_bytes};
use core::char::from_digit;
use core::cmp::min;
use std::default::Default;
use std::fmt;
use std::io::MemWriter;
use std::mem::transmute;
use std::hash::{Hash, Hasher};
use serialize::json::{mod, ToJson};

use crypto::digest::Digest;
use crypto::sha2;

use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder, SimpleEncoder};
use util::uint::Uint128;
use util::uint::Uint256;

/// A Bitcoin hash, 32-bytes, computed from x as SHA256(SHA256(x))
pub struct Sha256dHash([u8, ..32]);

/// A "hasher" which just truncates
pub struct DumbHasher;

// Allow these to be used as a key for Rust's HashMap et. al.
impl Hash<u64> for Sha256dHash {
  #[inline]
  fn hash(&self, state: &mut u64) {
    use std::mem;
    let myarr: [u64, ..4] = unsafe { mem::transmute(*self) };
    *state = myarr[0];
  }
}

impl Hash<u64> for Uint256 {
  #[inline]
  fn hash(&self, state: &mut u64) {
    use std::mem;
    let myarr: [u64, ..4] = unsafe { mem::transmute(*self) };
    *state = myarr[0];
  }
}

impl Hash<u64> for Uint128 {
  #[inline]
  fn hash(&self, state: &mut u64) {
    use std::mem;
    let myarr: [u64, ..2] = unsafe { mem::transmute(*self) };
    *state = myarr[0];
  }
}

impl Hasher<u64> for DumbHasher {
  #[inline]
  fn hash<T: Hash<u64>>(&self, value: &T) -> u64 {
    let mut ret = 0u64;
    value.hash(&mut ret);
    ret
  }
}

impl Default for DumbHasher {
  #[inline]
  fn default() -> DumbHasher { DumbHasher }
}

/// Returns the all-zeroes "hash"
pub fn zero_hash() -> Sha256dHash { Sha256dHash([0u8, ..32]) }

impl Sha256dHash {
  /// Create a hash by hashing some data
  pub fn from_data(data: &[u8]) -> Sha256dHash {
    let Sha256dHash(mut ret) = zero_hash();
    let mut sha2 = sha2::Sha256::new();
    sha2.input(data);
    sha2.result(ret.as_mut_slice());
    sha2.reset();
    sha2.input(ret.as_slice());
    sha2.result(ret.as_mut_slice());
    Sha256dHash(ret)
  }

  /// Returns a slice containing the bytes of the has
  pub fn as_slice<'a>(&'a self) -> &'a [u8] {
    let &Sha256dHash(ref data) = self;
    data.as_slice()
  }

  /// Converts a hash to a bit vector
  pub fn as_bitv(&self) -> Bitv {
    from_bytes(self.as_slice())
  }

  /// Converts a hash to a Uint256, interpreting it as a little endian number.
  pub fn into_uint256(self) -> Uint256 {
    let Sha256dHash(data) = self;
    unsafe { Uint256(transmute(data)) }
  }

  /// Converts a hash to a Uint128, interpreting it as a little endian number.
  pub fn into_uint128(self) -> Uint128 {
    let Sha256dHash(data) = self;
    // TODO: this function won't work correctly on big-endian machines
    unsafe { Uint128(transmute([data[16], data[17], data[18], data[19], data[20],
                                data[21], data[22], data[23], data[24], data[25],
                                data[26], data[27], data[28], data[29], data[30],
                                data[31]])) }
  }

  /// Human-readable hex output
  pub fn le_hex_string(&self) -> String {
    let &Sha256dHash(data) = self;
    let mut ret = String::with_capacity(64);
    for i in range(0u, 32).rev() {
      ret.push_char(from_digit((data[i] / 0x10) as uint, 16).unwrap());
      ret.push_char(from_digit((data[i] & 0x0f) as uint, 16).unwrap());
    }
    ret
  }
}

impl Clone for Sha256dHash {
  fn clone(&self) -> Sha256dHash {
    *self
  }
}

impl PartialEq for Sha256dHash {
  fn eq(&self, other: &Sha256dHash) -> bool {
    let &Sha256dHash(ref mydata) = self;
    let &Sha256dHash(ref yourdata) = other;
    for i in range(0u, 32) {
      if mydata[i] != yourdata[i] {
        return false;
      }
    }
    return true;
  }
}

impl Eq for Sha256dHash {}

impl Index<uint, u8> for Sha256dHash {
  #[inline]
  fn index<'a>(&'a self, idx: &uint) -> &'a u8 {
    let &Sha256dHash(ref data) = self;
    &data[*idx]
  }
}

// Note that this outputs hashes as big endian hex numbers, so this should be
// used only for user-facing stuff. Internal and network serialization is
// little-endian and should be done using the consensus `encodable::ConsensusEncodable`
// interface.
impl ToJson for Sha256dHash {
  fn to_json(&self) -> json::Json {
    json::String(self.le_hex_string())
  }
}

impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for Sha256dHash {
  #[inline]
  fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
    self.into_uint256().consensus_encode(s)
  }
}

impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Sha256dHash {
  #[inline]
  fn consensus_decode(d: &mut D) -> Result<Sha256dHash, E> {
    Ok(Sha256dHash(try!(ConsensusDecodable::consensus_decode(d))))
  }
}

impl fmt::LowerHex for Sha256dHash {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    let &Sha256dHash(ref data) = self;
    let mut rv = [0, ..64];
    let mut hex = data.iter().rev().map(|n| *n).enumerate();
    for (i, ch) in hex {
      rv[2*i]     = from_digit(ch as uint / 16, 16).unwrap() as u8;
      rv[2*i + 1] = from_digit(ch as uint % 16, 16).unwrap() as u8;
    }
    f.write(rv.as_slice())
  }
}

impl fmt::Show for Sha256dHash {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:x}", *self)
  }
}

/// Any collection of objects for which a merkle root makes sense to calculate
pub trait MerkleRoot {
  /// Construct a merkle tree from a collection, with elements ordered as
  /// they were in the original collection, and return the merkle root.
  fn merkle_root(&self) -> Sha256dHash;
}

impl<'a, T: BitcoinHash> MerkleRoot for &'a [T] {
  fn merkle_root(&self) -> Sha256dHash {
    fn merkle_root(data: Vec<Sha256dHash>) -> Sha256dHash {
      // Base case
      if data.len() < 1 {
        return zero_hash();
      }
      if data.len() < 2 {
        return data[0];
      }
      // Recursion
      let mut next = vec![];
      for idx in range(0, (data.len() + 1) / 2) {
        let idx1 = 2 * idx;
        let idx2 = min(idx1 + 1, data.len() - 1);
        let mut encoder = RawEncoder::new(MemWriter::new());
        data[idx1].consensus_encode(&mut encoder).unwrap();
        data[idx2].consensus_encode(&mut encoder).unwrap();
        next.push(encoder.unwrap().unwrap().bitcoin_hash());
      }
      merkle_root(next)
    }
    merkle_root(self.iter().map(|obj| obj.bitcoin_hash()).collect())
  }
}

impl <T: BitcoinHash> MerkleRoot for Vec<T> {
  fn merkle_root(&self) -> Sha256dHash {
    self.as_slice().merkle_root()
  }
}

#[cfg(test)]
mod tests {
  use std::prelude::*;
  use collections::bitv::from_bytes;

  use util::hash::Sha256dHash;
  use util::misc::hex_bytes;

  #[test]
  fn test_sha256d() {
    assert_eq!(Sha256dHash::from_data(&[]).as_slice(),
               hex_bytes("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap().as_slice());
    assert_eq!(Sha256dHash::from_data(&[]).le_hex_string(),
               "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d".to_string());
    assert_eq!(Sha256dHash::from_data(b"TEST").as_slice(),
               hex_bytes("d7bd34bfe44a18d2aa755a344fe3e6b06ed0473772e6dfce16ac71ba0b0a241c").unwrap().as_slice());
  }

  #[test]
  fn test_hash_to_bitvset() {
    assert_eq!(Sha256dHash::from_data(&[]).as_bitv(),
               from_bytes(hex_bytes("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap().as_slice()));
  }
}

<commit_msg>Sha256dHash: add string encoder/decoder<commit_after>// Rust Bitcoin Library
// Written in 2014 by
//   Andrew Poelstra <apoelstra@wpsoftware.net>
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Hash functions
//!
//! Utility functions related to hashing data, including merkleization

use collections::bitv::{Bitv, from_bytes};
use core::char::from_digit;
use core::cmp::min;
use std::default::Default;
use std::fmt;
use std::io::MemWriter;
use std::mem::transmute;
use std::hash::{Hash, Hasher};
use serialize::json::{mod, ToJson};

use crypto::digest::Digest;
use crypto::sha2;

use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::serialize::{RawEncoder, BitcoinHash, SimpleDecoder, SimpleEncoder};
use util::uint::Uint128;
use util::uint::Uint256;

/// A Bitcoin hash, 32-bytes, computed from x as SHA256(SHA256(x))
pub struct Sha256dHash([u8, ..32]);

/// A "hasher" which just truncates
pub struct DumbHasher;

// Allow these to be used as a key for Rust's HashMap et. al.
impl Hash<u64> for Sha256dHash {
  #[inline]
  fn hash(&self, state: &mut u64) {
    use std::mem;
    let myarr: [u64, ..4] = unsafe { mem::transmute(*self) };
    *state = myarr[0];
  }
}

impl Hash<u64> for Uint256 {
  #[inline]
  fn hash(&self, state: &mut u64) {
    use std::mem;
    let myarr: [u64, ..4] = unsafe { mem::transmute(*self) };
    *state = myarr[0];
  }
}

impl Hash<u64> for Uint128 {
  #[inline]
  fn hash(&self, state: &mut u64) {
    use std::mem;
    let myarr: [u64, ..2] = unsafe { mem::transmute(*self) };
    *state = myarr[0];
  }
}

impl Hasher<u64> for DumbHasher {
  #[inline]
  fn hash<T: Hash<u64>>(&self, value: &T) -> u64 {
    let mut ret = 0u64;
    value.hash(&mut ret);
    ret
  }
}

impl Default for DumbHasher {
  #[inline]
  fn default() -> DumbHasher { DumbHasher }
}

/// Returns the all-zeroes "hash"
pub fn zero_hash() -> Sha256dHash { Sha256dHash([0u8, ..32]) }

impl Sha256dHash {
  /// Create a hash by hashing some data
  pub fn from_data(data: &[u8]) -> Sha256dHash {
    let Sha256dHash(mut ret) = zero_hash();
    let mut sha2 = sha2::Sha256::new();
    sha2.input(data);
    sha2.result(ret.as_mut_slice());
    sha2.reset();
    sha2.input(ret.as_slice());
    sha2.result(ret.as_mut_slice());
    Sha256dHash(ret)
  }

  /// Returns a slice containing the bytes of the has
  pub fn as_slice<'a>(&'a self) -> &'a [u8] {
    let &Sha256dHash(ref data) = self;
    data.as_slice()
  }

  /// Converts a hash to a bit vector
  pub fn as_bitv(&self) -> Bitv {
    from_bytes(self.as_slice())
  }

  /// Converts a hash to a Uint256, interpreting it as a little endian number.
  pub fn into_uint256(self) -> Uint256 {
    let Sha256dHash(data) = self;
    unsafe { Uint256(transmute(data)) }
  }

  /// Converts a hash to a Uint128, interpreting it as a little endian number.
  pub fn into_uint128(self) -> Uint128 {
    let Sha256dHash(data) = self;
    // TODO: this function won't work correctly on big-endian machines
    unsafe { Uint128(transmute([data[16], data[17], data[18], data[19], data[20],
                                data[21], data[22], data[23], data[24], data[25],
                                data[26], data[27], data[28], data[29], data[30],
                                data[31]])) }
  }

  /// Human-readable hex output
  pub fn le_hex_string(&self) -> String {
    let &Sha256dHash(data) = self;
    let mut ret = String::with_capacity(64);
    for i in range(0u, 32).rev() {
      ret.push_char(from_digit((data[i] / 0x10) as uint, 16).unwrap());
      ret.push_char(from_digit((data[i] & 0x0f) as uint, 16).unwrap());
    }
    ret
  }

  /// Human-readable hex output
  pub fn be_hex_string(&self) -> String {
    let &Sha256dHash(data) = self;
    let mut ret = String::with_capacity(64);
    for i in range(0u, 32) {
      ret.push_char(from_digit((data[i] / 0x10) as uint, 16).unwrap());
      ret.push_char(from_digit((data[i] & 0x0f) as uint, 16).unwrap());
    }
    ret
  }
}

impl Clone for Sha256dHash {
  fn clone(&self) -> Sha256dHash {
    *self
  }
}

impl PartialEq for Sha256dHash {
  fn eq(&self, other: &Sha256dHash) -> bool {
    let &Sha256dHash(ref mydata) = self;
    let &Sha256dHash(ref yourdata) = other;
    for i in range(0u, 32) {
      if mydata[i] != yourdata[i] {
        return false;
      }
    }
    return true;
  }
}

impl Eq for Sha256dHash {}

impl Index<uint, u8> for Sha256dHash {
  #[inline]
  fn index<'a>(&'a self, idx: &uint) -> &'a u8 {
    let &Sha256dHash(ref data) = self;
    &data[*idx]
  }
}

// Note that this outputs hashes as big endian hex numbers, so this should be
// used only for user-facing stuff. Internal and network serialization is
// little-endian and should be done using the consensus `encodable::ConsensusEncodable`
// interface.
impl ToJson for Sha256dHash {
  fn to_json(&self) -> json::Json {
    json::String(self.be_hex_string())
  }
}

// Non-consensus encoding (big-endian hex string)
impl<S: ::serialize::Encoder<E>, E> ::serialize::Encodable<S, E> for Sha256dHash {
  #[inline]
  fn encode(&self, s: &mut S) -> Result<(), E> {
    s.emit_str(self.be_hex_string().as_slice())
  }
}

impl<D: ::serialize::Decoder<E>, E> ::serialize::Decodable<D, E> for Sha256dHash {
  #[inline]
  fn decode(d: &mut D) -> Result<Sha256dHash, E> {
    use serialize::hex::FromHex;

    let hex_str = try!(d.read_str());
    if hex_str.len() != 64 {
      d.error("incorrect hash length");
    }
    let raw_str = try!(hex_str.as_slice().from_hex()
                         .map_err(|_| d.error("non-hexadecimal hash string")));
    let mut ret = [0u8, ..32];
    for i in range(0, 32) {
      ret[i] = raw_str[i];
    }
    Ok(Sha256dHash(ret))
  }
}

// Consensus encoding (little-endian)
impl<S:SimpleEncoder<E>, E> ConsensusEncodable<S, E> for Sha256dHash {
  #[inline]
  fn consensus_encode(&self, s: &mut S) -> Result<(), E> {
    self.into_uint256().consensus_encode(s)
  }
}

impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Sha256dHash {
  #[inline]
  fn consensus_decode(d: &mut D) -> Result<Sha256dHash, E> {
    Ok(Sha256dHash(try!(ConsensusDecodable::consensus_decode(d))))
  }
}

impl fmt::LowerHex for Sha256dHash {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    let &Sha256dHash(ref data) = self;
    let mut rv = [0, ..64];
    let mut hex = data.iter().rev().map(|n| *n).enumerate();
    for (i, ch) in hex {
      rv[2*i]     = from_digit(ch as uint / 16, 16).unwrap() as u8;
      rv[2*i + 1] = from_digit(ch as uint % 16, 16).unwrap() as u8;
    }
    f.write(rv.as_slice())
  }
}

impl fmt::Show for Sha256dHash {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{:x}", *self)
  }
}

/// Any collection of objects for which a merkle root makes sense to calculate
pub trait MerkleRoot {
  /// Construct a merkle tree from a collection, with elements ordered as
  /// they were in the original collection, and return the merkle root.
  fn merkle_root(&self) -> Sha256dHash;
}

impl<'a, T: BitcoinHash> MerkleRoot for &'a [T] {
  fn merkle_root(&self) -> Sha256dHash {
    fn merkle_root(data: Vec<Sha256dHash>) -> Sha256dHash {
      // Base case
      if data.len() < 1 {
        return zero_hash();
      }
      if data.len() < 2 {
        return data[0];
      }
      // Recursion
      let mut next = vec![];
      for idx in range(0, (data.len() + 1) / 2) {
        let idx1 = 2 * idx;
        let idx2 = min(idx1 + 1, data.len() - 1);
        let mut encoder = RawEncoder::new(MemWriter::new());
        data[idx1].consensus_encode(&mut encoder).unwrap();
        data[idx2].consensus_encode(&mut encoder).unwrap();
        next.push(encoder.unwrap().unwrap().bitcoin_hash());
      }
      merkle_root(next)
    }
    merkle_root(self.iter().map(|obj| obj.bitcoin_hash()).collect())
  }
}

impl <T: BitcoinHash> MerkleRoot for Vec<T> {
  fn merkle_root(&self) -> Sha256dHash {
    self.as_slice().merkle_root()
  }
}

#[cfg(test)]
mod tests {
  use std::prelude::*;
  use collections::bitv::from_bytes;
  use std::io::{MemWriter, MemReader, Reader, Writer};
  use std::str::from_utf8;

  use serialize::Encodable;
  use serialize::json;
  use util::hash::Sha256dHash;
  use util::misc::hex_bytes;

  #[test]
  fn test_sha256d() {
    assert_eq!(Sha256dHash::from_data(&[]).as_slice(),
               hex_bytes("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap().as_slice());
    assert_eq!(Sha256dHash::from_data(&[]).le_hex_string(),
               "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d".to_string());
    assert_eq!(Sha256dHash::from_data(b"TEST").as_slice(),
               hex_bytes("d7bd34bfe44a18d2aa755a344fe3e6b06ed0473772e6dfce16ac71ba0b0a241c").unwrap().as_slice());
  }

  #[test]
  fn test_hash_to_bitvset() {
    assert_eq!(Sha256dHash::from_data(&[]).as_bitv(),
               from_bytes(hex_bytes("5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456").unwrap().as_slice()));
  }

  #[test]
  fn test_hash_encode_decode() {
    let hash = Sha256dHash::from_data(&[]);
    let mut writer = MemWriter::new();
    {
      let mut encoder = json::Encoder::new(&mut writer);
      assert!(hash.encode(&mut encoder).is_ok());
    }
    let res = writer.unwrap();
    assert_eq!(res.as_slice(),
               "\"5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456\"".as_bytes());
    assert_eq!(json::decode(from_utf8(res.as_slice()).unwrap()), Ok(hash));
  }
}

<|endoftext|>


<commit_before>use game::{Game, View, ViewAction};
use game::data::Rectangle;
use game::gfx::{CopySprite, Sprite};
use views::tilemap::{TerrainTile, TerrainSpriteSheet, TILES_PCS_W, TILES_PCS_H, TILESHEET_PCS_W, TILESHEET_PCS_H, get_tiles, viewport_move};
use views::background::{Background};
use data::{load_character};
use sdl2::mixer::{Chunk};
use std::path::Path;

mod tilemap;
mod background;

const PLAYER_SPEED: f64 = 170.0;
const ZOOM_SPEED: f32 = 0.01;
const CHARACTER_W: f64 = 56.0;
const CHARACTER_H: f64 = 43.0;

pub const SCREEN_WIDTH: f64 = 1280.0;
pub const SCREEN_HEIGHT: f64 = 720.0;

const FIRE_SPRITE_START_INDEX: usize = 211;

#[derive(Clone, Copy)]
enum CharacterFrame {
  Right = 0,
  UpRight = 1,
  Up = 2,
  UpLeft = 3,
  Left = 4,
  DownLeft = 5,
  Down = 6,
  DownRight = 7,
}

struct Character {
  rect: Rectangle,
  sprites: Vec<Sprite>,
  current: CharacterFrame,
  heading: CharacterFrame,
  move_anim_index: u32,
  fire_anim_index: u32
}

pub struct GameView {
  player: Character,
  tiles: Vec<TerrainTile>,
  sprite_sheet: Vec<Sprite>,
  background: Background,
  pistol: Chunk,
}

impl GameView {
  pub fn new(game: &mut Game) -> GameView {
    let spritesheet = Sprite::load(&mut game.renderer, "assets/character.png").unwrap();
    let pistol_audio = Chunk::from_file(Path::new("assets/audio/pistol.ogg")).unwrap();
    let character_datapoints = load_character();
    let mut sprites = Vec::with_capacity(512);

    for x in 0..(FIRE_SPRITE_START_INDEX - 1) {
      sprites.push(spritesheet.region(character_datapoints[x]).unwrap());
    }

    for x in FIRE_SPRITE_START_INDEX..255 {
      sprites.push(spritesheet.region(character_datapoints[x]).unwrap());
    }

    GameView {
      player: Character {
        rect: Rectangle {
          x: SCREEN_WIDTH * 0.5,
          y: SCREEN_HEIGHT * 0.4,
          w: CHARACTER_W,
          h: CHARACTER_H,
        },
        sprites: sprites.clone(),
        current: CharacterFrame::Down,
        heading: CharacterFrame::Down,
        move_anim_index: 0,
        fire_anim_index: 0
      },

      tiles: get_tiles(),

      sprite_sheet: TerrainSpriteSheet::new(&game),

      pistol: pistol_audio,

      background: Background {
        pos: 0.0,
        sprite: Sprite::load(&mut game.renderer, "assets/background.png").unwrap(),
      }
    }
  }
}

impl View for GameView {
  fn render(&mut self, game: &mut Game, elapsed: f64) -> ViewAction {
    if game.events.now.quit || game.events.now.key_escape == Some(true) {
      return ViewAction::Quit;
    }

    let diagonal = (game.events.key_up ^ game.events.key_down) && (game.events.key_left ^ game.events.key_right);
    let moved = if diagonal { 1.0 / 2.0f64.sqrt() } else { 1.0 } * PLAYER_SPEED * elapsed;
    let dx = match (game.events.key_left, game.events.key_right) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    let dy = match (game.events.key_up, game.events.key_down) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    self.player.rect.x += dx * 1.5;
    self.player.rect.y += dy * 0.75;

    let movable_region = Rectangle {
      x: 0.0,
      y: 0.0,
      w: game.output_size().0 * 2.0,
      h: game.output_size().1 * 2.0,
    };

    let curr_rect = game.renderer.viewport();
    let rect = viewport_move(&game, curr_rect);
    game.renderer.set_viewport(rect.to_sdl());

    self.background.render(&mut game.renderer);

    self.player.rect = self.player.rect.move_inside(movable_region).unwrap();
    self.player.current =
    if dx == 0.0 && dy < 0.0       { CharacterFrame::Up }
    else if dx > 0.0 && dy < 0.0   { CharacterFrame::UpRight }
    else if dx < 0.0 && dy < 0.0   { CharacterFrame::UpLeft }
    else if dx == 0.0 && dy == 0.0 { self.player.heading }
    else if dx > 0.0 && dy == 0.0  { CharacterFrame::Right }
    else if dx < 0.0 && dy == 0.0  { CharacterFrame::Left }
    else if dx == 0.0 && dy > 0.0  { CharacterFrame::Down }
    else if dx > 0.0 && dy > 0.0   { CharacterFrame::DownRight }
    else if dx < 0.0 && dy > 0.0   { CharacterFrame::DownLeft }
    else { unreachable!() };

    self.player.heading = self.player.current;
    for x in 0..TILES_PCS_W {
      for y in 0..TILES_PCS_H {
        let index = x * TILES_PCS_H + y;
        game.renderer.copy_sprite(&self.sprite_sheet[(self.tiles[index].current-1) as usize], self.tiles[index].rect);
      }
    }

    match game.events.mouse_click {
      Some(_) => {
        let index = 211 + self.player.current as usize * 5 + self.player.fire_anim_index as usize;
        game.renderer.copy_sprite(&self.player.sprites[index], self.player.rect);
        self.player.fire_anim_index =
          if dx == 0.0 && dy == 0.0 { 0u32 } else if self.player.fire_anim_index < 4u32 { self.player.fire_anim_index + 1u32 } else { 0u32 };
        if self.player.fire_anim_index == 0 {
          game.play_sound(&self.pistol);
        }
      },
      None => {
        let index = self.player.current as usize * 28 + self.player.move_anim_index as usize;
        game.renderer.copy_sprite(&self.player.sprites[index], self.player.rect);
        self.player.move_anim_index =
          if dx == 0.0 && dy == 0.0 { 0u32 } else if self.player.move_anim_index < 13u32 { self.player.move_anim_index + 1u32 } else { 0u32 };
      },
    };

    let scale = game.renderer.scale();
    if game.events.zoom_in == true && scale.0 <= 2.0 && scale.1 <= 2.0 {
      let _ = game.renderer.set_scale(scale.0 + ZOOM_SPEED, scale.1 + ZOOM_SPEED);
    } else if game.events.zoom_out == true && scale.0 > 0.85 && scale.1 > 0.85 {
      let _ = game.renderer.set_scale(scale.0 - ZOOM_SPEED, scale.1 - ZOOM_SPEED);
    }

    ViewAction::None
  }
}
<commit_msg>Add CHARACTER_POS_W/H variables<commit_after>use game::{Game, View, ViewAction};
use game::data::Rectangle;
use game::gfx::{CopySprite, Sprite};
use views::tilemap::{TerrainTile, TerrainSpriteSheet, TILES_PCS_W, TILES_PCS_H, TILESHEET_PCS_W, TILESHEET_PCS_H, get_tiles, viewport_move};
use views::background::{Background};
use data::{load_character};
use sdl2::mixer::{Chunk};
use std::path::Path;

mod tilemap;
mod background;

const PLAYER_SPEED: f64 = 170.0;
const ZOOM_SPEED: f32 = 0.01;
const CHARACTER_W: f64 = 56.0;
const CHARACTER_H: f64 = 43.0;

const CHARACTER_POS_W: f64 = SCREEN_WIDTH * 0.5;
const CHARACTER_POS_H: f64 = SCREEN_HEIGHT * 0.4;

pub const SCREEN_WIDTH: f64 = 1280.0;
pub const SCREEN_HEIGHT: f64 = 720.0;

const FIRE_SPRITE_START_INDEX: usize = 211;

#[derive(Clone, Copy)]
enum CharacterFrame {
  Right = 0,
  UpRight = 1,
  Up = 2,
  UpLeft = 3,
  Left = 4,
  DownLeft = 5,
  Down = 6,
  DownRight = 7,
}

struct Character {
  rect: Rectangle,
  sprites: Vec<Sprite>,
  current: CharacterFrame,
  heading: CharacterFrame,
  move_anim_index: u32,
  fire_anim_index: u32
}

pub struct GameView {
  player: Character,
  tiles: Vec<TerrainTile>,
  sprite_sheet: Vec<Sprite>,
  background: Background,
  pistol: Chunk,
}

impl GameView {
  pub fn new(game: &mut Game) -> GameView {
    let spritesheet = Sprite::load(&mut game.renderer, "assets/character.png").unwrap();
    let pistol_audio = Chunk::from_file(Path::new("assets/audio/pistol.ogg")).unwrap();
    let character_datapoints = load_character();
    let mut sprites = Vec::with_capacity(512);

    for x in 0..(FIRE_SPRITE_START_INDEX - 1) {
      sprites.push(spritesheet.region(character_datapoints[x]).unwrap());
    }

    for x in FIRE_SPRITE_START_INDEX..255 {
      sprites.push(spritesheet.region(character_datapoints[x]).unwrap());
    }

    GameView {
      player: Character {
        rect: Rectangle {
          x: CHARACTER_POS_W,
          y: CHARACTER_POS_H,
          w: CHARACTER_W,
          h: CHARACTER_H,
        },
        sprites: sprites.clone(),
        current: CharacterFrame::Down,
        heading: CharacterFrame::Down,
        move_anim_index: 0,
        fire_anim_index: 0
      },

      tiles: get_tiles(),

      sprite_sheet: TerrainSpriteSheet::new(&game),

      pistol: pistol_audio,

      background: Background {
        pos: 0.0,
        sprite: Sprite::load(&mut game.renderer, "assets/background.png").unwrap(),
      }
    }
  }
}

impl View for GameView {
  fn render(&mut self, game: &mut Game, elapsed: f64) -> ViewAction {
    if game.events.now.quit || game.events.now.key_escape == Some(true) {
      return ViewAction::Quit;
    }

    let diagonal = (game.events.key_up ^ game.events.key_down) && (game.events.key_left ^ game.events.key_right);
    let moved = if diagonal { 1.0 / 2.0f64.sqrt() } else { 1.0 } * PLAYER_SPEED * elapsed;
    let dx = match (game.events.key_left, game.events.key_right) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    let dy = match (game.events.key_up, game.events.key_down) {
      (true, true) | (false, false) => 0.0,
      (true, false) => -moved,
      (false, true) => moved,
    };

    self.player.rect.x += dx * 1.5;
    self.player.rect.y += dy * 0.75;

    let movable_region = Rectangle {
      x: 0.0,
      y: 0.0,
      w: game.output_size().0 * 2.0,
      h: game.output_size().1 * 2.0,
    };

    let curr_rect = game.renderer.viewport();
    let rect = viewport_move(&game, curr_rect);
    game.renderer.set_viewport(rect.to_sdl());

    self.background.render(&mut game.renderer);

    self.player.rect = self.player.rect.move_inside(movable_region).unwrap();
    self.player.current =
    if dx == 0.0 && dy < 0.0       { CharacterFrame::Up }
    else if dx > 0.0 && dy < 0.0   { CharacterFrame::UpRight }
    else if dx < 0.0 && dy < 0.0   { CharacterFrame::UpLeft }
    else if dx == 0.0 && dy == 0.0 { self.player.heading }
    else if dx > 0.0 && dy == 0.0  { CharacterFrame::Right }
    else if dx < 0.0 && dy == 0.0  { CharacterFrame::Left }
    else if dx == 0.0 && dy > 0.0  { CharacterFrame::Down }
    else if dx > 0.0 && dy > 0.0   { CharacterFrame::DownRight }
    else if dx < 0.0 && dy > 0.0   { CharacterFrame::DownLeft }
    else { unreachable!() };

    self.player.heading = self.player.current;
    for x in 0..TILES_PCS_W {
      for y in 0..TILES_PCS_H {
        let index = x * TILES_PCS_H + y;
        game.renderer.copy_sprite(&self.sprite_sheet[(self.tiles[index].current-1) as usize], self.tiles[index].rect);
      }
    }

    match game.events.mouse_click {
      Some(_) => {
        let index = 211 + self.player.current as usize * 5 + self.player.fire_anim_index as usize;
        game.renderer.copy_sprite(&self.player.sprites[index], self.player.rect);
        self.player.fire_anim_index =
          if dx == 0.0 && dy == 0.0 { 0u32 } else if self.player.fire_anim_index < 4u32 { self.player.fire_anim_index + 1u32 } else { 0u32 };
        if self.player.fire_anim_index == 0 {
          game.play_sound(&self.pistol);
        }
      },
      None => {
        let index = self.player.current as usize * 28 + self.player.move_anim_index as usize;
        game.renderer.copy_sprite(&self.player.sprites[index], self.player.rect);
        self.player.move_anim_index =
          if dx == 0.0 && dy == 0.0 { 0u32 } else if self.player.move_anim_index < 13u32 { self.player.move_anim_index + 1u32 } else { 0u32 };
      },
    };

    let scale = game.renderer.scale();
    if game.events.zoom_in == true && scale.0 <= 2.0 && scale.1 <= 2.0 {
      let _ = game.renderer.set_scale(scale.0 + ZOOM_SPEED, scale.1 + ZOOM_SPEED);
    } else if game.events.zoom_out == true && scale.0 > 0.85 && scale.1 > 0.85 {
      let _ = game.renderer.set_scale(scale.0 - ZOOM_SPEED, scale.1 - ZOOM_SPEED);
    }

    ViewAction::None
  }
}
<|endoftext|>


<commit_before>extern crate multipart;
extern crate iron;

use std::fs::File;
use std::io::Read;
use multipart::server::{Multipart, Entries, SaveResult};
use iron::prelude::*;
use iron::status;

fn main() {
    Iron::new(process_request).http("localhost:80").expect("Could not bind localhost:80");
}

/// Processes a request and returns response or an occured error.
fn process_request(request: &mut Request) -> IronResult<Response> {
    // Getting a multipart reader wrapper
    match Multipart::from_request(request) {
        Ok(mut multipart) => {
            // Fetching all data and processing it.
            // save_all() reads the request fully, parsing all fields and saving all files
            // in a new temporary directory under the OS temporary directory.
            match multipart.save_all() {
                SaveResult::Full(entries) => process_entries(entries),
                SaveResult::Partial(entries, error) => {
                    try!(process_entries(entries));
                    Err(IronError::new(error, status::InternalServerError))
                }
                SaveResult::Error(error) => Err(IronError::new(error, status::InternalServerError)),
            }
        }
        Err(_) => {
            Ok(Response::with((status::BadRequest,
                               (status::BadRequest, "The request is not multipart"))))
        }
    }
}

/// Processes saved entries from multipart request.
/// Returns an OK response or an error.
fn process_entries(entries: Entries) -> IronResult<Response> {
    for (name, field) in entries.fields {
        println!(r#"Field "{}": "{}""#, name, field);
    }

    for (name, savedfile) in entries.files {
        let filename = match savedfile.filename {
            Some(s) => s,
            None => "None".into(),
        };
        let mut file = match File::open(savedfile.path) {
            Ok(file) => file,
            Err(error) => {
                return Err(IronError::new(error,
                                          (status::InternalServerError,
                                           "Server couldn't save file")))
            }
        };
        let mut contents = String::new();
        if let Err(error) = file.read_to_string(&mut contents) {
            return Err(IronError::new(error, (status::BadRequest, "The file was not a text")));
        }

        println!(r#"Field "{}" is file "{}":"#, name, filename);
        println!("{}", contents);
    }
    Ok(Response::with((status::Ok, "Multipart data is processed")))
}
<commit_msg>Fixed a typo<commit_after>extern crate multipart;
extern crate iron;

use std::fs::File;
use std::io::Read;
use multipart::server::{Multipart, Entries, SaveResult};
use iron::prelude::*;
use iron::status;

fn main() {
    Iron::new(process_request).http("localhost:80").expect("Could not bind localhost:80");
}

/// Processes a request and returns response or an occured error.
fn process_request(request: &mut Request) -> IronResult<Response> {
    // Getting a multipart reader wrapper
    match Multipart::from_request(request) {
        Ok(mut multipart) => {
            // Fetching all data and processing it.
            // save_all() reads the request fully, parsing all fields and saving all files
            // in a new temporary directory under the OS temporary directory.
            match multipart.save_all() {
                SaveResult::Full(entries) => process_entries(entries),
                SaveResult::Partial(entries, error) => {
                    try!(process_entries(entries));
                    Err(IronError::new(error, status::InternalServerError))
                }
                SaveResult::Error(error) => Err(IronError::new(error, status::InternalServerError)),
            }
        }
        Err(_) => {
            Ok(Response::with((status::BadRequest, "The request is not multipart")))
        }
    }
}

/// Processes saved entries from multipart request.
/// Returns an OK response or an error.
fn process_entries(entries: Entries) -> IronResult<Response> {
    for (name, field) in entries.fields {
        println!(r#"Field "{}": "{}""#, name, field);
    }

    for (name, savedfile) in entries.files {
        let filename = match savedfile.filename {
            Some(s) => s,
            None => "None".into(),
        };
        let mut file = match File::open(savedfile.path) {
            Ok(file) => file,
            Err(error) => {
                return Err(IronError::new(error,
                                          (status::InternalServerError,
                                           "Server couldn't save file")))
            }
        };
        let mut contents = String::new();
        if let Err(error) = file.read_to_string(&mut contents) {
            return Err(IronError::new(error, (status::BadRequest, "The file was not a text")));
        }

        println!(r#"Field "{}" is file "{}":"#, name, filename);
        println!("{}", contents);
    }
    Ok(Response::with((status::Ok, "Multipart data is processed")))
}
<|endoftext|>


<commit_before>use native::task;
use std::comm::channel;

pub struct WorkUnit<ARG, RV> {
    arg: ARG,
    rv: Sender<RV>,
}

pub enum MessageToWorker<ARG, RV> {
    Work(WorkUnit<ARG, RV>),
    Halt,
}

enum MessageToDispatcher<ARG, RV> {
    Dispatch(WorkUnit<ARG, RV>),
    HaltAll,
    RegisterWorker(Sender<Sender<Sender<MessageToWorker<ARG, RV>>>>),
}

pub struct WorkQueue<ARG, RV> {
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

pub struct WorkQueueProxy<ARG, RV> {
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

impl<ARG:Send, RV:Send> WorkQueue<ARG, RV> {
    pub fn create() -> WorkQueue<ARG, RV> {
        let (dispatcher, dispatcher_inbox) = channel::<MessageToDispatcher<ARG, RV>>();

        // dispatcher
        task::spawn(proc() {
            let (want_work, idle_worker) = channel::<Sender<MessageToWorker<ARG, RV>>>();
            let mut worker_count = 0;
            let inbox = dispatcher_inbox;
            let idle_worker = idle_worker;
            loop {
                match inbox.recv() {
                    Dispatch(work_item) => {
                        idle_worker.recv().send(Work(work_item));
                    },
                    RegisterWorker(want_idle_sender) => {
                        worker_count += 1;
                        want_idle_sender.send(want_work.clone());
                    }
                    HaltAll => {
                        while worker_count > 0 {
                            idle_worker.recv().send(Halt);
                            worker_count -= 1;
                        }
                        return;
                    },
                };
            }
        });
        return WorkQueue{dispatcher: dispatcher};
    }

    pub fn proxy(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }

    pub fn register_worker(&self) -> Sender<Sender<MessageToWorker<ARG, RV>>> {
        let (reg_s, reg_r) = channel::<Sender<Sender<MessageToWorker<ARG, RV>>>>();
        self.dispatcher.send(RegisterWorker(reg_s));
        return reg_r.recv();
    }

    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch(WorkUnit{arg: arg, rv: rv}));
        return wait_for_rv;
    }
}

// rustc complais "cannot implement a destructor on a structure with
// type parameters", but our destruction is safe, we only send
// a simple message on a channel.
#[unsafe_destructor]
impl<ARG:Send, RV:Send> Drop for WorkQueue<ARG, RV> {
    fn drop(&mut self) {
        self.dispatcher.send(HaltAll);
    }
}

impl<ARG:Send, RV:Send> WorkQueueProxy<ARG, RV> {
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch(WorkUnit{arg: arg, rv: rv}));
        return wait_for_rv;
    }
}

impl<ARG:Send, RV:Send> Clone for WorkQueueProxy<ARG, RV> {
    fn clone(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }
}

#[cfg(test)]
mod test {
    use native::task;
    use test::BenchHarness;
    use workqueue::{WorkQueue, MessageToWorker, Work};

    fn spawn_test_worker(queue: &WorkQueue<int, int>) {
        let want_work = queue.register_worker();
        task::spawn(proc() {
            let want_work = want_work;
            loop {
                let (idle, get_work_unit) = channel::<MessageToWorker<int, int>>();
                want_work.send(idle);
                let work_unit = match get_work_unit.recv() {
                    Work(wu) => wu,
                    Halt     => return
                };
                let rv = work_unit.arg * 2;
                work_unit.rv.send(rv);
            }
        });
    }

    #[test]
    fn test_queue() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }
        let mut promise_list: ~[Receiver<int>] = ~[];
        for c in range(0, 10) {
            let rv = queue.push(c);
            promise_list.push(rv);
        }
        let return_list = promise_list.map(|promise| promise.recv());
        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }

    #[test]
    fn test_enqueue_from_tasks() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }
        let mut promise_list: ~[Receiver<int>] = ~[];
        let queue_proxy = queue.proxy();
        for c in range(0, 10) {
            let queue_proxy_clone = queue_proxy.clone();
            let (done, promise) = channel::<int>();
            promise_list.push(promise);
            task::spawn(proc() {
                let done = done;
                let queue = queue_proxy_clone;
                let rv = queue.push(c);
                done.send(rv.recv());
            });
        }
        let return_list = promise_list.map(|promise| promise.recv());
        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }

    #[bench]
    fn bench_50_tasks_4_threads(b: &mut BenchHarness) {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 4) {
            spawn_test_worker(&queue);
        }
        b.iter(|| {
            let mut promise_list: ~[Receiver<int>] = ~[];
            for _ in range(0, 50) {
                let rv = queue.push(1);
                promise_list.push(rv);
            }
            let _ = promise_list.map(|promise| promise.recv());
        });
    }

    #[bench]
    fn bench_spawn_5_workers(b: &mut BenchHarness) {
        b.iter(|| {
            let queue = WorkQueue::<int, int>::create();
            for _ in range(0, 5) {
                spawn_test_worker(&queue);
            }
        });
    }
}
<commit_msg>vec.map was deprecated; use iterator map<commit_after>use native::task;
use std::comm::channel;

pub struct WorkUnit<ARG, RV> {
    arg: ARG,
    rv: Sender<RV>,
}

pub enum MessageToWorker<ARG, RV> {
    Work(WorkUnit<ARG, RV>),
    Halt,
}

enum MessageToDispatcher<ARG, RV> {
    Dispatch(WorkUnit<ARG, RV>),
    HaltAll,
    RegisterWorker(Sender<Sender<Sender<MessageToWorker<ARG, RV>>>>),
}

pub struct WorkQueue<ARG, RV> {
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

pub struct WorkQueueProxy<ARG, RV> {
    dispatcher: Sender<MessageToDispatcher<ARG, RV>>,
}

impl<ARG:Send, RV:Send> WorkQueue<ARG, RV> {
    pub fn create() -> WorkQueue<ARG, RV> {
        let (dispatcher, dispatcher_inbox) = channel::<MessageToDispatcher<ARG, RV>>();

        // dispatcher
        task::spawn(proc() {
            let (want_work, idle_worker) = channel::<Sender<MessageToWorker<ARG, RV>>>();
            let mut worker_count = 0;
            let inbox = dispatcher_inbox;
            let idle_worker = idle_worker;
            loop {
                match inbox.recv() {
                    Dispatch(work_item) => {
                        idle_worker.recv().send(Work(work_item));
                    },
                    RegisterWorker(want_idle_sender) => {
                        worker_count += 1;
                        want_idle_sender.send(want_work.clone());
                    }
                    HaltAll => {
                        while worker_count > 0 {
                            idle_worker.recv().send(Halt);
                            worker_count -= 1;
                        }
                        return;
                    },
                };
            }
        });
        return WorkQueue{dispatcher: dispatcher};
    }

    pub fn proxy(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }

    pub fn register_worker(&self) -> Sender<Sender<MessageToWorker<ARG, RV>>> {
        let (reg_s, reg_r) = channel::<Sender<Sender<MessageToWorker<ARG, RV>>>>();
        self.dispatcher.send(RegisterWorker(reg_s));
        return reg_r.recv();
    }

    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch(WorkUnit{arg: arg, rv: rv}));
        return wait_for_rv;
    }
}

// rustc complais "cannot implement a destructor on a structure with
// type parameters", but our destruction is safe, we only send
// a simple message on a channel.
#[unsafe_destructor]
impl<ARG:Send, RV:Send> Drop for WorkQueue<ARG, RV> {
    fn drop(&mut self) {
        self.dispatcher.send(HaltAll);
    }
}

impl<ARG:Send, RV:Send> WorkQueueProxy<ARG, RV> {
    pub fn push(&self, arg: ARG) -> Receiver<RV> {
        let (rv, wait_for_rv) = channel::<RV>();
        self.dispatcher.send(Dispatch(WorkUnit{arg: arg, rv: rv}));
        return wait_for_rv;
    }
}

impl<ARG:Send, RV:Send> Clone for WorkQueueProxy<ARG, RV> {
    fn clone(&self) -> WorkQueueProxy<ARG, RV> {
        return WorkQueueProxy{dispatcher: self.dispatcher.clone()};
    }
}

#[cfg(test)]
mod test {
    use native::task;
    use test::BenchHarness;
    use workqueue::{WorkQueue, MessageToWorker, Work};

    fn spawn_test_worker(queue: &WorkQueue<int, int>) {
        let want_work = queue.register_worker();
        task::spawn(proc() {
            let want_work = want_work;
            loop {
                let (idle, get_work_unit) = channel::<MessageToWorker<int, int>>();
                want_work.send(idle);
                let work_unit = match get_work_unit.recv() {
                    Work(wu) => wu,
                    Halt     => return
                };
                let rv = work_unit.arg * 2;
                work_unit.rv.send(rv);
            }
        });
    }

    #[test]
    fn test_queue() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }

        let return_list: ~[int] =
            range(0, 10)
            .map(|c| queue.push(c))
            .map(|rv| rv.recv())
            .collect();

        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }

    #[test]
    fn test_enqueue_from_tasks() {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 3) {
            spawn_test_worker(&queue);
        }
        let mut promise_list: ~[Receiver<int>] = ~[];
        let queue_proxy = queue.proxy();
        for c in range(0, 10) {
            let queue_proxy_clone = queue_proxy.clone();
            let (done, promise) = channel::<int>();
            promise_list.push(promise);
            task::spawn(proc() {
                let done = done;
                let queue = queue_proxy_clone;
                let rv = queue.push(c);
                done.send(rv.recv());
            });
        }

        let return_list: ~[int] =
            promise_list
            .iter()
            .map(|promise| promise.recv())
            .collect();
        assert_eq!(return_list, ~[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]);
    }

    #[bench]
    fn bench_50_tasks_4_threads(b: &mut BenchHarness) {
        let queue = WorkQueue::<int, int>::create();
        for _ in range(0, 4) {
            spawn_test_worker(&queue);
        }
        b.iter(|| {
            let _: ~[int] =
                range(0, 50)
                .map(|_| queue.push(1))
                .map(|rv| rv.recv())
                .collect();
        });
    }

    #[bench]
    fn bench_spawn_5_workers(b: &mut BenchHarness) {
        b.iter(|| {
            let queue = WorkQueue::<int, int>::create();
            for _ in range(0, 5) {
                spawn_test_worker(&queue);
            }
        });
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use euclid::size::Size2D;
use layers::platform::surface::{NativeDisplay, NativeSurface};
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::hash::{Hash, Hasher};

/// This is a struct used to store surfaces when they are not in use.
/// The paint task can quickly query for a particular size of surface when it
/// needs it.
pub struct SurfaceMap {
    /// A HashMap that stores the Buffers.
    map: HashMap<SurfaceKey, SurfaceValue>,
    /// The current amount of memory stored by the SurfaceMap's surfaces.
    mem: usize,
    /// The maximum allowed memory. Unused surfaces will be deleted
    /// when this threshold is exceeded.
    max_mem: usize,
    /// A monotonically increasing counter to track how recently tile sizes were used.
    counter: usize,
}

/// A key with which to store surfaces. It is based on the size of the surface.
#[derive(Eq, Copy, Clone)]
struct SurfaceKey([i32; 2]);

impl Hash for SurfaceKey {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let SurfaceKey(ref bytes) = *self;
        bytes.hash(state);
    }
}

impl PartialEq for SurfaceKey {
    fn eq(&self, other: &SurfaceKey) -> bool {
        let SurfaceKey(s) = *self;
        let SurfaceKey(o) = *other;
        s[0] == o[0] && s[1] == o[1]
    }
}

/// Create a key from a given size
impl SurfaceKey {
    fn get(input: Size2D<i32>) -> SurfaceKey {
        SurfaceKey([input.width, input.height])
    }
}

/// A helper struct to keep track of surfaces in the HashMap
struct SurfaceValue {
    /// An array of surfaces, all the same size
    surfaces: Vec<NativeSurface>,
    /// The counter when this size was last requested
    last_action: usize,
}

impl SurfaceMap {
    // Creates a new SurfaceMap with a given surface limit.
    pub fn new(max_mem: usize) -> SurfaceMap {
        SurfaceMap {
            map: HashMap::new(),
            mem: 0,
            max_mem: max_mem,
            counter: 0,
        }
    }

    pub fn insert_surfaces<I>(&mut self, display: &NativeDisplay, surfaces: I)
        where I: IntoIterator<Item=NativeSurface>
    {
        for surface in surfaces {
            self.insert(display, surface);
        }
    }

    /// Insert a new buffer into the map.
    pub fn insert(&mut self, display: &NativeDisplay, mut new_surface: NativeSurface) {
        let new_key = SurfaceKey::get(new_surface.get_size());

        // If all our surfaces are the same size and we're already at our
        // memory limit, no need to store this new buffer; just let it drop.
        let new_total_memory_usage = self.mem + new_surface.get_memory_usage();
        if new_total_memory_usage > self.max_mem && self.map.len() == 1 &&
            self.map.contains_key(&new_key) {
            new_surface.destroy(display);
            return;
        }

        self.mem = new_total_memory_usage;
        new_surface.mark_wont_leak();

        // use lazy insertion function to prevent unnecessary allocation
        let counter = &self.counter;
        match self.map.entry(new_key) {
            Occupied(entry) => {
                entry.into_mut().surfaces.push(new_surface);
            }
            Vacant(entry) => {
                entry.insert(SurfaceValue {
                    surfaces: vec!(new_surface),
                    last_action: *counter,
                });
            }
        }

        let mut opt_key: Option<SurfaceKey> = None;
        while self.mem > self.max_mem {
            let old_key = match opt_key {
                Some(key) => key,
                None => {
                    match self.map.iter().min_by(|&(_, x)| x.last_action) {
                        Some((k, _)) => *k,
                        None => panic!("SurfaceMap: tried to delete with no elements in map"),
                    }
                }
            };
            if {
                let list = &mut self.map.get_mut(&old_key).unwrap().surfaces;
                let mut condemned_surface = list.pop().take().unwrap();
                self.mem -= condemned_surface.get_memory_usage();
                condemned_surface.destroy(display);
                list.is_empty()
            }
            { // then
                self.map.remove(&old_key); // Don't store empty vectors!
                opt_key = None;
            } else {
                opt_key = Some(old_key);
            }
        }
    }

    // Try to find a buffer for the given size.
    pub fn find(&mut self, size: Size2D<i32>) -> Option<NativeSurface> {
        let mut flag = false; // True if key needs to be popped after retrieval.
        let key = SurfaceKey::get(size);
        let ret = match self.map.get_mut(&key) {
            Some(ref mut surface_val) => {
                surface_val.last_action = self.counter;
                self.counter += 1;

                let surface = surface_val.surfaces.pop().take().unwrap();
                self.mem -= surface.get_memory_usage();
                if surface_val.surfaces.is_empty() {
                    flag = true;
                }
                Some(surface)
            }
            None => None,
        };

        if flag {
            self.map.remove(&key); // Don't store empty vectors!
        }

        ret
    }

    pub fn mem(&self) -> usize {
        self.mem
    }
}
<commit_msg>Fix warning: Use iterator.min_by_key instead of iterator.min_by<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use euclid::size::Size2D;
use layers::platform::surface::{NativeDisplay, NativeSurface};
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::hash::{Hash, Hasher};

/// This is a struct used to store surfaces when they are not in use.
/// The paint task can quickly query for a particular size of surface when it
/// needs it.
pub struct SurfaceMap {
    /// A HashMap that stores the Buffers.
    map: HashMap<SurfaceKey, SurfaceValue>,
    /// The current amount of memory stored by the SurfaceMap's surfaces.
    mem: usize,
    /// The maximum allowed memory. Unused surfaces will be deleted
    /// when this threshold is exceeded.
    max_mem: usize,
    /// A monotonically increasing counter to track how recently tile sizes were used.
    counter: usize,
}

/// A key with which to store surfaces. It is based on the size of the surface.
#[derive(Eq, Copy, Clone)]
struct SurfaceKey([i32; 2]);

impl Hash for SurfaceKey {
    fn hash<H: Hasher>(&self, state: &mut H) {
        let SurfaceKey(ref bytes) = *self;
        bytes.hash(state);
    }
}

impl PartialEq for SurfaceKey {
    fn eq(&self, other: &SurfaceKey) -> bool {
        let SurfaceKey(s) = *self;
        let SurfaceKey(o) = *other;
        s[0] == o[0] && s[1] == o[1]
    }
}

/// Create a key from a given size
impl SurfaceKey {
    fn get(input: Size2D<i32>) -> SurfaceKey {
        SurfaceKey([input.width, input.height])
    }
}

/// A helper struct to keep track of surfaces in the HashMap
struct SurfaceValue {
    /// An array of surfaces, all the same size
    surfaces: Vec<NativeSurface>,
    /// The counter when this size was last requested
    last_action: usize,
}

impl SurfaceMap {
    // Creates a new SurfaceMap with a given surface limit.
    pub fn new(max_mem: usize) -> SurfaceMap {
        SurfaceMap {
            map: HashMap::new(),
            mem: 0,
            max_mem: max_mem,
            counter: 0,
        }
    }

    pub fn insert_surfaces<I>(&mut self, display: &NativeDisplay, surfaces: I)
        where I: IntoIterator<Item=NativeSurface>
    {
        for surface in surfaces {
            self.insert(display, surface);
        }
    }

    /// Insert a new buffer into the map.
    pub fn insert(&mut self, display: &NativeDisplay, mut new_surface: NativeSurface) {
        let new_key = SurfaceKey::get(new_surface.get_size());

        // If all our surfaces are the same size and we're already at our
        // memory limit, no need to store this new buffer; just let it drop.
        let new_total_memory_usage = self.mem + new_surface.get_memory_usage();
        if new_total_memory_usage > self.max_mem && self.map.len() == 1 &&
            self.map.contains_key(&new_key) {
            new_surface.destroy(display);
            return;
        }

        self.mem = new_total_memory_usage;
        new_surface.mark_wont_leak();

        // use lazy insertion function to prevent unnecessary allocation
        let counter = &self.counter;
        match self.map.entry(new_key) {
            Occupied(entry) => {
                entry.into_mut().surfaces.push(new_surface);
            }
            Vacant(entry) => {
                entry.insert(SurfaceValue {
                    surfaces: vec!(new_surface),
                    last_action: *counter,
                });
            }
        }

        let mut opt_key: Option<SurfaceKey> = None;
        while self.mem > self.max_mem {
            let old_key = match opt_key {
                Some(key) => key,
                None => {
                    match self.map.iter().min_by_key(|&(_, x)| x.last_action) {
                        Some((k, _)) => *k,
                        None => panic!("SurfaceMap: tried to delete with no elements in map"),
                    }
                }
            };
            if {
                let list = &mut self.map.get_mut(&old_key).unwrap().surfaces;
                let mut condemned_surface = list.pop().take().unwrap();
                self.mem -= condemned_surface.get_memory_usage();
                condemned_surface.destroy(display);
                list.is_empty()
            }
            { // then
                self.map.remove(&old_key); // Don't store empty vectors!
                opt_key = None;
            } else {
                opt_key = Some(old_key);
            }
        }
    }

    // Try to find a buffer for the given size.
    pub fn find(&mut self, size: Size2D<i32>) -> Option<NativeSurface> {
        let mut flag = false; // True if key needs to be popped after retrieval.
        let key = SurfaceKey::get(size);
        let ret = match self.map.get_mut(&key) {
            Some(ref mut surface_val) => {
                surface_val.last_action = self.counter;
                self.counter += 1;

                let surface = surface_val.surfaces.pop().take().unwrap();
                self.mem -= surface.get_memory_usage();
                if surface_val.surfaces.is_empty() {
                    flag = true;
                }
                Some(surface)
            }
            None => None,
        };

        if flag {
            self.map.remove(&key); // Don't store empty vectors!
        }

        ret
    }

    pub fn mem(&self) -> usize {
        self.mem
    }
}
<|endoftext|>


<commit_before>use std::cmp;
use std::io::Read;
use std::io::Write;

use bufstream::BufStream;

use protocol::cmd::Cmd;
use protocol::cmd::Get;
use protocol::cmd::Resp;
use protocol::cmd::Set;

use super::conversions::as_number;
use super::conversions::as_string;
use super::errors::TcpTransportError;
use super::stats::TransportStats;
use super::typedefs::TcpTransportResult;

pub struct TcpTransport<T: Read + Write> {
    stream: BufStream<T>,

    pub line_buffer: Vec<u8>,
    pub line_cursor: usize,
    pub line_break_pos: usize,

    key_maxlen: u64,

    stats: TransportStats,
}

impl<T: Read + Write> TcpTransport<T> {
    pub fn new(stream: T) -> TcpTransport<T> {
        TcpTransport {
            key_maxlen: 250, // memcached standard

            // Used to read the first line of a command, which includes a
            // keyword, a key, flags and a bytecount. We don't expect it to be
            // much longer than the key itself. If it is we panic...
            line_buffer: vec![0; 250 + 100],
            line_cursor: 0,
            line_break_pos: 0,

            stats: TransportStats::new(),
            stream: BufStream::new(stream),
        }
    }

    pub fn with_key_maxlen(&mut self,
                           key_maxlen: u64)
                           -> &mut TcpTransport<T> {
        self.key_maxlen = key_maxlen;
        self
    }

    pub fn get_stats_clone(&self) -> TransportStats {
        self.stats.clone()
    }

    pub fn get_stream(&self) -> &T {
        self.stream.get_ref()
    }

    // Basic bytes manipulation and reading from the stream

    pub fn read_byte(&mut self) -> TcpTransportResult<u8> {
        let mut bytes = [0; 1];

        match self.stream.read(&mut bytes) {
            Ok(1) => {
                // Update stats
                self.stats.bytes_read += 1;

                Ok(bytes[0])
            }
            _ => Err(TcpTransportError::StreamReadError),
        }
    }

    pub fn read_bytes(&mut self, len: u64) -> TcpTransportResult<Vec<u8>> {
        let mut bytes = vec![0; len as usize];

        match self.stream.read(&mut bytes[..]) {
            Ok(n) => {
                // Update stats
                self.stats.bytes_read += n as u64;

                Ok(bytes)
            }
            _ => Err(TcpTransportError::StreamReadError),
        }
    }

    pub fn preread_line(&mut self) -> TcpTransportResult<()> {
        let mut cursor = 0;

        // We keep reading one byte at a time into line_buffer, looking for
        // a line terminator \r\n. The underlying stream is buffered.
        loop {
            // Make sure we don't go over bounds
            if cursor >= self.line_buffer.len() {
                panic!("Line too long to be read");
            }

            let rv = self.stream.read(&mut self.line_buffer[cursor..cursor+1]);

            // If there was an error or if there was nothing to read we bail
            if rv.is_err() || rv.unwrap() == 0 {
                return Err(TcpTransportError::StreamReadError);
            }

            // We found \r
            if self.line_buffer[cursor] == 13 {
                // Read one more, hoping it's \n
                cursor += 1;
                let rv = self.stream.read(&mut self.line_buffer[cursor..cursor+1]);

                // If there was an error or if there was nothing to read we bail
                if rv.is_err() || rv.unwrap() == 0 {
                    return Err(TcpTransportError::StreamReadError);
                }

                // Woops, it's not \n, we bail
                if self.line_buffer[cursor] != 10 {
                    return Err(TcpTransportError::StreamReadError);
                }

                break;
            }

            cursor += 1;
        }

        self.line_cursor = 0;
        self.line_break_pos = cursor - 1;  // point it at \r, not \n

        Ok(())
    }

    pub fn line_is_empty(&self) -> bool {
        // If the cursor precedes the line break then there are still bytes to
        // read from the line, otherwise it's empty
        self.line_cursor >= self.line_break_pos
    }

    pub fn line_remove_first_char(&mut self) -> TcpTransportResult<()> {
        match !self.line_is_empty() {
            true => {
                self.line_cursor += 1;
                Ok(())
            }
            false => Err(TcpTransportError::LineReadError),
        }
    }

    pub fn line_parse_word(&mut self) -> TcpTransportResult<&[u8]> {
        // If the very first char is a space then our caller is out of sync
        if self.line_buffer[self.line_cursor] == 32 {
            return Err(TcpTransportError::StreamReadError);
        }

        let mut space_idx = 0;
        let mut found = false;

        for i in self.line_cursor + 1..self.line_break_pos {
            // We found a space
            if self.line_buffer[i] == 32 {
                space_idx = i;
                found = true;
                break;
            }
        }

        // If we didn't find a space then the whole line is a word
        if !found {
            space_idx = self.line_break_pos;
        }

        // Advance the cursor, we've now "consumed" the word we found
        let word = &self.line_buffer[self.line_cursor..space_idx];
        self.line_cursor = space_idx;

        Ok(word)
    }

    // Writing to the stream

    pub fn flush_writes(&mut self) -> TcpTransportResult<()> {
        match self.stream.flush() {
            Ok(_) => Ok(()),
            Err(_) => Err(TcpTransportError::StreamWriteError),
        }
    }

    pub fn write_bytes(&mut self,
                       bytes: &Vec<u8>)
                       -> TcpTransportResult<usize> {
        match self.stream.write(bytes) {
            Ok(cnt_written) => {
                // Update stats
                self.stats.bytes_written += cnt_written as u64;

                Ok(cnt_written)
            }
            Err(_) => Err(TcpTransportError::StreamWriteError),
        }
    }

    pub fn write_string(&mut self, string: &str) -> TcpTransportResult<usize> {
        let bytes = string.to_string().into_bytes();
        Ok(try!(self.write_bytes(&bytes)))
    }

    // Parse individual commands

    pub fn parse_cmd_get(&mut self) -> TcpTransportResult<Cmd> {
        // remove the space after the keyword
        try!(self.line_remove_first_char());

        // parse the key
        let key_str = {
            let key = try!(self.line_parse_word());
            try!(as_string(key))
        };

        // We expect to find the end of the line now
        if self.line_is_empty() {
            Ok(Cmd::Get(Get { key: key_str }))
        } else {
            Err(TcpTransportError::CommandParseError)
        }
    }

    pub fn parse_cmd_set(&mut self) -> TcpTransportResult<Cmd> {
        // remove the space after the keyword
        try!(self.line_remove_first_char());

        // parse the key + remove trailing space
        let key_str = {
            let key = try!(self.line_parse_word());
            try!(as_string(key))
        };
        try!(self.line_remove_first_char());

        // parse the flags + remove trailing space
        let flags_num = {
            let flags = try!(self.line_parse_word());
            try!(as_number::<u16>(flags))
        };
        try!(self.line_remove_first_char());

        // parse the exptime + remove trailing space
        let exptime_num = {
            let exptime = try!(self.line_parse_word());
            try!(as_number::<u32>(exptime))
        };
        try!(self.line_remove_first_char());

        // parse the bytelen
        let bytelen_num = {
            let bytelen = try!(self.line_parse_word());
            try!(as_number::<u64>(bytelen))
        };

        // We know the byte length, so now read the value
        let value = try!(self.read_bytes(bytelen_num));

        // Read the line termination marker and verify it
        let newline = try!(self.read_bytes(2));
        if !newline.starts_with(&[13, 10]) {
            return Err(TcpTransportError::CommandParseError);
        }

        // We got all the values we expected and there is nothing left
        return Ok(Cmd::Set(Set {
            key: key_str,
            exptime: exptime_num,
            data: value,
        }));
    }

    // High level functions

    pub fn read_cmd(&mut self) -> TcpTransportResult<Cmd> {
        // read the first line
        try!(self.preread_line());

        let keyword_str = {
            let keyword = try!(self.line_parse_word());
            try!(as_string(keyword))
        };

        if keyword_str == "get" {
            return self.parse_cmd_get();
        } else if keyword_str == "set" {
            return self.parse_cmd_set();
        } else if keyword_str == "stats" {
            return Ok(Cmd::Stats);
        }

        Err(TcpTransportError::InvalidCmd)
    }

    pub fn write_resp(&mut self, resp: &Resp) -> TcpTransportResult<()> {
        match *resp {
            Resp::Error => {
                try!(self.write_string("ERROR\r\n"));
            }
            Resp::Stats(ref stats) => {
                for stat in stats {
                    try!(self.write_string("STAT "));
                    try!(self.write_string(&stat.key));
                    try!(self.write_string(" "));
                    try!(self.write_string(&stat.value));
                    try!(self.write_string("\r\n"));
                }
                try!(self.write_string("END\r\n"));
            }
            Resp::Stored => {
                try!(self.write_string("STORED\r\n"));
            }
            Resp::Value(ref value) => {
                try!(self.write_string("VALUE ")); // keyword
                try!(self.write_string(&value.key)); // key
                try!(self.write_string(" 0 ")); // flags
                try!(self.write_string(&value.data.len().to_string())); // bytelen
                try!(self.write_string(&"\r\n".to_string())); // newline
                try!(self.write_bytes(&value.data)); // data block
                try!(self.write_string(&"\r\n".to_string())); // newline
            }
            _ => {
                return Err(TcpTransportError::StreamWriteError);
            }
        }

        // Make sure all bytes were actually sent
        self.flush_writes()
    }
}
<commit_msg>add missing stats update<commit_after>use std::cmp;
use std::io::Read;
use std::io::Write;

use bufstream::BufStream;

use protocol::cmd::Cmd;
use protocol::cmd::Get;
use protocol::cmd::Resp;
use protocol::cmd::Set;

use super::conversions::as_number;
use super::conversions::as_string;
use super::errors::TcpTransportError;
use super::stats::TransportStats;
use super::typedefs::TcpTransportResult;

pub struct TcpTransport<T: Read + Write> {
    stream: BufStream<T>,

    pub line_buffer: Vec<u8>,
    pub line_cursor: usize,
    pub line_break_pos: usize,

    key_maxlen: u64,

    stats: TransportStats,
}

impl<T: Read + Write> TcpTransport<T> {
    pub fn new(stream: T) -> TcpTransport<T> {
        TcpTransport {
            key_maxlen: 250, // memcached standard

            // Used to read the first line of a command, which includes a
            // keyword, a key, flags and a bytecount. We don't expect it to be
            // much longer than the key itself. If it is we panic...
            line_buffer: vec![0; 250 + 100],
            line_cursor: 0,
            line_break_pos: 0,

            stats: TransportStats::new(),
            stream: BufStream::new(stream),
        }
    }

    pub fn with_key_maxlen(&mut self,
                           key_maxlen: u64)
                           -> &mut TcpTransport<T> {
        self.key_maxlen = key_maxlen;
        self
    }

    pub fn get_stats_clone(&self) -> TransportStats {
        self.stats.clone()
    }

    pub fn get_stream(&self) -> &T {
        self.stream.get_ref()
    }

    // Basic bytes manipulation and reading from the stream

    pub fn read_byte(&mut self) -> TcpTransportResult<u8> {
        let mut bytes = [0; 1];

        match self.stream.read(&mut bytes) {
            Ok(1) => {
                // Update stats
                self.stats.bytes_read += 1;

                Ok(bytes[0])
            }
            _ => Err(TcpTransportError::StreamReadError),
        }
    }

    pub fn read_bytes(&mut self, len: u64) -> TcpTransportResult<Vec<u8>> {
        let mut bytes = vec![0; len as usize];

        match self.stream.read(&mut bytes[..]) {
            Ok(n) => {
                // Update stats
                self.stats.bytes_read += n as u64;

                Ok(bytes)
            }
            _ => Err(TcpTransportError::StreamReadError),
        }
    }

    pub fn preread_line(&mut self) -> TcpTransportResult<()> {
        let mut cursor = 0;

        // We keep reading one byte at a time into line_buffer, looking for
        // a line terminator \r\n. The underlying stream is buffered.
        loop {
            // Make sure we don't go over bounds
            if cursor >= self.line_buffer.len() {
                panic!("Line too long to be read");
            }

            let rv = self.stream.read(&mut self.line_buffer[cursor..cursor+1]);

            // If there was an error or if there was nothing to read we bail
            if rv.is_err() || rv.unwrap() == 0 {
                return Err(TcpTransportError::StreamReadError);
            }

            // Update stats
            self.stats.bytes_read += 1;

            // We found \r
            if self.line_buffer[cursor] == 13 {
                // Read one more, hoping it's \n
                cursor += 1;
                let rv = self.stream.read(&mut self.line_buffer[cursor..cursor+1]);

                // If there was an error or if there was nothing to read we bail
                if rv.is_err() || rv.unwrap() == 0 {
                    return Err(TcpTransportError::StreamReadError);
                }

                // Update stats
                self.stats.bytes_read += 1;

                // Woops, it's not \n, we bail
                if self.line_buffer[cursor] != 10 {
                    return Err(TcpTransportError::StreamReadError);
                }

                break;
            }

            cursor += 1;
        }

        self.line_cursor = 0;
        self.line_break_pos = cursor - 1;  // point it at \r, not \n

        Ok(())
    }

    pub fn line_is_empty(&self) -> bool {
        // If the cursor precedes the line break then there are still bytes to
        // read from the line, otherwise it's empty
        self.line_cursor >= self.line_break_pos
    }

    pub fn line_remove_first_char(&mut self) -> TcpTransportResult<()> {
        match !self.line_is_empty() {
            true => {
                self.line_cursor += 1;
                Ok(())
            }
            false => Err(TcpTransportError::LineReadError),
        }
    }

    pub fn line_parse_word(&mut self) -> TcpTransportResult<&[u8]> {
        // If the very first char is a space then our caller is out of sync
        if self.line_buffer[self.line_cursor] == 32 {
            return Err(TcpTransportError::StreamReadError);
        }

        let mut space_idx = 0;
        let mut found = false;

        for i in self.line_cursor + 1..self.line_break_pos {
            // We found a space
            if self.line_buffer[i] == 32 {
                space_idx = i;
                found = true;
                break;
            }
        }

        // If we didn't find a space then the whole line is a word
        if !found {
            space_idx = self.line_break_pos;
        }

        // Advance the cursor, we've now "consumed" the word we found
        let word = &self.line_buffer[self.line_cursor..space_idx];
        self.line_cursor = space_idx;

        Ok(word)
    }

    // Writing to the stream

    pub fn flush_writes(&mut self) -> TcpTransportResult<()> {
        match self.stream.flush() {
            Ok(_) => Ok(()),
            Err(_) => Err(TcpTransportError::StreamWriteError),
        }
    }

    pub fn write_bytes(&mut self,
                       bytes: &Vec<u8>)
                       -> TcpTransportResult<usize> {
        match self.stream.write(bytes) {
            Ok(cnt_written) => {
                // Update stats
                self.stats.bytes_written += cnt_written as u64;

                Ok(cnt_written)
            }
            Err(_) => Err(TcpTransportError::StreamWriteError),
        }
    }

    pub fn write_string(&mut self, string: &str) -> TcpTransportResult<usize> {
        let bytes = string.to_string().into_bytes();
        Ok(try!(self.write_bytes(&bytes)))
    }

    // Parse individual commands

    pub fn parse_cmd_get(&mut self) -> TcpTransportResult<Cmd> {
        // remove the space after the keyword
        try!(self.line_remove_first_char());

        // parse the key
        let key_str = {
            let key = try!(self.line_parse_word());
            try!(as_string(key))
        };

        // We expect to find the end of the line now
        if self.line_is_empty() {
            Ok(Cmd::Get(Get { key: key_str }))
        } else {
            Err(TcpTransportError::CommandParseError)
        }
    }

    pub fn parse_cmd_set(&mut self) -> TcpTransportResult<Cmd> {
        // remove the space after the keyword
        try!(self.line_remove_first_char());

        // parse the key + remove trailing space
        let key_str = {
            let key = try!(self.line_parse_word());
            try!(as_string(key))
        };
        try!(self.line_remove_first_char());

        // parse the flags + remove trailing space
        let flags_num = {
            let flags = try!(self.line_parse_word());
            try!(as_number::<u16>(flags))
        };
        try!(self.line_remove_first_char());

        // parse the exptime + remove trailing space
        let exptime_num = {
            let exptime = try!(self.line_parse_word());
            try!(as_number::<u32>(exptime))
        };
        try!(self.line_remove_first_char());

        // parse the bytelen
        let bytelen_num = {
            let bytelen = try!(self.line_parse_word());
            try!(as_number::<u64>(bytelen))
        };

        // We know the byte length, so now read the value
        let value = try!(self.read_bytes(bytelen_num));

        // Read the line termination marker and verify it
        let newline = try!(self.read_bytes(2));
        if !newline.starts_with(&[13, 10]) {
            return Err(TcpTransportError::CommandParseError);
        }

        // We got all the values we expected and there is nothing left
        return Ok(Cmd::Set(Set {
            key: key_str,
            exptime: exptime_num,
            data: value,
        }));
    }

    // High level functions

    pub fn read_cmd(&mut self) -> TcpTransportResult<Cmd> {
        // read the first line
        try!(self.preread_line());

        let keyword_str = {
            let keyword = try!(self.line_parse_word());
            try!(as_string(keyword))
        };

        if keyword_str == "get" {
            return self.parse_cmd_get();
        } else if keyword_str == "set" {
            return self.parse_cmd_set();
        } else if keyword_str == "stats" {
            return Ok(Cmd::Stats);
        }

        Err(TcpTransportError::InvalidCmd)
    }

    pub fn write_resp(&mut self, resp: &Resp) -> TcpTransportResult<()> {
        match *resp {
            Resp::Error => {
                try!(self.write_string("ERROR\r\n"));
            }
            Resp::Stats(ref stats) => {
                for stat in stats {
                    try!(self.write_string("STAT "));
                    try!(self.write_string(&stat.key));
                    try!(self.write_string(" "));
                    try!(self.write_string(&stat.value));
                    try!(self.write_string("\r\n"));
                }
                try!(self.write_string("END\r\n"));
            }
            Resp::Stored => {
                try!(self.write_string("STORED\r\n"));
            }
            Resp::Value(ref value) => {
                try!(self.write_string("VALUE ")); // keyword
                try!(self.write_string(&value.key)); // key
                try!(self.write_string(" 0 ")); // flags
                try!(self.write_string(&value.data.len().to_string())); // bytelen
                try!(self.write_string(&"\r\n".to_string())); // newline
                try!(self.write_bytes(&value.data)); // data block
                try!(self.write_string(&"\r\n".to_string())); // newline
            }
            _ => {
                return Err(TcpTransportError::StreamWriteError);
            }
        }

        // Make sure all bytes were actually sent
        self.flush_writes()
    }
}
<|endoftext|>