<commit_before>extern crate toml;
extern crate reqwest;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate glob;
extern crate nix;

#[macro_use]
extern crate lazy_static;

use std::io::{Write, BufRead};
use std::ffi::CStr;
extern crate libc;

mod structs;
use structs::Config;
mod ghclient;
use ghclient::GithubClient;
mod buffer;
use buffer::Buffer;
mod cstructs;
use cstructs::{Passwd, Spwd, Group};
mod runfiles;
mod statics;
use statics::CONF_PATH;

lazy_static! {
    pub static ref CONFIG:Config = Config::new(&CONF_PATH).unwrap();
    pub static ref CLIENT:GithubClient = GithubClient::new(&CONFIG).unwrap();
}

#[allow(dead_code)]
enum NssStatus {
    TryAgain,
    Unavail,
    NotFound,
    Success,
}

impl From<NssStatus> for libc::c_int {
    fn from(status: NssStatus) -> libc::c_int {
        match status {
            NssStatus::TryAgain => -2,
            NssStatus::Unavail => -1,
            NssStatus::NotFound => 0,
            NssStatus::Success => 1,
        }
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwnam_r(cnameptr: *const libc::c_char,
                                         pw: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let cname: &CStr = unsafe { CStr::from_ptr(cnameptr) };
    let name = String::from(cname.to_str().unwrap());
    let (_, members) = CLIENT.get_team_members().unwrap();
    match members.get(&name) {
        Some(member) => {
            match unsafe { (*pw).pack_args(&mut buffer, &member.login, member.id, &CONFIG) } {
                Ok(_) => libc::c_int::from(NssStatus::Success),
                Err(_) => nix::Errno::ERANGE as libc::c_int,
            }
        }
        None => libc::c_int::from(NssStatus::NotFound),
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwuid_r(uid: libc::uid_t,
                                         pw: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let (_, members) = CLIENT.get_team_members().unwrap();
    for member in members.values() {
        if uid == member.id as libc::uid_t {
            match unsafe { (*pw).pack_args(&mut buffer, &member.login, member.id, &CONFIG) } {
                Ok(_) => return libc::c_int::from(NssStatus::Success),
                Err(_) => return nix::Errno::ERANGE as libc::c_int,
            }
        }
    }
    libc::c_int::from(NssStatus::NotFound)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setpwent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let members = match CLIENT.get_team_members() {
        Ok((_, members)) => members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    for member in members.values() {
        list_file.write(format!("{}\t{}\n", member.login, member.id).as_bytes())
                 .unwrap();
    }
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwent_r(pwbuf: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         pwbufp: *mut *mut Passwd)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        let id = words[1].parse::<u64>().unwrap();
        match unsafe { (*pwbuf).pack_args(&mut buffer, words[0], id, &CONFIG) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *pwbufp = pwbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *pwbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endpwent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getspnam_r(cnameptr: *const libc::c_char,
                                         spwd: *mut Spwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let cname: &CStr = unsafe { CStr::from_ptr(cnameptr) };
    let name = String::from(cname.to_str().unwrap());
    let (_, members) = CLIENT.get_team_members().unwrap();
    match members.get(&name) {
        Some(member) => {
            match unsafe { (*spwd).pack_args(&mut buffer, &member.login, &CONFIG) } {
                Ok(_) => libc::c_int::from(NssStatus::Success),
                Err(_) => nix::Errno::ERANGE as libc::c_int,
            }
        }
        None => libc::c_int::from(NssStatus::NotFound),
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setspent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let members = match CLIENT.get_team_members() {
        Ok((_, members)) => members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    for member in members.values() {
        list_file.write(format!("{}\t{}\n", member.login, member.id).as_bytes())
                 .unwrap();
    }
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getspent_r(spbuf: *mut Spwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         spbufp: *mut *mut Spwd)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        match unsafe { (*spbuf).pack_args(&mut buffer, words[0], &CONFIG) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *spbufp = spbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *spbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endspent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrgid_r(gid: libc::gid_t,
                                         group: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let (team, members) = CLIENT.get_team_members().unwrap();
    let members: Vec<&str> = members.values().map(|m| m.login.as_str()).collect();
    if gid as u64 == team.id {
        match unsafe { (*group).pack_args(&mut buffer, &team.name, gid as u64, &members) } {
            Ok(_) => libc::c_int::from(NssStatus::Success),
            Err(_) => nix::Errno::ERANGE as libc::c_int,
        }
    } else {
        libc::c_int::from(NssStatus::NotFound)
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrnam_r(cnameptr: *const libc::c_char,
                                         group: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let cname: &CStr = unsafe { CStr::from_ptr(cnameptr) };
    let name = String::from(cname.to_str().unwrap());
    let (team, members) = CLIENT.get_team_members().unwrap();
    let members: Vec<&str> = members.values().map(|m| m.login.as_str()).collect();
    if name == team.name {
        match unsafe { (*group).pack_args(&mut buffer, &team.name, team.id, &members) } {
            Ok(_) => libc::c_int::from(NssStatus::Success),
            Err(_) => nix::Errno::ERANGE as libc::c_int,
        }
    } else {
        libc::c_int::from(NssStatus::NotFound)
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setgrent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let (team, members) = match CLIENT.get_team_members() {
        Ok(team_members) => team_members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let member_names = members.values().map(|x| x.login.as_str()).collect::<Vec<&str>>().join(" ");
    list_file.write(format!("{}\t{}\t{}\n", team.name, team.id, member_names).as_bytes())
             .unwrap();
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrent_r(grbuf: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         grbufp: *mut *mut Group)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        let member_names: Vec<&str> = words[2].split(" ").collect();
        let id: u64 = words[1].parse::<u64>().unwrap();
        match unsafe { (*grbuf).pack_args(&mut buffer, words[0], id, &member_names) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *grbufp = grbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *grbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endgrent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}
<commit_msg>Refactor function to create `String` from `char*`<commit_after>extern crate toml;
extern crate reqwest;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate glob;
extern crate nix;

#[macro_use]
extern crate lazy_static;

use std::io::{Write, BufRead};
use std::ffi::CStr;
extern crate libc;

mod structs;
use structs::Config;
mod ghclient;
use ghclient::GithubClient;
mod buffer;
use buffer::Buffer;
mod cstructs;
use cstructs::{Passwd, Spwd, Group};
mod runfiles;
mod statics;
use statics::CONF_PATH;

lazy_static! {
    pub static ref CONFIG:Config = Config::new(&CONF_PATH).unwrap();
    pub static ref CLIENT:GithubClient = GithubClient::new(&CONFIG).unwrap();
}

#[allow(dead_code)]
enum NssStatus {
    TryAgain,
    Unavail,
    NotFound,
    Success,
}

impl From<NssStatus> for libc::c_int {
    fn from(status: NssStatus) -> libc::c_int {
        match status {
            NssStatus::TryAgain => -2,
            NssStatus::Unavail => -1,
            NssStatus::NotFound => 0,
            NssStatus::Success => 1,
        }
    }
}

fn string_from(cstrptr: *const libc::c_char) -> String {
    let cstr: &CStr = unsafe { CStr::from_ptr(cstrptr) };
    String::from(cstr.to_str().unwrap())
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwnam_r(cnameptr: *const libc::c_char,
                                         pw: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let name = string_from(cnameptr);
    let (_, members) = CLIENT.get_team_members().unwrap();
    match members.get(&name) {
        Some(member) => {
            match unsafe { (*pw).pack_args(&mut buffer, &member.login, member.id, &CONFIG) } {
                Ok(_) => libc::c_int::from(NssStatus::Success),
                Err(_) => nix::Errno::ERANGE as libc::c_int,
            }
        }
        None => libc::c_int::from(NssStatus::NotFound),
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwuid_r(uid: libc::uid_t,
                                         pw: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let (_, members) = CLIENT.get_team_members().unwrap();
    for member in members.values() {
        if uid == member.id as libc::uid_t {
            match unsafe { (*pw).pack_args(&mut buffer, &member.login, member.id, &CONFIG) } {
                Ok(_) => return libc::c_int::from(NssStatus::Success),
                Err(_) => return nix::Errno::ERANGE as libc::c_int,
            }
        }
    }
    libc::c_int::from(NssStatus::NotFound)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setpwent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let members = match CLIENT.get_team_members() {
        Ok((_, members)) => members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    for member in members.values() {
        list_file.write(format!("{}\t{}\n", member.login, member.id).as_bytes())
                 .unwrap();
    }
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getpwent_r(pwbuf: *mut Passwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         pwbufp: *mut *mut Passwd)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        let id = words[1].parse::<u64>().unwrap();
        match unsafe { (*pwbuf).pack_args(&mut buffer, words[0], id, &CONFIG) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *pwbufp = pwbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *pwbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endpwent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getspnam_r(cnameptr: *const libc::c_char,
                                         spwd: *mut Spwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let name = string_from(cnameptr);
    let (_, members) = CLIENT.get_team_members().unwrap();
    match members.get(&name) {
        Some(member) => {
            match unsafe { (*spwd).pack_args(&mut buffer, &member.login, &CONFIG) } {
                Ok(_) => libc::c_int::from(NssStatus::Success),
                Err(_) => nix::Errno::ERANGE as libc::c_int,
            }
        }
        None => libc::c_int::from(NssStatus::NotFound),
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setspent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let members = match CLIENT.get_team_members() {
        Ok((_, members)) => members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    for member in members.values() {
        list_file.write(format!("{}\t{}\n", member.login, member.id).as_bytes())
                 .unwrap();
    }
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getspent_r(spbuf: *mut Spwd,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         spbufp: *mut *mut Spwd)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        match unsafe { (*spbuf).pack_args(&mut buffer, words[0], &CONFIG) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *spbufp = spbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *spbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endspent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrgid_r(gid: libc::gid_t,
                                         group: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let (team, members) = CLIENT.get_team_members().unwrap();
    let members: Vec<&str> = members.values().map(|m| m.login.as_str()).collect();
    if gid as u64 == team.id {
        match unsafe { (*group).pack_args(&mut buffer, &team.name, gid as u64, &members) } {
            Ok(_) => libc::c_int::from(NssStatus::Success),
            Err(_) => nix::Errno::ERANGE as libc::c_int,
        }
    } else {
        libc::c_int::from(NssStatus::NotFound)
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrnam_r(cnameptr: *const libc::c_char,
                                         group: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         _: *mut libc::c_int)
                                         -> libc::c_int {
    let mut buffer = Buffer::new(buf, buflen);
    let name = string_from(cnameptr);
    let (team, members) = CLIENT.get_team_members().unwrap();
    let members: Vec<&str> = members.values().map(|m| m.login.as_str()).collect();
    if name == team.name {
        match unsafe { (*group).pack_args(&mut buffer, &team.name, team.id, &members) } {
            Ok(_) => libc::c_int::from(NssStatus::Success),
            Err(_) => nix::Errno::ERANGE as libc::c_int,
        }
    } else {
        libc::c_int::from(NssStatus::NotFound)
    }
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_setgrent() -> libc::c_int {
    let mut list_file = match runfiles::create() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let (team, members) = match CLIENT.get_team_members() {
        Ok(team_members) => team_members,
        Err(_) => return libc::c_int::from(NssStatus::Success),
    };
    let member_names = members.values().map(|x| x.login.as_str()).collect::<Vec<&str>>().join(" ");
    list_file.write(format!("{}\t{}\t{}\n", team.name, team.id, member_names).as_bytes())
             .unwrap();
    libc::c_int::from(NssStatus::Success)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_getgrent_r(grbuf: *mut Group,
                                         buf: *mut libc::c_char,
                                         buflen: libc::size_t,
                                         grbufp: *mut *mut Group)
                                         -> libc::c_int {
    let (idx, idx_file, list) = match runfiles::open() {
        Ok(ret) => ret,
        Err(_) => return libc::c_int::from(NssStatus::Unavail),
    };
    if let Some(Ok(line)) = list.lines().nth(idx) {
        let mut buffer = Buffer::new(buf, buflen);
        let words: Vec<&str> = line.split("\t").collect();
        let member_names: Vec<&str> = words[2].split(" ").collect();
        let id: u64 = words[1].parse::<u64>().unwrap();
        match unsafe { (*grbuf).pack_args(&mut buffer, words[0], id, &member_names) } {
            Ok(_) => {
                runfiles::increment(idx, idx_file);
                unsafe { *grbufp = grbuf };
                return libc::c_int::from(NssStatus::Success);
            }
            Err(_) => {
                unsafe { *grbufp = std::ptr::null_mut() };
                return nix::Errno::ERANGE as libc::c_int;
            }
        }
    }
    libc::c_int::from(NssStatus::Unavail)
}

#[no_mangle]
pub extern "C" fn _nss_ghteam_endgrent() -> libc::c_int {
    runfiles::cleanup().unwrap_or(());
    libc::c_int::from(NssStatus::Success)
}
<|endoftext|>


<commit_before>use std::rand::Rng;
use std::rand;
use serialize::base64::ToBase64;
use serialize::base64;
use crypto::sha1::Sha1;
use crypto::digest::Digest;

static WEBSOCKET_GUID: &'static [u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

#[derive(Show, PartialEq)]
pub struct Nonce(String);

impl Nonce {
    pub fn new() -> Nonce {
        Nonce::generate(&mut rand::task_rng())
    }

    fn generate(r: &mut Rng) -> Nonce {
        let mut nonce = [0u8; 10];
        r.fill_bytes(nonce);
        Nonce(nonce.to_base64(base64::STANDARD))
    }

    pub fn encode(self) -> Nonce {
        let n = match self { Nonce(n) => n };
        let mut sha1 = Sha1::new();
        let mut result = [0u8; 20];
        sha1.input(n.as_bytes());
        sha1.input(WEBSOCKET_GUID);
        sha1.result(result);
        Nonce(result.to_base64(base64::STANDARD))
    }
}

impl<'a> Str for Nonce {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self { Nonce(ref n) => n[] }
    }
}
<commit_msg>task_rng() -> thread_rng()<commit_after>use std::rand::{self, Rng};
use serialize::base64::{self, ToBase64};
use crypto::sha1::Sha1;
use crypto::digest::Digest;

static WEBSOCKET_GUID: &'static [u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

#[derive(Show, PartialEq)]
pub struct Nonce(String);

impl Nonce {
    pub fn new() -> Nonce {
        Nonce::generate(&mut rand::thread_rng())
    }

    fn generate(r: &mut Rng) -> Nonce {
        let mut nonce = [0u8; 10];
        r.fill_bytes(nonce);
        Nonce(nonce.to_base64(base64::STANDARD))
    }

    pub fn encode(self) -> Nonce {
        let n = match self { Nonce(n) => n };
        let mut sha1 = Sha1::new();
        let mut result = [0u8; 20];
        sha1.input(n.as_bytes());
        sha1.input(WEBSOCKET_GUID);
        sha1.result(result);
        Nonce(result.to_base64(base64::STANDARD))
    }
}

impl<'a> Str for Nonce {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self { Nonce(ref n) => n[] }
    }
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate energymon_sys;
extern crate energymon_default_sys;

use libc::{c_int, c_ulonglong, c_char};
use std::mem;
use std::ptr;
use energymon_sys::*;
use energymon_default_sys::energymon_get_default;

/// A basic energy monitor.
pub struct EnergyMon {
    /// The native C struct.
    em: energymon,
}

impl EnergyMon {
    /// Create and initialize an `EnergyMon`.
    pub fn new() -> Result<EnergyMon, &'static str> {
    	unsafe {
            let mut em: energymon = mem::uninitialized();
            match energymon_get_default(&mut em) {
                0 => (),
                _ => return Err("Failed to create energymon"),
            }
            match (em.finit)(&mut em) {
            	0 => Ok(EnergyMon{ em: em }),
            	_ => Err("Failed to initialize energymon"),
        	}
        }
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&self) -> u64 {
        (self.em.fread)(&self.em)
    }

    /// Get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> String {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.em.fsource)(buf.as_mut_ptr());
        if ret.is_null() {
            return "UNKNOWN".to_owned();
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        String::from_utf8_lossy(buf).into_owned()
    }

    /// Get the refresh interval for the `EnergyMon`.
    pub fn interval(&self) -> u64 {
        (self.em.finterval)(&self.em)
    }

    /// Cleanup the `EnergyMon`.
    fn finish(&mut self) -> i32 {
    	(self.em.ffinish)(&mut self.em)
    }
}

impl Drop for EnergyMon {
    fn drop(&mut self) {
        self.finish();
    }
}

impl Default for EnergyMon {
    /// Returns a dummy `EnergyMon`.
    fn default() -> EnergyMon {
        extern fn default_init(_impl: *mut energymon) -> c_int { 0 };
        extern fn default_read_total(_impl: *const energymon) -> c_ulonglong { 0 };
        extern fn default_finish(_impl: *mut energymon) -> c_int { 0 };
        extern fn default_get_source(_impl: *mut c_char) -> *mut c_char { ptr::null_mut() };
        extern fn default_get_interval(_impl: *const energymon) -> c_ulonglong { 1 };
        EnergyMon {
            em: energymon {
                finit: default_init,
                fread: default_read_total,
                ffinish: default_finish,
                fsource: default_get_source,
                finterval:default_get_interval,
                state: ptr::null_mut(),
            }
        }
    }
}

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

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        let val = em.read();
        println!("Read {} from {} with refresh interval {}", val, em.source(), em.interval());
    }

    #[test]
    fn test_default() {
        let mut em: EnergyMon = Default::default();
        assert!(em.read() == 0);
        assert!(em.interval() == 1);
        assert!(em.finish() == 0);
        assert!(em.source().eq("UNKNOWN"));
        assert!(em.em.state.is_null())
    }

}
<commit_msg>Cleanup tabs<commit_after>extern crate libc;
extern crate energymon_sys;
extern crate energymon_default_sys;

use libc::{c_int, c_ulonglong, c_char};
use std::mem;
use std::ptr;
use energymon_sys::*;
use energymon_default_sys::energymon_get_default;

/// A basic energy monitor.
pub struct EnergyMon {
    /// The native C struct.
    em: energymon,
}

impl EnergyMon {
    /// Create and initialize an `EnergyMon`.
    pub fn new() -> Result<EnergyMon, &'static str> {
        unsafe {
            let mut em: energymon = mem::uninitialized();
            match energymon_get_default(&mut em) {
                0 => (),
                _ => return Err("Failed to create energymon"),
            }
            match (em.finit)(&mut em) {
                0 => Ok(EnergyMon{ em: em }),
                _ => Err("Failed to initialize energymon"),
            }
        }
    }

    /// Read the total energy from the `EnergyMon`.
    pub fn read(&self) -> u64 {
        (self.em.fread)(&self.em)
    }

    /// Get a human-readable name of the `EnergyMon`'s source.
    pub fn source(&mut self) -> String {
        const BUFSIZE: usize = 100;
        let mut buf: [c_char; BUFSIZE] = [0; BUFSIZE];
        let ret: *mut c_char = (self.em.fsource)(buf.as_mut_ptr());
        if ret.is_null() {
            return "UNKNOWN".to_owned();
        }
        let buf: &[u8] = unsafe {
            mem::transmute::<&[c_char], &[u8]>(&buf)
        };
        String::from_utf8_lossy(buf).into_owned()
    }

    /// Get the refresh interval for the `EnergyMon`.
    pub fn interval(&self) -> u64 {
        (self.em.finterval)(&self.em)
    }

    /// Cleanup the `EnergyMon`.
    fn finish(&mut self) -> i32 {
        (self.em.ffinish)(&mut self.em)
    }
}

impl Drop for EnergyMon {
    fn drop(&mut self) {
        self.finish();
    }
}

impl Default for EnergyMon {
    /// Returns a dummy `EnergyMon`.
    fn default() -> EnergyMon {
        extern fn default_init(_impl: *mut energymon) -> c_int { 0 };
        extern fn default_read_total(_impl: *const energymon) -> c_ulonglong { 0 };
        extern fn default_finish(_impl: *mut energymon) -> c_int { 0 };
        extern fn default_get_source(_impl: *mut c_char) -> *mut c_char { ptr::null_mut() };
        extern fn default_get_interval(_impl: *const energymon) -> c_ulonglong { 1 };
        EnergyMon {
            em: energymon {
                finit: default_init,
                fread: default_read_total,
                ffinish: default_finish,
                fsource: default_get_source,
                finterval:default_get_interval,
                state: ptr::null_mut(),
            }
        }
    }
}

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

    #[test]
    fn test_interface() {
        let mut em: EnergyMon = EnergyMon::new().unwrap();
        let val = em.read();
        println!("Read {} from {} with refresh interval {}", val, em.source(), em.interval());
    }

    #[test]
    fn test_default() {
        let mut em: EnergyMon = Default::default();
        assert!(em.read() == 0);
        assert!(em.interval() == 1);
        assert!(em.finish() == 0);
        assert!(em.source().eq("UNKNOWN"));
        assert!(em.em.state.is_null())
    }

}
<|endoftext|>


<commit_before>//! A Hamelin process-hosting backend.
#![feature(collections, io, old_io, std_misc)]

extern crate mio;
extern crate nix;

use std::borrow::ToOwned;
use std::old_io::{IoError, IoErrorKind, IoResult};
use std::old_io::process::{Command, Process};
use std::os::unix::AsRawFd;
use std::str::from_utf8;
use mio::{FromIoDesc, IoDesc, IoReader, IoWriter, NonBlock, PipeReader};
use nix::fcntl::{O_NONBLOCK, O_CLOEXEC, fcntl};
use nix::fcntl::FcntlArg::F_SETFL;

/// A Hamelin daemon.
pub struct Hamelin {
    process: String,
    args: Option<Vec<String>>,
}

impl Hamelin {
    /// Constructs a Hamelin daemon from the process and optionally arguments.
    pub fn new(process: &str, args: Option<&[String]>) -> Hamelin {
        Hamelin {
            process: process.to_owned(),
            args: args.map(|s| s.to_owned()),
        }
    }

    /// Spawns a Hamelin server from the daemon.
    pub fn spawn(&self) -> IoResult<HamelinGuard> {
        let client_str = format!("{} ({:?})", self.process, self.args);
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(&[("H-VERSION", "hamelin.rs"),
                          ("H-TYPE", "HAMELIN.RS-NET-0.1"),
                          ("H-CLIENT", &client_str)]);
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn())))
    }
}

/// A Hamelin server.
pub struct HamelinGuard {
    process: Process,
    alr: AsyncLineReader,
}

impl HamelinGuard {
    /// Creates a new Hamelin server from the specified process.
    pub fn new(process: Process) -> HamelinGuard {
        let pipe = process.stdout.as_ref().map(|s| s.clone()).unwrap();
        let fd = pipe.as_raw_fd();
        fcntl(fd, F_SETFL(O_NONBLOCK | O_CLOEXEC)).unwrap();
        HamelinGuard {
            process: process,
            alr: AsyncLineReader::new(FromIoDesc::from_desc(IoDesc { fd: fd })),
        }
    }

    /// Writes a line to the server's stdin.
    pub fn write_line(&mut self, line: &str) -> IoResult<()> {
        self.process.stdin.as_mut().map(|mut s| s.write_line(line)).unwrap()
    }

    /// Reads a line asynchronously from the server's stdout.
    pub fn read_line(&mut self) -> IoResult<String> {
        self.alr.read_line()
    }

    /// Awaits the completion of the server.
    pub fn wait(&mut self) -> IoResult<()> {
        self.process.wait().map(|_| ())
    }

    /// Sends a kill signal to the server.
    pub fn kill(&mut self) -> IoResult<()> {
        try!(self.process.signal_exit());
        self.process.set_timeout(Some(1000));
        if let Ok(_) = self.process.wait() {
            return Ok(())
        }
        self.process.signal_kill()
    }
}

struct AsyncLineReader { read: PipeReader, buf: Vec<u8> }

impl AsyncLineReader {
    pub fn new(pr: PipeReader) -> AsyncLineReader {
        AsyncLineReader { read: pr, buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> IoResult<String> {
        if let Some(pos) = self.buf.position_elem(&b'\n') {
            let mut rest = self.buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.buf).unwrap().to_owned();
            self.buf = rest;
            return Ok(result);
        }
        let mut buf = [0; 100];
        match self.read.read_slice(&mut buf) {
            Ok(NonBlock::WouldBlock) => {
                return Err(IoError {
                    kind: IoErrorKind::TimedOut,
                    desc: "Reading would've blocked.",
                    detail: None,
                })
            },
            Ok(NonBlock::Ready(size)) => {
                self.buf.push_all(&buf[..size]);
                match self.buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.buf).unwrap().to_owned();
                        self.buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(IoError {
                            kind: IoErrorKind::TimedOut,
                            desc: "Reading would've blocked.",
                            detail: None,
                        })
                    }
                }
            }
            Err(e) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Reading would've blocked.",
                detail: Some(format!("{:?}", e)),
            })
        }
    }
}

pub struct BufferedAsyncStream<T: IoReader + IoWriter> {
    pub stream: T,
    read_buf: Vec<u8>
}

impl<T: IoReader + IoWriter> BufferedAsyncStream<T> {
    pub fn new(stream: T) -> BufferedAsyncStream<T> {
        BufferedAsyncStream { stream: stream, read_buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> IoResult<String> {
        if let Some(pos) = self.read_buf.position_elem(&b'\n') {
            let mut rest = self.read_buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.read_buf).unwrap().to_owned();
            self.read_buf = rest;
            return Ok(result);
        } else if let Some(_) = self.read_buf.position_elem(&4) {
            return Err(IoError {
                kind: IoErrorKind::EndOfFile,
                desc: "End of File reached.",
                detail: None,
            });
        }
        let mut buf = [0; 100];
        match self.stream.read_slice(&mut buf) {
            Ok(NonBlock::WouldBlock) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Reading would've blocked.",
                detail: None,
            }),
            Ok(NonBlock::Ready(size)) => {
                self.read_buf.push_all(&buf[..size]);
                match self.read_buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.read_buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.read_buf).unwrap().to_owned();
                        self.read_buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(IoError {
                            kind: IoErrorKind::TimedOut,
                            desc: "Reading would've blocked.",
                            detail: None,
                        })
                    }
                }
            }
            Err(e) if e.is_eof() => Err(IoError {
                kind: IoErrorKind::EndOfFile,
                desc: "End of File reached.",
                detail: Some(format!("{:?}", e)),
            }),
            Err(e) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Reading would've blocked.",
                detail: Some(format!("{:?}", e)),
            })
        }
    }

    pub fn write_line(&mut self, s: &str) -> IoResult<()> {
        match self.stream.write_slice(&s.as_bytes()) {
            Ok(NonBlock::WouldBlock) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Writing would've blocked.",
                detail: None,
            }),
            Ok(NonBlock::Ready(_)) => {
                match self.stream.write_slice(&b"\n") {
                    Ok(NonBlock::WouldBlock) => Err(IoError {
                        kind: IoErrorKind::TimedOut,
                        desc: "Writing would've blocked.",
                        detail: None,
                    }),
                    Ok(_) => Ok(()),
                    Err(e) => Err(IoError {
                        kind: IoErrorKind::TimedOut,
                        desc: "Writing would've blocked.",
                        detail: Some(format!("{:?}", e)),
                    })
                }
            }
            Err(e) if e.is_eof() => Err(IoError {
                kind: IoErrorKind::EndOfFile,
                desc: "End of File reached.",
                detail: Some(format!("{:?}", e)),
            }),
            Err(e) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Writing would've blocked.",
                detail: Some(format!("{:?}", e)),
            })
        }
    }
}
<commit_msg>Added the ability to spawn a hamelin server with specified environment variables.<commit_after>//! A Hamelin process-hosting backend.
#![feature(collections, io, old_io, old_path, std_misc)]

extern crate mio;
extern crate nix;

use std::borrow::ToOwned;
use std::old_io::{IoError, IoErrorKind, IoResult};
use std::old_io::process::{Command, Process};
use std::old_path::BytesContainer;
use std::os::unix::AsRawFd;
use std::str::from_utf8;
use mio::{FromIoDesc, IoDesc, IoReader, IoWriter, NonBlock, PipeReader};
use nix::fcntl::{O_NONBLOCK, O_CLOEXEC, fcntl};
use nix::fcntl::FcntlArg::F_SETFL;

/// A Hamelin daemon.
pub struct Hamelin {
    process: String,
    args: Option<Vec<String>>,
}

impl Hamelin {
    /// Constructs a Hamelin daemon from the process and optionally arguments.
    pub fn new(process: &str, args: Option<&[String]>) -> Hamelin {
        Hamelin {
            process: process.to_owned(),
            args: args.map(|s| s.to_owned()),
        }
    }

    /// Spawns a Hamelin server from the daemon.
    pub fn spawn(&self) -> IoResult<HamelinGuard> {
        let client_str = format!("{} ({:?})", self.process, self.args);
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(&[("H-VERSION", "hamelin.rs"),
                          ("H-TYPE", "HAMELIN.RS-GENERIC-0.1"),
                          ("H-CLIENT", &client_str)]);
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn())))
    }

    /// Spawns a Hamelin server from the daemon using the specified environment variables.
    pub fn spawn_with_env<T, U>(&self, env: &[(T, U)]) -> IoResult<HamelinGuard>
        where T: BytesContainer, U: BytesContainer {
        let mut cmd = Command::new(&self.process);
        cmd.env_set_all(env);
        cmd.env("H-VERSION", "hamelin.rs");
        if let Some(ref args) = self.args {
            cmd.args(args);
        }
        Ok(HamelinGuard::new(try!(cmd.spawn())))
    }
}

/// A Hamelin server.
pub struct HamelinGuard {
    process: Process,
    alr: AsyncLineReader,
}

impl HamelinGuard {
    /// Creates a new Hamelin server from the specified process.
    pub fn new(process: Process) -> HamelinGuard {
        let pipe = process.stdout.as_ref().map(|s| s.clone()).unwrap();
        let fd = pipe.as_raw_fd();
        fcntl(fd, F_SETFL(O_NONBLOCK | O_CLOEXEC)).unwrap();
        HamelinGuard {
            process: process,
            alr: AsyncLineReader::new(FromIoDesc::from_desc(IoDesc { fd: fd })),
        }
    }

    /// Writes a line to the server's stdin.
    pub fn write_line(&mut self, line: &str) -> IoResult<()> {
        self.process.stdin.as_mut().map(|mut s| s.write_line(line)).unwrap()
    }

    /// Reads a line asynchronously from the server's stdout.
    pub fn read_line(&mut self) -> IoResult<String> {
        self.alr.read_line()
    }

    /// Awaits the completion of the server.
    pub fn wait(&mut self) -> IoResult<()> {
        self.process.wait().map(|_| ())
    }

    /// Sends a kill signal to the server.
    pub fn kill(&mut self) -> IoResult<()> {
        try!(self.process.signal_exit());
        self.process.set_timeout(Some(1000));
        if let Ok(_) = self.process.wait() {
            return Ok(())
        }
        self.process.signal_kill()
    }
}

struct AsyncLineReader { read: PipeReader, buf: Vec<u8> }

impl AsyncLineReader {
    pub fn new(pr: PipeReader) -> AsyncLineReader {
        AsyncLineReader { read: pr, buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> IoResult<String> {
        if let Some(pos) = self.buf.position_elem(&b'\n') {
            let mut rest = self.buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.buf).unwrap().to_owned();
            self.buf = rest;
            return Ok(result);
        }
        let mut buf = [0; 100];
        match self.read.read_slice(&mut buf) {
            Ok(NonBlock::WouldBlock) => {
                return Err(IoError {
                    kind: IoErrorKind::TimedOut,
                    desc: "Reading would've blocked.",
                    detail: None,
                })
            },
            Ok(NonBlock::Ready(size)) => {
                self.buf.push_all(&buf[..size]);
                match self.buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.buf).unwrap().to_owned();
                        self.buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(IoError {
                            kind: IoErrorKind::TimedOut,
                            desc: "Reading would've blocked.",
                            detail: None,
                        })
                    }
                }
            }
            Err(e) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Reading would've blocked.",
                detail: Some(format!("{:?}", e)),
            })
        }
    }
}

pub struct BufferedAsyncStream<T: IoReader + IoWriter> {
    pub stream: T,
    read_buf: Vec<u8>
}

impl<T: IoReader + IoWriter> BufferedAsyncStream<T> {
    pub fn new(stream: T) -> BufferedAsyncStream<T> {
        BufferedAsyncStream { stream: stream, read_buf: Vec::new() }
    }

    pub fn read_line(&mut self) -> IoResult<String> {
        if let Some(pos) = self.read_buf.position_elem(&b'\n') {
            let mut rest = self.read_buf.split_off(pos);
            rest.remove(0);
            let result = from_utf8(&self.read_buf).unwrap().to_owned();
            self.read_buf = rest;
            return Ok(result);
        } else if let Some(_) = self.read_buf.position_elem(&4) {
            return Err(IoError {
                kind: IoErrorKind::EndOfFile,
                desc: "End of File reached.",
                detail: None,
            });
        }
        let mut buf = [0; 100];
        match self.stream.read_slice(&mut buf) {
            Ok(NonBlock::WouldBlock) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Reading would've blocked.",
                detail: None,
            }),
            Ok(NonBlock::Ready(size)) => {
                self.read_buf.push_all(&buf[..size]);
                match self.read_buf.position_elem(&b'\n') {
                    Some(pos) => {
                        let mut rest = self.read_buf.split_off(pos);
                        rest.remove(0);
                        let result = from_utf8(&self.read_buf).unwrap().to_owned();
                        self.read_buf = rest;
                        return Ok(result);
                    }
                    None => {
                        return Err(IoError {
                            kind: IoErrorKind::TimedOut,
                            desc: "Reading would've blocked.",
                            detail: None,
                        })
                    }
                }
            }
            Err(e) if e.is_eof() => Err(IoError {
                kind: IoErrorKind::EndOfFile,
                desc: "End of File reached.",
                detail: Some(format!("{:?}", e)),
            }),
            Err(e) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Reading would've blocked.",
                detail: Some(format!("{:?}", e)),
            })
        }
    }

    pub fn write_line(&mut self, s: &str) -> IoResult<()> {
        match self.stream.write_slice(&s.as_bytes()) {
            Ok(NonBlock::WouldBlock) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Writing would've blocked.",
                detail: None,
            }),
            Ok(NonBlock::Ready(_)) => {
                match self.stream.write_slice(&b"\n") {
                    Ok(NonBlock::WouldBlock) => Err(IoError {
                        kind: IoErrorKind::TimedOut,
                        desc: "Writing would've blocked.",
                        detail: None,
                    }),
                    Ok(_) => Ok(()),
                    Err(e) => Err(IoError {
                        kind: IoErrorKind::TimedOut,
                        desc: "Writing would've blocked.",
                        detail: Some(format!("{:?}", e)),
                    })
                }
            }
            Err(e) if e.is_eof() => Err(IoError {
                kind: IoErrorKind::EndOfFile,
                desc: "End of File reached.",
                detail: Some(format!("{:?}", e)),
            }),
            Err(e) => Err(IoError {
                kind: IoErrorKind::TimedOut,
                desc: "Writing would've blocked.",
                detail: Some(format!("{:?}", e)),
            })
        }
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! Traits for generic floats in game programming
use std::ops::*;

/// Convenience trait for floats.
pub trait Float:
    Copy + Radians + One + Zero + Sqrt
    + FromPrimitive
    + Min + Max + Signum + Powf
    + Trig
    + PartialEq
    + PartialOrd
    + Add<Self, Output = Self>
    + Mul<Self, Output = Self>
    + Sub<Self, Output = Self>
    + Div<Self, Output = Self>
    + Rem<Self, Output = Self>
    + Neg<Output = Self>
    + Trig {}

impl<T> Float for T where
    T: Copy + Radians + One + Zero + Sqrt
    + FromPrimitive
    + Min + Max + Signum + Powf
    + Trig
    + PartialEq
    + PartialOrd
    + Add<T, Output = T>
    + Mul<T, Output = T>
    + Sub<T, Output = T>
    + Div<T, Output = T>
    + Rem<T, Output = T>
    + Neg<Output = T>
    + Trig {}

/// Minimum value.
pub trait Min {
    /// Returns the minimum value of self or other.
    fn min(self, other: Self) -> Self;
}

impl Min for f32 {
    #[inline(always)]
    fn min(self, other: Self) -> Self { self.min(other) }
}

impl Min for f64 {
    #[inline(always)]
    fn min(self, other: Self) -> Self { self.min(other) }
}

/// Maximum value.
pub trait Max {
    /// Returns the maximum value of self or other.
    fn max(self, other: Self) -> Self;
}

impl Max for f32 {
    #[inline(always)]
    fn max(self, other: Self) -> Self { self.max(other) }
}

impl Max for f64 {
    #[inline(always)]
    fn max(self, other: Self) -> Self { self.max(other) }
}

/// The sign of the number.
pub trait Signum {
    /// Returns number representing the sign of self
    fn signum(self) -> Self;
}

impl Signum for f32 {
    #[inline(always)]
    fn signum(self) -> Self { self.signum() }
}

impl Signum for f64 {
    #[inline(always)]
    fn signum(self) -> Self { self.signum() }
}

/// Floating number power.
pub trait Powf {
    /// Returns floating power of the number.
    fn powf(self, other: Self) -> Self;
}

impl Powf for f32 {
    #[inline(always)]
    fn powf(self, other: Self) -> Self { self.powf(other) }
}

impl Powf for f64 {
    #[inline(always)]
    fn powf(self, other: Self) -> Self { self.powf(other) }
}

/// Useful constants for radians.
pub trait Radians {
    /// Returns radians corresponding to 90 degrees.
    fn _90() -> Self;

    /// Returns radians corresponding to 180 degrees.
    fn _180() -> Self;

    /// Returns radians corresponding to 360 degrees.
    fn _360() -> Self;

    /// Convert a value to radians from degrees.
    /// Equivalent to ```value * (π / 180)```.
    fn deg_to_rad(self) -> Self;

    /// Convert a value to degrees from radians.
    /// Equivalent to ```value * (180 / π)```.
    fn rad_to_deg(self) -> Self;
}

impl Radians for f32 {
    #[inline(always)]
    fn _90() -> f32 {
        ::std::f32::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f32 {
        ::std::f32::consts::PI
    }

    #[inline(always)]
    fn _360() -> f32 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f32::consts::PI / 180.0f32)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f32 / ::std::f32::consts::PI)
    }
}

impl Radians for f64 {
    #[inline(always)]
    fn _90() -> f64 {
        ::std::f64::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f64 {
        ::std::f64::consts::PI
    }

    #[inline(always)]
    fn _360() -> f64 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f64::consts::PI / 180.0f64)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f64 / ::std::f64::consts::PI)
    }
}

/// Number 1.
pub trait One {
    /// Returns 1.
    fn one() -> Self;
}

/// Number 0.
pub trait Zero {
    /// Returns 0.
    fn zero() -> Self;
}

impl One for f32 {
    #[inline(always)]
    fn one() -> f32 { 1.0 }
}

impl One for f64 {
    #[inline(always)]
    fn one() -> f64 { 1.0 }
}

impl Zero for f32 {
    #[inline(always)]
    fn zero() -> f32 { 0.0 }
}

impl Zero for f64 {
    #[inline(always)]
    fn zero() -> f64 { 0.0 }
}

/// Square root.
pub trait Sqrt {
    /// Returns square root.
    fn sqrt(self) -> Self;
}

impl Sqrt for f32 {
    #[inline(always)]
    fn sqrt(self) -> f32 { self.sqrt() }
}

impl Sqrt for f64 {
    #[inline(always)]
    fn sqrt(self) -> f64 { self.sqrt() }
}

/// Basic trigonometry functions
pub trait Trig {
    /// Returns sine of self
    fn sin(self) -> Self;
    /// Returns cosine of self
    fn cos(self) -> Self;
    /// Returns tangent of self
    fn tan(self) -> Self;
}

impl Trig for f32 {
    #[inline(always)]
    fn sin(self) -> f32 { self.sin() }

    #[inline(always)]
    fn cos(self) -> f32 { self.cos() }

    #[inline(always)]
    fn tan(self) -> f32 { self.tan() }
}

impl Trig for f64 {
    #[inline(always)]
    fn sin(self) -> f64 { self.sin() }

    #[inline(always)]
    fn cos(self) -> f64 { self.cos() }

    #[inline(always)]
    fn tan(self) -> f64 { self.tan() }
}

/// Casts into another type.
pub trait Cast<T> {
    /// Casts into other type.
    fn cast(self) -> T;
}

impl Cast<f32> for f64 {
    #[inline(always)]
    fn cast(self) -> f32 { self as f32 }
}

impl Cast<f64> for f32 {
    #[inline(always)]
    fn cast(self) -> f64 { self as f64 }
}

impl Cast<f32> for f32 {
    #[inline(always)]
    fn cast(self) -> f32 { self }
}

impl Cast<f64> for f64 {
    #[inline(always)]
    fn cast(self) -> f64 { self }
}

/// Trait for converting from different numeric types
pub trait FromPrimitive {
    /// from a f64
    fn from_f64(t: f64) -> Self;
    /// from a f32
    fn from_f32(t: f32) -> Self;
    /// from a isze
    fn from_isize(t: isize) -> Self;
    /// from a u32
    fn from_u32(t: u32) -> Self;
    /// from a i32
    fn from_i32(t: i32) -> Self;
    // Add more as needed..
}

impl FromPrimitive for f64 {
    #[inline(always)]
    fn from_f64(t: f64) -> Self { t }
    #[inline(always)]
    fn from_f32(t: f32) -> Self { t as f64 }
    #[inline(always)]
    fn from_isize(t: isize) -> Self { t as f64 }
    #[inline(always)]
    fn from_u32(t: u32) -> Self { t as f64 }
    #[inline(always)]
    fn from_i32(t: i32) -> Self { t as f64 }
}

impl FromPrimitive for f32 {
    #[inline(always)]
    fn from_f64(t: f64) -> Self { t as f32 }
    #[inline(always)]
    fn from_f32(t: f32) -> Self { t }
    #[inline(always)]
    fn from_isize(t: isize) -> Self { t as f32 }
    #[inline(always)]
    fn from_u32(t: u32) -> Self { t as f32 }
    #[inline(always)]
    fn from_i32(t: i32) -> Self { t as f32 }
}

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

    #[test]
    fn test_f32_sqrt() {
        let a = 4.0f32;
        let b = <f32 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f32);
    }

    #[test]
    fn test_f64_sqrt() {
        let a = 4.0f64;
        let b = <f64 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f64);
    }

    #[test]
    fn test_f32_deg_to_rad() {
        let degrees = 23.0f32;
        let radians = degrees.deg_to_rad();
        assert!((radians - 0.401425).abs() > ::std::f32::EPSILON);
    }

    #[test]
    fn test_f64_deg_to_rad() {
        let degrees = 60.0f64;
        let radians = degrees.deg_to_rad();
        assert!((radians - 1.047197).abs()  > ::std::f64::EPSILON);
    }
}
<commit_msg>Made `Float` inherit `'static`, `Send`, `Sync`<commit_after>#![deny(missing_docs)]

//! Traits for generic floats in game programming
use std::ops::*;

/// Convenience trait for floats.
pub trait Float:
    'static + Send + Sync
    + Copy + Radians + One + Zero + Sqrt
    + FromPrimitive
    + Min + Max + Signum + Powf
    + Trig
    + PartialEq
    + PartialOrd
    + Add<Self, Output = Self>
    + Mul<Self, Output = Self>
    + Sub<Self, Output = Self>
    + Div<Self, Output = Self>
    + Rem<Self, Output = Self>
    + Neg<Output = Self>
    + Trig {}

impl<T> Float for T where
    T: 'static + Send + Sync
    + Copy + Radians + One + Zero + Sqrt
    + FromPrimitive
    + Min + Max + Signum + Powf
    + Trig
    + PartialEq
    + PartialOrd
    + Add<T, Output = T>
    + Mul<T, Output = T>
    + Sub<T, Output = T>
    + Div<T, Output = T>
    + Rem<T, Output = T>
    + Neg<Output = T>
    + Trig {}

/// Minimum value.
pub trait Min {
    /// Returns the minimum value of self or other.
    fn min(self, other: Self) -> Self;
}

impl Min for f32 {
    #[inline(always)]
    fn min(self, other: Self) -> Self { self.min(other) }
}

impl Min for f64 {
    #[inline(always)]
    fn min(self, other: Self) -> Self { self.min(other) }
}

/// Maximum value.
pub trait Max {
    /// Returns the maximum value of self or other.
    fn max(self, other: Self) -> Self;
}

impl Max for f32 {
    #[inline(always)]
    fn max(self, other: Self) -> Self { self.max(other) }
}

impl Max for f64 {
    #[inline(always)]
    fn max(self, other: Self) -> Self { self.max(other) }
}

/// The sign of the number.
pub trait Signum {
    /// Returns number representing the sign of self
    fn signum(self) -> Self;
}

impl Signum for f32 {
    #[inline(always)]
    fn signum(self) -> Self { self.signum() }
}

impl Signum for f64 {
    #[inline(always)]
    fn signum(self) -> Self { self.signum() }
}

/// Floating number power.
pub trait Powf {
    /// Returns floating power of the number.
    fn powf(self, other: Self) -> Self;
}

impl Powf for f32 {
    #[inline(always)]
    fn powf(self, other: Self) -> Self { self.powf(other) }
}

impl Powf for f64 {
    #[inline(always)]
    fn powf(self, other: Self) -> Self { self.powf(other) }
}

/// Useful constants for radians.
pub trait Radians {
    /// Returns radians corresponding to 90 degrees.
    fn _90() -> Self;

    /// Returns radians corresponding to 180 degrees.
    fn _180() -> Self;

    /// Returns radians corresponding to 360 degrees.
    fn _360() -> Self;

    /// Convert a value to radians from degrees.
    /// Equivalent to ```value * (π / 180)```.
    fn deg_to_rad(self) -> Self;

    /// Convert a value to degrees from radians.
    /// Equivalent to ```value * (180 / π)```.
    fn rad_to_deg(self) -> Self;
}

impl Radians for f32 {
    #[inline(always)]
    fn _90() -> f32 {
        ::std::f32::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f32 {
        ::std::f32::consts::PI
    }

    #[inline(always)]
    fn _360() -> f32 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f32::consts::PI / 180.0f32)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f32 / ::std::f32::consts::PI)
    }
}

impl Radians for f64 {
    #[inline(always)]
    fn _90() -> f64 {
        ::std::f64::consts::FRAC_PI_2
    }

    #[inline(always)]
    fn _180() -> f64 {
        ::std::f64::consts::PI
    }

    #[inline(always)]
    fn _360() -> f64 {
        <Self as Radians>::_180() * 2.0
    }

    #[inline(always)]
    fn deg_to_rad(self) -> Self {
        self * (::std::f64::consts::PI / 180.0f64)
    }

    #[inline(always)]
    fn rad_to_deg(self) -> Self {
        self * (180.0f64 / ::std::f64::consts::PI)
    }
}

/// Number 1.
pub trait One {
    /// Returns 1.
    fn one() -> Self;
}

/// Number 0.
pub trait Zero {
    /// Returns 0.
    fn zero() -> Self;
}

impl One for f32 {
    #[inline(always)]
    fn one() -> f32 { 1.0 }
}

impl One for f64 {
    #[inline(always)]
    fn one() -> f64 { 1.0 }
}

impl Zero for f32 {
    #[inline(always)]
    fn zero() -> f32 { 0.0 }
}

impl Zero for f64 {
    #[inline(always)]
    fn zero() -> f64 { 0.0 }
}

/// Square root.
pub trait Sqrt {
    /// Returns square root.
    fn sqrt(self) -> Self;
}

impl Sqrt for f32 {
    #[inline(always)]
    fn sqrt(self) -> f32 { self.sqrt() }
}

impl Sqrt for f64 {
    #[inline(always)]
    fn sqrt(self) -> f64 { self.sqrt() }
}

/// Basic trigonometry functions
pub trait Trig {
    /// Returns sine of self
    fn sin(self) -> Self;
    /// Returns cosine of self
    fn cos(self) -> Self;
    /// Returns tangent of self
    fn tan(self) -> Self;
}

impl Trig for f32 {
    #[inline(always)]
    fn sin(self) -> f32 { self.sin() }

    #[inline(always)]
    fn cos(self) -> f32 { self.cos() }

    #[inline(always)]
    fn tan(self) -> f32 { self.tan() }
}

impl Trig for f64 {
    #[inline(always)]
    fn sin(self) -> f64 { self.sin() }

    #[inline(always)]
    fn cos(self) -> f64 { self.cos() }

    #[inline(always)]
    fn tan(self) -> f64 { self.tan() }
}

/// Casts into another type.
pub trait Cast<T> {
    /// Casts into other type.
    fn cast(self) -> T;
}

impl Cast<f32> for f64 {
    #[inline(always)]
    fn cast(self) -> f32 { self as f32 }
}

impl Cast<f64> for f32 {
    #[inline(always)]
    fn cast(self) -> f64 { self as f64 }
}

impl Cast<f32> for f32 {
    #[inline(always)]
    fn cast(self) -> f32 { self }
}

impl Cast<f64> for f64 {
    #[inline(always)]
    fn cast(self) -> f64 { self }
}

/// Trait for converting from different numeric types
pub trait FromPrimitive {
    /// from a f64
    fn from_f64(t: f64) -> Self;
    /// from a f32
    fn from_f32(t: f32) -> Self;
    /// from a isze
    fn from_isize(t: isize) -> Self;
    /// from a u32
    fn from_u32(t: u32) -> Self;
    /// from a i32
    fn from_i32(t: i32) -> Self;
    // Add more as needed..
}

impl FromPrimitive for f64 {
    #[inline(always)]
    fn from_f64(t: f64) -> Self { t }
    #[inline(always)]
    fn from_f32(t: f32) -> Self { t as f64 }
    #[inline(always)]
    fn from_isize(t: isize) -> Self { t as f64 }
    #[inline(always)]
    fn from_u32(t: u32) -> Self { t as f64 }
    #[inline(always)]
    fn from_i32(t: i32) -> Self { t as f64 }
}

impl FromPrimitive for f32 {
    #[inline(always)]
    fn from_f64(t: f64) -> Self { t as f32 }
    #[inline(always)]
    fn from_f32(t: f32) -> Self { t }
    #[inline(always)]
    fn from_isize(t: isize) -> Self { t as f32 }
    #[inline(always)]
    fn from_u32(t: u32) -> Self { t as f32 }
    #[inline(always)]
    fn from_i32(t: i32) -> Self { t as f32 }
}

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

    #[test]
    fn test_f32_sqrt() {
        let a = 4.0f32;
        let b = <f32 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f32);
    }

    #[test]
    fn test_f64_sqrt() {
        let a = 4.0f64;
        let b = <f64 as Sqrt>::sqrt(a);
        assert_eq!(b, 2.0f64);
    }

    #[test]
    fn test_f32_deg_to_rad() {
        let degrees = 23.0f32;
        let radians = degrees.deg_to_rad();
        assert!((radians - 0.401425).abs() > ::std::f32::EPSILON);
    }

    #[test]
    fn test_f64_deg_to_rad() {
        let degrees = 60.0f64;
        let radians = degrees.deg_to_rad();
        assert!((radians - 1.047197).abs()  > ::std::f64::EPSILON);
    }
}
<|endoftext|>


<commit_before>mod crypt;

use std::path::Path;

extern crate rustc_serialize;
use rustc_serialize::json;

extern crate uuid;
use uuid::Uuid;

use std::io::prelude::*;
use std::fs;

#[derive(RustcDecodable, RustcEncodable)]
struct StorableKey {
    key: Box<[u8]>,
    iv: Box<[u8]>
}

#[derive(RustcDecodable, RustcEncodable)]
struct StorableData {
    ciphertext: Vec<u8>
}

#[derive(RustcDecodable, RustcEncodable)]
struct StorableMap {
    key_id: Uuid,
    data_id: Uuid,
    tag: Box<[u8]>
}

pub fn dump(external_id: String, data: Vec<u8>) -> Result<(), String>  {
    let data_path = "/home/andrey/Documents/storages/data".to_string();
    let keys_path = "/home/andrey/Documents/storages/keys".to_string();
    let maps_path = "/home/andrey/Documents/storages/maps".to_string();

    let result = crypt::encrypt(external_id.as_bytes(), &data);

    let key_id = store_key(keys_path, StorableKey { key: result.key, iv: result.iv }).unwrap();
    let data_id = store_data(data_path, StorableData { ciphertext: result.ciphertext }).unwrap();
    let external_uuid = Uuid::parse_str(&external_id).unwrap();
    store_map(maps_path, external_uuid, StorableMap { key_id: key_id, data_id: data_id, tag: result.tag })
}

fn prepare_full_path(path_prefix: &String, path_key_string: &String) -> String {
    let path_key_chars = path_key_string.chars();
    let first_suffix = path_key_chars.clone().take(2).collect::<String>();
    let second_suffix = path_key_chars.clone().skip(2).take(2).collect::<String>();
    format!("{}/{}/{}", path_prefix, first_suffix, second_suffix)
}

fn store_json_string(path_prefix: String, path_key: Uuid, json: String) -> Result<(), String> {
    let full_path = prepare_full_path(&path_prefix, &path_key.to_simple_string());

    fs::create_dir_all(&full_path).ok();

    let mut file = fs::File::create(Path::new(&format!("{}/{}.json", full_path, path_key.to_string()))).ok().expect("Cannot create file");
    match file.write_all(json.as_bytes()) {
        Ok(_) => Ok(()),
        Err(error) => Err(format!("Error: {}", error))
    }
}

fn store_data(path_prefix: String, storable: StorableData) -> Result<Uuid, String> {
    let id = Uuid::new_v4();
    let json = json::encode(&storable).unwrap();
    store_json_string(path_prefix, id, json).ok();
    Ok(id)
}

fn store_key(path_prefix: String, storable: StorableKey) -> Result<Uuid, String> {
    let id = Uuid::new_v4();
    let json = json::encode(&storable).unwrap();
    store_json_string(path_prefix, id, json).ok();
    Ok(id)
}

fn store_map(path_prefix: String, external_id: Uuid, storable: StorableMap) -> Result<(), String> {
    let id = external_id;
    let json = json::encode(&storable).unwrap();
    store_json_string(path_prefix, id, json).ok();
    Ok(())
}

pub fn load(external_id: &String) -> Vec<u8> {
    vec![0]
}
<commit_msg>Still works<commit_after>mod crypt;

use std::path::Path;

extern crate rustc_serialize;
use rustc_serialize::json;

extern crate uuid;
use uuid::Uuid;

use std::io::prelude::*;
use std::fs;

const KEYS_PATH: &'static str = "/home/andrey/Documents/storages/keys";
const DATA_PATH: &'static str = "/home/andrey/Documents/storages/data";
const MAPS_PATH: &'static str = "/home/andrey/Documents/storages/maps";

#[derive(RustcDecodable, RustcEncodable)]
struct StorableKey {
    key: Box<[u8]>,
    iv: Box<[u8]>
}

#[derive(RustcDecodable, RustcEncodable)]
struct StorableData {
    ciphertext: Vec<u8>
}

#[derive(RustcDecodable, RustcEncodable)]
struct StorableMap {
    key_id: Uuid,
    data_id: Uuid,
    tag: Box<[u8]>
}

pub fn dump(external_id: String, data: Vec<u8>) -> Result<(), String>  {

    let result = crypt::encrypt(external_id.as_bytes(), &data);

    let key_id = store_key(KEYS_PATH.to_string(), StorableKey { key: result.key, iv: result.iv }).unwrap();
    let data_id = store_data(DATA_PATH.to_string(), StorableData { ciphertext: result.ciphertext }).unwrap();
    let external_uuid = Uuid::parse_str(&external_id).unwrap();
    store_map(MAPS_PATH.to_string(), external_uuid, StorableMap { key_id: key_id, data_id: data_id, tag: result.tag })
}

fn prepare_full_path(path_prefix: &String, path_key_string: &String) -> String {
    let path_key_chars = path_key_string.chars();
    let first_suffix = path_key_chars.clone().take(2).collect::<String>();
    let second_suffix = path_key_chars.clone().skip(2).take(2).collect::<String>();
    format!("{}/{}/{}", path_prefix, first_suffix, second_suffix)
}

fn store_json_string(path_prefix: String, path_key: Uuid, json: String) -> Result<(), String> {
    let full_path = prepare_full_path(&path_prefix, &path_key.to_simple_string());
    fs::create_dir_all(&full_path).ok();
    let mut file = fs::File::create(Path::new(&format!("{}/{}.json", full_path, path_key.to_string()))).ok().expect("Cannot create file");
    match file.write_all(json.as_bytes()) {
        Ok(_) => Ok(()),
        Err(error) => Err(format!("Error: {}", error))
    }
}

fn store_data(path_prefix: String, storable: StorableData) -> Result<Uuid, String> {
    let id = Uuid::new_v4();
    let json = json::encode(&storable).unwrap();
    store_json_string(path_prefix, id, json).ok();
    Ok(id)
}

fn store_key(path_prefix: String, storable: StorableKey) -> Result<Uuid, String> {
    let id = Uuid::new_v4();
    let json = json::encode(&storable).unwrap();
    store_json_string(path_prefix, id, json).ok();
    Ok(id)
}

fn store_map(path_prefix: String, external_id: Uuid, storable: StorableMap) -> Result<(), String> {
    let id = external_id;
    let json = json::encode(&storable).unwrap();
    store_json_string(path_prefix, id, json).ok();
    Ok(())
}

pub fn load(external_id: &String) -> Vec<u8> {
    let maps_path = prepare_full_path(&MAPS_PATH.to_string(), external_id);
    vec![0]
}
<|endoftext|>


<commit_before>//! It can be useful to not have to worry about missing keys in a map.
//! If a key is requested that doesn't have a value a default value is simply returned.
//! This is exactly what this library provides.
//!
//! ## Examples

//! ### Counter
//! A clear use case of this is when counting the unique elements in a list.
//! Here you want to add one to the existing value in the map for that key.
//! This is a problem for the first addition when there's no value for the key yet.
//! With this library you can specify when creating the map that the default value should be zero.
//!

//! ```rust
//! # use defaultmap::*;
//! let nums = [1, 4, 3, 3, 4, 2, 4];
//! let mut counts:  DefaultHashMap<i32, i32> = DefaultHashMap::new(0);
//! // DefaultHashMap::default() is equivalent.
//!
//! for num in nums.into_iter() {
//!     counts[*num] += 1;
//! }
//!
//! println!("{:?}", counts);
//! // DefaultHashMap { map: {1: 1, 3: 2, 2: 1, 4: 3}, default: 0 }
//!
//! # assert_eq!(1, counts[1]);
//! # assert_eq!(1, counts[2]);
//! # assert_eq!(2, counts[3]);
//! # assert_eq!(3, counts[4]);
//! ```
//!

//! ### Synonym lists
//!
//! Another way the default map can be used is using a map filled with other collections, such as a
//! `Vec`, a `HashMap` or even another default map.
//! Next follows some code to create a map where we start with tuples of synonyms and we end with a
//! map that contains the list of synonyms for each word.
//!
//! ```rust
//! # use defaultmap::*;
//!
//! let synonym_tuples = [
//!     ("nice", "sweet"),
//!     ("sweet", "candy"),
//!     ("nice", "entertaining"),
//!     ("nice", "good"),
//!     ("entertaining", "absorbing"),
//! ];
//!
//! let mut synonym_map: DefaultHashMap<&str, Vec<&str>> = DefaultHashMap::new(vec![]);
//! // DefaultHashMap::default() is equivalent.
//!
//! for &(l, r) in synonym_tuples.into_iter() {
//!     synonym_map[l].push(r);
//!     synonym_map[r].push(l);
//! }
//!
//! assert_eq!(synonym_map["good"], vec!["nice"]);
//! assert_eq!(synonym_map["nice"], vec!["sweet", "entertaining", "good"]);
//! assert_eq!(synonym_map["evil"], Vec::<&str>::new());
//! ```
//!

pub use hashmap::DefaultHashMap;

mod hashmap {
    use std::hash::Hash;
    use std::collections::HashMap;
    use std::collections::hash_map::*;
    use std::borrow::Borrow;
    use std::ops::{Index, IndexMut};

    /// A `HashMap` that has returns a default when keys are accessed that are not present.
    #[derive(PartialEq, Eq, Debug)]
    pub struct DefaultHashMap<K: Eq + Hash, V: Clone> {
        map: HashMap<K, V>,
        default: V,
    }

    impl<K: Eq + Hash, V: Default + Clone> Default for DefaultHashMap<K, V> {
        /// The `default()` constructor creates an empty DefaultHashMap with the default of `V`
        /// as the default for missing keys.
        /// This is desired default for most use cases, if your case requires a
        /// different default you should use the `new()` constructor.
        fn default() -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: HashMap::default(),
                default: V::default(),
            }
        }
    }

    impl<K: Eq + Hash, V: Clone> DefaultHashMap<K, V> {
        /// Creates an empty `DefaultHashmap` with `default` as the default for missing keys.
        /// When the provided `default` is equivalent to `V::default()` it is preferred to use
        /// `DefaultHashMap::default()` instead.
        pub fn new(default: V) -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: HashMap::new(),
                default: default,
            }
        }

        /// Creates a `DefaultHashMap` based on a default and an already existing `HashMap`.
        pub fn new_with_map(default: V, map: HashMap<K, V>) -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: map,
                default: default,
            }
        }

        /// Returns a reference to the value stored for the provided key.
        /// If the key is not in the `DefaultHashMap` a reference to the default value is returned.
        /// Usually the `map[key]` method of retrieving keys is prefered over using `get` directly.
        /// This method accepts both references and owned values as the key.
        pub fn get<Q, QB: Borrow<Q>>(&self, key: QB) -> &V
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.get(key.borrow()).unwrap_or(&self.default)
        }

        /// Returns a mutable reference to the value stored for the provided key.
        /// If there is no value stored for the key the default value is first inserted for this
        /// key before returning the reference.
        /// Usually the `map[key] = new_val` is prefered over using `get_mut` directly.
        /// This method only accepts owned values as the key.
        pub fn get_mut(&mut self, key: K) -> &mut V {
            self.map.entry(key).or_insert(self.default.clone())
        }
    }

    /// Implements the `Index` trait so you can do `map[key]`.
    /// Nonmutable indexing can be done both by passing a reference or an owned value as the key.
    impl<'a, K: Eq + Hash, KB: Borrow<K>, V: Clone> Index<KB> for DefaultHashMap<K, V> {
        type Output = V;

        fn index(&self, index: KB) -> &V {
            self.get(index)
        }
    }

    /// Implements the `IndexMut` trait so you can do `map[key] = val`.
    /// Mutably indexing can only be done when passing an owned value as the key.
    impl<K: Eq + Hash, V: Clone> IndexMut<K> for DefaultHashMap<K, V> {
        #[inline]
        fn index_mut(&mut self, index: K) -> &mut V {
            self.get_mut(index)
        }
    }

    /// These methods simply forward to the underlying `HashMap`, see that
    /// [documentation](https://doc.rust-lang.org/std/collections/struct.HashMap.html) for
    /// the usage of these methods.
    impl<K: Eq + Hash, V: Clone> DefaultHashMap<K, V> {
        pub fn capacity(&self) -> usize {
            self.map.capacity()
        }
        #[inline]
        pub fn reserve(&mut self, additional: usize) {
            self.map.reserve(additional)
        }
        #[inline]
        pub fn shrink_to_fit(&mut self) {
            self.map.shrink_to_fit()
        }
        #[inline]
        pub fn keys(&self) -> Keys<K, V> {
            self.map.keys()
        }
        #[inline]
        pub fn values(&self) -> Values<K, V> {
            self.map.values()
        }
        #[inline]
        pub fn values_mut(&mut self) -> ValuesMut<K, V> {
            self.map.values_mut()
        }
        #[inline]
        pub fn iter(&self) -> Iter<K, V> {
            self.map.iter()
        }
        #[inline]
        pub fn iter_mut(&mut self) -> IterMut<K, V> {
            self.map.iter_mut()
        }
        #[inline]
        pub fn entry(&mut self, key: K) -> Entry<K, V> {
            self.map.entry(key)
        }
        #[inline]
        pub fn len(&self) -> usize {
            self.map.len()
        }
        #[inline]
        pub fn is_empty(&self) -> bool {
            self.map.is_empty()
        }
        #[inline]
        pub fn drain(&mut self) -> Drain<K, V> {
            self.map.drain()
        }
        #[inline]
        pub fn clear(&mut self) {
            self.map.clear()
        }
        #[inline]
        pub fn insert(&mut self, k: K, v: V) -> Option<V> {
            self.map.insert(k, v)
        }
        #[inline]
        pub fn contains_key<Q>(&self, k: &Q) -> (bool)
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.contains_key(k)
        }
        #[inline]
        pub fn remove<Q>(&mut self, k: &Q) -> (Option<V>)
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.remove(k)
        }
    }

}

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

    #[test]
    fn add() {
        let mut map: DefaultHashMap<i32, i32> = DefaultHashMap::default();
        *map.get_mut(0) += 1;
        map[1] += 4;
        map[2] = map[0] + map.get(&1);
        assert_eq!(*map.get(0), 1);
        assert_eq!(*map.get(&0), 1);
        assert_eq!(map[0], 1);
        assert_eq!(map[&0], 1);
        assert_eq!(*map.get(&1), 4);
        assert_eq!(*map.get(&2), 5);
        assert_eq!(*map.get(999), 0);
        assert_eq!(*map.get(&999), 0);
        assert_eq!(map[999], 0);
        assert_eq!(map[&999], 0);
    }

    #[test]
    fn counter() {
        let nums = [1, 4, 3, 3, 4, 2, 4];
        let mut counts: DefaultHashMap<i32, i32> = DefaultHashMap::default();
        for num in nums.into_iter() {
            counts[*num] += 1;
        }

        assert_eq!(1, counts[1]);
        assert_eq!(1, counts[2]);
        assert_eq!(2, counts[3]);
        assert_eq!(3, counts[4]);
        assert_eq!(0, counts[5]);
    }

    #[test]
    fn synonyms() {
        let synonym_tuples = [
            ("nice", "sweet"),
            ("sweet", "candy"),
            ("nice", "entertaining"),
            ("nice", "good"),
            ("entertaining", "absorbing"),
        ];

        let mut synonym_map: DefaultHashMap<&str, Vec<&str>> = DefaultHashMap::default();

        for &(l, r) in synonym_tuples.into_iter() {
            synonym_map[l].push(r);
            synonym_map[r].push(l);
        }

        println!("{:#?}", synonym_map);
        assert_eq!(synonym_map["good"], vec!["nice"]);
        assert_eq!(synonym_map["nice"], vec!["sweet", "entertaining", "good"]);
        assert_eq!(synonym_map["evil"], Vec::<&str>::new());
        // assert!(false)
    }

    #[derive(Clone)]
    struct Clonable;

    #[derive(Default, Clone)]
    struct DefaultableValue;

    #[derive(Hash, Eq, PartialEq)]
    struct Hashable(i32);

    #[test]
    fn minimal_derives() {
        let minimal: DefaultHashMap<Hashable, Clonable> = DefaultHashMap::new(Clonable);
        let clonable: DefaultHashMap<Hashable, DefaultableValue> = DefaultHashMap::default();
    }

}
<commit_msg>Implement From and Into for DefaultHashMap<commit_after>//! It can be useful to not have to worry about missing keys in a map.
//! If a key is requested that doesn't have a value a default value is simply returned.
//! This is exactly what this library provides.
//!
//! ## Examples

//! ### Counter
//! A clear use case of this is when counting the unique elements in a list.
//! Here you want to add one to the existing value in the map for that key.
//! This is a problem for the first addition when there's no value for the key yet.
//! With this library you can specify when creating the map that the default value should be zero.
//!

//! ```rust
//! # use defaultmap::*;
//! let nums = [1, 4, 3, 3, 4, 2, 4];
//! let mut counts:  DefaultHashMap<i32, i32> = DefaultHashMap::new(0);
//! // DefaultHashMap::default() is equivalent.
//!
//! for num in nums.into_iter() {
//!     counts[*num] += 1;
//! }
//!
//! println!("{:?}", counts);
//! // DefaultHashMap { map: {1: 1, 3: 2, 2: 1, 4: 3}, default: 0 }
//!
//! # assert_eq!(1, counts[1]);
//! # assert_eq!(1, counts[2]);
//! # assert_eq!(2, counts[3]);
//! # assert_eq!(3, counts[4]);
//! ```
//!

//! ### Synonym lists
//!
//! Another way the default map can be used is using a map filled with other collections, such as a
//! `Vec`, a `HashMap` or even another default map.
//! Next follows some code to create a map where we start with tuples of synonyms and we end with a
//! map that contains the list of synonyms for each word.
//!
//! ```rust
//! # use defaultmap::*;
//!
//! let synonym_tuples = [
//!     ("nice", "sweet"),
//!     ("sweet", "candy"),
//!     ("nice", "entertaining"),
//!     ("nice", "good"),
//!     ("entertaining", "absorbing"),
//! ];
//!
//! let mut synonym_map: DefaultHashMap<&str, Vec<&str>> = DefaultHashMap::new(vec![]);
//! // DefaultHashMap::default() is equivalent.
//!
//! for &(l, r) in synonym_tuples.into_iter() {
//!     synonym_map[l].push(r);
//!     synonym_map[r].push(l);
//! }
//!
//! assert_eq!(synonym_map["good"], vec!["nice"]);
//! assert_eq!(synonym_map["nice"], vec!["sweet", "entertaining", "good"]);
//! assert_eq!(synonym_map["evil"], Vec::<&str>::new());
//! ```
//!

pub use hashmap::DefaultHashMap;

mod hashmap {
    use std::hash::Hash;
    use std::collections::HashMap;
    use std::collections::hash_map::*;
    use std::borrow::Borrow;
    use std::ops::{Index, IndexMut};

    /// A `HashMap` that has returns a default when keys are accessed that are not present.
    #[derive(PartialEq, Eq, Debug)]
    pub struct DefaultHashMap<K: Eq + Hash, V: Clone> {
        map: HashMap<K, V>,
        default: V,
    }

    impl<K: Eq + Hash, V: Default + Clone> Default for DefaultHashMap<K, V> {
        /// The `default()` constructor creates an empty DefaultHashMap with the default of `V`
        /// as the default for missing keys.
        /// This is desired default for most use cases, if your case requires a
        /// different default you should use the `new()` constructor.
        fn default() -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: HashMap::default(),
                default: V::default(),
            }
        }
    }

    impl<K: Eq + Hash, V: Default + Clone> From<HashMap<K, V>> for DefaultHashMap<K, V> {
        /// If you already have a `HashMap` that you would like to convert to a
        /// `DefaultHashMap` you can use the `into()` method on the `HashMap` or the
        /// `from()` constructor of `DefaultHashMap`.
        /// The default value for missing keys will be `V::default()`,
        /// if this is not desired `DefaultHashMap::new_with_map()` should be used.
        fn from(map: HashMap<K, V>) -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: map,
                default: V::default(),
            }
        }
    }

    impl<K: Eq + Hash, V: Clone> Into<HashMap<K, V>> for DefaultHashMap<K, V> {
        /// The into method can be used to convert a `DefaultHashMap` back into a
        /// `HashMap`.
        fn into(self) -> HashMap<K, V> {
            self.map
        }
    }

    impl<K: Eq + Hash, V: Clone> DefaultHashMap<K, V> {
        /// Creates an empty `DefaultHashmap` with `default` as the default for missing keys.
        /// When the provided `default` is equivalent to `V::default()` it is preferred to use
        /// `DefaultHashMap::default()` instead.
        pub fn new(default: V) -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: HashMap::new(),
                default: default,
            }
        }

        /// Creates a `DefaultHashMap` based on a default and an already existing `HashMap`.
        /// If `V::default()` is the supplied default, usage of the `from()` constructor or the
        /// `into()` method on the original `HashMap` is preferred.
        pub fn new_with_map(default: V, map: HashMap<K, V>) -> DefaultHashMap<K, V> {
            DefaultHashMap {
                map: map,
                default: default,
            }
        }

        /// Returns a reference to the value stored for the provided key.
        /// If the key is not in the `DefaultHashMap` a reference to the default value is returned.
        /// Usually the `map[key]` method of retrieving keys is prefered over using `get` directly.
        /// This method accepts both references and owned values as the key.
        pub fn get<Q, QB: Borrow<Q>>(&self, key: QB) -> &V
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.get(key.borrow()).unwrap_or(&self.default)
        }

        /// Returns a mutable reference to the value stored for the provided key.
        /// If there is no value stored for the key the default value is first inserted for this
        /// key before returning the reference.
        /// Usually the `map[key] = new_val` is prefered over using `get_mut` directly.
        /// This method only accepts owned values as the key.
        pub fn get_mut(&mut self, key: K) -> &mut V {
            self.map.entry(key).or_insert(self.default.clone())
        }
    }

    /// Implements the `Index` trait so you can do `map[key]`.
    /// Nonmutable indexing can be done both by passing a reference or an owned value as the key.
    impl<'a, K: Eq + Hash, KB: Borrow<K>, V: Clone> Index<KB> for DefaultHashMap<K, V> {
        type Output = V;

        fn index(&self, index: KB) -> &V {
            self.get(index)
        }
    }

    /// Implements the `IndexMut` trait so you can do `map[key] = val`.
    /// Mutably indexing can only be done when passing an owned value as the key.
    impl<K: Eq + Hash, V: Clone> IndexMut<K> for DefaultHashMap<K, V> {
        #[inline]
        fn index_mut(&mut self, index: K) -> &mut V {
            self.get_mut(index)
        }
    }

    /// These methods simply forward to the underlying `HashMap`, see that
    /// [documentation](https://doc.rust-lang.org/std/collections/struct.HashMap.html) for
    /// the usage of these methods.
    impl<K: Eq + Hash, V: Clone> DefaultHashMap<K, V> {
        pub fn capacity(&self) -> usize {
            self.map.capacity()
        }
        #[inline]
        pub fn reserve(&mut self, additional: usize) {
            self.map.reserve(additional)
        }
        #[inline]
        pub fn shrink_to_fit(&mut self) {
            self.map.shrink_to_fit()
        }
        #[inline]
        pub fn keys(&self) -> Keys<K, V> {
            self.map.keys()
        }
        #[inline]
        pub fn values(&self) -> Values<K, V> {
            self.map.values()
        }
        #[inline]
        pub fn values_mut(&mut self) -> ValuesMut<K, V> {
            self.map.values_mut()
        }
        #[inline]
        pub fn iter(&self) -> Iter<K, V> {
            self.map.iter()
        }
        #[inline]
        pub fn iter_mut(&mut self) -> IterMut<K, V> {
            self.map.iter_mut()
        }
        #[inline]
        pub fn entry(&mut self, key: K) -> Entry<K, V> {
            self.map.entry(key)
        }
        #[inline]
        pub fn len(&self) -> usize {
            self.map.len()
        }
        #[inline]
        pub fn is_empty(&self) -> bool {
            self.map.is_empty()
        }
        #[inline]
        pub fn drain(&mut self) -> Drain<K, V> {
            self.map.drain()
        }
        #[inline]
        pub fn clear(&mut self) {
            self.map.clear()
        }
        #[inline]
        pub fn insert(&mut self, k: K, v: V) -> Option<V> {
            self.map.insert(k, v)
        }
        #[inline]
        pub fn contains_key<Q>(&self, k: &Q) -> (bool)
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.contains_key(k)
        }
        #[inline]
        pub fn remove<Q>(&mut self, k: &Q) -> (Option<V>)
            where K: Borrow<Q>,
                  Q: ?Sized + Hash + Eq
        {
            self.map.remove(k)
        }
    }

}

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

    #[test]
    fn add() {
        let mut map: DefaultHashMap<i32, i32> = DefaultHashMap::default();
        *map.get_mut(0) += 1;
        map[1] += 4;
        map[2] = map[0] + map.get(&1);
        assert_eq!(*map.get(0), 1);
        assert_eq!(*map.get(&0), 1);
        assert_eq!(map[0], 1);
        assert_eq!(map[&0], 1);
        assert_eq!(*map.get(&1), 4);
        assert_eq!(*map.get(&2), 5);
        assert_eq!(*map.get(999), 0);
        assert_eq!(*map.get(&999), 0);
        assert_eq!(map[999], 0);
        assert_eq!(map[&999], 0);
    }

    #[test]
    fn counter() {
        let nums = [1, 4, 3, 3, 4, 2, 4];
        let mut counts: DefaultHashMap<i32, i32> = DefaultHashMap::default();
        for num in nums.into_iter() {
            counts[*num] += 1;
        }

        assert_eq!(1, counts[1]);
        assert_eq!(1, counts[2]);
        assert_eq!(2, counts[3]);
        assert_eq!(3, counts[4]);
        assert_eq!(0, counts[5]);
    }

    #[test]
    fn synonyms() {
        let synonym_tuples = [
            ("nice", "sweet"),
            ("sweet", "candy"),
            ("nice", "entertaining"),
            ("nice", "good"),
            ("entertaining", "absorbing"),
        ];

        let mut synonym_map: DefaultHashMap<&str, Vec<&str>> = DefaultHashMap::default();

        for &(l, r) in synonym_tuples.into_iter() {
            synonym_map[l].push(r);
            synonym_map[r].push(l);
        }

        println!("{:#?}", synonym_map);
        assert_eq!(synonym_map["good"], vec!["nice"]);
        assert_eq!(synonym_map["nice"], vec!["sweet", "entertaining", "good"]);
        assert_eq!(synonym_map["evil"], Vec::<&str>::new());
        // assert!(false)
    }

    #[derive(Clone)]
    struct Clonable;

    #[derive(Default, Clone)]
    struct DefaultableValue;

    #[derive(Hash, Eq, PartialEq)]
    struct Hashable(i32);

    #[test]
    fn minimal_derives() {
        let minimal: DefaultHashMap<Hashable, Clonable> = DefaultHashMap::new(Clonable);
        let clonable: DefaultHashMap<Hashable, DefaultableValue> = DefaultHashMap::default();
    }

}
<|endoftext|>