<commit_before>// Copyright 2015, Igor Shaula
// Licensed under the MIT License <LICENSE or
// http://opensource.org/licenses/MIT>. This file
// may not be copied, modified, or distributed
// except according to those terms.
//! Crate for accessing MS Windows registry
extern crate winapi;
extern crate kernel32;
extern crate advapi32;
use std::ptr;
use std::fmt;
use std::default::Default;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use types::{FromReg, ToReg};

pub mod types;

pub struct RegError {
    err: winapi::DWORD,
}

impl fmt::Debug for RegError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RegError {{ err: {:?}, message: {:?} }}",
                   self.err, error_string(self.err))
    }
}

pub type RegResult<T> = std::result::Result<T, RegError>;

#[derive(Debug)]
pub struct RegKey {
    hkey: winapi::HKEY,
}

#[derive(Debug,Default)]
pub struct RegKeyMetadata {
    // Class: winapi::LPWSTR,
    // ClassLen: winapi::DWORD,
    sub_keys: winapi::DWORD,
    max_sub_key_len: winapi::DWORD,
    max_class_len: winapi::DWORD,
    values: winapi::DWORD,
    max_value_name_len: winapi::DWORD,
    max_value_len: winapi::DWORD,
    // SecurityDescriptor: winapi::DWORD,
    // LastWriteTime: winapi::PFILETIME,
}

impl RegKey {
    pub fn predef(hkey: winapi::HKEY) -> RegKey {
        RegKey{ hkey: hkey }
    }

    /// Open subkey with `KEY_ALL_ACCESS` permissions.
    /// To open with different permissions use `open_subkey_with_flags`.
    pub fn open_subkey<P: AsRef<OsStr>>(&self, path: P) -> RegResult<RegKey> {
        self.open_subkey_with_flags(path, winapi::KEY_ALL_ACCESS)
    }

    pub fn open_subkey_with_flags<P: AsRef<OsStr>>(&self, path: P, perms: winapi::REGSAM) -> RegResult<RegKey> {
        let c_path = to_utf16(path);
        let mut new_hkey: winapi::HKEY = ptr::null_mut();
        match unsafe {
            advapi32::RegOpenKeyExW(
                self.hkey,
                c_path.as_ptr(),
                0,
                perms,
                &mut new_hkey,
            ) as winapi::DWORD
        } {
            0 => Ok(RegKey{ hkey: new_hkey }),
            err => Err(RegError{ err: err })
        }
    }

    /// Create subkey (and all missing parent keys)
    /// and open it with `KEY_ALL_ACCESS` permissions.
    /// Will just open key if it already exists.
    /// To create with different permissions use `create_subkey_with_flags`.
    pub fn create_subkey<P: AsRef<OsStr>>(&self, path: P) -> RegResult<RegKey> {
        self.create_subkey_with_flags(path, winapi::KEY_ALL_ACCESS)
    }

    pub fn create_subkey_with_flags<P: AsRef<OsStr>>(&self, path: P, perms: winapi::REGSAM) -> RegResult<RegKey> {
        let c_path = to_utf16(path);
        let mut new_hkey: winapi::HKEY = ptr::null_mut();
        let mut disp: winapi::DWORD = 0;
        match unsafe {
            advapi32::RegCreateKeyExW(
                self.hkey,
                c_path.as_ptr(),
                0,
                ptr::null(),
                winapi::REG_OPTION_NON_VOLATILE,
                perms,
                ptr::null_mut(),
                &mut new_hkey,
                &mut disp // TODO: return this somehow
            ) as winapi::DWORD
        } {
            0 => Ok(RegKey{ hkey: new_hkey }),
            err => Err(RegError{ err: err })
        }
    }

    pub fn query_info(&self) -> RegResult<RegKeyMetadata> {
        let mut info: RegKeyMetadata = Default::default();
        match unsafe {
            advapi32::RegQueryInfoKeyW(
                self.hkey,
                ptr::null_mut(), // Class: winapi::LPWSTR,
                ptr::null_mut(), // ClassLen: winapi::DWORD,
                ptr::null_mut(), // Reserved
                &mut info.sub_keys,
                &mut info.max_sub_key_len,
                &mut info.max_class_len,
                &mut info.values,
                &mut info.max_value_name_len,
                &mut info.max_value_len,
                ptr::null_mut(), // lpcbSecurityDescriptor: LPDWORD,
                ptr::null_mut(), // lpftLastWriteTime: PFILETIME,
            ) as winapi::DWORD
        } {
            0 => Ok(info),
            err => Err(RegError{ err: err })
        }
    }

    pub fn enum_keys<'a>(&'a self) -> EnumKeys<'a> {
        EnumKeys{key: self, index: 0}
    }

    /// Delete key. Cannot delete if it nas subkeys.
    /// Use `delete_subkey_all` for that.
    pub fn delete_subkey<P: AsRef<OsStr>>(&self, path: P) -> RegResult<()> {
        let c_path = to_utf16(path);
        match unsafe {
            advapi32::RegDeleteKeyW(
                self.hkey,
                c_path.as_ptr(),
            ) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }

    /// Recursively delete key with all its subkeys and values.
    pub fn delete_subkey_all<P: AsRef<OsStr>>(&self, path: P) -> RegResult<()> {
        let c_path = to_utf16(path);
        match unsafe{
            advapi32::RegDeleteTreeW(
                self.hkey,
                c_path.as_ptr(),
            ) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }

    /// Get the `Default` value if `name` is an empty string
    pub fn get_value<T: FromReg, P: AsRef<OsStr>>(&self, name: P) -> RegResult<T> {
        let c_name = to_utf16(name);
        let mut buf_len: winapi::DWORD = 2048 as winapi::DWORD;
        let mut buf_type: winapi::DWORD = 0;
        let mut buf: Vec<u16> = Vec::with_capacity(buf_len as usize);
        match unsafe {
            advapi32::RegQueryValueExW(
                self.hkey,
                c_name.as_ptr() as *const u16,
                ptr::null_mut(),
                &mut buf_type,
                buf.as_mut_ptr() as winapi::LPBYTE,
                &mut buf_len
            ) as winapi::DWORD
        } {
            0 => {
                unsafe{ buf.set_len((buf_len >> 1) as usize); }
                FromReg::convert_from_bytes(buf, buf_type)
            },
            err => Err(RegError{ err: err })
        }
    }

    /// Set the `Default` value if `name` is an empty string
    pub fn set_value<T: ToReg, P: AsRef<OsStr>>(&self, name: P, value: &T) -> RegResult<()> {
        let c_name = to_utf16(name);
        let c_value = value.convert_to_bytes();
        let v_type = value.get_val_type();
        match unsafe{
            advapi32::RegSetValueExW(
                self.hkey,
                c_name.as_ptr(),
                0,
                v_type,
                c_value.as_ptr() as *const winapi::BYTE,
                (c_value.len()*2) as u32
            ) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }

    /// Delete the `Default` value if `name` is an empty string
    pub fn delete_value<P: AsRef<OsStr>>(&self, name: P) -> RegResult<()> {
        let c_name = to_utf16(name);
        match unsafe {
            advapi32::RegDeleteValueW(
                self.hkey,
                c_name.as_ptr(),
            ) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }

    fn close_(&mut self) -> RegResult<()> {
        // don't try to close predefined keys
        if self.hkey >= winapi::HKEY_CLASSES_ROOT { return Ok(()) };
        match unsafe {
            advapi32::RegCloseKey(self.hkey) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }
}

impl Drop for RegKey {
    fn drop(&mut self) {
        self.close_().unwrap();
    }
}

pub struct EnumKeys<'key> {
    key: &'key RegKey,
    index: winapi::DWORD,
}

impl<'key> Iterator for EnumKeys<'key> {
    type Item = RegResult<String>;

    fn next(&mut self) -> Option<Self::Item> {
        let mut name_len = 2048;
        let mut name = [0 as winapi::WCHAR; 2048];
        match unsafe {
            advapi32::RegEnumKeyExW(
                self.key.hkey,
                self.index,
                name.as_mut_ptr(),
                &mut name_len,
                ptr::null_mut(), // reserved
                ptr::null_mut(), // lpClass: LPWSTR,
                ptr::null_mut(), // lpcClass: LPDWORD,
                ptr::null_mut(), // lpftLastWriteTime: PFILETIME,
            ) as winapi::DWORD
        } {
            0 => {
                self.index += 1;
                Some(Ok(String::from_utf16(&name[..name_len as usize]).unwrap()))
            },
            winapi::ERROR_NO_MORE_ITEMS => None,
            err => {
                Some(Err(RegError{ err: err }))
            }
        }
    }
}

fn to_utf16<P: AsRef<OsStr>>(s: P) -> Vec<u16> {
    s.as_ref().encode_wide().chain(Some(0).into_iter()).collect()
}

// copycat of rust/src/libstd/sys/windows/os.rs::error_string
// `use std::sys::os::error_string` leads to
// error: function `error_string` is private.
// Get a detailed string description for the given error number
fn error_string(errnum: winapi::DWORD) -> String {
    let mut buf = [0 as winapi::WCHAR; 2048];
    unsafe {
        let res = kernel32::FormatMessageW(winapi::FORMAT_MESSAGE_FROM_SYSTEM |
                                 winapi::FORMAT_MESSAGE_IGNORE_INSERTS,
                                 ptr::null_mut(),
                                 errnum as winapi::DWORD,
                                 0,
                                 buf.as_mut_ptr(),
                                 buf.len() as winapi::DWORD,
                                 ptr::null_mut());
        if res == 0 {
            // Sometimes FormatMessageW can fail e.g. system doesn't like langId,
            // let fm_err = errno();
            return format!("OS Error {} (FormatMessageW() returned error)",
                           errnum);
        }

        let b = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
        let msg = String::from_utf16(&buf[..b]);
        match msg {
            Ok(msg) => msg,
            Err(..) => format!("OS Error {} (FormatMessageW() returned \
                                invalid UTF-16)", errnum),
        }
    }
}

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

    #[test]
    fn test_open_subkey_with_flags_query_info() {
        let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
        let win = hklm.open_subkey_with_flags("Software\\Microsoft\\Windows", KEY_READ).unwrap();
        assert!(win.query_info().is_ok());
        assert!(win.open_subkey_with_flags("CurrentVersion\\", KEY_READ).is_ok());
        assert!(hklm.open_subkey_with_flags("i\\just\\hope\\nobody\\created\\that\\key", KEY_READ).is_err());
    }

    fn create_test_key(path: &str) -> RegKey {
        let mut full_path = "Software\\WinRegRsTest".to_string();
        full_path.push_str(path);
        RegKey::predef(HKEY_CURRENT_USER)
        .create_subkey(full_path).unwrap()
    }

    fn delete_test_key(path: &str) {
        let mut full_path = "Software\\WinRegRsTest".to_string();
        full_path.push_str(path);
        RegKey::predef(HKEY_CURRENT_USER)
        .delete_subkey(full_path).unwrap();
    }

    #[test]
    fn test_create_delete_subkey() {
        let path = "CreateDeleteSubkey";
        create_test_key(path);
        delete_test_key(path);
    }

    #[test]
    fn test_delete_subkey_all() {
        let path = "DeleteSubkeyAll";
        let key = create_test_key(path);
        key.create_subkey_with_flags("with\\sub\\keys", KEY_READ).unwrap();
        assert!(RegKey::predef(HKEY_CURRENT_USER)
            .delete_subkey_all("Software\\WinRegRsTestDeleteSubkeyAll").is_ok());
    }

    #[test]
    fn test_string_value() {
        let path = "StringValue";
        let key = create_test_key(path);
        let name = "RustStringVal";
        let val1 = "Test123 \n$%^&|+-*/\\()".to_string();

        key.set_value(name, &val1).unwrap();
        let val2: String = key.get_value(name).unwrap();
        assert_eq!(val1, val2);
        delete_test_key(path);
    }

    #[test]
    fn test_u32_value() {
        let path = "U32Value";
        let key = create_test_key(path);
        let name = "RustU32Val";
        let val1 = 1234567890u32;

        key.set_value(name, &val1).unwrap();
        let val2: u32 = key.get_value(name).unwrap();
        assert_eq!(val1, val2);
        delete_test_key(path);
    }

    #[test]
    fn test_u64_value() {
        let path = "U32Value";
        let key = create_test_key(path);
        let name = "RustU32Val";
        let val1 = 1234567891011121314u64;

        key.set_value(name, &val1).unwrap();
        let val2: u64 = key.get_value(name).unwrap();
        assert_eq!(val1, val2);
        delete_test_key(path);
    }

    #[test]
    fn test_delete_value() {
        let path = "StringValue";
        let key = create_test_key(path);
        let name = "WinregRsTestVal";
        key.set_value(name, &"Qwerty123").unwrap();
        assert!(key.delete_value(name).is_ok());
        delete_test_key(path);
    }
}
<commit_msg>Fix for rust-1.0.0_beta<commit_after>// Copyright 2015, Igor Shaula
// Licensed under the MIT License <LICENSE or
// http://opensource.org/licenses/MIT>. This file
// may not be copied, modified, or distributed
// except according to those terms.
//! Crate for accessing MS Windows registry
extern crate winapi;
extern crate kernel32;
extern crate advapi32;
use std::ptr;
use std::fmt;
use std::default::Default;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use types::{FromReg, ToReg};

pub mod types;

pub struct RegError {
    err: winapi::DWORD,
}

impl fmt::Debug for RegError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "RegError {{ err: {:?}, message: {:?} }}",
                   self.err, error_string(self.err))
    }
}

pub type RegResult<T> = std::result::Result<T, RegError>;

#[derive(Debug)]
pub struct RegKey {
    hkey: winapi::HKEY,
}

#[derive(Debug,Default)]
pub struct RegKeyMetadata {
    // Class: winapi::LPWSTR,
    // ClassLen: winapi::DWORD,
    sub_keys: winapi::DWORD,
    max_sub_key_len: winapi::DWORD,
    max_class_len: winapi::DWORD,
    values: winapi::DWORD,
    max_value_name_len: winapi::DWORD,
    max_value_len: winapi::DWORD,
    // SecurityDescriptor: winapi::DWORD,
    // LastWriteTime: winapi::PFILETIME,
}

impl RegKey {
    pub fn predef(hkey: winapi::HKEY) -> RegKey {
        RegKey{ hkey: hkey }
    }

    /// Open subkey with `KEY_ALL_ACCESS` permissions.
    /// To open with different permissions use `open_subkey_with_flags`.
    pub fn open_subkey<P: AsRef<OsStr>>(&self, path: P) -> RegResult<RegKey> {
        self.open_subkey_with_flags(path, winapi::KEY_ALL_ACCESS)
    }

    pub fn open_subkey_with_flags<P: AsRef<OsStr>>(&self, path: P, perms: winapi::REGSAM) -> RegResult<RegKey> {
        let c_path = to_utf16(path);
        let mut new_hkey: winapi::HKEY = ptr::null_mut();
        match unsafe {
            advapi32::RegOpenKeyExW(
                self.hkey,
                c_path.as_ptr(),
                0,
                perms,
                &mut new_hkey,
            ) as winapi::DWORD
        } {
            0 => Ok(RegKey{ hkey: new_hkey }),
            err => Err(RegError{ err: err })
        }
    }

    /// Create subkey (and all missing parent keys)
    /// and open it with `KEY_ALL_ACCESS` permissions.
    /// Will just open key if it already exists.
    /// To create with different permissions use `create_subkey_with_flags`.
    pub fn create_subkey<P: AsRef<OsStr>>(&self, path: P) -> RegResult<RegKey> {
        self.create_subkey_with_flags(path, winapi::KEY_ALL_ACCESS)
    }

    pub fn create_subkey_with_flags<P: AsRef<OsStr>>(&self, path: P, perms: winapi::REGSAM) -> RegResult<RegKey> {
        let c_path = to_utf16(path);
        let mut new_hkey: winapi::HKEY = ptr::null_mut();
        let mut disp: winapi::DWORD = 0;
        match unsafe {
            advapi32::RegCreateKeyExW(
                self.hkey,
                c_path.as_ptr(),
                0,
                ptr::null(),
                winapi::REG_OPTION_NON_VOLATILE,
                perms,
                ptr::null_mut(),
                &mut new_hkey,
                &mut disp // TODO: return this somehow
            ) as winapi::DWORD
        } {
            0 => Ok(RegKey{ hkey: new_hkey }),
            err => Err(RegError{ err: err })
        }
    }

    pub fn query_info(&self) -> RegResult<RegKeyMetadata> {
        let mut info: RegKeyMetadata = Default::default();
        match unsafe {
            advapi32::RegQueryInfoKeyW(
                self.hkey,
                ptr::null_mut(), // Class: winapi::LPWSTR,
                ptr::null_mut(), // ClassLen: winapi::DWORD,
                ptr::null_mut(), // Reserved
                &mut info.sub_keys,
                &mut info.max_sub_key_len,
                &mut info.max_class_len,
                &mut info.values,
                &mut info.max_value_name_len,
                &mut info.max_value_len,
                ptr::null_mut(), // lpcbSecurityDescriptor: LPDWORD,
                ptr::null_mut(), // lpftLastWriteTime: PFILETIME,
            ) as winapi::DWORD
        } {
            0 => Ok(info),
            err => Err(RegError{ err: err })
        }
    }

    pub fn enum_keys<'a>(&'a self) -> EnumKeys<'a> {
        EnumKeys{key: self, index: 0}
    }

    /// Delete key. Cannot delete if it nas subkeys.
    /// Use `delete_subkey_all` for that.
    pub fn delete_subkey<P: AsRef<OsStr>>(&self, path: P) -> RegResult<()> {
        let c_path = to_utf16(path);
        match unsafe {
            advapi32::RegDeleteKeyW(
                self.hkey,
                c_path.as_ptr(),
            ) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }

    /// Recursively delete key with all its subkeys and values.
    pub fn delete_subkey_all<P: AsRef<OsStr>>(&self, path: P) -> RegResult<()> {
        let c_path = to_utf16(path);
        match unsafe{
            advapi32::RegDeleteTreeW(
                self.hkey,
                c_path.as_ptr(),
            ) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }

    /// Get the `Default` value if `name` is an empty string
    pub fn get_value<T: FromReg, P: AsRef<OsStr>>(&self, name: P) -> RegResult<T> {
        let c_name = to_utf16(name);
        let mut buf_len: winapi::DWORD = 2048 as winapi::DWORD;
        let mut buf_type: winapi::DWORD = 0;
        let mut buf: Vec<u16> = Vec::with_capacity(buf_len as usize);
        match unsafe {
            advapi32::RegQueryValueExW(
                self.hkey,
                c_name.as_ptr() as *const u16,
                ptr::null_mut(),
                &mut buf_type,
                buf.as_mut_ptr() as winapi::LPBYTE,
                &mut buf_len
            ) as winapi::DWORD
        } {
            0 => {
                unsafe{ buf.set_len((buf_len >> 1) as usize); }
                FromReg::convert_from_bytes(buf, buf_type)
            },
            err => Err(RegError{ err: err })
        }
    }

    /// Set the `Default` value if `name` is an empty string
    pub fn set_value<T: ToReg, P: AsRef<OsStr>>(&self, name: P, value: &T) -> RegResult<()> {
        let c_name = to_utf16(name);
        let c_value = value.convert_to_bytes();
        let v_type = value.get_val_type();
        match unsafe{
            advapi32::RegSetValueExW(
                self.hkey,
                c_name.as_ptr(),
                0,
                v_type,
                c_value.as_ptr() as *const winapi::BYTE,
                (c_value.len()*2) as u32
            ) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }

    /// Delete the `Default` value if `name` is an empty string
    pub fn delete_value<P: AsRef<OsStr>>(&self, name: P) -> RegResult<()> {
        let c_name = to_utf16(name);
        match unsafe {
            advapi32::RegDeleteValueW(
                self.hkey,
                c_name.as_ptr(),
            ) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }

    fn close_(&mut self) -> RegResult<()> {
        // don't try to close predefined keys
        if self.hkey >= winapi::HKEY_CLASSES_ROOT { return Ok(()) };
        match unsafe {
            advapi32::RegCloseKey(self.hkey) as winapi::DWORD
        } {
            0 => Ok(()),
            err => Err(RegError{ err: err })
        }
    }
}

impl Drop for RegKey {
    fn drop(&mut self) {
        self.close_().unwrap();
    }
}

pub struct EnumKeys<'key> {
    key: &'key RegKey,
    index: winapi::DWORD,
}

impl<'key> Iterator for EnumKeys<'key> {
    type Item = RegResult<String>;

    fn next(&mut self) -> Option<RegResult<String>> {
        let mut name_len = 2048;
        let mut name = [0 as winapi::WCHAR; 2048];
        match unsafe {
            advapi32::RegEnumKeyExW(
                self.key.hkey,
                self.index,
                name.as_mut_ptr(),
                &mut name_len,
                ptr::null_mut(), // reserved
                ptr::null_mut(), // lpClass: LPWSTR,
                ptr::null_mut(), // lpcClass: LPDWORD,
                ptr::null_mut(), // lpftLastWriteTime: PFILETIME,
            ) as winapi::DWORD
        } {
            0 => {
                self.index += 1;
                Some(Ok(String::from_utf16(&name[..name_len as usize]).unwrap()))
            },
            winapi::ERROR_NO_MORE_ITEMS => None,
            err => {
                Some(Err(RegError{ err: err }))
            }
        }
    }
}

fn to_utf16<P: AsRef<OsStr>>(s: P) -> Vec<u16> {
    s.as_ref().encode_wide().chain(Some(0).into_iter()).collect()
}

// copycat of rust/src/libstd/sys/windows/os.rs::error_string
// `use std::sys::os::error_string` leads to
// error: function `error_string` is private.
// Get a detailed string description for the given error number
fn error_string(errnum: winapi::DWORD) -> String {
    let mut buf = [0 as winapi::WCHAR; 2048];
    unsafe {
        let res = kernel32::FormatMessageW(winapi::FORMAT_MESSAGE_FROM_SYSTEM |
                                 winapi::FORMAT_MESSAGE_IGNORE_INSERTS,
                                 ptr::null_mut(),
                                 errnum as winapi::DWORD,
                                 0,
                                 buf.as_mut_ptr(),
                                 buf.len() as winapi::DWORD,
                                 ptr::null_mut());
        if res == 0 {
            // Sometimes FormatMessageW can fail e.g. system doesn't like langId,
            // let fm_err = errno();
            return format!("OS Error {} (FormatMessageW() returned error)",
                           errnum);
        }

        let b = buf.iter().position(|&b| b == 0).unwrap_or(buf.len());
        let msg = String::from_utf16(&buf[..b]);
        match msg {
            Ok(msg) => msg,
            Err(..) => format!("OS Error {} (FormatMessageW() returned \
                                invalid UTF-16)", errnum),
        }
    }
}

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

    #[test]
    fn test_open_subkey_with_flags_query_info() {
        let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
        let win = hklm.open_subkey_with_flags("Software\\Microsoft\\Windows", KEY_READ).unwrap();
        assert!(win.query_info().is_ok());
        assert!(win.open_subkey_with_flags("CurrentVersion\\", KEY_READ).is_ok());
        assert!(hklm.open_subkey_with_flags("i\\just\\hope\\nobody\\created\\that\\key", KEY_READ).is_err());
    }

    fn create_test_key(path: &str) -> RegKey {
        let mut full_path = "Software\\WinRegRsTest".to_string();
        full_path.push_str(path);
        RegKey::predef(HKEY_CURRENT_USER)
        .create_subkey(full_path).unwrap()
    }

    fn delete_test_key(path: &str) {
        let mut full_path = "Software\\WinRegRsTest".to_string();
        full_path.push_str(path);
        RegKey::predef(HKEY_CURRENT_USER)
        .delete_subkey(full_path).unwrap();
    }

    #[test]
    fn test_create_delete_subkey() {
        let path = "CreateDeleteSubkey";
        create_test_key(path);
        delete_test_key(path);
    }

    #[test]
    fn test_delete_subkey_all() {
        let path = "DeleteSubkeyAll";
        let key = create_test_key(path);
        key.create_subkey_with_flags("with\\sub\\keys", KEY_READ).unwrap();
        assert!(RegKey::predef(HKEY_CURRENT_USER)
            .delete_subkey_all("Software\\WinRegRsTestDeleteSubkeyAll").is_ok());
    }

    #[test]
    fn test_string_value() {
        let path = "StringValue";
        let key = create_test_key(path);
        let name = "RustStringVal";
        let val1 = "Test123 \n$%^&|+-*/\\()".to_string();

        key.set_value(name, &val1).unwrap();
        let val2: String = key.get_value(name).unwrap();
        assert_eq!(val1, val2);
        delete_test_key(path);
    }

    #[test]
    fn test_u32_value() {
        let path = "U32Value";
        let key = create_test_key(path);
        let name = "RustU32Val";
        let val1 = 1234567890u32;

        key.set_value(name, &val1).unwrap();
        let val2: u32 = key.get_value(name).unwrap();
        assert_eq!(val1, val2);
        delete_test_key(path);
    }

    #[test]
    fn test_u64_value() {
        let path = "U32Value";
        let key = create_test_key(path);
        let name = "RustU32Val";
        let val1 = 1234567891011121314u64;

        key.set_value(name, &val1).unwrap();
        let val2: u64 = key.get_value(name).unwrap();
        assert_eq!(val1, val2);
        delete_test_key(path);
    }

    #[test]
    fn test_delete_value() {
        let path = "StringValue";
        let key = create_test_key(path);
        let name = "WinregRsTestVal";
        key.set_value(name, &"Qwerty123").unwrap();
        assert!(key.delete_value(name).is_ok());
        delete_test_key(path);
    }
}
<|endoftext|>


<commit_before>#[test]
fn it_works() {
}
<commit_msg>Added initial logger<commit_after>#![feature(phase)]
#[phase(plugin, link)]extern crate log;
#[phase(plugin, link)]extern crate time;
/// import
use log::{Logger,LogRecord,LogLevel,LogLocation, set_logger};
use std::io::{ LineBufferedWriter, stdio, stderr};
/// Custom Logger
struct CustomLogger {
	handle: LineBufferedWriter<stdio::StdWriter>,
}
/// Implements Logger trait for Custom Logger which support logging timestamp, file name and line number
/// in addition to log level, module path and message.
impl Logger for CustomLogger {
	fn log(&mut self, record: &LogRecord) {
		match writeln!(&mut self.handle,
				"{}:{}:{}:{}:{} {}",
				time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).unwrap(),
				record.level,
				record.module_path,
				record.file,
				record.line,
				record.args) {
		Err(e) => panic!("failed to log: {}", e),
		Ok(()) => {}
		}
	}
}
<|endoftext|>


<commit_before>#![feature(slice_concat_ext)]

use unicode_segmentation::UnicodeSegmentation;
use std::slice::SliceConcatExt;

extern crate unicode_segmentation;

pub fn normalize_tag(tag: &str) -> Result<String, &'static str> {

    if tag.is_empty() {
        Err("Tag is empty")
    } else {
        let lc = tag.to_lowercase();
        let words: Vec<&str> = lc.unicode_words().collect();
        let joined = words.join("-");
        Ok(joined)
    }
}

#[test]
fn test_tag_normalize() {
    assert!(normalize_tag("").is_err());
    assert_eq!(Ok("abc".to_string()), normalize_tag("ABC"));
    assert_eq!(Ok("abc-this-is-a-tag".to_string()), normalize_tag("ABC this is a tag\""));
    assert_eq!(Ok("abc-this-is-a-tag".to_string()), normalize_tag("   ABC this     is a tag\""));
    assert_eq!(Ok("abc-this-is-a-tag".to_string()), normalize_tag("--   ABC this     is a tag--\""));
}
<commit_msg>Check if empty after normalization<commit_after>#![feature(slice_concat_ext)]

use unicode_segmentation::UnicodeSegmentation;
use std::slice::SliceConcatExt;

extern crate unicode_segmentation;

pub fn normalize_tag(tag: &str) -> Result<String, &'static str> {
    if tag.is_empty() {
        Err("Tag is empty")
    } else {
        let lc = tag.to_lowercase();
        let words: Vec<&str> = lc.unicode_words().collect();
        let joined = words.join("-");
        if joined.is_empty() {
            Err("Tag is empty after normalization")
        } else {
            Ok(joined)
        }
    }
}

#[test]
fn test_tag_normalize() {
    assert!(normalize_tag("").is_err());
    assert_eq!(Ok("abc".to_string()), normalize_tag("ABC"));
    assert_eq!(Ok("abc-this-is-a-tag".to_string()), normalize_tag("ABC this is a tag\""));
    assert_eq!(Ok("abc-this-is-a-tag".to_string()), normalize_tag("   ABC this     is a tag\""));
    assert_eq!(Ok("abc-this-is-a-tag".to_string()), normalize_tag("--   ABC this     is a tag--\""));
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 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.
//
// ignore-lexer-test FIXME #15679

//! Operations on ASCII strings and characters

use std::fmt;
use std::mem;
use std::borrow::Borrow;
use std::ascii::AsciiExt;

/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash, Copy)]
pub struct Ascii { chr: u8 }

impl Ascii {
    /// Converts an ascii character into a `u8`.
    #[inline]
    pub fn as_byte(&self) -> u8 {
        self.chr
    }

    /// Converts an ascii character into a `char`.
    #[inline]
    pub fn as_char(&self) -> char {
        self.chr as char
    }

    /// Convert to lowercase.
    #[inline]
    pub fn to_lowercase(&self) -> Ascii {
        Ascii{chr: self.chr.to_ascii_lowercase()}
    }

    /// Convert to uppercase.
    #[inline]
    pub fn to_uppercase(&self) -> Ascii {
        Ascii{chr: self.chr.to_ascii_uppercase()}
    }

    // the following methods are like ctype, and the implementation is inspired by musl

    /// Check if the character is a letter (a-z, A-Z)
    #[inline]
    pub fn is_alphabetic(&self) -> bool {
        (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
    }

    /// Check if the character is a number (0-9)
    #[inline]
    pub fn is_digit(&self) -> bool {
        self.chr >= 0x30 && self.chr <= 0x39
    }

    /// Check if the character is a letter or number
    #[inline]
    pub fn is_alphanumeric(&self) -> bool {
        self.is_alphabetic() || self.is_digit()
    }

    /// Check if the character is a space or horizontal tab
    #[inline]
    pub fn is_blank(&self) -> bool {
        self.chr == b' ' || self.chr == b'\t'
    }

    /// Check if the character is a control character
    #[inline]
    pub fn is_control(&self) -> bool {
        self.chr < 0x20 || self.chr == 0x7F
    }

    /// Checks if the character is printable (except space)
    #[inline]
    pub fn is_graph(&self) -> bool {
        (self.chr - 0x21) < 0x5E
    }

    /// Checks if the character is printable (including space)
    #[inline]
    pub fn is_print(&self) -> bool {
        (self.chr - 0x20) < 0x5F
    }

    /// Checks if the character is alphabetic and lowercase
    #[inline]
    pub fn is_lowercase(&self) -> bool {
        (self.chr - b'a') < 26
    }

    /// Checks if the character is alphabetic and uppercase
    #[inline]
    pub fn is_uppercase(&self) -> bool {
        (self.chr - b'A') < 26
    }

    /// Checks if the character is punctuation
    #[inline]
    pub fn is_punctuation(&self) -> bool {
        self.is_graph() && !self.is_alphanumeric()
    }

    /// Checks if the character is a valid hex digit
    #[inline]
    pub fn is_hex(&self) -> bool {
        self.is_digit() || ((self.chr | 32u8) - b'a') < 6
    }
}

impl fmt::Display for Ascii {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&(self.chr as char), f)
    }
}

impl fmt::Display for Vec<Ascii> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self[], f)
    }
}

impl fmt::Display for [Ascii] {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.as_str(), f)
    }
}

impl fmt::Debug for Ascii {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&(self.chr as char), f)
    }
}

// TODO: The following impls conflict with the generic impls in std.
// impl fmt::Show for Vec<Ascii> {
//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//         fmt::Show::fmt(&self[], f)
//     }
// }

// impl fmt::Show for [Ascii] {
//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//         fmt::Show::fmt(self.as_str(), f)
//     }
// }

/// Trait for converting into an ascii type.
pub trait AsciiCast : AsciiExt {
    type Target;

    /// Convert to an ascii type, return Err(()) on non-ASCII input.
    #[inline]
    fn to_ascii(&self) -> Result<Self::Target, ()> {
        if self.is_ascii() {
            Ok(unsafe { self.to_ascii_nocheck() })
        } else {
            Err(())
        }
    }

    /// Convert to an ascii type, not doing any range asserts
    unsafe fn to_ascii_nocheck(&self) -> Self::Target;
}

impl<'a> AsciiCast for [u8] {
    type Target = &'a [Ascii];

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
        mem::transmute(self)
    }
}

impl<'a> AsciiCast for str {
    type Target = &'a [Ascii];

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
        mem::transmute(self)
    }
}

impl AsciiCast for u8 {
    type Target = Ascii;

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self }
    }
}

impl AsciiCast for char {
    type Target = Ascii;

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self as u8 }
    }
}

/// Trait for copyless casting to an ascii vector.
pub trait OwnedAsciiCast<T: ?Sized> : Sized + Borrow<T>
where T: AsciiExt<Owned=Self> {
    /// Take ownership and cast to an ascii vector. On non-ASCII input return ownership of data
    /// that was attempted to cast to ascii in `Err(Self)`.
    #[inline]
    fn into_ascii(self) -> Result<Vec<Ascii>, Self> {
        if self.borrow().is_ascii() {
            Ok(unsafe { self.into_ascii_nocheck() })
        } else {
            Err(self)
        }
    }

    /// Take ownership and cast to an ascii vector.
    /// Does not perform validation checks.
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
}

impl OwnedAsciiCast<str> for String {
    #[inline]
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
        self.into_bytes().into_ascii_nocheck()
    }
}

impl OwnedAsciiCast<[u8]> for Vec<u8> {
    #[inline]
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
        let v = Vec::from_raw_parts(self.as_ptr() as *mut Ascii,
                                    self.len(),
                                    self.capacity());

        // We forget `self` to avoid freeing it at the end of the scope
        // Otherwise, the returned `Vec` would point to freed memory
        mem::forget(self);
        v
    }
}

/// Trait for converting a type to a string, consuming it in the process.
pub trait IntoString {
    /// Consume and convert to a string.
    fn into_string(self) -> String;
}

/// Trait for converting an ascii type to a string. Needed to convert
/// `&[Ascii]` to `&str`.
pub trait AsciiStr {
    /// Convert to a string.
    fn as_str<'a>(&'a self) -> &'a str;

    /// Convert to bytes.
    fn as_bytes<'a>(&'a self) -> &'a [u8];
}

impl AsciiStr for [Ascii] {
    #[inline]
    fn as_str<'a>(&'a self) -> &'a str {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn as_bytes<'a>(&'a self) -> &'a [u8] {
        unsafe { mem::transmute(self) }
    }
}

impl IntoString for Vec<Ascii> {
    #[inline]
    fn into_string(self) -> String {
        unsafe { String::from_utf8_unchecked(self.into_bytes()) }
    }
}

/// Trait to convert to an owned byte vector by consuming self
pub trait IntoBytes {
    /// Converts to an owned byte vector by consuming self
    fn into_bytes(self) -> Vec<u8>;
}

impl IntoBytes for Vec<Ascii> {
    fn into_bytes(self) -> Vec<u8> {
        unsafe {
            let v = Vec::from_raw_parts(self.as_ptr() as *mut u8,
                                        self.len(),
                                        self.capacity());

            // We forget `self` to avoid freeing it at the end of the scope
            // Otherwise, the returned `Vec` would point to freed memory
            mem::forget(self);
            v
        }
    }
}

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

    macro_rules! v2ascii (
        ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
        (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
    );

    macro_rules! vec2ascii (
        ($($e:expr),*) => ([$(Ascii{chr:$e}),*].to_vec());
    );

    #[test]
    fn test_ascii() {
        assert_eq!(65u8.to_ascii().unwrap().as_byte(), 65u8);
        assert_eq!(65u8.to_ascii().unwrap().as_char(), 'A');
        assert_eq!('A'.to_ascii().unwrap().as_char(), 'A');
        assert_eq!('A'.to_ascii().unwrap().as_byte(), 65u8);

        assert!('0'.to_ascii().unwrap().is_digit());
        assert!('9'.to_ascii().unwrap().is_digit());
        assert!(!'/'.to_ascii().unwrap().is_digit());
        assert!(!':'.to_ascii().unwrap().is_digit());

        assert!(0x1f_u8.to_ascii().unwrap().is_control());
        assert!(!' '.to_ascii().unwrap().is_control());
        assert!(0x7f_u8.to_ascii().unwrap().is_control());
    }

    #[test]
    fn test_ascii_vec() {
        let test = &[40u8, 32u8, 59u8];
        let b: &[_] = v2ascii!([40, 32, 59]);
        assert_eq!(test.to_ascii().unwrap(), b);
        assert_eq!("( ;".to_ascii().unwrap(), b);
        let v = vec![40u8, 32u8, 59u8];
        assert_eq!(v.as_slice().to_ascii().unwrap(), b);
        assert_eq!("( ;".to_string().as_slice().to_ascii().unwrap(), b);
    }

    #[test]
    fn test_ascii_as_str() {
        let v = v2ascii!([40, 32, 59]);
        assert_eq!(v.as_str(), "( ;");
    }

    #[test]
    fn test_ascii_as_bytes() {
        let v = v2ascii!([40, 32, 59]);
        assert_eq!(v.as_bytes(), b"( ;");
    }

    #[test]
    fn test_ascii_into_string() {
        assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
        assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
    }

    #[test]
    fn test_ascii_to_bytes() {
        assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
    }

    #[test]
    fn test_opt() {
        assert_eq!(65u8.to_ascii(), Ok(Ascii { chr: 65u8 }));
        assert_eq!(255u8.to_ascii(), Err(()));

        assert_eq!('A'.to_ascii(), Ok(Ascii { chr: 65u8 }));
        assert_eq!('λ'.to_ascii(), Err(()));

        assert_eq!("zoä华".to_ascii(), Err(()));

        let test1 = &[127u8, 128u8, 255u8];
        assert_eq!(test1.to_ascii(), Err(()));

        let v = [40u8, 32u8, 59u8];
        let v2: &[_] = v2ascii!(&[40, 32, 59]);
        assert_eq!(v.to_ascii(), Ok(v2));
        let v = [127u8, 128u8, 255u8];
        assert_eq!(v.to_ascii(), Err(()));

        let v = "( ;";
        assert_eq!(v.to_ascii(), Ok(v2));
        assert_eq!("zoä华".to_ascii(), Err(()));

        assert_eq!(vec![40u8, 32u8, 59u8].into_ascii(), Ok(vec2ascii![40, 32, 59]));
        assert_eq!(vec![127u8, 128u8, 255u8].into_ascii(), Err(vec![127u8, 128u8, 255u8]));

        assert_eq!("( ;".to_string().into_ascii(), Ok(vec2ascii![40, 32, 59]));
        assert_eq!("zoä华".to_string().into_ascii(), Err("zoä华".to_string()));
    }

    #[test]
    fn fmt_string_ascii() {
        let s = Ascii{ chr: b't' };
        assert_eq!(format!("{}", s), "t".to_string());
    }

    #[test]
    fn fmt_string_ascii_slice() {
        let s = "abc".to_ascii().unwrap();
        assert_eq!(format!("{}", s), "abc".to_string());
    }

    #[test]
    fn fmt_string_ascii_vec() {
        let s = "abc".to_string().into_ascii().unwrap();
        assert_eq!(format!("{}", s), "abc".to_string());
    }

    #[test]
    fn fmt_show_ascii() {
        let c = Ascii { chr: b't' };
        assert_eq!(format!("{:?}", c), "'t'".to_string());
    }

    // NOTE: The following tests fail intentionally until custom `fmt::Show`
    //       implementations for `Vec<Ascii>` and `&[Ascii]` can be provided.
    //       (Or the current types are newtyped.)
    // #[test]
    // fn fmt_show_ascii_slice() {
    //     let s = "abc".to_ascii().unwrap();
    //     assert_eq!(format!("{}", s), "\"abc\"".to_string());
    // }

    // #[test]
    // fn fmt_show_ascii_vec() {
    //     let s = "abc".to_string().into_ascii().unwrap();
    //     assert_eq!(format!("{}", s), "\"abc\"".to_string());
    // }
}
<commit_msg>Miscellaneous cleanups<commit_after>// Copyright 2013-2014 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.
//
// ignore-lexer-test FIXME #15679

//! Operations on ASCII strings and characters

use std::fmt;
use std::mem;
use std::borrow::Borrow;
use std::ascii::AsciiExt;

/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash, Copy)]
pub struct Ascii { chr: u8 }

impl Ascii {
    /// Converts an ascii character into a `u8`.
    #[inline]
    pub fn as_byte(&self) -> u8 {
        self.chr
    }

    /// Converts an ascii character into a `char`.
    #[inline]
    pub fn as_char(&self) -> char {
        self.chr as char
    }

    /// Convert to lowercase.
    #[inline]
    pub fn to_lowercase(&self) -> Ascii {
        Ascii{chr: self.chr.to_ascii_lowercase()}
    }

    /// Convert to uppercase.
    #[inline]
    pub fn to_uppercase(&self) -> Ascii {
        Ascii{chr: self.chr.to_ascii_uppercase()}
    }

    // the following methods are like ctype, and the implementation is inspired by musl

    /// Check if the character is a letter (a-z, A-Z)
    #[inline]
    pub fn is_alphabetic(&self) -> bool {
        (self.chr >= 0x41 && self.chr <= 0x5A) || (self.chr >= 0x61 && self.chr <= 0x7A)
    }

    /// Check if the character is a number (0-9)
    #[inline]
    pub fn is_digit(&self) -> bool {
        self.chr >= 0x30 && self.chr <= 0x39
    }

    /// Check if the character is a letter or number
    #[inline]
    pub fn is_alphanumeric(&self) -> bool {
        self.is_alphabetic() || self.is_digit()
    }

    /// Check if the character is a space or horizontal tab
    #[inline]
    pub fn is_blank(&self) -> bool {
        self.chr == b' ' || self.chr == b'\t'
    }

    /// Check if the character is a control character
    #[inline]
    pub fn is_control(&self) -> bool {
        self.chr < 0x20 || self.chr == 0x7F
    }

    /// Checks if the character is printable (except space)
    #[inline]
    pub fn is_graph(&self) -> bool {
        (self.chr - 0x21) < 0x5E
    }

    /// Checks if the character is printable (including space)
    #[inline]
    pub fn is_print(&self) -> bool {
        (self.chr - 0x20) < 0x5F
    }

    /// Checks if the character is alphabetic and lowercase
    #[inline]
    pub fn is_lowercase(&self) -> bool {
        (self.chr - b'a') < 26
    }

    /// Checks if the character is alphabetic and uppercase
    #[inline]
    pub fn is_uppercase(&self) -> bool {
        (self.chr - b'A') < 26
    }

    /// Checks if the character is punctuation
    #[inline]
    pub fn is_punctuation(&self) -> bool {
        self.is_graph() && !self.is_alphanumeric()
    }

    /// Checks if the character is a valid hex digit
    #[inline]
    pub fn is_hex(&self) -> bool {
        self.is_digit() || ((self.chr | 32u8) - b'a') < 6
    }
}

impl fmt::Display for Ascii {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&(self.chr as char), f)
    }
}

impl fmt::Display for Vec<Ascii> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self[..], f)
    }
}

impl fmt::Display for [Ascii] {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.as_str(), f)
    }
}

impl fmt::Debug for Ascii {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&(self.chr as char), f)
    }
}

// NOTE: The following impls conflict with the generic impls in std.
// impl fmt::Debug for Vec<Ascii> {
//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//         fmt::Show::fmt(&self[..], f)
//     }
// }

// impl fmt::Debug for [Ascii] {
//     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//         fmt::Show::fmt(self.as_str(), f)
//     }
// }

/// Trait for converting into an ascii type.
pub trait AsciiCast : AsciiExt {
    type Target;

    /// Convert to an ascii type, return Err(()) on non-ASCII input.
    #[inline]
    fn to_ascii(&self) -> Result<Self::Target, ()> {
        if self.is_ascii() {
            Ok(unsafe { self.to_ascii_nocheck() })
        } else {
            Err(())
        }
    }

    /// Convert to an ascii type, not doing any range asserts
    unsafe fn to_ascii_nocheck(&self) -> Self::Target;
}

impl<'a> AsciiCast for [u8] {
    type Target = &'a [Ascii];

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'a[Ascii] {
        mem::transmute(self)
    }
}

impl<'a> AsciiCast for str {
    type Target = &'a [Ascii];

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> &'a [Ascii] {
        mem::transmute(self)
    }
}

impl AsciiCast for u8 {
    type Target = Ascii;

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self }
    }
}

impl AsciiCast for char {
    type Target = Ascii;

    #[inline]
    unsafe fn to_ascii_nocheck(&self) -> Ascii {
        Ascii{ chr: *self as u8 }
    }
}

/// Trait for copyless casting to an ascii vector.
pub trait OwnedAsciiCast<T: ?Sized> : Sized + Borrow<T>
where T: AsciiExt<Owned=Self> {
    /// Take ownership and cast to an ascii vector. On non-ASCII input return ownership of data
    /// that was attempted to cast to ascii in `Err(Self)`.
    #[inline]
    fn into_ascii(self) -> Result<Vec<Ascii>, Self> {
        if self.borrow().is_ascii() {
            Ok(unsafe { self.into_ascii_nocheck() })
        } else {
            Err(self)
        }
    }

    /// Take ownership and cast to an ascii vector.
    /// Does not perform validation checks.
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii>;
}

impl OwnedAsciiCast<str> for String {
    #[inline]
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
        self.into_bytes().into_ascii_nocheck()
    }
}

impl OwnedAsciiCast<[u8]> for Vec<u8> {
    #[inline]
    unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
        let v = Vec::from_raw_parts(self.as_ptr() as *mut Ascii,
                                    self.len(),
                                    self.capacity());

        // We forget `self` to avoid freeing it at the end of the scope
        // Otherwise, the returned `Vec` would point to freed memory
        mem::forget(self);
        v
    }
}

/// Trait for converting a type to a string, consuming it in the process.
pub trait IntoString {
    /// Consume and convert to a string.
    fn into_string(self) -> String;
}

/// Trait for converting an ascii type to a string. Needed to convert
/// `&[Ascii]` to `&str`.
pub trait AsciiStr {
    /// Convert to a string.
    fn as_str<'a>(&'a self) -> &'a str;

    /// Convert to bytes.
    fn as_bytes<'a>(&'a self) -> &'a [u8];
}

impl AsciiStr for [Ascii] {
    #[inline]
    fn as_str<'a>(&'a self) -> &'a str {
        unsafe { mem::transmute(self) }
    }

    #[inline]
    fn as_bytes<'a>(&'a self) -> &'a [u8] {
        unsafe { mem::transmute(self) }
    }
}

impl IntoString for Vec<Ascii> {
    #[inline]
    fn into_string(self) -> String {
        unsafe { String::from_utf8_unchecked(self.into_bytes()) }
    }
}

/// Trait to convert to an owned byte vector by consuming self
pub trait IntoBytes {
    /// Converts to an owned byte vector by consuming self
    fn into_bytes(self) -> Vec<u8>;
}

impl IntoBytes for Vec<Ascii> {
    fn into_bytes(self) -> Vec<u8> {
        unsafe {
            let v = Vec::from_raw_parts(self.as_ptr() as *mut u8,
                                        self.len(),
                                        self.capacity());

            // We forget `self` to avoid freeing it at the end of the scope
            // Otherwise, the returned `Vec` would point to freed memory
            mem::forget(self);
            v
        }
    }
}

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

    macro_rules! v2ascii (
        ( [$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
        (&[$($e:expr),*]) => (&[$(Ascii{chr:$e}),*]);
    );

    macro_rules! vec2ascii (
        ($($e:expr),*) => ([$(Ascii{chr:$e}),*].to_vec());
    );

    #[test]
    fn test_ascii() {
        assert_eq!(65u8.to_ascii().unwrap().as_byte(), 65u8);
        assert_eq!(65u8.to_ascii().unwrap().as_char(), 'A');
        assert_eq!('A'.to_ascii().unwrap().as_char(), 'A');
        assert_eq!('A'.to_ascii().unwrap().as_byte(), 65u8);

        assert!('0'.to_ascii().unwrap().is_digit());
        assert!('9'.to_ascii().unwrap().is_digit());
        assert!(!'/'.to_ascii().unwrap().is_digit());
        assert!(!':'.to_ascii().unwrap().is_digit());

        assert!(0x1f_u8.to_ascii().unwrap().is_control());
        assert!(!' '.to_ascii().unwrap().is_control());
        assert!(0x7f_u8.to_ascii().unwrap().is_control());
    }

    #[test]
    fn test_ascii_vec() {
        let test = &[40u8, 32u8, 59u8];
        let b: &[_] = v2ascii!([40, 32, 59]);
        assert_eq!(test.to_ascii().unwrap(), b);
        assert_eq!("( ;".to_ascii().unwrap(), b);
        let v = vec![40u8, 32u8, 59u8];
        assert_eq!(v.to_ascii().unwrap(), b);
        assert_eq!("( ;".to_string().to_ascii().unwrap(), b);
    }

    #[test]
    fn test_ascii_as_str() {
        let v = v2ascii!([40, 32, 59]);
        assert_eq!(v.as_str(), "( ;");
    }

    #[test]
    fn test_ascii_as_bytes() {
        let v = v2ascii!([40, 32, 59]);
        assert_eq!(v.as_bytes(), b"( ;");
    }

    #[test]
    fn test_ascii_into_string() {
        assert_eq!(vec2ascii![40, 32, 59].into_string(), "( ;".to_string());
        assert_eq!(vec2ascii!(40, 32, 59).into_string(), "( ;".to_string());
    }

    #[test]
    fn test_ascii_to_bytes() {
        assert_eq!(vec2ascii![40, 32, 59].into_bytes(), vec![40u8, 32u8, 59u8]);
    }

    #[test]
    fn test_opt() {
        assert_eq!(65u8.to_ascii(), Ok(Ascii { chr: 65u8 }));
        assert_eq!(255u8.to_ascii(), Err(()));

        assert_eq!('A'.to_ascii(), Ok(Ascii { chr: 65u8 }));
        assert_eq!('λ'.to_ascii(), Err(()));

        assert_eq!("zoä华".to_ascii(), Err(()));

        let test1 = &[127u8, 128u8, 255u8];
        assert_eq!(test1.to_ascii(), Err(()));

        let v = [40u8, 32u8, 59u8];
        let v2: &[_] = v2ascii!(&[40, 32, 59]);
        assert_eq!(v.to_ascii(), Ok(v2));
        let v = [127u8, 128u8, 255u8];
        assert_eq!(v.to_ascii(), Err(()));

        let v = "( ;";
        assert_eq!(v.to_ascii(), Ok(v2));
        assert_eq!("zoä华".to_ascii(), Err(()));

        assert_eq!(vec![40u8, 32u8, 59u8].into_ascii(), Ok(vec2ascii![40, 32, 59]));
        assert_eq!(vec![127u8, 128u8, 255u8].into_ascii(), Err(vec![127u8, 128u8, 255u8]));

        assert_eq!("( ;".to_string().into_ascii(), Ok(vec2ascii![40, 32, 59]));
        assert_eq!("zoä华".to_string().into_ascii(), Err("zoä华".to_string()));
    }

    #[test]
    fn fmt_string_ascii() {
        let s = Ascii{ chr: b't' };
        assert_eq!(format!("{}", s), "t".to_string());
    }

    #[test]
    fn fmt_string_ascii_slice() {
        let s = "abc".to_ascii().unwrap();
        assert_eq!(format!("{}", s), "abc".to_string());
    }

    #[test]
    fn fmt_string_ascii_vec() {
        let s = "abc".to_string().into_ascii().unwrap();
        assert_eq!(format!("{}", s), "abc".to_string());
    }

    #[test]
    fn fmt_debug_ascii() {
        let c = Ascii { chr: b't' };
        assert_eq!(format!("{:?}", c), "'t'".to_string());
    }

    // NOTE: The following tests fail intentionally until custom `fmt::Show`
    //       implementations for `Vec<Ascii>` and `&[Ascii]` can be provided.
    //       (Or the current types are newtyped.)
    // #[test]
    // fn fmt_show_ascii_slice() {
    //     let s = "abc".to_ascii().unwrap();
    //     assert_eq!(format!("{}", s), "\"abc\"".to_string());
    // }

    // #[test]
    // fn fmt_show_ascii_vec() {
    //     let s = "abc".to_string().into_ascii().unwrap();
    //     assert_eq!(format!("{}", s), "\"abc\"".to_string());
    // }
}
<|endoftext|>


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

//! `Genmesh`'s is a library that offers ways to generate and manipulate vertex streams.
//!
//! The core problem that this library solves is to find a nice way to build meshes that
//! does not just result in throwing all the vertices and indices into a `Vec<T>` and
//! calling it done. While doing so is simple from a library writers point of view, the
//! consumer will often have to translate that buffer to the format that they need before
//! it can be used. This produces needless buffering that can be avoided.
//!
//! `Genmesh`'s solution is to utilize the `Iterator` trait to build a vertex processing
//! pipeline. The `Iterator` trait has a number of useful functions like `zip`, `map` and
//! `collect` that are useful in themselves. `Genmesh` includes a number of traits that
//! can be used with the built in `Iterator` traits to build the meshes that your engine
//! needs.

extern crate core;
extern crate debug;

pub use poly::{
    Quad,
    Triangle,
    Polygon,
    PolyTri,
    PolyQuad,
    Vertices,
    VerticesIterator,
    MapToVertices,
    MapVertex
};

pub use triangulate::{
    EmitTriangles,
    Triangulate,
    TriangulateIterator
};

pub use indexer::{
    Indexer,
    LruIndexer
};

mod triangulate;
mod poly;
mod indexer;
mod generator;

mod cube;
mod plane;
mod sphere;

/// a collection of utilties that can be used to build
/// meshes programmatically
pub mod generators {
    pub use generator::{
        SharedVertex,
        IndexedPolygon
    };
    pub use cube::Cube;
    pub use plane::Plane;
    pub use sphere::SphereUV;
}
<commit_msg>Removed debug crate<commit_after>//   Copyright Colin Sherratt 2014
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

//! `Genmesh`'s is a library that offers ways to generate and manipulate vertex streams.
//!
//! The core problem that this library solves is to find a nice way to build meshes that
//! does not just result in throwing all the vertices and indices into a `Vec<T>` and
//! calling it done. While doing so is simple from a library writers point of view, the
//! consumer will often have to translate that buffer to the format that they need before
//! it can be used. This produces needless buffering that can be avoided.
//!
//! `Genmesh`'s solution is to utilize the `Iterator` trait to build a vertex processing
//! pipeline. The `Iterator` trait has a number of useful functions like `zip`, `map` and
//! `collect` that are useful in themselves. `Genmesh` includes a number of traits that
//! can be used with the built in `Iterator` traits to build the meshes that your engine
//! needs.

extern crate core;

pub use poly::{
    Quad,
    Triangle,
    Polygon,
    PolyTri,
    PolyQuad,
    Vertices,
    VerticesIterator,
    MapToVertices,
    MapVertex
};

pub use triangulate::{
    EmitTriangles,
    Triangulate,
    TriangulateIterator
};

pub use indexer::{
    Indexer,
    LruIndexer
};

mod triangulate;
mod poly;
mod indexer;
mod generator;

mod cube;
mod plane;
mod sphere;

/// a collection of utilties that can be used to build
/// meshes programmatically
pub mod generators {
    pub use generator::{
        SharedVertex,
        IndexedPolygon
    };
    pub use cube::Cube;
    pub use plane::Plane;
    pub use sphere::SphereUV;
}
<|endoftext|>


<commit_before>pub mod ffi;
use std::ffi::{CStr, CString};
use std::fmt::Write;

#[repr(C)]
#[derive(Debug)]
pub struct Rect {
    x: f32,
    y: f32,
    w: f32,
    h: f32,
}

#[derive(Debug)]
pub struct Detection {
    rect: Rect,
    label: String,
    prob: f32
}

#[repr(C)]
#[derive(Debug)]
pub struct Detections {
    pub num: usize,
    pub detections: Vec<Detection>,
    pub proc_time_in_ms: f32,
}

impl Detection {
    pub fn csv(&self) -> String {
        format!("{}, {}, {}, {}, {}, {}",
                self.label, self.prob, self.rect.x, self.rect.y, self.rect.w, self.rect.h)
    }
}

impl Detections {
    pub fn csv(&self) -> String {
        let mut res = String::new();
        for i in 0..self.num {
            write!(&mut res, "{}, {}\n", self.proc_time_in_ms, self.detections[i].csv()).unwrap();
        }
        res
    }
}

#[repr(C)]
pub struct InputImage {
    inner: ffi::image,
}

impl InputImage {
    pub fn new(w: i32, h: i32, c: i32) -> InputImage {
        InputImage {
            inner: unsafe {
                make_image(w, h, c)
            }
        }
    }

    pub fn data_mut(&mut self) -> *mut f32 {
        self.inner.data
    }
}

pub struct Darknet {
    inner: *mut ffi::Darknet,
}

impl Darknet {
    pub fn new(data: &str, network: &str, weight: &str, label: &str) -> Self {
        let datacfg_cstring = CString::new(data).expect("cstring failed");
        let network_cstring = CString::new(network).expect("cstring failed");
        let weight_cstring = CString::new(weight).expect("cstring failed");
        let label_cstring = CString::new(label).expect("cstring failed");

        let config = ffi::DarknetConfig {
            datacfg: datacfg_cstring.as_ptr(),
            network_file: network_cstring.as_ptr(),
            weight_file: weight_cstring.as_ptr(),
            label_file: label_cstring.as_ptr(),
        };

        Darknet {
            inner: unsafe {
                darknet_new(config)
            },
        }
    }

    pub fn detect(&mut self, image: InputImage) -> Detections {
        let c_detections = unsafe { darknet_detect(self.inner, image.inner) };
        let num = c_detections.num;
        let mut detections = Vec::with_capacity(num as usize);
        for i in 0..(num as isize) {
            let label = unsafe {
                CStr::from_ptr(*c_detections.labels.offset(i)).to_string_lossy().into_owned()
            };
            let d = unsafe {
                Detection {
                    label: label,
                    prob:  *(c_detections.probs.offset(i)),
                    rect: Rect {
                        x: (*c_detections.rects.offset(i)).x,
                        y: (*c_detections.rects.offset(i)).y,
                        w: (*c_detections.rects.offset(i)).w,
                        h: (*c_detections.rects.offset(i)).h,
                    },
                }
            };
            detections.push(d);
        }
        unsafe { detections_drop(c_detections) }
        Detections {
            num: num as usize,
            detections: detections,
            proc_time_in_ms: c_detections.proc_time_in_ms,
        }
    }
}

impl Drop for Darknet {
    fn drop(&mut self) {
        unsafe {
            darknet_drop(self.inner);
        }
    }
}

extern "C" {
    fn darknet_new(config: ffi::DarknetConfig) -> *mut ffi::Darknet;
    fn darknet_drop(dn: *mut ffi::Darknet);
    fn darknet_detect(dn: *mut ffi::Darknet, image: ffi::image) -> ffi::Detections;
    fn detections_drop(dt: ffi::Detections);
    fn make_image(w: i32, h: i32, c: i32) -> ffi::image;
}
<commit_msg>feat: convert time to ms<commit_after>pub mod ffi;
use std::ffi::{CStr, CString};
use std::fmt::Write;

#[repr(C)]
#[derive(Debug)]
pub struct Rect {
    x: f32,
    y: f32,
    w: f32,
    h: f32,
}

#[derive(Debug)]
pub struct Detection {
    rect: Rect,
    label: String,
    prob: f32
}

#[repr(C)]
#[derive(Debug)]
pub struct Detections {
    pub num: usize,
    pub detections: Vec<Detection>,
    pub proc_time_in_ms: f32,
}

impl Detection {
    pub fn csv(&self) -> String {
        format!("{}, {}, {}, {}, {}, {}",
                self.label, self.prob, self.rect.x, self.rect.y, self.rect.w, self.rect.h)
    }
}

impl Detections {
    pub fn csv(&self) -> String {
        let mut res = String::new();
        for i in 0..self.num {
            write!(&mut res, "{}, {}\n", self.proc_time_in_ms, self.detections[i].csv()).unwrap();
        }
        res
    }
}

#[repr(C)]
pub struct InputImage {
    inner: ffi::image,
}

impl InputImage {
    pub fn new(w: i32, h: i32, c: i32) -> InputImage {
        InputImage {
            inner: unsafe {
                make_image(w, h, c)
            }
        }
    }

    pub fn data_mut(&mut self) -> *mut f32 {
        self.inner.data
    }
}

pub struct Darknet {
    inner: *mut ffi::Darknet,
}

impl Darknet {
    pub fn new(data: &str, network: &str, weight: &str, label: &str) -> Self {
        let datacfg_cstring = CString::new(data).expect("cstring failed");
        let network_cstring = CString::new(network).expect("cstring failed");
        let weight_cstring = CString::new(weight).expect("cstring failed");
        let label_cstring = CString::new(label).expect("cstring failed");

        let config = ffi::DarknetConfig {
            datacfg: datacfg_cstring.as_ptr(),
            network_file: network_cstring.as_ptr(),
            weight_file: weight_cstring.as_ptr(),
            label_file: label_cstring.as_ptr(),
        };

        Darknet {
            inner: unsafe {
                darknet_new(config)
            },
        }
    }

    pub fn detect(&mut self, image: InputImage) -> Detections {
        let c_detections = unsafe { darknet_detect(self.inner, image.inner) };
        let num = c_detections.num;
        let mut detections = Vec::with_capacity(num as usize);
        for i in 0..(num as isize) {
            let label = unsafe {
                CStr::from_ptr(*c_detections.labels.offset(i)).to_string_lossy().into_owned()
            };
            let d = unsafe {
                Detection {
                    label: label,
                    prob:  *(c_detections.probs.offset(i)),
                    rect: Rect {
                        x: (*c_detections.rects.offset(i)).x,
                        y: (*c_detections.rects.offset(i)).y,
                        w: (*c_detections.rects.offset(i)).w,
                        h: (*c_detections.rects.offset(i)).h,
                    },
                }
            };
            detections.push(d);
        }
        unsafe { detections_drop(c_detections) }
        Detections {
            num: num as usize,
            detections: detections,
            proc_time_in_ms: c_detections.proc_time_in_ms * 1000,
        }
    }
}

impl Drop for Darknet {
    fn drop(&mut self) {
        unsafe {
            darknet_drop(self.inner);
        }
    }
}

extern "C" {
    fn darknet_new(config: ffi::DarknetConfig) -> *mut ffi::Darknet;
    fn darknet_drop(dn: *mut ffi::Darknet);
    fn darknet_detect(dn: *mut ffi::Darknet, image: ffi::image) -> ffi::Detections;
    fn detections_drop(dt: ffi::Detections);
    fn make_image(w: i32, h: i32, c: i32) -> ffi::image;
}
<|endoftext|>


<commit_before>#![feature(
    i128_type,
    rustc_private,
)]

// From rustc.
#[macro_use]
extern crate log;
extern crate log_settings;
#[macro_use]
extern crate rustc;
extern crate rustc_borrowck;
extern crate rustc_const_math;
extern crate rustc_data_structures;
extern crate rustc_mir;
extern crate syntax;

// From crates.io.
extern crate byteorder;

mod cast;
mod error;
mod eval_context;
mod lvalue;
mod memory;
mod operator;
mod step;
mod terminator;
mod traits;
mod value;

pub use error::{
    EvalError,
    EvalResult,
};

pub use eval_context::{
    EvalContext,
    Frame,
    ResourceLimits,
    StackPopCleanup,
    eval_main,
};

pub use lvalue::{
    Lvalue,
    LvalueExtra,
};

pub use memory::{
    AllocId,
    Memory,
    Pointer,
};

pub use value::{
    PrimVal,
    PrimValKind,
    Value,
};
<commit_msg>Removed unused crate imports<commit_after>#![feature(
    i128_type,
    rustc_private,
)]

// From rustc.
#[macro_use]
extern crate log;
extern crate log_settings;
#[macro_use]
extern crate rustc;
extern crate rustc_const_math;
extern crate rustc_data_structures;
extern crate syntax;

// From crates.io.
extern crate byteorder;

mod cast;
mod error;
mod eval_context;
mod lvalue;
mod memory;
mod operator;
mod step;
mod terminator;
mod traits;
mod value;

pub use error::{
    EvalError,
    EvalResult,
};

pub use eval_context::{
    EvalContext,
    Frame,
    ResourceLimits,
    StackPopCleanup,
    eval_main,
};

pub use lvalue::{
    Lvalue,
    LvalueExtra,
};

pub use memory::{
    AllocId,
    Memory,
    Pointer,
};

pub use value::{
    PrimVal,
    PrimValKind,
    Value,
};
<|endoftext|>


<commit_before>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate "sha1-hasher" as sha1;
//! use std::io::Write;
//!
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.write("Hello World!".as_bytes());
//! assert_eq!(&*m.hexdigest(), "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(io)]

#![allow(unused_features)]
#![feature(test)]

#[cfg(test)] extern crate test;

use std::io::{Write, BufWriter};
use std::io::Result as IoResult;
use std::num::Int;
use std::num::wrapping::WrappingOps;
use std::default::Default;
use std::mem::transmute;

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&*format!("{:02x}", *b));
    }
    return s;
}

impl Default for Sha1 {
    #[inline]
    fn default() -> Sha1 {
        Sha1::new()
    }
}

impl Write for Sha1 {
    fn write(&mut self, bytes: &[u8]) -> IoResult<usize> {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(bytes);

        for chunk in d[..].chunks(64) {
            if chunk.len() == 64 {
                self.len += 64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }

        Ok(bytes.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        Ok(())
    }
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    pub fn finish(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut *buf);
        buf
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in (16..80) {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in (0..80) {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);

            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w = Vec::<u8>::with_capacity(137);
        w.push_all(&*self.data);
        w.push_all(&[0x80u8]);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in (0..padding) {
            w.push(0u8);
        }
        w.push_all(unsafe { &transmute::<_, [u8; 8]>(((self.data.len() as u64 + self.len) * 8).to_be()) });
        for chunk in w[..].chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_all(unsafe { &transmute::<_, [u8; 4]>(n.to_be()) });
        }
    }

    pub fn hexdigest(&self) -> String {
        to_hex(&*self.finish())
    }
}

#[cfg(test)]
mod tests {
    use std::io::Write;
    use test::Bencher;
    use super::{Sha1, to_hex};

    #[test]
    fn test_simple() {
        let mut m = Sha1::new();

        let tests = [
            ("The quick brown fox jumps over the lazy dog",
            "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
            ("The quick brown fox jumps over the lazy cog",
            "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
            ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
            ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
            ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
        ];

        for &(s, ref h) in tests.iter() {
            let data = s.as_bytes();

            m.reset();
            m.write(data).unwrap();
            let hh = m.hexdigest();

            assert_eq!(hh.len(), h.len());
            assert_eq!(&*hh, *h);
        }
    }

    #[test]
    fn test_dirty_run() {
        let mut m = Sha1::new();

        m.write(b"123").unwrap();
        let out1 = m.finish();

        m.write_all(b"123").unwrap();
        let out2 = m.finish();

        assert!(out1 != out2);
        assert_eq!(&*to_hex(&*out1), "40bd001563085fc35165329ea1ff5c5ecbdbbeef");
        assert_eq!(&*to_hex(&*out2), "601f1889667efaebb33b8c12572835da3f027f78");
    }

    #[bench]
    fn test_sha1_speed(b: &mut Bencher) {
        let mut m = Sha1::new();
        let s = "The quick brown fox jumps over the lazy dog.";
        let n = 1000u64;

        b.bytes = n * s.len() as u64;
        b.iter(|| {
            m.reset();
            for _ in (0..n) {
                m.write_all(s.as_bytes()).unwrap();
            }
            assert_eq!(m.hexdigest(), "7ca27655f67fceaa78ed2e645a81c7f1d6e249d2");
        });
    }
}
<commit_msg>update to latest rust<commit_after>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate sha1_hasher as sha1;
//! use std::io::Write;
//!
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.write("Hello World!".as_bytes());
//! assert_eq!(&*m.hexdigest(), "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(io)]

#![allow(unused_features)]
#![feature(test)]

#[cfg(test)] extern crate test;

use std::io::{Write, BufWriter};
use std::io::Result as IoResult;
use std::default::Default;
use std::mem::transmute;

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&*format!("{:02x}", *b));
    }
    return s;
}

impl Default for Sha1 {
    #[inline]
    fn default() -> Sha1 {
        Sha1::new()
    }
}

impl Write for Sha1 {
    fn write(&mut self, bytes: &[u8]) -> IoResult<usize> {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(bytes);

        for chunk in d[..].chunks(64) {
            if chunk.len() == 64 {
                self.len += 64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }

        Ok(bytes.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        Ok(())
    }
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    pub fn finish(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut *buf);
        buf
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in (16..80) {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in (0..80) {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);

            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w = Vec::<u8>::with_capacity(137);
        w.push_all(&*self.data);
        w.push_all(&[0x80u8]);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in (0..padding) {
            w.push(0u8);
        }
        w.push_all(unsafe { &transmute::<_, [u8; 8]>(((self.data.len() as u64 + self.len) * 8).to_be()) });
        for chunk in w[..].chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_all(unsafe { &transmute::<_, [u8; 4]>(n.to_be()) });
        }
    }

    pub fn hexdigest(&self) -> String {
        to_hex(&*self.finish())
    }
}

#[cfg(test)]
mod tests {
    use std::io::Write;
    use test::Bencher;
    use super::{Sha1, to_hex};

    #[test]
    fn test_simple() {
        let mut m = Sha1::new();

        let tests = [
            ("The quick brown fox jumps over the lazy dog",
            "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
            ("The quick brown fox jumps over the lazy cog",
            "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
            ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
            ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
            ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
        ];

        for &(s, ref h) in tests.iter() {
            let data = s.as_bytes();

            m.reset();
            m.write(data).unwrap();
            let hh = m.hexdigest();

            assert_eq!(hh.len(), h.len());
            assert_eq!(&*hh, *h);
        }
    }

    #[test]
    fn test_dirty_run() {
        let mut m = Sha1::new();

        m.write(b"123").unwrap();
        let out1 = m.finish();

        m.write_all(b"123").unwrap();
        let out2 = m.finish();

        assert!(out1 != out2);
        assert_eq!(&*to_hex(&*out1), "40bd001563085fc35165329ea1ff5c5ecbdbbeef");
        assert_eq!(&*to_hex(&*out2), "601f1889667efaebb33b8c12572835da3f027f78");
    }

    #[bench]
    fn test_sha1_speed(b: &mut Bencher) {
        let mut m = Sha1::new();
        let s = "The quick brown fox jumps over the lazy dog.";
        let n = 1000u64;

        b.bytes = n * s.len() as u64;
        b.iter(|| {
            m.reset();
            for _ in (0..n) {
                m.write_all(s.as_bytes()).unwrap();
            }
            assert_eq!(m.hexdigest(), "7ca27655f67fceaa78ed2e645a81c7f1d6e249d2");
        });
    }
}
<|endoftext|>


<commit_before>pub enum Fx {
    Fizz,
    Buzz,
    FizzBuzz,
    I(u32),
}

impl Fx {
    pub fn new(n: u32) -> Fx {
        Fx::arbitrary(n, |n| n % 3 == 0, |n| n % 5 == 0)
    }

    pub fn arbitrary<FA, FB>(n: u32, fa: FA, fb: FB) -> Fx
        where FA: Fn(u32) -> bool,
              FB: Fn(u32) -> bool
    {
        match (n, fa(n), fb(n)) {
            (_, true, true) => Fx::FizzBuzz,
            (_, true, _) => Fx::Fizz,
            (_, _, true) => Fx::Buzz,
            (n, _, _) => Fx::I(n),
        }
    }
}

impl std::fmt::Display for Fx {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            &Fx::FizzBuzz => write!(f, "FizzBuzz"),
            &Fx::Fizz => write!(f, "Fizz"),
            &Fx::Buzz => write!(f, "Buzz"),
            &Fx::I(n) => write!(f, "{}", n),
        }
    }
}

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

    #[test]
    fn integers_work() {
        assert!(format!("{}", Fx::new(2)) == "2");
    }

    #[test]
    fn fizz_works() {
        assert!(format!("{}", Fx::new(3)) == "Fizz");
    }

    #[test]
    fn buzz_works() {
        assert!(format!("{}", Fx::new(5)) == "Buzz");
    }

    #[test]
    fn fizz_buzz_works() {
        assert!(format!("{}", Fx::new(15)) == "FizzBuzz");
    }
}
<commit_msg>add example<commit_after>//! FizzBuzz helper library for Rust and Cargo
//!
//! Instructions: Add to your cargo tomato and go!
//!
//! ## Example
//!
//! ```
//! use fx::Fx;
//!
//! let sum_of_non_fizz_buzz_values = (0..101)
//!     .fold(0, |a,b| a + if let I(n) = b {
//!         n
//!     } else {
//!         0
//!     });
//!
//! assert!(sum_of_non_fizz_buzz_values == 2632);
//! ```

/// Enum representing value status.
pub enum Fx {
    Fizz,
    Buzz,
    FizzBuzz,
    I(u32),
}

impl Fx {
    /// Create new Fx enum using standard FizzBuzz rules.
    pub fn new(n: u32) -> Fx {
        Fx::arbitrary(n, |n| n % 3 == 0, |n| n % 5 == 0)
    }

    /// Create new Fx enum using arbitrary FizzBuzz rules.
    pub fn arbitrary<FA, FB>(n: u32, fa: FA, fb: FB) -> Fx
        where FA: Fn(u32) -> bool,
              FB: Fn(u32) -> bool
    {
        match (n, fa(n), fb(n)) {
            (_, true, true) => Fx::FizzBuzz,
            (_, true, _) => Fx::Fizz,
            (_, _, true) => Fx::Buzz,
            (n, _, _) => Fx::I(n),
        }
    }
}

/// Print Fx value to console; no need to futz with formatting.
/// on the client side.
impl std::fmt::Display for Fx {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            &Fx::FizzBuzz => write!(f, "FizzBuzz"),
            &Fx::Fizz => write!(f, "Fizz"),
            &Fx::Buzz => write!(f, "Buzz"),
            &Fx::I(n) => write!(f, "{}", n),
        }
    }
}

/// Convenience method for creating a new default Fx enum.
pub fn default(n: u32) -> Fx {
    Fx::new(u32)
}

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

    #[test]
    fn integers_work() {
        assert!(format!("{}", Fx::new(2)) == "2");
    }

    #[test]
    fn fizz_works() {
        assert!(format!("{}", Fx::new(3)) == "Fizz");
    }

    #[test]
    fn buzz_works() {
        assert!(format!("{}", Fx::new(5)) == "Buzz");
    }

    #[test]
    fn fizz_buzz_works() {
        assert!(format!("{}", Fx::new(15)) == "FizzBuzz");
    }
}
<|endoftext|>