<commit_before>// Module for reading sprides and saving them in a HashMap

use std::collections::HashMap;
use piston_window::*;
use io::sprite::Sprite;

/// HashMap for all given sprites
pub struct SpriteMap {
    pub map: HashMap<&'static str, Sprite>,
}

impl SpriteMap {
    /// Initialize the SpriteMap with given window, fills Map with all Sprites
    pub fn init(mut w: &mut PistonWindow) -> Self {
        let mut map2: HashMap<&'static str, Sprite> = HashMap::new();
        for i in SPRITES {
            map2.insert(i.image,
                        Sprite::fill_sprite(i.image, i.size_x as u32, i.size_y as u32,i.dur as u64, i.once, w));
        }

        SpriteMap { map: map2 }

    }

    /// creates empty SpriteMap
    pub fn new() -> Self {
        SpriteMap { map: HashMap::new() }
    }
    pub fn get_sprite(&self, file: String) -> Option<&Sprite> {
        self.map.get(file.as_str())
    }
}

/// Struct for representing Necessary information about sprites
struct SpriteModel {
    image: &'static str,
    size_x: usize,
    size_y: usize,
    dur: usize,
    once: bool,
}

/// const with all Sprites
const SPRITES: &'static [SpriteModel] = &[SpriteModel {
                                              image: "bowman.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_brown.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_pink.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_white.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "explosion.png",
                                              size_x: 59,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "knight.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "paladin.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "swipe_broadsword.png",
                                              size_x: 64,
                                              size_y: 192,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "swipe_dagger.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "swipe_longsword.png",
                                              size_x: 128,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "weapon_broadsword.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_dagger.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_spear.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "wizard.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_empty.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_full.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_half.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_broadsword_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_dagger_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_spear_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_10.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_20.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "swipe_enemy.png",
                                              size_x: 72,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          }];
<commit_msg>Update all_sprites.rs<commit_after>// Module for reading sprides and saving them in a HashMap

use std::collections::HashMap;
use piston_window::*;
use io::sprite::Sprite;

/// HashMap for all given sprites
pub struct SpriteMap {
    pub map: HashMap<&'static str, Sprite>,
}

impl SpriteMap {
    /// Initialize the SpriteMap with given window, fills Map with all Sprites
    pub fn init(mut w: &mut PistonWindow) -> Self {
        let mut map2: HashMap<&'static str, Sprite> = HashMap::new();
        for i in SPRITES {
            map2.insert(i.image,
                        Sprite::fill_sprite(i.image, i.size_x as u32, i.size_y as u32,i.dur as u64, i.once, w));
        }

        SpriteMap { map: map2 }

    }

    /// creates empty SpriteMap
    pub fn new() -> Self {
        SpriteMap { map: HashMap::new() }
    }
    pub fn get_sprite(&self, file: String) -> Option<&Sprite> {
        self.map.get(file.as_str())
    }
}

/// Struct for representing Necessary information about sprites
struct SpriteModel {
    image: &'static str,
    size_x: usize,
    size_y: usize,
    dur: usize,
    once: bool,
}

/// const with all Sprites
const SPRITES: &'static [SpriteModel] = &[SpriteModel {
                                              image: "bowman.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_brown.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_pink.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "chicken_white.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "explosion.png",
                                              size_x: 59,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "knight.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "paladin.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "swipe_broadsword.png",
                                              size_x: 64,
                                              size_y: 192,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "swipe_dagger.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "swipe_longsword.png",
                                              size_x: 128,
                                              size_y: 64,
                                              dur: 100,
                                              once: true,
                                          },
                                          SpriteModel {
                                              image: "weapon_broadsword.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_dagger.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_spear.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "wizard.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_empty.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_full.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_half.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_broadsword_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_dagger_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "weapon_spear_small.png",
                                              size_x: 32,
                                              size_y: 32,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_10.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "Heart_20.png",
                                              size_x: 64,
                                              size_y: 64,
                                              dur: 1000,
                                              once: false,
                                          },
                                          SpriteModel {
                                              image: "swipe_enemy.png",
                                              size_x: 72,
                                              size_y: 64,
                                              dur: 250,
                                              once: true,
                                          }];
<|endoftext|>


<commit_before>#![allow(unused_must_use)]

use formatter::RdbParseFormatter;
use std::io;

pub struct JSONFormatter {
    out: Box<Writer+'static>,
    is_first_db: bool,
    has_databases: bool,
    is_first_key_in_db: bool,
    elements_in_key: u32,
    element_index: u32
}

impl JSONFormatter {
    pub fn new() -> JSONFormatter {
        let out = Box::new(io::stdout());
        JSONFormatter {
            out: out,
            is_first_db: true,
            has_databases: false,
            is_first_key_in_db: true,
            elements_in_key: 0,
            element_index: 0
        }
    }
}

impl JSONFormatter {
    fn start_key(&mut self, length: u32) {
        if !self.is_first_key_in_db {
            self.out.write_str(",");
        }

        self.is_first_key_in_db = false;
        self.elements_in_key = length;
        self.element_index = 0;
    }

    fn end_key(&mut self) { }

    fn write_comma(&mut self) {
        if self.element_index > 0 && self.element_index < self.elements_in_key {
            self.out.write_str(",");
        }
        self.element_index += 1;
    }

    fn write_key(&mut self, key: &[u8]) {
        self.out.write_str("\"");
        self.out.write(key);
        self.out.write_str("\"");
    }
    fn write_value(&mut self, value: &[u8]) {
        self.out.write_str("\"");
        self.out.write(value);
        self.out.write_str("\"");
    }
}

impl RdbParseFormatter for JSONFormatter {
    fn start_rdb(&mut self) {
        self.out.write_str("[");
    }

    fn end_rdb(&mut self) {
        if self.has_databases {
            self.out.write_str("}");
        }
        self.out.write_str("]\n");
    }

    fn start_database(&mut self, _db_number: u32) {
        if !self.is_first_db {
            self.out.write_str("}");
        }

        self.out.write_str("{");
        self.is_first_db = false;
        self.has_databases = true;
        self.is_first_key_in_db = true;
    }

    fn set(&mut self, key: &[u8], value: &[u8], _expiry: Option<u64>) {
        self.start_key(0);
        self.write_key(key.as_slice());
        self.out.write_str(":");
        self.write_key(value.as_slice());
    }

    fn start_hash(&mut self, key: &[u8], length: u32,
                  _expiry: Option<u64>, _info: Option<()>) {
        self.start_key(length);
        self.write_key(key.as_slice());
        self.out.write_str(":{");
        self.out.flush();
    }
    fn end_hash(&mut self, _key: &[u8]) {
        self.end_key();
        self.out.write_str("}");
        self.out.flush();
    }
    fn hash_element(&mut self, _key: &[u8], field: &[u8], value: &[u8]) {
        self.write_comma();
        self.write_key(field.as_slice());
        self.out.write_str(":");
        self.write_value(value.as_slice());
        self.out.flush();
    }

    fn start_set(&mut self, key: &[u8], cardinality: u32,
                 _expiry: Option<u64>, _info: Option<()>) {
        self.start_key(cardinality);
        self.write_key(key);
        self.out.write_str(":[");
        self.out.flush();
    }
    fn end_set(&mut self, _key: &[u8]) {
        self.end_key();
        self.out.write_str("]");
    }
    fn set_element(&mut self, _key: &[u8], member: &[u8]) {
        self.write_comma();
        self.write_value(member.as_slice());
    }

    fn start_list(&mut self, key: &[u8], length: u32,
                  _expiry: Option<u64>, _info: Option<()>) {
        self.start_key(length);
        self.write_key(key.as_slice());
        self.out.write_str(":[");
    }
    fn end_list(&mut self, _key: &[u8]) {
        self.end_key();
        self.out.write_str("]");
    }
    fn list_element(&mut self, _key: &[u8], value: &[u8]) {
        self.write_comma();
        self.write_value(value.as_slice());
    }

    fn start_sorted_set(&mut self, key: &[u8], length: u32,
                        _expiry: Option<u64>, _info: Option<()>) {
        self.start_key(length);
        self.write_key(key.as_slice());
        self.out.write_str(":{");
    }
    fn end_sorted_set(&mut self, _key: &[u8]) {
        self.end_key();
        self.out.write_str("}");
    }
    fn sorted_set_element(&mut self, _key: &[u8],
                          score: f64, member: &[u8]) {
        self.write_comma();
        self.write_key(member.as_slice());
        self.out.write_str(":");
        self.out.write_str(score.to_string().as_slice());
    }

}
<commit_msg>Write comma when necessary (even for databases)<commit_after>#![allow(unused_must_use)]

use formatter::RdbParseFormatter;
use std::io;

pub struct JSONFormatter {
    out: Box<Writer+'static>,
    is_first_db: bool,
    has_databases: bool,
    is_first_key_in_db: bool,
    elements_in_key: u32,
    element_index: u32
}

impl JSONFormatter {
    pub fn new() -> JSONFormatter {
        let out = Box::new(io::stdout());
        JSONFormatter {
            out: out,
            is_first_db: true,
            has_databases: false,
            is_first_key_in_db: true,
            elements_in_key: 0,
            element_index: 0
        }
    }
}

impl JSONFormatter {
    fn start_key(&mut self, length: u32) {
        if !self.is_first_key_in_db {
            self.out.write_str(",");
        }

        self.is_first_key_in_db = false;
        self.elements_in_key = length;
        self.element_index = 0;
    }

    fn end_key(&mut self) { }

    fn write_comma(&mut self) {
        if self.element_index > 0 {
            self.out.write_str(",");
        }
        self.element_index += 1;
    }

    fn write_key(&mut self, key: &[u8]) {
        self.out.write_str("\"");
        self.out.write(key);
        self.out.write_str("\"");
    }
    fn write_value(&mut self, value: &[u8]) {
        self.out.write_str("\"");
        self.out.write(value);
        self.out.write_str("\"");
    }
}

impl RdbParseFormatter for JSONFormatter {
    fn start_rdb(&mut self) {
        self.out.write_str("[");
    }

    fn end_rdb(&mut self) {
        if self.has_databases {
            self.out.write_str("}");
        }
        self.out.write_str("]\n");
    }

    fn start_database(&mut self, _db_number: u32) {
        if !self.is_first_db {
            self.out.write_str("},");
        }

        self.out.write_str("{");
        self.is_first_db = false;
        self.has_databases = true;
        self.is_first_key_in_db = true;
    }

    fn set(&mut self, key: &[u8], value: &[u8], _expiry: Option<u64>) {
        self.start_key(0);
        self.write_key(key.as_slice());
        self.out.write_str(":");
        self.write_key(value.as_slice());
    }

    fn start_hash(&mut self, key: &[u8], length: u32,
                  _expiry: Option<u64>, _info: Option<()>) {
        self.start_key(length);
        self.write_key(key.as_slice());
        self.out.write_str(":{");
        self.out.flush();
    }
    fn end_hash(&mut self, _key: &[u8]) {
        self.end_key();
        self.out.write_str("}");
        self.out.flush();
    }
    fn hash_element(&mut self, _key: &[u8], field: &[u8], value: &[u8]) {
        self.write_comma();
        self.write_key(field.as_slice());
        self.out.write_str(":");
        self.write_value(value.as_slice());
        self.out.flush();
    }

    fn start_set(&mut self, key: &[u8], cardinality: u32,
                 _expiry: Option<u64>, _info: Option<()>) {
        self.start_key(cardinality);
        self.write_key(key);
        self.out.write_str(":[");
        self.out.flush();
    }
    fn end_set(&mut self, _key: &[u8]) {
        self.end_key();
        self.out.write_str("]");
    }
    fn set_element(&mut self, _key: &[u8], member: &[u8]) {
        self.write_comma();
        self.write_value(member.as_slice());
    }

    fn start_list(&mut self, key: &[u8], length: u32,
                  _expiry: Option<u64>, _info: Option<()>) {
        self.start_key(length);
        self.write_key(key.as_slice());
        self.out.write_str(":[");
    }
    fn end_list(&mut self, _key: &[u8]) {
        self.end_key();
        self.out.write_str("]");
    }
    fn list_element(&mut self, _key: &[u8], value: &[u8]) {
        self.write_comma();
        self.write_value(value.as_slice());
    }

    fn start_sorted_set(&mut self, key: &[u8], length: u32,
                        _expiry: Option<u64>, _info: Option<()>) {
        self.start_key(length);
        self.write_key(key.as_slice());
        self.out.write_str(":{");
    }
    fn end_sorted_set(&mut self, _key: &[u8]) {
        self.end_key();
        self.out.write_str("}");
    }
    fn sorted_set_element(&mut self, _key: &[u8],
                          score: f64, member: &[u8]) {
        self.write_comma();
        self.write_key(member.as_slice());
        self.out.write_str(":");
        self.out.write_str(score.to_string().as_slice());
    }

}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

use rand::Rng;
use ops::Drop;
use path::Path;

#[cfg(unix)]
use rand::reader::ReaderRng;
#[cfg(unix)]
use rt::io::file;

#[cfg(windows)]
use cast;
#[cfg(windows)]
use libc::{c_long, DWORD, BYTE};
#[cfg(windows)]
type HCRYPTPROV = c_long;
// the extern functions imported from the runtime on Windows are
// implemented so that they either succeed or abort(), so we can just
// assume they work when we call them.

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
///   `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
///   service provider with the `PROV_RSA_FULL` type.
///
/// This does not block.
#[cfg(unix)]
pub struct OSRng {
    priv inner: ReaderRng<file::FileReader>
}
/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
///   `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
///   service provider with the `PROV_RSA_FULL` type.
///
/// This does not block.
#[cfg(windows)]
pub struct OSRng {
    priv hcryptprov: HCRYPTPROV
}

impl OSRng {
    /// Create a new `OSRng`.
    #[cfg(unix)]
    pub fn new() -> OSRng {
        let reader = file::open(&Path::new("/dev/urandom"));
        let reader = reader.expect("Error opening /dev/urandom");
        let reader_rng = ReaderRng::new(reader);

        OSRng { inner: reader_rng }
    }

    /// Create a new `OSRng`.
    #[cfg(windows)]
    pub fn new() -> OSRng {
        externfn!(fn rust_win32_rand_acquire(phProv: *mut HCRYPTPROV))

        let mut hcp = 0;
        unsafe {rust_win32_rand_acquire(&mut hcp)};

        OSRng { hcryptprov: hcp }
    }
}

#[cfg(unix)]
impl Rng for OSRng {
    fn next_u32(&mut self) -> u32 {
        self.inner.next_u32()
    }
    fn next_u64(&mut self) -> u64 {
        self.inner.next_u64()
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        self.inner.fill_bytes(v)
    }
}

#[cfg(windows)]
impl Rng for OSRng {
    fn next_u32(&mut self) -> u32 {
        let mut v = [0u8, .. 4];
        self.fill_bytes(v);
        unsafe { cast::transmute(v) }
    }
    fn next_u64(&mut self) -> u64 {
        let mut v = [0u8, .. 8];
        self.fill_bytes(v);
        unsafe { cast::transmute(v) }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        externfn!(fn rust_win32_rand_gen(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: *mut BYTE))

        do v.as_mut_buf |ptr, len| {
            unsafe {rust_win32_rand_gen(self.hcryptprov, len as DWORD, ptr)}
        }
    }
}

impl Drop for OSRng {
    #[cfg(unix)]
    fn drop(&mut self) {
        // ensure that OSRng is not implicitly copyable on all
        // platforms, for consistency.
    }

    #[cfg(windows)]
    fn drop(&mut self) {
        externfn!(fn rust_win32_rand_release(hProv: HCRYPTPROV))

        unsafe {rust_win32_rand_release(self.hcryptprov)}
    }
}

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

    #[test]
    fn test_os_rng() {
        let mut r = OSRng::new();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {
        use task;
        use comm;
        use comm::{GenericChan, GenericPort};
        use option::{None, Some};
        use iter::{Iterator, range};
        use vec::{ImmutableVector, OwnedVector};

        let mut chans = ~[];
        for _ in range(0, 20) {
            let (p, c) = comm::stream();
            chans.push(c);
            do task::spawn_with(p) |p| {
                // wait until all the tasks are ready to go.
                p.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OSRng::new();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            }
        }

        // start all the tasks
        for c in chans.iter() {
            c.send(())
        }
    }
}
<commit_msg>Fill out the remaining functionality in io::file<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

use rand::Rng;
use ops::Drop;

#[cfg(unix)]
use rand::reader::ReaderRng;
#[cfg(unix)]
use rt::io::File;

#[cfg(windows)]
use cast;
#[cfg(windows)]
use libc::{c_long, DWORD, BYTE};
#[cfg(windows)]
type HCRYPTPROV = c_long;
// the extern functions imported from the runtime on Windows are
// implemented so that they either succeed or abort(), so we can just
// assume they work when we call them.

/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
///   `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
///   service provider with the `PROV_RSA_FULL` type.
///
/// This does not block.
#[cfg(unix)]
pub struct OSRng {
    priv inner: ReaderRng<File>
}
/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
///   `/dev/urandom`.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
///   service provider with the `PROV_RSA_FULL` type.
///
/// This does not block.
#[cfg(windows)]
pub struct OSRng {
    priv hcryptprov: HCRYPTPROV
}

impl OSRng {
    /// Create a new `OSRng`.
    #[cfg(unix)]
    pub fn new() -> OSRng {
        use path::Path;
        let reader = File::open(&Path::new("/dev/urandom"));
        let reader = reader.expect("Error opening /dev/urandom");
        let reader_rng = ReaderRng::new(reader);

        OSRng { inner: reader_rng }
    }

    /// Create a new `OSRng`.
    #[cfg(windows)]
    pub fn new() -> OSRng {
        externfn!(fn rust_win32_rand_acquire(phProv: *mut HCRYPTPROV))

        let mut hcp = 0;
        unsafe {rust_win32_rand_acquire(&mut hcp)};

        OSRng { hcryptprov: hcp }
    }
}

#[cfg(unix)]
impl Rng for OSRng {
    fn next_u32(&mut self) -> u32 {
        self.inner.next_u32()
    }
    fn next_u64(&mut self) -> u64 {
        self.inner.next_u64()
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        self.inner.fill_bytes(v)
    }
}

#[cfg(windows)]
impl Rng for OSRng {
    fn next_u32(&mut self) -> u32 {
        let mut v = [0u8, .. 4];
        self.fill_bytes(v);
        unsafe { cast::transmute(v) }
    }
    fn next_u64(&mut self) -> u64 {
        let mut v = [0u8, .. 8];
        self.fill_bytes(v);
        unsafe { cast::transmute(v) }
    }
    fn fill_bytes(&mut self, v: &mut [u8]) {
        externfn!(fn rust_win32_rand_gen(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: *mut BYTE))

        do v.as_mut_buf |ptr, len| {
            unsafe {rust_win32_rand_gen(self.hcryptprov, len as DWORD, ptr)}
        }
    }
}

impl Drop for OSRng {
    #[cfg(unix)]
    fn drop(&mut self) {
        // ensure that OSRng is not implicitly copyable on all
        // platforms, for consistency.
    }

    #[cfg(windows)]
    fn drop(&mut self) {
        externfn!(fn rust_win32_rand_release(hProv: HCRYPTPROV))

        unsafe {rust_win32_rand_release(self.hcryptprov)}
    }
}

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

    #[test]
    fn test_os_rng() {
        let mut r = OSRng::new();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {
        use task;
        use comm;
        use comm::{GenericChan, GenericPort};
        use option::{None, Some};
        use iter::{Iterator, range};
        use vec::{ImmutableVector, OwnedVector};

        let mut chans = ~[];
        for _ in range(0, 20) {
            let (p, c) = comm::stream();
            chans.push(c);
            do task::spawn_with(p) |p| {
                // wait until all the tasks are ready to go.
                p.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OSRng::new();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            }
        }

        // start all the tasks
        for c in chans.iter() {
            c.send(())
        }
    }
}
<|endoftext|>


<commit_before>use bson;
use bson::{Bson, Document};
use mongodb::{Client, ThreadedClient};
use mongodb::db::ThreadedDatabase;
use errors::*;

use editor::control_group::ControlGroup;
use editor::control_metadata::ControlMetadata;
use project::project_capability_group::ProjectCapabilityGroup;
use project::project_capability::ProjectCapability;

#[derive(Clone)]
pub struct DB {
    name: String,
    client: Option<Client>,
}

impl DB {
    pub fn new<T: Into<String>>(name: T) -> Self {
        DB {
            name: name.into(),
            client: None,
        }
    }

    pub fn connect(&mut self, host: &str, port: u16) -> Result<()> {
        self.client = Some(Client::connect(host, port)?);

        // TODO: Move this to a docker initialization script.
        self.fill_db_if_empty()?;

        Ok(())
    }

    /// Queries control groups from the database.
    pub fn get_control_groups(&self) -> Result<Vec<ControlGroup>> {
        let db = self.client.as_ref().unwrap().db(&self.name);

        let mut result: Vec<ControlGroup> = vec![];
        let cursor = db.collection("groups").find(None, None)?;
        for cursor_item in cursor {
            info!("Iterating through database records {:?}", cursor_item);
            if let Ok(item) = cursor_item {
                result.push(bson::from_bson(bson::Bson::Document(item))?);
            }
        }

        Ok(result)
    }

    /// Queries project capabilities grouped by type from the database.
    pub fn get_project_capabilities(&self) -> Result<Vec<ProjectCapabilityGroup>> {
        let db = self.client.as_ref().unwrap().db(&self.name);

        let mut result: Vec<ProjectCapabilityGroup> = vec![];
        let cursor = db.collection("project_capabilities").find(None, None)?;
        for cursor_item in cursor {
            info!("Iterating through database records {:?}", cursor_item);
            if let Ok(item) = cursor_item {
                result.push(bson::from_bson(bson::Bson::Document(item))?);
            }
        }

        Ok(result)
    }

    fn fill_db_if_empty(&self) -> Result<()> {
        let db = self.client.as_ref().unwrap().db(&self.name);

        let groups_collection = db.collection("groups");
        if groups_collection.find_one(None, None)?.is_none() {
            info!("Control groups are not ready, filling DB with the corresponding data...");
            groups_collection.insert_many(self.generate_control_groups()?, None)?;
        }

        let project_capabilities_collection = db.collection("project_capabilities");
        if project_capabilities_collection.find_one(None, None)?.is_none() {
            info!("Project capabilities are not ready, filling DB with the corresponding data...");
            project_capabilities_collection.insert_many(self.generate_project_capabilities()?,
                                                        None)?;
        }

        info!("Database is ready.");

        Ok(())
    }

    // TODO: Below are temporary methods that will be replaced by the pre-loaded DB files.
    fn generate_control_groups(&self) -> Result<Vec<Document>> {
        let control_groups = vec![ControlGroup {
            type_name: "group#1".to_string(),
            name: "Group #1".to_string(),
            description: "Group #1 Description".to_string(),
            items: vec![ControlMetadata {
                type_name: "type#11".to_string(),
                name: "Item #11".to_string(),
                description: "Item #11 Description".to_string(),
            }, ControlMetadata {
                type_name: "type#12".to_string(),
                name: "Item #12".to_string(),
                description: "Item #12 Description".to_string(),
            }],
        }, ControlGroup {
            type_name: "group#2".to_string(),
            name: "Group #2".to_string(),
            description: "Group #2 Description".to_string(),
            items: vec![ControlMetadata {
                type_name: "type#21".to_string(),
                name: "Item #21".to_string(),
                description: "Item #21 Description".to_string(),
            }, ControlMetadata {
                type_name: "type#22".to_string(),
                name: "Item #22".to_string(),
                description: "Item #22 Description".to_string(),
            }],
        }];

        let bson_entities: Vec<Bson> = control_groups.iter()
            .map(|entity| bson::to_bson(&entity).map_err(|e| e.into()))
            .collect::<Result<Vec<Bson>>>()?;

        Ok(bson_entities.into_iter().filter_map(|entity| {
            if let Bson::Document(document) = entity { Some(document) } else { None }
        }).collect::<Vec<Document>>())
    }

    fn generate_project_capabilities(&self) -> Result<Vec<Document>> {
        let project_capability_groups = vec![ProjectCapabilityGroup {
            type_name: "connectivity".to_string(),
            name: "Connectivity".to_string(),
            hint: "Items in this group allows your device to be connected to somewhere (Internet, \
                other device etc.).".to_string(),
            capabilities: vec![ProjectCapability {
                type_name: "wifi".to_string(),
                name: "WiFi Connection".to_string(),
                hint: "Enables WiFi connectivity.".to_string()
            }, ProjectCapability {
                type_name: "bluetooth".to_string(),
                name: "Bluetooth Connection".to_string(),
                hint: "Enables Bluetooth connectivity.".to_string()
            }]
        }, ProjectCapabilityGroup {
            type_name: "output".to_string(),
            name: "Indicators and Output".to_string(),
            hint: "Items in this group allows your device to talk to the world or indicate \
                something (various audio/visual indicators).".to_string(),
            capabilities: vec![ProjectCapability {
                type_name: "led".to_string(),
                name: "LED Indicator".to_string(),
                hint: "Allows your device to light up LEDs whenever needed.".to_string()
            }, ProjectCapability {
                type_name: "speaker".to_string(),
                name: "Speaker".to_string(),
                hint: "Allows your device to play sounds and music.".to_string()
            }]
        }, ProjectCapabilityGroup {
            type_name: "input".to_string(),
            name: "Sensors and Input".to_string(),
            hint: "Items in this group allows your device to get input from the world (various \
                sensors, microphones etc.).".to_string(),
            capabilities: vec![ProjectCapability {
                type_name: "mic".to_string(),
                name: "Microphone".to_string(),
                hint: "Allows your device to listen and record audio.".to_string()
            }, ProjectCapability {
                type_name: "light".to_string(),
                name: "Light Sensor".to_string(),
                hint: "Allows your device to react on changes in light conditions.".to_string()
            }]
        }];

        let bson_entities: Vec<Bson> = project_capability_groups.iter()
            .map(|entity| bson::to_bson(&entity).map_err(|e| e.into()))
            .collect::<Result<Vec<Bson>>>()?;

        Ok(bson_entities.into_iter().filter_map(|entity| {
            if let Bson::Document(document) = entity { Some(document) } else { None }
        }).collect::<Vec<Document>>())
    }
}<commit_msg>[DB] Extend the list of available capabilities.<commit_after>use bson;
use bson::{Bson, Document};
use mongodb::{Client, ThreadedClient};
use mongodb::db::ThreadedDatabase;
use errors::*;

use editor::control_group::ControlGroup;
use editor::control_metadata::ControlMetadata;
use project::project_capability_group::ProjectCapabilityGroup;
use project::project_capability::ProjectCapability;

#[derive(Clone)]
pub struct DB {
    name: String,
    client: Option<Client>,
}

impl DB {
    pub fn new<T: Into<String>>(name: T) -> Self {
        DB {
            name: name.into(),
            client: None,
        }
    }

    pub fn connect(&mut self, host: &str, port: u16) -> Result<()> {
        self.client = Some(Client::connect(host, port)?);

        // TODO: Move this to a docker initialization script.
        self.fill_db_if_empty()?;

        Ok(())
    }

    /// Queries control groups from the database.
    pub fn get_control_groups(&self) -> Result<Vec<ControlGroup>> {
        let db = self.client.as_ref().unwrap().db(&self.name);

        let mut result: Vec<ControlGroup> = vec![];
        let cursor = db.collection("groups").find(None, None)?;
        for cursor_item in cursor {
            info!("Iterating through database records {:?}", cursor_item);
            if let Ok(item) = cursor_item {
                result.push(bson::from_bson(bson::Bson::Document(item))?);
            }
        }

        Ok(result)
    }

    /// Queries project capabilities grouped by type from the database.
    pub fn get_project_capabilities(&self) -> Result<Vec<ProjectCapabilityGroup>> {
        let db = self.client.as_ref().unwrap().db(&self.name);

        let mut result: Vec<ProjectCapabilityGroup> = vec![];
        let cursor = db.collection("project_capabilities").find(None, None)?;
        for cursor_item in cursor {
            info!("Iterating through database records {:?}", cursor_item);
            if let Ok(item) = cursor_item {
                result.push(bson::from_bson(bson::Bson::Document(item))?);
            }
        }

        Ok(result)
    }

    fn fill_db_if_empty(&self) -> Result<()> {
        let db = self.client.as_ref().unwrap().db(&self.name);

        let groups_collection = db.collection("groups");
        if groups_collection.find_one(None, None)?.is_none() {
            info!("Control groups are not ready, filling DB with the corresponding data...");
            groups_collection.insert_many(self.generate_control_groups()?, None)?;
        }

        let project_capabilities_collection = db.collection("project_capabilities");
        if project_capabilities_collection.find_one(None, None)?.is_none() {
            info!("Project capabilities are not ready, filling DB with the corresponding data...");
            project_capabilities_collection.insert_many(self.generate_project_capabilities()?,
                                                        None)?;
        }

        info!("Database is ready.");

        Ok(())
    }

    // TODO: Below are temporary methods that will be replaced by the pre-loaded DB files.
    fn generate_control_groups(&self) -> Result<Vec<Document>> {
        let control_groups = vec![ControlGroup {
            type_name: "group#1".to_string(),
            name: "Group #1".to_string(),
            description: "Group #1 Description".to_string(),
            items: vec![ControlMetadata {
                type_name: "type#11".to_string(),
                name: "Item #11".to_string(),
                description: "Item #11 Description".to_string(),
            }, ControlMetadata {
                type_name: "type#12".to_string(),
                name: "Item #12".to_string(),
                description: "Item #12 Description".to_string(),
            }],
        }, ControlGroup {
            type_name: "group#2".to_string(),
            name: "Group #2".to_string(),
            description: "Group #2 Description".to_string(),
            items: vec![ControlMetadata {
                type_name: "type#21".to_string(),
                name: "Item #21".to_string(),
                description: "Item #21 Description".to_string(),
            }, ControlMetadata {
                type_name: "type#22".to_string(),
                name: "Item #22".to_string(),
                description: "Item #22 Description".to_string(),
            }],
        }];

        let bson_entities: Vec<Bson> = control_groups.iter()
            .map(|entity| bson::to_bson(&entity).map_err(|e| e.into()))
            .collect::<Result<Vec<Bson>>>()?;

        Ok(bson_entities.into_iter().filter_map(|entity| {
            if let Bson::Document(document) = entity { Some(document) } else { None }
        }).collect::<Vec<Document>>())
    }

    fn generate_project_capabilities(&self) -> Result<Vec<Document>> {
        let project_capability_groups = vec![ProjectCapabilityGroup {
            type_name: "connectivity".to_string(),
            name: "Connectivity".to_string(),
            hint: "Everything that allows devices to be connected.".to_string(),
            capabilities: vec![ProjectCapability {
                type_name: "wifi".to_string(),
                name: "WiFi Connection".to_string(),
                hint: "Enables WiFi connectivity.".to_string()
            }, ProjectCapability {
                type_name: "ethernet".to_string(),
                name: "Ethernet Connection".to_string(),
                hint: "Enables Ethernet connectivity.".to_string()
            }, ProjectCapability {
                type_name: "bluetooth".to_string(),
                name: "Bluetooth Connection".to_string(),
                hint: "Enables Bluetooth connectivity.".to_string()
            }, ProjectCapability {
                type_name: "cellular".to_string(),
                name: "Cellular connection".to_string(),
                hint: "Enables Cellular connectivity.".to_string()
            }, ProjectCapability {
                type_name: "nfc".to_string(),
                name: "NFC connection".to_string(),
                hint: "Enables Near field communication connectivity.".to_string()
            }, ProjectCapability {
                type_name: "lora".to_string(),
                name: "LoRa WAN connection".to_string(),
                hint: "Enables LoRa WAN connectivity.".to_string()
            }]
        }, ProjectCapabilityGroup {
            type_name: "output".to_string(),
            name: "Indicators and Output".to_string(),
            hint: "Items in this group allows your device to talk to the world or indicate \
                something (various audio/visual indicators).".to_string(),
            capabilities: vec![ProjectCapability {
                type_name: "led".to_string(),
                name: "LED Indicator".to_string(),
                hint: "Allows your device to light up LEDs whenever needed.".to_string()
            }, ProjectCapability {
                type_name: "led-display".to_string(),
                name: "LED Display".to_string(),
                hint: "Allows your device to use basic LED display.".to_string()
            }, ProjectCapability {
                type_name: "lcd-display".to_string(),
                name: "Display".to_string(),
                hint: "Allows your device to use LCD.".to_string()
            }, ProjectCapability {
                type_name: "speaker".to_string(),
                name: "Speaker".to_string(),
                hint: "Allows your device to play sounds and music.".to_string()
            },ProjectCapability {
                type_name: "beeper".to_string(),
                name: "Beeper".to_string(),
                hint: "Allows your device to produce very basic sounds or beeps.".to_string()
            }]
        }, ProjectCapabilityGroup {
            type_name: "input".to_string(),
            name: "Sensors and Input".to_string(),
            hint: "Items in this group allows your device to get input from the world (various \
                sensors, microphones etc.).".to_string(),
            capabilities: vec![ProjectCapability {
                type_name: "mic".to_string(),
                name: "Microphone".to_string(),
                hint: "Allows your device to listen and record audio.".to_string()
            }, ProjectCapability {
                type_name: "light".to_string(),
                name: "Light Sensor".to_string(),
                hint: "Allows your device to react on changes in light conditions.".to_string()
            }, ProjectCapability {
                type_name: "humidity".to_string(),
                name: "Humidity Sensor".to_string(),
                hint: "Allows your device to measure humidity level.".to_string()
            }, ProjectCapability {
                type_name: "motion".to_string(),
                name: "Motion Sensor".to_string(),
                hint: "Allows your device to detect motion.".to_string()
            }, ProjectCapability {
                type_name: "temperature".to_string(),
                name: "Temperature Sensor".to_string(),
                hint: "Allows your device to measure temperature.".to_string()
            }, ProjectCapability {
                type_name: "magnetic".to_string(),
                name: "Magnetic Field Sensor".to_string(),
                hint: "Allows your device to detect changes in magnetic field.".to_string()
            }, ProjectCapability {
                type_name: "air-pollution".to_string(),
                name: "Air Pollution Sensor".to_string(),
                hint: "Allows your device to measure air pollution level.".to_string()
            }]
        }, ProjectCapabilityGroup {
            type_name: "mechanical".to_string(),
            name: "Mechanical".to_string(),
            hint: "Items in this group allows your device to perform mechanical \
                actions.".to_string(),
            capabilities: vec![ProjectCapability {
                type_name: "motor".to_string(),
                name: "DC Motor".to_string(),
                hint: "Allows your device to spin a DC motor.".to_string()
            }, ProjectCapability {
                type_name: "servo".to_string(),
                name: "Servo Motor".to_string(),
                hint: "Allows your device to control a servo motor.".to_string()
            }, ProjectCapability {
                type_name: "vibrator".to_string(),
                name: "Vibrator".to_string(),
                hint: "Allows your device to vibrate.".to_string()
            }]
        }, ProjectCapabilityGroup {
            type_name: "switches".to_string(),
            name: "Switches".to_string(),
            hint: "Items in this group allows your device to have various switches.".to_string(),
            capabilities: vec![ProjectCapability {
                type_name: "momentary-switch".to_string(),
                name: "Momentary Switch".to_string(),
                hint: "Allows your device to have a mechanical momentary switch.".to_string()
            }, ProjectCapability {
                type_name: "maintained-switch".to_string(),
                name: "Maintained Switch".to_string(),
                hint: "Allows your device to have a mechanical switch with a maintained \
                    state.".to_string()
            }, ProjectCapability {
                type_name: "slide-switch".to_string(),
                name: "Slide Switch".to_string(),
                hint: "Allows your device to have a slide switch.".to_string()
            }]
        }];

        let bson_entities: Vec<Bson> = project_capability_groups.iter()
            .map(|entity| bson::to_bson(&entity).map_err(|e| e.into()))
            .collect::<Result<Vec<Bson>>>()?;

        Ok(bson_entities.into_iter().filter_map(|entity| {
            if let Bson::Document(document) = entity { Some(document) } else { None }
        }).collect::<Vec<Document>>())
    }
}<|endoftext|>


<commit_before>use syntax::ast::{Method_};
use syntax::ext::quote::rt::ToSource;
use racer::ast::with_error_checking_parse;
use racer::{Match, MatchType};
use racer::typeinf::get_function_declaration;

pub fn snippet_for_match(m : &Match) -> String {
    match m.mtype {
        MatchType::Function => {
            let method= get_function_declaration(&m);
            MethodInfo::from_source_str(&method).snippet()
        }
        _ => m.matchstr.clone()
    }
}

struct MethodInfo {
    name : String,
    args : Vec<String>
}

impl MethodInfo {

    ///Parses method declaration as string and returns relevant data
    fn from_source_str(source : &str) -> MethodInfo {

        let trim: &[_] = &['\n', '\r', '{', ' '];
        let decorated = format!("{} {{}}()", source.trim_right_matches(trim));

        with_error_checking_parse(decorated, |p| {

            let ref method = p.parse_method_with_outer_attributes();

            match method.node {
                Method_::MethDecl(ident, _, _, _, _,ref decl, _, _) =>
                    MethodInfo {
                        name: ident.to_source(),
                        args: decl.inputs.iter().map(|a| (*a).to_source()).collect(),
                    },
                _ => panic!("Unable to parse method declaration.")
            }
        })
    }

    ///Returns completion snippets usable by some editors
    fn snippet(&self) -> String {
        format!("{}({})", self.name, &self.args.iter()
            .filter(|&s| *s != "self").enumerate()
            .fold(String::new(), |cur, (i, ref s)| {
                let arg = format!("${{{}:{}}}", i+1, s);
                let delim = if i > 0 {", "} else {""};
                cur + delim + &arg
        }))
    }
}

#[test]
fn method_info_test() {
    let info = MethodInfo::from_source_str("pub fn new() -> Vec<T>");
    assert_eq!(info.name, "new".as_slice());
    assert_eq!(info.args.len(), 0);
    assert_eq!(info.snippet(), "new()");

    let info = MethodInfo::from_source_str("pub fn reserve(&mut self, additional: uint)");
    assert_eq!(info.name, "reserve".as_slice());
    assert_eq!(info.args.len(), 2);
    assert_eq!(info.args[0].as_slice(), "self");
    assert_eq!(info.snippet(), "reserve(${1:additional: uint})");
}
<commit_msg>Fixed unresolved import from removed ast::{Method_}.<commit_after>use syntax::ast::{ImplItem_};
use syntax::ext::quote::rt::ToSource;
use racer::ast::with_error_checking_parse;
use racer::{Match, MatchType};
use racer::typeinf::get_function_declaration;

pub fn snippet_for_match(m : &Match) -> String {
    match m.mtype {
        MatchType::Function => {
            let method= get_function_declaration(&m);
            MethodInfo::from_source_str(&method).snippet()
        }
        _ => m.matchstr.clone()
    }
}

struct MethodInfo {
    name : String,
    args : Vec<String>
}

impl MethodInfo {

    ///Parses method declaration as string and returns relevant data
    fn from_source_str(source : &str) -> MethodInfo {

        let trim: &[_] = &['\n', '\r', '{', ' '];
        let decorated = format!("{} {{}}()", source.trim_right_matches(trim));

        with_error_checking_parse(decorated, |p| {
            let ref method = p.parse_impl_item_with_outer_attributes();

            match method.node {
                ImplItem_::MethodImplItem(ref msig, _) => {
                    let ref decl = msig.decl;
                    MethodInfo {
                        name: method.ident.to_source(),
                        args: decl.inputs.iter().map(|a| (*a).to_source()).collect(),
                    }
                },
                _ => { panic!("Unable to parse method declaration.") }
            }
        })
    }

    ///Returns completion snippets usable by some editors
    fn snippet(&self) -> String {
        format!("{}({})", self.name, &self.args.iter()
            .filter(|&s| *s != "self").enumerate()
            .fold(String::new(), |cur, (i, ref s)| {
                let arg = format!("${{{}:{}}}", i+1, s);
                let delim = if i > 0 {", "} else {""};
                cur + delim + &arg
        }))
    }
}

#[test]
fn method_info_test() {
    let info = MethodInfo::from_source_str("pub fn new() -> Vec<T>");
    assert_eq!(info.name, "new".as_slice());
    assert_eq!(info.args.len(), 0);
    assert_eq!(info.snippet(), "new()");

    let info = MethodInfo::from_source_str("pub fn reserve(&mut self, additional: uint)");
    assert_eq!(info.name, "reserve".as_slice());
    assert_eq!(info.args.len(), 2);
    assert_eq!(info.args[0].as_slice(), "self");
    assert_eq!(info.snippet(), "reserve(${1:additional: uint})");
}
<|endoftext|>


<commit_before>use libc::{c_int, c_char, c_double};
use std::ffi::CString;
use std::path::Path;
use super::super::geom::Point;
use utils::_string;
use raster::{gdal, Driver};
use raster::driver::_register_drivers;

pub struct Dataset {
    c_dataset: *const (),
}

impl Drop for Dataset {
    fn drop(&mut self) {
        unsafe { gdal::GDALClose(self.c_dataset); }
    }
}

impl Dataset {
    pub fn open(path: &Path) -> Option<Dataset> {
        _register_drivers();
        let filename = path.to_str().unwrap();
        let c_filename = CString::new(filename.as_bytes()).unwrap();
        let c_dataset = unsafe { gdal::GDALOpen(c_filename.as_ptr(), gdal::GA_READONLY) };
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub unsafe fn _with_c_ptr(c_dataset: *const ()) -> Dataset {
        return Dataset{c_dataset: c_dataset};
    }

    pub unsafe fn _c_ptr(&self) -> *const () {
        return self.c_dataset;
    }

    pub fn size(&self) -> (isize, isize) {
        let size_x = unsafe { gdal::GDALGetRasterXSize(self.c_dataset) } as isize;
        let size_y = unsafe { gdal::GDALGetRasterYSize(self.c_dataset) } as isize;
        return (size_x, size_y);
    }

    pub fn driver(&self) -> Driver {
        unsafe {
            let c_driver = gdal::GDALGetDatasetDriver(self.c_dataset);
            return Driver::_with_c_ptr(c_driver);
        };
    }

    pub fn count(&self) -> isize {
        return unsafe { gdal::GDALGetRasterCount(self.c_dataset) } as isize;
    }

    pub fn projection(&self) -> String {
        let rv = unsafe { gdal::GDALGetProjectionRef(self.c_dataset) };
        return _string(rv);
    }

    pub fn set_projection(&self, projection: &str) {
        let c_projection = CString::new(projection.as_bytes()).unwrap();
        unsafe { gdal::GDALSetProjection(self.c_dataset, c_projection.as_ptr()) };
    }

    pub fn set_geo_transform(&self, tr: &[f64]) {
        assert_eq!(tr.len(), 6);
        let rv = unsafe {
            gdal::GDALSetGeoTransform(self.c_dataset, tr.as_ptr())
        } as isize;
        assert!(rv == 0);
    }

    pub fn geo_transform(&self) -> Vec<f64> {
        let mut tr: Vec<c_double> = Vec::with_capacity(6);
        for _ in range(0is, 6) { tr.push(0.0); }
        let rv = unsafe {
            gdal::GDALGetGeoTransform(
                self.c_dataset,
                tr.as_mut_ptr()
            )
        } as isize;
        assert!(rv == 0);
        return tr;
    }

    pub fn create_copy(
        &self,
        driver: Driver,
        filename: &str
    ) -> Option<Dataset> {
        use std::ptr::null;
        let c_filename = CString::new(filename.as_bytes()).unwrap();
        let c_dataset = unsafe { gdal::GDALCreateCopy(
                driver._c_ptr(),
                c_filename.as_ptr(),
                self.c_dataset,
                0,
                null(),
                null(),
                null()
            ) };
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub fn read_raster(&self,
        band_index: isize,
        window: Point<isize>,
        window_size: Point<usize>,
        size: Point<usize>
        ) -> ByteBuffer
    {
        let nbytes = size.x * size.y;
        let mut data: Vec<u8> = range(0, nbytes).map(|_| 0u8).collect();
        unsafe {
            let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = gdal::GDALRasterIO(
                c_band,
                gdal::GF_READ,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                data.as_mut_ptr() as *const (),
                size.x as c_int,
                size.y as c_int,
                gdal::GDT_BYTE,
                0,
                0
            ) as isize;
            assert!(rv == 0);
        };
        return ByteBuffer{
            size: size,
            data: data,
        };
    }

    pub fn write_raster(
        &self,
        band_index: isize,
        window: Point<isize>,
        window_size: Point<usize>,
        buffer: ByteBuffer
    ) {
        assert_eq!(buffer.data.len(), buffer.size.x * buffer.size.y);
        unsafe {
            let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = gdal::GDALRasterIO(
                c_band,
                gdal::GF_WRITE,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                buffer.data.as_ptr() as *const (),
                buffer.size.x as c_int,
                buffer.size.y as c_int,
                gdal::GDT_BYTE,
                0,
                0
            ) as isize;
            assert!(rv == 0);
        };
    }
}

pub struct ByteBuffer {
    pub size: Point<usize>,
    pub data: Vec<u8>,
}
<commit_msg>new syntax for ranges<commit_after>use libc::{c_int, c_char, c_double};
use std::ffi::CString;
use std::path::Path;
use super::super::geom::Point;
use utils::_string;
use raster::{gdal, Driver};
use raster::driver::_register_drivers;

pub struct Dataset {
    c_dataset: *const (),
}

impl Drop for Dataset {
    fn drop(&mut self) {
        unsafe { gdal::GDALClose(self.c_dataset); }
    }
}

impl Dataset {
    pub fn open(path: &Path) -> Option<Dataset> {
        _register_drivers();
        let filename = path.to_str().unwrap();
        let c_filename = CString::new(filename.as_bytes()).unwrap();
        let c_dataset = unsafe { gdal::GDALOpen(c_filename.as_ptr(), gdal::GA_READONLY) };
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub unsafe fn _with_c_ptr(c_dataset: *const ()) -> Dataset {
        return Dataset{c_dataset: c_dataset};
    }

    pub unsafe fn _c_ptr(&self) -> *const () {
        return self.c_dataset;
    }

    pub fn size(&self) -> (isize, isize) {
        let size_x = unsafe { gdal::GDALGetRasterXSize(self.c_dataset) } as isize;
        let size_y = unsafe { gdal::GDALGetRasterYSize(self.c_dataset) } as isize;
        return (size_x, size_y);
    }

    pub fn driver(&self) -> Driver {
        unsafe {
            let c_driver = gdal::GDALGetDatasetDriver(self.c_dataset);
            return Driver::_with_c_ptr(c_driver);
        };
    }

    pub fn count(&self) -> isize {
        return unsafe { gdal::GDALGetRasterCount(self.c_dataset) } as isize;
    }

    pub fn projection(&self) -> String {
        let rv = unsafe { gdal::GDALGetProjectionRef(self.c_dataset) };
        return _string(rv);
    }

    pub fn set_projection(&self, projection: &str) {
        let c_projection = CString::new(projection.as_bytes()).unwrap();
        unsafe { gdal::GDALSetProjection(self.c_dataset, c_projection.as_ptr()) };
    }

    pub fn set_geo_transform(&self, tr: &[f64]) {
        assert_eq!(tr.len(), 6);
        let rv = unsafe {
            gdal::GDALSetGeoTransform(self.c_dataset, tr.as_ptr())
        } as isize;
        assert!(rv == 0);
    }

    pub fn geo_transform(&self) -> Vec<f64> {
        let mut tr: Vec<c_double> = Vec::with_capacity(6);
        for _ in (0isize..6) { tr.push(0.0); }
        let rv = unsafe {
            gdal::GDALGetGeoTransform(
                self.c_dataset,
                tr.as_mut_ptr()
            )
        } as isize;
        assert!(rv == 0);
        return tr;
    }

    pub fn create_copy(
        &self,
        driver: Driver,
        filename: &str
    ) -> Option<Dataset> {
        use std::ptr::null;
        let c_filename = CString::new(filename.as_bytes()).unwrap();
        let c_dataset = unsafe { gdal::GDALCreateCopy(
                driver._c_ptr(),
                c_filename.as_ptr(),
                self.c_dataset,
                0,
                null(),
                null(),
                null()
            ) };
        return match c_dataset.is_null() {
            true  => None,
            false => Some(Dataset{c_dataset: c_dataset}),
        };
    }

    pub fn read_raster(&self,
        band_index: isize,
        window: Point<isize>,
        window_size: Point<usize>,
        size: Point<usize>
        ) -> ByteBuffer
    {
        let nbytes = size.x * size.y;
        let mut data: Vec<u8> = (0..nbytes).map(|_| 0u8).collect();
        unsafe {
            let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = gdal::GDALRasterIO(
                c_band,
                gdal::GF_READ,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                data.as_mut_ptr() as *const (),
                size.x as c_int,
                size.y as c_int,
                gdal::GDT_BYTE,
                0,
                0
            ) as isize;
            assert!(rv == 0);
        };
        return ByteBuffer{
            size: size,
            data: data,
        };
    }

    pub fn write_raster(
        &self,
        band_index: isize,
        window: Point<isize>,
        window_size: Point<usize>,
        buffer: ByteBuffer
    ) {
        assert_eq!(buffer.data.len(), buffer.size.x * buffer.size.y);
        unsafe {
            let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
            let rv = gdal::GDALRasterIO(
                c_band,
                gdal::GF_WRITE,
                window.x as c_int,
                window.y as c_int,
                window_size.x as c_int,
                window_size.y as c_int,
                buffer.data.as_ptr() as *const (),
                buffer.size.x as c_int,
                buffer.size.y as c_int,
                gdal::GDT_BYTE,
                0,
                0
            ) as isize;
            assert!(rv == 0);
        };
    }
}

pub struct ByteBuffer {
    pub size: Point<usize>,
    pub data: Vec<u8>,
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::net::IpAddr;
use std::path::{PathBuf, Path, Component};

use id_map::{IdMap, mapping_validator};
use ipnetwork::IpNetwork;
use quire::validate::{Sequence, Mapping, Scalar, Numeric};
use quire::validate::{Structure};
use range::Range;

#[derive(Deserialize)]
pub struct BridgedNetwork {
    pub bridge: String,
    #[serde(with="::serde_str")]
    pub network: IpNetwork,
    pub default_gateway: Option<IpAddr>,
}

#[derive(Deserialize)]
pub struct SandboxConfig {
    pub config_file: Option<PathBuf>,
    pub image_dir: PathBuf,
    pub image_dir_levels: u32,
    pub used_images_list: Option<PathBuf>,
    pub log_file: Option<PathBuf>,
    pub log_level: Option<String>,
    pub readonly_paths: BTreeMap<PathBuf, PathBuf>,
    pub writable_paths: BTreeMap<PathBuf, PathBuf>,
    pub allow_users: Vec<Range>,
    pub default_user: Option<u32>,
    pub allow_groups: Vec<Range>,
    pub default_group: Option<u32>,
    pub allow_tcp_ports: Vec<Range>,
    pub additional_hosts: BTreeMap<String, String>,
    pub uid_map: Vec<IdMap>,
    pub gid_map: Vec<IdMap>,
    pub auto_clean: bool,
    pub resolv_conf: PathBuf,
    pub hosts_file: PathBuf,
    pub bridged_network: Option<BridgedNetwork>,
    pub secrets_private_key: Option<PathBuf>,
    pub secrets_namespaces: Vec<String>,
}

impl SandboxConfig {
    pub fn check_path<P: AsRef<Path>>(&self, path: P) -> bool {
        let mut num = 0;
        for component in path.as_ref().components() {
            match component {
                Component::Normal(x) if x.to_str().is_some() => num += 1,
                _ => return false,
            }
        }
        return num == self.image_dir_levels;
    }
    pub fn validator<'x>() -> Structure<'x> {
        Structure::new()
        .member("config_file", Scalar::new().optional())
        .member("image_dir", Scalar::new().optional()
            .default("/var/lib/lithos/containers"))
        .member("image_dir_levels",
            Numeric::new().min(1).max(16).default(1))
        .member("used_images_list", Scalar::new().optional())
        .member("log_file", Scalar::new().optional())
        .member("log_level", Scalar::new().optional())
        .member("readonly_paths", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("writable_paths", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("allow_users", Sequence::new(Scalar::new()))
        .member("default_user", Scalar::new().optional())
        .member("allow_groups", Sequence::new(Scalar::new()))
        .member("default_group", Scalar::new().default(0))
        .member("allow_tcp_ports", Sequence::new(Scalar::new()))
        .member("uid_map", mapping_validator())
        .member("gid_map", mapping_validator())
        .member("additional_hosts", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("auto_clean", Scalar::new().default("true").optional())
        .member("hosts_file", Scalar::new().default("/etc/hosts"))
        .member("resolv_conf", Scalar::new().default("/etc/resolv.conf"))
        .member("bridged_network", Structure::new()
            .member("bridge", Scalar::new())
            .member("network", Scalar::new())
            .member("default_gateway", Scalar::new())
            .optional())
        .member("secrets_private_key", Scalar::new().optional())
        .member("secrets_namespaces", Scalar::new().optional())
    }
}
<commit_msg>Fix bug in validator of secrets-namespaces<commit_after>use std::collections::BTreeMap;
use std::net::IpAddr;
use std::path::{PathBuf, Path, Component};

use id_map::{IdMap, mapping_validator};
use ipnetwork::IpNetwork;
use quire::validate::{Sequence, Mapping, Scalar, Numeric};
use quire::validate::{Structure};
use range::Range;

#[derive(Deserialize)]
pub struct BridgedNetwork {
    pub bridge: String,
    #[serde(with="::serde_str")]
    pub network: IpNetwork,
    pub default_gateway: Option<IpAddr>,
}

#[derive(Deserialize)]
pub struct SandboxConfig {
    pub config_file: Option<PathBuf>,
    pub image_dir: PathBuf,
    pub image_dir_levels: u32,
    pub used_images_list: Option<PathBuf>,
    pub log_file: Option<PathBuf>,
    pub log_level: Option<String>,
    pub readonly_paths: BTreeMap<PathBuf, PathBuf>,
    pub writable_paths: BTreeMap<PathBuf, PathBuf>,
    pub allow_users: Vec<Range>,
    pub default_user: Option<u32>,
    pub allow_groups: Vec<Range>,
    pub default_group: Option<u32>,
    pub allow_tcp_ports: Vec<Range>,
    pub additional_hosts: BTreeMap<String, String>,
    pub uid_map: Vec<IdMap>,
    pub gid_map: Vec<IdMap>,
    pub auto_clean: bool,
    pub resolv_conf: PathBuf,
    pub hosts_file: PathBuf,
    pub bridged_network: Option<BridgedNetwork>,
    pub secrets_private_key: Option<PathBuf>,
    pub secrets_namespaces: Vec<String>,
}

impl SandboxConfig {
    pub fn check_path<P: AsRef<Path>>(&self, path: P) -> bool {
        let mut num = 0;
        for component in path.as_ref().components() {
            match component {
                Component::Normal(x) if x.to_str().is_some() => num += 1,
                _ => return false,
            }
        }
        return num == self.image_dir_levels;
    }
    pub fn validator<'x>() -> Structure<'x> {
        Structure::new()
        .member("config_file", Scalar::new().optional())
        .member("image_dir", Scalar::new().optional()
            .default("/var/lib/lithos/containers"))
        .member("image_dir_levels",
            Numeric::new().min(1).max(16).default(1))
        .member("used_images_list", Scalar::new().optional())
        .member("log_file", Scalar::new().optional())
        .member("log_level", Scalar::new().optional())
        .member("readonly_paths", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("writable_paths", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("allow_users", Sequence::new(Scalar::new()))
        .member("default_user", Scalar::new().optional())
        .member("allow_groups", Sequence::new(Scalar::new()))
        .member("default_group", Scalar::new().default(0))
        .member("allow_tcp_ports", Sequence::new(Scalar::new()))
        .member("uid_map", mapping_validator())
        .member("gid_map", mapping_validator())
        .member("additional_hosts", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("auto_clean", Scalar::new().default("true").optional())
        .member("hosts_file", Scalar::new().default("/etc/hosts"))
        .member("resolv_conf", Scalar::new().default("/etc/resolv.conf"))
        .member("bridged_network", Structure::new()
            .member("bridge", Scalar::new())
            .member("network", Scalar::new())
            .member("default_gateway", Scalar::new())
            .optional())
        .member("secrets_private_key", Scalar::new().optional())
        .member("secrets_namespaces", Sequence::new(Scalar::new()))
    }
}
<|endoftext|>


<commit_before>// Included by src/config.rs until stable Rust supports custom_derive.
//
// See https://serde.rs/codegen-stable.html for more information.

/// Represents an email address.
#[derive(Clone, Deserialize)]
pub struct Smtp {
    pub address: String
}

/// Represents an email address.
#[derive(Clone, Deserialize)]
pub struct Email {
    pub address: String,
    pub name: String,
}

/// Represents an OpenID Connect provider.
#[derive(Clone, Deserialize)]
pub struct Provider {
    pub discovery: String,
    pub client_id: String,
    pub secret: String,
    pub issuer: String,
}

/// Holds runtime configuration data for this daemon instance.
#[derive(Clone, Deserialize)]
pub struct AppConfig {
    pub base_url: String, // Origin of this instance, used for constructing URLs
    pub keys: Vec<crypto::NamedKey>, // Signing keys
    pub store: store::Store, // Redis Client
    pub smtp: Smtp, // SMTP client
    pub sender: Email, // From address for email
    pub token_validity: usize, // JWT validity duration, in seconds
    pub providers: HashMap<String, Provider>, // Mapping of Domain -> OIDC Provider
}
<commit_msg>Reformat AppConfig comments.<commit_after>// Included by src/config.rs until stable Rust supports custom_derive.
//
// See https://serde.rs/codegen-stable.html for more information.

/// Represents an email address.
#[derive(Clone, Deserialize)]
pub struct Smtp {
    pub address: String
}

/// Represents an email address.
#[derive(Clone, Deserialize)]
pub struct Email {
    pub address: String,
    pub name: String,
}

/// Represents an OpenID Connect provider.
#[derive(Clone, Deserialize)]
pub struct Provider {
    pub discovery: String,
    pub client_id: String,
    pub secret: String,
    pub issuer: String,
}

/// Holds runtime configuration data for this daemon instance.
#[derive(Clone, Deserialize)]
pub struct AppConfig {
    /// Origin of this instance, used for constructing URLs
    pub base_url: String,
    /// Signing keys
    pub keys: Vec<crypto::NamedKey>,
    /// Redis Client
    pub store: store::Store,
    /// SMTP client
    pub smtp: Smtp,
    /// From address for email
    pub sender: Email,
    /// JWT validity duration, in seconds
    pub token_validity: usize,
    /// Mapping of Domain -> OIDC Provider
    pub providers: HashMap<String, Provider>,
}
<|endoftext|>


<commit_before>use std::thread::{self, JoinHandle};
use std::io::{Read, Write, Cursor};
use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian};
use mio::{Handler, EventLoop, Token, EventSet, PollOpt};
use mio::tcp::TcpStream;
use steam_data::Message;
use std::sync::mpsc::{self, Sender, Receiver};

enum SteamConnectionEvent {
    Shutdown,
    SendMessage(Message),
    SetKey(Vec<u8>)
}

struct SteamConnectionRuntime {
    stream: TcpStream,
    token: Token,
    event_set: EventSet,
    msg_sender: Sender<Message>,
    queued_messages: Vec<Message>,
    encryption_key: Option<Vec<u8>>
}

impl Handler for SteamConnectionRuntime {
    type Timeout = ();
    type Message = SteamConnectionEvent;

    fn ready(&mut self, event_loop: &mut EventLoop<SteamConnectionRuntime>, _token: Token, events: EventSet) {
        trace!("Handling ready() event with EventSet {:?}...", events);

        if events.is_readable() {
            self.readable();
        }

        if events.is_writable() {
            self.writeable(event_loop);
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<SteamConnectionRuntime>, event: SteamConnectionEvent) {
        trace!("Handling notify() event...");

        match event {
            SteamConnectionEvent::Shutdown => {
                debug!("Shutting down event loop...");
                event_loop.shutdown();
            },
            SteamConnectionEvent::SendMessage(msg) => {
                debug!("Received message for sending");
                self.queued_messages.push(msg);
                self.event_set.insert(EventSet::writable());
                event_loop
                    .reregister(&self.stream, self.token, self.event_set, PollOpt::edge())
                    .unwrap();
            },
            SteamConnectionEvent::SetKey(key) => {
                debug!("Switching to encrypted mode");
                self.encryption_key = Some(key);
            }
        }
    }
}

impl SteamConnectionRuntime {
    fn readable(&mut self) {
        // TODO: Detect if we were dropped by the server, in which case we'll read 0 bytes
        trace!("Received connection readable event");

        // Read in the packet header
        let mut header = vec![0u8; 8];
        self.stream.read(&mut header).unwrap();
        let mut header_c = Cursor::new(header);
        let length = header_c.read_u32::<LittleEndian>().unwrap();

        // Sanity check
        let magic = header_c.read_u32::<LittleEndian>().unwrap();
        if magic != 0x31305456 {
            debug!("Data for following panic: {} {}", length, magic);
            panic!("Invalid magic, you are not connecting to a steam server");
        }

        // Read in the actual data
        let mut data = vec![0u8; length as usize];
        self.stream.read(&mut data).unwrap();

        // TODO: decrypt the data here if encryption is on

        // Turn the data into a message and send it over
        let msg = Message::parse(&mut Cursor::new(&data));
        self.msg_sender.send(msg).unwrap();
    }

    fn writeable(&mut self, event_loop: &mut EventLoop<SteamConnectionRuntime>) {
        // Go over all queued messages
        for msg in &self.queued_messages {
            trace!("Sending queued message...");

            // TODO: Perhaps send this all at once? See if it improves performance later.
            // TODO: Pre-estimate the packet size needed.
            let packet: Vec<u8> = Vec::new();
            let mut packet_c = Cursor::new(packet);

            // Turn the message into data
            let msg_data = msg.into_bytes();

            // Write the packet header and the message to the data
            packet_c.write_u32::<LittleEndian>(msg_data.len() as u32).unwrap(); // Msg length
            packet_c.write_u32::<LittleEndian>(0x31305456).unwrap(); // Magic
            packet_c.write(&msg_data).unwrap();

            // Send the message finally
            self.stream.write(&packet_c.into_inner()).unwrap();
        }

        // Now that all of those are sent, clear the list and stop asking for writeable
        self.queued_messages.clear();
        self.event_set.remove(EventSet::writable());
        event_loop
            .reregister(&self.stream, self.token, self.event_set, PollOpt::edge())
            .unwrap();
    }
}

/// A token to interact with a steam connection. Used to receive and send messages from and to a
/// steam server.
pub struct SteamConnection {
    runtime: JoinHandle<()>,
    incoming_receiver: Receiver<Message>,
    event_sender: ::mio::Sender<SteamConnectionEvent>
}

impl SteamConnection {
    /// Connects to a steam server. Aquires the server it should connect to automatically.
    pub fn connect() -> Self {
        // Set up the channels to send messages through
        let (incoming_sender, incoming_receiver) = mpsc::channel();

        // Set up the event loop and get the event sender from it
        let event_loop = EventLoop::new().unwrap();
        let event_sender = event_loop.channel();

        // Start the runtime
        let handle = thread::Builder::new()
            .name("boiler-runtime".into())
            .spawn(move || {
                Self::client_runtime(event_loop, incoming_sender);
            })
            .unwrap();

        // Return the token that keeps track of the runtime
        SteamConnection {
            runtime: handle,
            incoming_receiver: incoming_receiver,
            event_sender: event_sender,
        }
    }

    /// Disconnects this connection.
    pub fn disconnect(&mut self) {
        debug!("Sending disconnect event to runtime...");
        self.event_sender.send(SteamConnectionEvent::Shutdown).unwrap();
    }

    /// Blocks until a single message has been received, then returns it.
    pub fn recv(&mut self) -> Message {
        self.incoming_receiver.recv().unwrap()
    }

    /// Queues up a single message for sending.
    pub fn send(&mut self, message: Message) {
        self.event_sender.send(SteamConnectionEvent::SendMessage(message)).unwrap();
    }

    /// Notifies the runtime to use an ecryption key from now on for all messages.
    pub fn set_encryption_key(&mut self, key: Vec<u8>) {
        self.event_sender.send(SteamConnectionEvent::SetKey(key)).unwrap();
    }

    /// Blocks until this connection has been closed.
    pub fn wait_close(self) {
        self.runtime.join().unwrap();
    }

    fn client_runtime(mut event_loop: EventLoop<SteamConnectionRuntime>, msg_sender: Sender<Message>) {
        // Get a server to connect to
        // TODO: Take one address from a list of many
        // TODO: Actually fetch a server using the API
        let server_addr = "72.165.61.185:27017".parse().unwrap();
        info!("Connecting to {}", server_addr);

        // Start the connection to the server
        let stream = TcpStream::connect(&server_addr).unwrap();
        let event_set = EventSet::readable();
        let token = Token(0);
        event_loop.register(&stream, token, event_set, PollOpt::edge()).unwrap();

        // Run the event loop
        let mut runtime = SteamConnectionRuntime {
            stream: stream,
            token: token,
            event_set: event_set,
            msg_sender: msg_sender,
            queued_messages: Vec::new(),
            encryption_key: None
        };
        event_loop.run(&mut runtime).unwrap();
    }
}
<commit_msg>Make use of encryption in the connection helper type<commit_after>use std::thread::{self, JoinHandle};
use std::io::{Read, Write, Cursor};
use std::sync::mpsc::{self, Sender, Receiver};
use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian};
use mio::{Handler, EventLoop, Token, EventSet, PollOpt};
use mio::tcp::TcpStream;
use crypto;
use steam_data::Message;

enum SteamConnectionEvent {
    Shutdown,
    SendMessage(Message),
    SetKey(Vec<u8>)
}

struct SteamConnectionRuntime {
    stream: TcpStream,
    token: Token,
    event_set: EventSet,
    msg_sender: Sender<Message>,
    queued_messages: Vec<Message>,
    encryption_key: Option<Vec<u8>>
}

impl Handler for SteamConnectionRuntime {
    type Timeout = ();
    type Message = SteamConnectionEvent;

    fn ready(&mut self, event_loop: &mut EventLoop<SteamConnectionRuntime>, _token: Token, events: EventSet) {
        trace!("Handling ready() event with EventSet {:?}...", events);

        if events.is_readable() {
            self.readable();
        }

        if events.is_writable() {
            self.writeable(event_loop);
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<SteamConnectionRuntime>, event: SteamConnectionEvent) {
        trace!("Handling notify() event...");

        match event {
            SteamConnectionEvent::Shutdown => {
                debug!("Shutting down event loop...");
                event_loop.shutdown();
            },
            SteamConnectionEvent::SendMessage(msg) => {
                debug!("Received message for sending");
                self.queued_messages.push(msg);
                self.event_set.insert(EventSet::writable());
                event_loop
                    .reregister(&self.stream, self.token, self.event_set, PollOpt::edge())
                    .unwrap();
            },
            SteamConnectionEvent::SetKey(key) => {
                debug!("Switching to encrypted mode");
                self.encryption_key = Some(key);
            }
        }
    }
}

impl SteamConnectionRuntime {
    fn readable(&mut self) {
        // TODO: Detect if we were dropped by the server, in which case we'll read 0 bytes
        trace!("Received connection readable event");

        // Read in the packet header
        let mut header = vec![0u8; 8];
        self.stream.read(&mut header).unwrap();
        let mut header_c = Cursor::new(header);
        let length = header_c.read_u32::<LittleEndian>().unwrap();

        // Sanity check
        let magic = header_c.read_u32::<LittleEndian>().unwrap();
        if magic != 0x31305456 {
            debug!("Data for following panic: {} {}", length, magic);
            panic!("Invalid magic, you are not connecting to a steam server");
        }

        // Read in the actual data
        let mut data = vec![0u8; length as usize];
        self.stream.read(&mut data).unwrap();

        // Decrypt the data if encryption is on
        if let &Some(ref key) = &self.encryption_key {
            data = crypto::symmetric_decrypt(&data, key);
        }

        // Turn the data into a message and send it over
        let msg = Message::parse(&mut Cursor::new(&data));
        self.msg_sender.send(msg).unwrap();
    }

    fn writeable(&mut self, event_loop: &mut EventLoop<SteamConnectionRuntime>) {
        // Go over all queued messages
        for msg in &self.queued_messages {
            trace!("Sending queued message...");

            // TODO: Perhaps send this all at once? See if it improves performance later.
            // TODO: Pre-estimate the packet size needed.
            let packet: Vec<u8> = Vec::new();
            let mut packet_c = Cursor::new(packet);

            // Turn the message into data
            let mut msg_data = msg.into_bytes();

            // Encrypt the data if encryption is on
            if let &Some(ref key) = &self.encryption_key {
                msg_data = crypto::symmetric_encrypt(&msg_data, key);
            }

            // Write the packet header and the message to the data
            packet_c.write_u32::<LittleEndian>(msg_data.len() as u32).unwrap(); // Msg length
            packet_c.write_u32::<LittleEndian>(0x31305456).unwrap(); // Magic
            packet_c.write(&msg_data).unwrap();

            // Send the message finally
            self.stream.write(&packet_c.into_inner()).unwrap();
        }

        // Now that all of those are sent, clear the list and stop asking for writeable
        self.queued_messages.clear();
        self.event_set.remove(EventSet::writable());
        event_loop
            .reregister(&self.stream, self.token, self.event_set, PollOpt::edge())
            .unwrap();
    }
}

/// A token to interact with a steam connection. Used to receive and send messages from and to a
/// steam server.
pub struct SteamConnection {
    runtime: JoinHandle<()>,
    incoming_receiver: Receiver<Message>,
    event_sender: ::mio::Sender<SteamConnectionEvent>
}

impl SteamConnection {
    /// Connects to a steam server. Aquires the server it should connect to automatically.
    pub fn connect() -> Self {
        // Set up the channels to send messages through
        let (incoming_sender, incoming_receiver) = mpsc::channel();

        // Set up the event loop and get the event sender from it
        let event_loop = EventLoop::new().unwrap();
        let event_sender = event_loop.channel();

        // Start the runtime
        let handle = thread::Builder::new()
            .name("boiler-runtime".into())
            .spawn(move || {
                Self::client_runtime(event_loop, incoming_sender);
            })
            .unwrap();

        // Return the token that keeps track of the runtime
        SteamConnection {
            runtime: handle,
            incoming_receiver: incoming_receiver,
            event_sender: event_sender,
        }
    }

    /// Disconnects this connection.
    pub fn disconnect(&mut self) {
        debug!("Sending disconnect event to runtime...");
        self.event_sender.send(SteamConnectionEvent::Shutdown).unwrap();
    }

    /// Blocks until a single message has been received, then returns it.
    pub fn recv(&mut self) -> Message {
        self.incoming_receiver.recv().unwrap()
    }

    /// Queues up a single message for sending.
    pub fn send(&mut self, message: Message) {
        self.event_sender.send(SteamConnectionEvent::SendMessage(message)).unwrap();
    }

    /// Notifies the runtime to use an ecryption key from now on for all messages.
    pub fn set_encryption_key(&mut self, key: Vec<u8>) {
        self.event_sender.send(SteamConnectionEvent::SetKey(key)).unwrap();
    }

    /// Blocks until this connection has been closed.
    pub fn wait_close(self) {
        self.runtime.join().unwrap();
    }

    fn client_runtime(mut event_loop: EventLoop<SteamConnectionRuntime>, msg_sender: Sender<Message>) {
        // Get a server to connect to
        // TODO: Take one address from a list of many
        // TODO: Actually fetch a server using the API
        let server_addr = "72.165.61.185:27017".parse().unwrap();
        info!("Connecting to {}", server_addr);

        // Start the connection to the server
        let stream = TcpStream::connect(&server_addr).unwrap();
        let event_set = EventSet::readable();
        let token = Token(0);
        event_loop.register(&stream, token, event_set, PollOpt::edge()).unwrap();

        // Run the event loop
        let mut runtime = SteamConnectionRuntime {
            stream: stream,
            token: token,
            event_set: event_set,
            msg_sender: msg_sender,
            queued_messages: Vec::new(),
            encryption_key: None
        };
        event_loop.run(&mut runtime).unwrap();
    }
}
<|endoftext|>