<commit_before>extern crate libc;
extern crate notify;
extern crate libloading;
extern crate tempdir;

use libloading::Library;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver, Sender};
use notify::{RecommendedWatcher, Watcher, Event};
use tempdir::TempDir;
use std::time::Duration;
use std::thread;
use std::fs;
use std::env;
use std::fmt::Write;

/// Formats dll name on Windows ("test_foo" -> "test_foo.dll")
#[cfg(target_os="windows")]
fn get_dynamiclib_name(name: &str) -> String {
    format!("{}.dll", name)
}

/// Formats dll name on Mac ("test_foo" -> "libtest_foo.dylib")
#[cfg(target_os="macos")]
fn get_dynamiclib_name(name: &str) -> String {
    format!("lib{}.dylib", name)
}

/// Formats dll name on *nix ("test_foo" -> "libtest_foo.so")
#[cfg(any(target_os="linux",
          target_os="freebsd",
          target_os="dragonfly",
          target_os="netbsd",
          target_os="openbsd"))]
fn get_dynamiclib_name(name: &str) -> String {
    format!("lib{}.so", name)
}

pub struct Lib {
    pub lib: Library,
    pub loaded_path: PathBuf,
    pub original_path: Option<PathBuf>,
}

pub struct DynamicReload {
    libs: Vec<Lib>,
    watcher: Option<RecommendedWatcher>,
    shadow_dir: Option<TempDir>,
    search_paths: Vec<&'static str>,
    watch_recv: Receiver<Event>,
}

pub enum Search {
    Default,
    Backwards,
}

#[derive(PartialEq)]
pub enum UsePlatformName {
    No,
    Yes
}

impl DynamicReload {

    ///
    ///
    pub fn new(search_paths: Option<Vec<&'static str>>, shadow_dir: Option<&'static str>, search: Search) -> DynamicReload {
        let (tx, rx) = channel();
        DynamicReload {
            libs: Vec::new(),
            shadow_dir: Self::get_temp_dir(shadow_dir),
            watch_recv: rx,
            watcher: Self::get_watcher(tx),
            search_paths: Self::get_search_paths(search_paths),
        }
    }

    ///
    /// Add a library to be loaded and to be reloaded once updated.
    /// If UsePlatformName is set to Yes the input name will be formatted according
    /// to the standard way libraries looks on that platform examples:
    ///
    /// ```ignore
    /// Windows: foobar -> foobar.dll
    /// Linux:   foobar -> libfoobar.so
    /// Mac:     foobar -> libfoobar.dylib
    /// ````
    ///
    /// If set to no the given inputname will be used as is. This function
    /// will also search for the file in this priority order
    ///
    ///
    /// ```ignore
    /// 1. Current directory
    /// 2. In the search paths (relative to currect directory)
    /// 3. Currect directory of the executable
    /// 4. Serach backwards from executable if Backwards has been set in [new](struct.DynamicReload.html#method.new)
    /// ```
    ///
    pub fn add_library(&mut self, name: &str, name_format: UsePlatformName) -> Result<Rc<Lib>, String> {
        if let Some(path) = Self::search_dirs(self, name, name_format) {
            Self::load_library(self, &path)
        } else {
            let mut t = "Unable to find ".to_string();
            t.push_str(name);
            Err(t)
        }
    }

    ///
    /// Update the will check if a dynamic library needs to be reloaded and if that is the case
    /// then the supplied callback functions will be called
    ///
    /// First the before_reload code. This allows the calling application to performe actions
    /// before the dynamic library is unloaded. This can for example be to save some internal
    /// state that needs to be restorted when relodaded
    ///
    /// After the reloading is comple the post_reload function will be called giving the host
    /// application the possibility to restore any potentially saved state
    ///
    /// If no callbacks are needed use the regular [update](struct.DynamicReload.html#method.update) call instead
    ///
    pub fn update_with_callback<F, T>(&self, before_update: F, after_update: F, data: T) where F : Fn(T, Rc<Lib>) {

    }

    ///
    /// Updates the DynamicReload handler and reloads the dynamic libraries if needed
    ///
    ///
    pub fn update(&self) {
        /*
           match self.watch_recv.try_recv() {
           Ok(file) => {
           plugin_handler.reload_plugin(file.path.as_ref().unwrap());
           }
           _ => (),
           }
           */
    }

    fn load_library(&mut self, full_path: &PathBuf) -> Result<Rc<Lib>, String> {
        let path;
        let original_path;

        if let Some(sd) = self.shadow_dir.as_ref() {
            path = sd.path().join(full_path.file_name().unwrap());
            if !Self::try_copy(&full_path, &path) {
                let mut error = "".to_string();
                write!(error, "Unable to copy {:?} to {:?}", full_path, path).unwrap();
                return Err(error);
            }
            original_path = Some(full_path.clone());
        } else {
            original_path = None;
            path = full_path.clone();
        }

        Self::init_library(original_path, path)
    }

    fn init_library(org_path: Option<PathBuf>, path: PathBuf) -> Result<Rc<Lib>, String> {
        match Library::new(&path) {
            Ok(l) => Ok(Rc::new(Lib {
                original_path: org_path,
                loaded_path: path,
                lib: l
            })),
            Err(e) => {
                let mut error = "".to_string();
                write!(error, "Unable to load library {:?}", e);
                Err(error)
            }
        }
    }

    fn search_dirs(&self, name: &str, name_format: UsePlatformName) -> Option<PathBuf> {
        let lib_name = Self::get_library_name(name, name_format);

        // 1. Serach the current directory
        if let Some(path) = Self::search_current_dir(&lib_name) {
            return Some(path);
        }

        // 2. search the relative paths
        if let Some(path) = Self::search_relative_paths(self, &lib_name) {
            return Some(path);
        }

        // 3. searches in the executable dir and then backwards
        Self::search_backwards_from_exe(&lib_name)
    }

    fn search_current_dir(name: &String) -> Option<PathBuf> {
        Self::is_file(&Path::new(name).to_path_buf())
    }

    fn search_relative_paths(&self, name: &String) -> Option<PathBuf> {
        for p in self.search_paths.iter() {
            let path = Path::new(p).join(name);
            if let Some(file) = Self::is_file(&path) {
                return Some(file);
            }
        }

        None
    }

    fn get_parent_dir(path: &PathBuf) -> Option<PathBuf> {
        match path.parent() {
            Some(p) => Some(p.to_path_buf()),
            _ => None,
        }
    }

    fn search_backwards_from_file(path: &PathBuf, lib_name: &String) -> Option<PathBuf> {
        match Self::get_parent_dir(path) {
            Some(p) => {
                let new_path = Path::new(&p).join(lib_name);
                if let Some(f) = Self::is_file(&new_path) {
                    return Some(new_path);
                }
                Self::search_backwards_from_file(&p, lib_name)
            },
            _ => None,
        }
    }

    fn search_backwards_from_exe(lib_name: &String) -> Option<PathBuf> {
        let exe_path = env::current_exe().unwrap_or(PathBuf::new());
        Self::search_backwards_from_file(&exe_path, lib_name)
    }

    fn get_temp_dir(shadow_dir: Option<&str>) -> Option<TempDir> {
        match shadow_dir {
            Some(dir) => {
                match TempDir::new_in(dir, "shadow_libs") {
                    Ok(td) => Some(td),
                    Err(er) => {
                        println!("Unable to create tempdir {}", er);
                        None
                    }
                }
            }
            _ => None,
        }
    }

    fn is_file(path: &PathBuf) -> Option<PathBuf> {
        match fs::metadata(path) {
            Ok(md) => Some(path.clone()),
            _ => None,
        }
    }

    //
    // In some cases when a file has been set that it's reloaded it's actually not possible
    // to read from it directly so this code does some testing first to ensure we
    // can actually read from it (by using metadata which does a stat on the file)
    // If we can't read from it we wait for 100 ms before we try again, if we can't
    // do it with in 1 sec we give up
    //
    fn try_copy(src: &Path, dest: &Path) -> bool {
        for _ in 0..10 {
            match fs::metadata(src) {
                Ok(file) => {
                    let len = file.len();
                    if len > 0 {
                        fs::copy(&src, &dest).unwrap();
                        //println!("Copy from {} {}", src.to_str().unwrap(), dest.to_str().unwrap());
                        return true;
                    }
                }
                _ => (),
            }

            thread::sleep(Duration::from_millis(100));
        }

        false
    }

    fn get_watcher(tx: Sender<Event>) -> Option<RecommendedWatcher> {
        match Watcher::new(tx) {
            Ok(watcher) => Some(watcher),
            Err(e) => {
                println!("Unable to create file watcher, no dynamic reloading will be done, error: {:?}", e);
                None
            }
        }
    }

    pub fn get_search_paths(search_paths: Option<Vec<&'static str>>) -> Vec<&'static str> {
        match search_paths {
            Some(paths) => {
                paths.clone()
            },
            None => Vec::new(),
        }
    }

    fn get_library_name(name: &str, name_format: UsePlatformName) -> String {
        if name_format == UsePlatformName::Yes  {
            get_dynamiclib_name(name)
        } else {
            name.to_string()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::{channel, Receiver, Sender};
    use std::path::{Path, PathBuf};
    use std::env;

    #[test]
    fn test_search_paths_none() {
        assert_eq!(DynamicReload::get_search_paths(None).len(), 0);
    }

    #[test]
    fn test_search_paths_some() {
        assert_eq!(DynamicReload::get_search_paths(Some(vec!["test", "test"])).len(), 2);
    }

    #[test]
    fn test_get_watcher() {
        let (tx, _) = channel();
        // We expect this to always work
        assert!(DynamicReload::get_watcher(tx).is_some());
    }

    #[test]
    fn test_get_temp_dir_fail() {
        assert!(DynamicReload::get_temp_dir(Some("_no_such_dir")).is_none());
    }

    #[test]
    fn test_get_temp_dir_none() {
        assert!(DynamicReload::get_temp_dir(None).is_none());
    }

    #[test]
    fn test_get_temp_dir_ok() {
        assert!(DynamicReload::get_temp_dir(Some("")).is_some());
    }

    #[test]
    fn test_is_file_fail() {
        assert!(DynamicReload::is_file(&Path::new("haz_no_file_with_this_name").to_path_buf()).is_none());
    }

    #[test]
    fn test_is_file_ok() {
        assert!(DynamicReload::is_file(&env::current_exe().unwrap()).is_some());
    }

    #[test]
    #[cfg(target_os="macos")]
    fn test_get_library_name_mac() {
        assert_eq!(DynamicReload::get_library_name("foobar", UsePlatformName::Yes), "libfoobar.dylib");
    }

    #[test]
    fn test_get_library_name() {
        assert_eq!(DynamicReload::get_library_name("foobar", UsePlatformName::No), "foobar");
    }

    #[test]
    fn test_search_backwards_from_file_ok() {
        // While this rely on that we have a Cargo project it should be fine
        assert!(DynamicReload::search_backwards_from_exe(&"Cargo.toml".to_string()).is_some());
    }

    #[test]
    fn test_search_backwards_from_file_fail() {
        assert!(DynamicReload::search_backwards_from_exe(&"_no_such_file".to_string()).is_none());
    }
}
<commit_msg>Iixed warnings<commit_after>extern crate libc;
extern crate notify;
extern crate libloading;
extern crate tempdir;

use libloading::Library;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver, Sender};
use notify::{RecommendedWatcher, Watcher, Event};
use tempdir::TempDir;
use std::time::Duration;
use std::thread;
use std::fs;
use std::env;
use std::fmt::Write;

/// Formats dll name on Windows ("test_foo" -> "test_foo.dll")
#[cfg(target_os="windows")]
fn get_dynamiclib_name(name: &str) -> String {
    format!("{}.dll", name)
}

/// Formats dll name on Mac ("test_foo" -> "libtest_foo.dylib")
#[cfg(target_os="macos")]
fn get_dynamiclib_name(name: &str) -> String {
    format!("lib{}.dylib", name)
}

/// Formats dll name on *nix ("test_foo" -> "libtest_foo.so")
#[cfg(any(target_os="linux",
          target_os="freebsd",
          target_os="dragonfly",
          target_os="netbsd",
          target_os="openbsd"))]
fn get_dynamiclib_name(name: &str) -> String {
    format!("lib{}.so", name)
}

pub struct Lib {
    pub lib: Library,
    pub loaded_path: PathBuf,
    pub original_path: Option<PathBuf>,
}

pub struct DynamicReload {
    _libs: Vec<Lib>,
    _watcher: Option<RecommendedWatcher>,
    shadow_dir: Option<TempDir>,
    search_paths: Vec<&'static str>,
    _watch_recv: Receiver<Event>,
}

pub enum Search {
    Default,
    Backwards,
}

#[derive(PartialEq)]
pub enum UsePlatformName {
    No,
    Yes
}

// Test

impl DynamicReload {

    ///
    ///
    pub fn new(search_paths: Option<Vec<&'static str>>, shadow_dir: Option<&'static str>, _search: Search) -> DynamicReload {
        let (tx, rx) = channel();
        DynamicReload {
            _libs: Vec::new(),
            _watcher: Self::get_watcher(tx),
            shadow_dir: Self::get_temp_dir(shadow_dir),
            _watch_recv: rx,
            search_paths: Self::get_search_paths(search_paths),
        }
    }

    ///
    /// Add a library to be loaded and to be reloaded once updated.
    /// If UsePlatformName is set to Yes the input name will be formatted according
    /// to the standard way libraries looks on that platform examples:
    ///
    /// ```ignore
    /// Windows: foobar -> foobar.dll
    /// Linux:   foobar -> libfoobar.so
    /// Mac:     foobar -> libfoobar.dylib
    /// ````
    ///
    /// If set to no the given inputname will be used as is. This function
    /// will also search for the file in this priority order
    ///
    ///
    /// ```ignore
    /// 1. Current directory
    /// 2. In the search paths (relative to currect directory)
    /// 3. Currect directory of the executable
    /// 4. Serach backwards from executable if Backwards has been set in [new](struct.DynamicReload.html#method.new)
    /// ```
    ///
    pub fn add_library(&mut self, name: &str, name_format: UsePlatformName) -> Result<Rc<Lib>, String> {
        if let Some(path) = Self::search_dirs(self, name, name_format) {
            Self::load_library(self, &path)
        } else {
            let mut t = "Unable to find ".to_string();
            t.push_str(name);
            Err(t)
        }
    }

    ///
    /// Update the will check if a dynamic library needs to be reloaded and if that is the case
    /// then the supplied callback functions will be called
    ///
    /// First the before_reload code. This allows the calling application to performe actions
    /// before the dynamic library is unloaded. This can for example be to save some internal
    /// state that needs to be restorted when relodaded
    ///
    /// After the reloading is comple the post_reload function will be called giving the host
    /// application the possibility to restore any potentially saved state
    ///
    /// If no callbacks are needed use the regular [update](struct.DynamicReload.html#method.update) call instead
    ///
    pub fn update_with_callback<F, T>(&self, _before_update: F, _after_update: F, _data: T) where F : Fn(T, Rc<Lib>) {

    }

    ///
    /// Updates the DynamicReload handler and reloads the dynamic libraries if needed
    ///
    ///
    pub fn update(&self) {
        /*
           match self.watch_recv.try_recv() {
           Ok(file) => {
           plugin_handler.reload_plugin(file.path.as_ref().unwrap());
           }
           _ => (),
           }
           */
    }

    fn load_library(&mut self, full_path: &PathBuf) -> Result<Rc<Lib>, String> {
        let path;
        let original_path;

        if let Some(sd) = self.shadow_dir.as_ref() {
            path = sd.path().join(full_path.file_name().unwrap());
            if !Self::try_copy(&full_path, &path) {
                let mut error = "".to_string();
                write!(error, "Unable to copy {:?} to {:?}", full_path, path).unwrap();
                return Err(error);
            }
            original_path = Some(full_path.clone());
        } else {
            original_path = None;
            path = full_path.clone();
        }

        Self::init_library(original_path, path)
    }

    fn init_library(org_path: Option<PathBuf>, path: PathBuf) -> Result<Rc<Lib>, String> {
        match Library::new(&path) {
            Ok(l) => Ok(Rc::new(Lib {
                original_path: org_path,
                loaded_path: path,
                lib: l
            })),
            Err(e) => {
                let mut error = "".to_string();
                write!(error, "Unable to load library {:?}", e).unwrap();
                Err(error)
            }
        }
    }

    fn search_dirs(&self, name: &str, name_format: UsePlatformName) -> Option<PathBuf> {
        let lib_name = Self::get_library_name(name, name_format);

        // 1. Serach the current directory
        if let Some(path) = Self::search_current_dir(&lib_name) {
            return Some(path);
        }

        // 2. search the relative paths
        if let Some(path) = Self::search_relative_paths(self, &lib_name) {
            return Some(path);
        }

        // 3. searches in the executable dir and then backwards
        Self::search_backwards_from_exe(&lib_name)
    }

    fn search_current_dir(name: &String) -> Option<PathBuf> {
        Self::is_file(&Path::new(name).to_path_buf())
    }

    fn search_relative_paths(&self, name: &String) -> Option<PathBuf> {
        for p in self.search_paths.iter() {
            let path = Path::new(p).join(name);
            if let Some(file) = Self::is_file(&path) {
                return Some(file);
            }
        }

        None
    }

    fn get_parent_dir(path: &PathBuf) -> Option<PathBuf> {
        match path.parent() {
            Some(p) => Some(p.to_path_buf()),
            _ => None,
        }
    }

    fn search_backwards_from_file(path: &PathBuf, lib_name: &String) -> Option<PathBuf> {
        match Self::get_parent_dir(path) {
            Some(p) => {
                let new_path = Path::new(&p).join(lib_name);
                if Self::is_file(&new_path).is_some() {
                    return Some(new_path);
                }
                Self::search_backwards_from_file(&p, lib_name)
            },
            _ => None,
        }
    }

    fn search_backwards_from_exe(lib_name: &String) -> Option<PathBuf> {
        let exe_path = env::current_exe().unwrap_or(PathBuf::new());
        Self::search_backwards_from_file(&exe_path, lib_name)
    }

    fn get_temp_dir(shadow_dir: Option<&str>) -> Option<TempDir> {
        match shadow_dir {
            Some(dir) => {
                match TempDir::new_in(dir, "shadow_libs") {
                    Ok(td) => Some(td),
                    Err(er) => {
                        println!("Unable to create tempdir {}", er);
                        None
                    }
                }
            }
            _ => None,
        }
    }

    fn is_file(path: &PathBuf) -> Option<PathBuf> {
        match fs::metadata(path) {
            Ok(md) => {
                if md.is_file() {
                    Some(path.clone())
                } else {
                    None
                }
            }
            _ => None,
        }
    }

    //
    // In some cases when a file has been set that it's reloaded it's actually not possible
    // to read from it directly so this code does some testing first to ensure we
    // can actually read from it (by using metadata which does a stat on the file)
    // If we can't read from it we wait for 100 ms before we try again, if we can't
    // do it with in 1 sec we give up
    //
    fn try_copy(src: &Path, dest: &Path) -> bool {
        for _ in 0..10 {
            match fs::metadata(src) {
                Ok(file) => {
                    let len = file.len();
                    if len > 0 {
                        fs::copy(&src, &dest).unwrap();
                        //println!("Copy from {} {}", src.to_str().unwrap(), dest.to_str().unwrap());
                        return true;
                    }
                }
                _ => (),
            }

            thread::sleep(Duration::from_millis(100));
        }

        false
    }

    fn get_watcher(tx: Sender<Event>) -> Option<RecommendedWatcher> {
        match Watcher::new(tx) {
            Ok(watcher) => Some(watcher),
            Err(e) => {
                println!("Unable to create file watcher, no dynamic reloading will be done, error: {:?}", e);
                None
            }
        }
    }

    pub fn get_search_paths(search_paths: Option<Vec<&'static str>>) -> Vec<&'static str> {
        match search_paths {
            Some(paths) => {
                paths.clone()
            },
            None => Vec::new(),
        }
    }

    fn get_library_name(name: &str, name_format: UsePlatformName) -> String {
        if name_format == UsePlatformName::Yes  {
            get_dynamiclib_name(name)
        } else {
            name.to_string()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::channel;
    use std::path::Path;
    use std::env;

    #[test]
    fn test_search_paths_none() {
        assert_eq!(DynamicReload::get_search_paths(None).len(), 0);
    }

    #[test]
    fn test_search_paths_some() {
        assert_eq!(DynamicReload::get_search_paths(Some(vec!["test", "test"])).len(), 2);
    }

    #[test]
    fn test_get_watcher() {
        let (tx, _) = channel();
        // We expect this to always work
        assert!(DynamicReload::get_watcher(tx).is_some());
    }

    #[test]
    fn test_get_temp_dir_fail() {
        assert!(DynamicReload::get_temp_dir(Some("_no_such_dir")).is_none());
    }

    #[test]
    fn test_get_temp_dir_none() {
        assert!(DynamicReload::get_temp_dir(None).is_none());
    }

    #[test]
    fn test_get_temp_dir_ok() {
        assert!(DynamicReload::get_temp_dir(Some("")).is_some());
    }

    #[test]
    fn test_is_file_fail() {
        assert!(DynamicReload::is_file(&Path::new("haz_no_file_with_this_name").to_path_buf()).is_none());
    }

    #[test]
    fn test_is_file_ok() {
        assert!(DynamicReload::is_file(&env::current_exe().unwrap()).is_some());
    }

    #[test]
    #[cfg(target_os="macos")]
    fn test_get_library_name_mac() {
        assert_eq!(DynamicReload::get_library_name("foobar", UsePlatformName::Yes), "libfoobar.dylib");
    }

    #[test]
    fn test_get_library_name() {
        assert_eq!(DynamicReload::get_library_name("foobar", UsePlatformName::No), "foobar");
    }

    #[test]
    fn test_search_backwards_from_file_ok() {
        // While this rely on that we have a Cargo project it should be fine
        assert!(DynamicReload::search_backwards_from_exe(&"Cargo.toml".to_string()).is_some());
    }

    #[test]
    fn test_search_backwards_from_file_fail() {
        assert!(DynamicReload::search_backwards_from_exe(&"_no_such_file".to_string()).is_none());
    }
}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![crate_name = "fsnotify"]

// Required by operations.rs
#![feature(hash)]
#[macro_use] extern crate bitflags;

mod fsnotify;
pub use self::fsnotify::*;<commit_msg>unsafe_destructor (Drop needs this...)<commit_after>#![crate_type = "lib"]
#![crate_name = "fsnotify"]

// https://github.com/rust-lang/rust/issues/17858
#![feature(unsafe_destructor)]

// Required by operations.rs
#![feature(hash)]
#[macro_use] extern crate bitflags;

mod fsnotify;
pub use self::fsnotify::*;

#[cfg(target_os="linux")]
pub mod linux;

#[cfg(target_os="osx")]
pub mod osx;

#[cfg(target_os="windows")]
pub mod win;<|endoftext|>


<commit_before>extern crate file;
extern crate rpassword;
extern crate rprompt;
#[macro_use] extern crate serde_derive;
extern crate serde_json;
extern crate xdg;

use std::path::PathBuf;
use xdg::BaseDirectories;

#[derive(Debug,PartialEq,Deserialize,Serialize)]
#[serde(tag = "type")]
pub enum Entity {
    Credentials(Credentials),
}

#[derive(Debug,PartialEq,Deserialize,Serialize)]
pub struct Credentials {
    pub url:         String,
    pub login:       String,
    pub password:    String,
    pub totp_secret: Option<String>
}

#[derive(Debug)]
pub struct MnemesisUtils {
    base_dirs: BaseDirectories,
}

impl MnemesisUtils {
    pub fn new() -> MnemesisUtils {
        MnemesisUtils {
            base_dirs: BaseDirectories::with_prefix("mnemesis").expect("Failed getting base directories"),
        }
    }

    pub fn prompt_for_input(msg: &str) -> String {
        rprompt::prompt_reply_stdout(msg).expect("Failed reading from stdin")
    }

    pub fn prompt_for_password(msg: &str) -> String {
        rpassword::prompt_password_stdout(msg).expect("Failed reading password")
    }

    fn credentials_directory(&self, path: &str) -> PathBuf {
        self.base_dirs.place_data_file(path).expect("Failed computing credentials directory")
    }

    pub fn read_entities(&self, path: &str) -> Vec<Entity> {
        let full_path = self.credentials_directory(path);

        if full_path.exists() {
            if full_path.is_file() {
                let data = file::get_text(full_path.to_str().expect(&format!("{:?} is not valid UTF-8", full_path))).expect(&format!("Failed to read {:?}", full_path));
                serde_json::from_str::<Vec<Entity>>(&data).expect(&format!("Found garbage in {:?}", full_path))
            } else {
                panic!("{:?} exists and is not a file", full_path);
            }
        } else {
            Vec::new()
        }
    }

    pub fn write_entities(&self, path: &str, entities: Vec<Entity>) {
        let full_path = self.credentials_directory(path);

        file::put_text(full_path.to_str().expect(&format!("{:?} is not valid UTF-8", full_path)), serde_json::to_string(&entities).expect("Failed to serialize entities")).expect(&format!("Failed to write {:?}", full_path));
    }
}
<commit_msg>hook up initial config support<commit_after>extern crate file;
extern crate rpassword;
extern crate rprompt;
#[macro_use] extern crate serde_derive;
extern crate serde_json;
extern crate xdg;

use std::path::PathBuf;
use xdg::BaseDirectories;

#[derive(Debug,PartialEq,Deserialize,Serialize)]
#[serde(tag = "type")]
pub enum Entity {
    Credentials(Credentials),
}

#[derive(Debug,PartialEq,Deserialize,Serialize)]
pub struct Credentials {
    pub url:         String,
    pub login:       String,
    pub password:    String,
    pub totp_secret: Option<String>
}

#[derive(Debug)]
pub struct MnemesisUtils {
    base_dirs: BaseDirectories,
    config:    MnemesisConfig,
}

#[derive(Debug,PartialEq,Deserialize,Serialize)]
struct MnemesisConfig {
    secret: String,
}

impl MnemesisUtils {
    pub fn new() -> MnemesisUtils {
        let base_dirs = BaseDirectories::with_prefix("mnemesis").expect("Failed getting base directories");
        let config    = MnemesisConfig::load(&base_dirs);

        MnemesisUtils {
            base_dirs,
            config,
        }
    }

    pub fn prompt_for_input(msg: &str) -> String {
        rprompt::prompt_reply_stdout(msg).expect("Failed reading from stdin")
    }

    pub fn prompt_for_password(msg: &str) -> String {
        rpassword::prompt_password_stdout(msg).expect("Failed reading password")
    }

    fn credentials_directory(&self, path: &str) -> PathBuf {
        self.base_dirs.place_data_file(path).expect("Failed computing credentials directory")
    }

    pub fn read_entities(&self, path: &str) -> Vec<Entity> {
        let full_path = self.credentials_directory(path);

        if full_path.exists() {
            if full_path.is_file() {
                let data = file::get_text(full_path.to_str().expect(&format!("{:?} is not valid UTF-8", full_path))).expect(&format!("Failed to read {:?}", full_path));
                serde_json::from_str::<Vec<Entity>>(&data).expect(&format!("Found garbage in {:?}", full_path))
            } else {
                panic!("{:?} exists and is not a file", full_path);
            }
        } else {
            Vec::new()
        }
    }

    pub fn write_entities(&self, path: &str, entities: Vec<Entity>) {
        let full_path = self.credentials_directory(path);

        file::put_text(full_path.to_str().expect(&format!("{:?} is not valid UTF-8", full_path)), serde_json::to_string(&entities).expect("Failed to serialize entities")).expect(&format!("Failed to write {:?}", full_path));
    }
}

impl MnemesisConfig {
    pub fn load(base_dirs: &BaseDirectories) -> MnemesisConfig {
        base_dirs.find_config_file("mnemesis-config.json").and_then(|conf_file| {
            conf_file.to_str().and_then(|conf_file| file::get_text(conf_file).ok())
        }).and_then(|conf| {
            serde_json::from_str::<MnemesisConfig>(&conf).ok()
        }).unwrap_or(MnemesisConfig {
            // FIXME: generate default config or error out?
            secret: "".to_string(),
        })
    }
}
<|endoftext|>


<commit_before>
#[cfg(test)]
#[macro_use]
extern crate lazy_static;

use std::marker::PhantomData;
use std::ptr;
use std::mem;
use std::cmp::{Ord, Ordering};

pub trait MapInPlace<A, B>: Sized {
    /// Should be of the same base type as the implementor.
    /// E.g. `Vec<B>` when implementing for `Vec<A>`
    type Output;

    /// Apply a mapping function to `self` without allocating.
    /// Makes best effort to maintain the invariant
    ///
    /// `self.as_ptr() as *const () == self.map_in_place(..).as_ptr() as *const ()`
    ///
    /// An example of a case where this isn't possible is for Vec where B is zero-sized but A is not.
    fn map_in_place<F>(self, f: F) -> Self::Output where F: FnMut(A) -> B;
}

struct Dropper<A, B> {
    idx: usize,
    owned: Vec<A>,
    _marker: PhantomData<B>,
}

impl<A, B> Drop for Dropper<A, B> {
    #[inline]
    fn drop(&mut self) {
        let owned = &mut self.owned;
        let idx = self.idx;
        let len = owned.len();
        let ptr_a = owned.as_mut_ptr();
        let ptr_b = ptr_a as *mut B;

        unsafe {
            owned.set_len(0);

            if idx != len {
                // panicked; manual cleanup needed
                for i in 0..idx {
                    ptr::drop_in_place(ptr_b.offset(i as isize));
                }

                for i in idx..len {
                    ptr::drop_in_place(ptr_a.offset(i as isize));
                }
            } else {
                // everything went well, no cleanup required
                mem::forget(mem::replace(owned, Vec::with_capacity(0)));
            }
        }
    }
}

#[inline]
unsafe fn map_in_place<A, B, F>(owned: Vec<A>, mut f: F)
    where F: FnMut(A) -> B
{
    let ptr_a = owned.as_ptr();
    let ptr_b = ptr_a as *mut B;
    let len = owned.len();

    let mut dropper = Dropper {
        idx: 0,
        owned: owned,
        _marker: PhantomData::<B>,
    };

    for i in 0..len {
        let ptr_a = ptr_a.offset(i as isize);
        let ptr_b = ptr_b.offset(i as isize);

        let v = ptr::read(ptr_a);
        dropper.idx += 1;

        ptr::write(ptr_b, f(v));
    }
}

impl<A, B> MapInPlace<A, B> for Vec<A> {
    type Output = Vec<B>;

    #[inline]
    fn map_in_place<F>(self, mut f: F) -> Self::Output
        where F: FnMut(A) -> B
    {
        let a_size = mem::size_of::<A>();
        let b_size = mem::size_of::<B>();
        let ptr_a = self.as_ptr();
        let ptr_b = ptr_a as *mut B;
        let len = self.len();

        match a_size.cmp(&b_size) {
            Ordering::Equal => {
                let cap = self.capacity();

                unsafe {
                    if a_size == 0 {
                        for _ in 0..len {
                            f(ptr::read(ptr_a));
                        }

                        mem::transmute(self)
                    } else {
                        map_in_place(self, f);
                        Vec::from_raw_parts(ptr_b, len, cap)
                    }
                }
            }
            Ordering::Greater => {
                if b_size == 0 {
                    // doesn't preserve address invariant
                    let mut v = Vec::with_capacity(0);

                    for e in self.into_iter() {
                        v.push(f(e));
                    }

                    v
                } else {
                    // nA * bytes/A = nbytes
                    // nbytes / bytes/B = nbytes * B/bytes = nB
                    // (assuming bytes/B divides evenly into nbytes)
                    let cap = {
                        let tmp = self.capacity().checked_mul(a_size).unwrap();
                        // TODO: don't require the divisibility constraint
                        assert_eq!(tmp % b_size, 0);
                        tmp / b_size
                    };

                    unsafe {
                        map_in_place(self, f);
                        Vec::from_raw_parts(ptr_b, len, cap)
                    }
                }
            }
            Ordering::Less => {
                panic!("map_in_place(Vec<A>): Size of A must be greater than or equal to size of B")
            }
        }
    }
}

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

    use std::mem;
    use std::sync::Mutex;
    use std::panic::catch_unwind;

    #[test]
    fn vec_elements_drop() {
        lazy_static! {
            static ref DROPS: Mutex<Vec<String>> = Mutex::new(vec![]);
        }

        #[derive(Debug, PartialEq, Clone)]
        struct X(usize);

        impl Drop for X {
            fn drop(&mut self) {
                DROPS.lock().unwrap().push(format!("X({})", self.0));
            }
        }

        #[derive(Debug, PartialEq, Clone)]
        struct Y(usize);

        impl Drop for Y {
            fn drop(&mut self) {
                DROPS.lock().unwrap().push(format!("Y({})", self.0));
            }
        }

        assert_eq!(mem::size_of::<X>(), mem::size_of::<Y>());

        let v = vec![X(0), X(1), X(2), X(3)];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|X(v)| Y(v));

        {
            let drops = DROPS.lock().unwrap().clone();
            assert_eq!(drops, vec!["X(0)", "X(1)", "X(2)", "X(3)"]);
        }

        let ap = v.as_ptr() as *const ();
        let expected = vec![Y(0), Y(1), Y(2), Y(3)];

        assert_eq!(bp, ap); // still at same memory addr
        assert_eq!(v, expected);

        mem::drop(v);

        {
            let drops = DROPS.lock().unwrap().clone();
            assert_eq!(drops,
                       vec!["X(0)", "X(1)", "X(2)", "X(3)", "Y(0)", "Y(1)", "Y(2)", "Y(3)"]);
        }

        mem::drop(expected);
    }

    #[test]
    fn vec_panic_drop() {
        lazy_static! {
            static ref DROPS: Mutex<Vec<String>> = Mutex::new(vec![]);
        }

        #[derive(Debug, PartialEq, Clone)]
        struct X(usize);

        impl Drop for X {
            fn drop(&mut self) {
                DROPS.lock().unwrap().push(format!("X({})", self.0));
            }
        }

        #[derive(Debug, PartialEq, Clone)]
        struct Y(usize);

        impl Drop for Y {
            fn drop(&mut self) {
                DROPS.lock().unwrap().push(format!("Y({})", self.0));
            }
        }

        assert_eq!(mem::size_of::<X>(), mem::size_of::<Y>());

        let v = vec![X(0), X(1), X(2), X(3), X(4)];

        match catch_unwind(|| {
            v.map_in_place(|X(v)| {
                if v == 2 {
                    panic!();
                }
                Y(v)
            })
        }) {
            Ok(_) => unreachable!(),
            Err(_) => {
                let drops = DROPS.lock().unwrap().clone();
                assert_eq!(drops,
                           vec![// consume Xs
                                "X(0)",
                                "X(1)",
                                "X(2)",
                                // panic here
                                // drop generated Ys
                                "Y(0)",
                                "Y(1)",
                                "Y(2)",
                                // drop remaining unprocessed Xs
                                "X(3)",
                                "X(4)"]);
            }
        }
    }

    #[test]
    fn same_size_vec() {
        let v = vec![0, 1, 2, 3];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|x: u32| (x * x) as i32);
        let ap = v.as_ptr() as *const ();

        assert_eq!(bp, ap); // still at same memory addr
        assert_eq!(v, vec![0, 1, 4, 9]);
    }

    #[test]
    fn different_sizes_vec() {
        let v = vec![0, 1, 2, 3];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|x: u32| (x * x) as i16);
        let ap = v.as_ptr() as *const ();

        assert_eq!(bp, ap); // still at same memory addr
        assert_eq!(v, vec![0, 1, 4, 9]);
    }

    #[test]
    fn both_zst_vec() {
        #[derive(Debug)]
        struct Zst;

        let v = vec![(), (), (), ()];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|_| Zst);
        let ap = v.as_ptr() as *const ();

        assert_eq!(bp, ap); // still at same memory addr
    }

    #[test]
    fn nzst_to_zst_vec() {
        let v = vec![0, 1, 2, 3];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|_: u32| ());
        let ap = v.as_ptr() as *const ();

        assert!(bp != ap); // -- NOT -- still at same memory addr
    }

    #[test]
    #[should_panic]
    fn zst_to_nzst_vec() {
        let v = vec![(), (), (), ()];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|_| 0usize);
        let ap = v.as_ptr() as *const ();

        assert_eq!(bp, ap); // still at same memory addr
    }
}
<commit_msg>Refactor<commit_after>
#[cfg(test)]
#[macro_use]
extern crate lazy_static;

use std::marker::PhantomData;
use std::ptr;
use std::mem;

pub trait MapInPlace<A, B>: Sized {
    /// Should be of the same base type as the implementor.
    /// E.g. `Vec<B>` when implementing for `Vec<A>`
    type Output;

    /// Apply a mapping function to `self` without allocating.
    /// Makes best effort to maintain the invariant
    ///
    /// `self.as_ptr() as *const () == self.map_in_place(..).as_ptr() as *const ()`
    ///
    /// An example of a case where this isn't possible is for Vec where B is zero-sized but A is not.
    fn map_in_place<F>(self, f: F) -> Self::Output where F: FnMut(A) -> B;
}

impl<A, B> MapInPlace<A, B> for Vec<A> {
    type Output = Vec<B>;

    #[inline]
    fn map_in_place<F>(self, mut f: F) -> Self::Output
        where F: FnMut(A) -> B
    {
        let a_size = mem::size_of::<A>();
        let b_size = mem::size_of::<B>();
        let ptr_a = self.as_ptr();
        let ptr_b = ptr_a as *mut B;
        let len = self.len();

        if b_size == 0 {
            // doesn't preserve address invariant if a_size != 0
            let mut v = Vec::with_capacity(0);

            for e in self.into_iter() {
                v.push(f(e));
            }

            v
        } else {
            let cap = if a_size == b_size {
                self.capacity()
            } else if a_size > b_size {
                // nA * bytes/A = nbytes
                // nbytes / bytes/B = nbytes * B/bytes = nB
                // (assuming bytes/B divides evenly into nbytes)
                let n_bytes = self.capacity().checked_mul(a_size).unwrap();
                // TODO: don't require the divisibility constraint
                assert_eq!(n_bytes % b_size, 0);
                n_bytes / b_size
            } else {
                panic!("map_in_place(Vec<A>): Size of A must be greater than or equal to size of B")
            };

            let mut dropper = VecDropper {
                idx: 0,
                owned: self,
                _marker: PhantomData::<B>,
            };

            unsafe {
                for i in 0..len {
                    let ptr_a = ptr_a.offset(i as isize);
                    let ptr_b = ptr_b.offset(i as isize);

                    let v = ptr::read(ptr_a);
                    dropper.idx += 1;

                    ptr::write(ptr_b, f(v));
                }

                Vec::from_raw_parts(ptr_b, len, cap)
            }
        }
    }
}

struct VecDropper<A, B> {
    idx: usize,
    owned: Vec<A>,
    _marker: PhantomData<B>,
}

impl<A, B> Drop for VecDropper<A, B> {
    #[inline]
    fn drop(&mut self) {
        let owned = &mut self.owned;
        let idx = self.idx;
        let len = owned.len();
        let ptr_a = owned.as_mut_ptr();
        let ptr_b = ptr_a as *mut B;

        unsafe {
            owned.set_len(0);

            if idx != len {
                // panicked; manual cleanup needed
                for i in 0..idx {
                    ptr::drop_in_place(ptr_b.offset(i as isize));
                }

                for i in idx..len {
                    ptr::drop_in_place(ptr_a.offset(i as isize));
                }
            } else {
                // everything went well, no cleanup required
                mem::forget(mem::replace(owned, Vec::with_capacity(0)));
            }
        }
    }
}

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

    use std::mem;
    use std::sync::Mutex;
    use std::panic::catch_unwind;

    #[test]
    fn vec_elements_drop() {
        lazy_static! {
            static ref DROPS: Mutex<Vec<String>> = Mutex::new(vec![]);
        }

        #[derive(Debug, PartialEq, Clone)]
        struct X(usize);

        impl Drop for X {
            fn drop(&mut self) {
                DROPS.lock().unwrap().push(format!("X({})", self.0));
            }
        }

        #[derive(Debug, PartialEq, Clone)]
        struct Y(usize);

        impl Drop for Y {
            fn drop(&mut self) {
                DROPS.lock().unwrap().push(format!("Y({})", self.0));
            }
        }

        assert_eq!(mem::size_of::<X>(), mem::size_of::<Y>());

        let v = vec![X(0), X(1), X(2), X(3)];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|X(v)| Y(v));

        {
            let drops = DROPS.lock().unwrap().clone();
            assert_eq!(drops, vec!["X(0)", "X(1)", "X(2)", "X(3)"]);
        }

        let ap = v.as_ptr() as *const ();
        let expected = vec![Y(0), Y(1), Y(2), Y(3)];

        assert_eq!(bp, ap); // still at same memory addr
        assert_eq!(v, expected);

        mem::drop(v);

        {
            let drops = DROPS.lock().unwrap().clone();
            assert_eq!(drops,
                       vec!["X(0)", "X(1)", "X(2)", "X(3)", "Y(0)", "Y(1)", "Y(2)", "Y(3)"]);
        }

        mem::drop(expected);
    }

    #[test]
    fn vec_panic_drop() {
        lazy_static! {
            static ref DROPS: Mutex<Vec<String>> = Mutex::new(vec![]);
        }

        #[derive(Debug, PartialEq, Clone)]
        struct X(usize);

        impl Drop for X {
            fn drop(&mut self) {
                DROPS.lock().unwrap().push(format!("X({})", self.0));
            }
        }

        #[derive(Debug, PartialEq, Clone)]
        struct Y(usize);

        impl Drop for Y {
            fn drop(&mut self) {
                DROPS.lock().unwrap().push(format!("Y({})", self.0));
            }
        }

        assert_eq!(mem::size_of::<X>(), mem::size_of::<Y>());

        let v = vec![X(0), X(1), X(2), X(3), X(4)];

        match catch_unwind(|| {
            v.map_in_place(|X(v)| {
                if v == 2 {
                    panic!();
                }
                Y(v)
            })
        }) {
            Ok(_) => unreachable!(),
            Err(_) => {
                let drops = DROPS.lock().unwrap().clone();
                assert_eq!(drops,
                           vec![// consume Xs
                                "X(0)",
                                "X(1)",
                                "X(2)",
                                // panic here
                                // drop generated Ys
                                "Y(0)",
                                "Y(1)",
                                "Y(2)",
                                // drop remaining unprocessed Xs
                                "X(3)",
                                "X(4)"]);
            }
        }
    }

    #[test]
    fn same_size_vec() {
        let v = vec![0, 1, 2, 3];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|x: u32| (x * x) as i32);
        let ap = v.as_ptr() as *const ();

        assert_eq!(bp, ap); // still at same memory addr
        assert_eq!(v, vec![0, 1, 4, 9]);
    }

    #[test]
    fn different_sizes_vec() {
        let v = vec![0, 1, 2, 3];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|x: u32| (x * x) as i16);
        let ap = v.as_ptr() as *const ();

        assert_eq!(bp, ap); // still at same memory addr
        assert_eq!(v, vec![0, 1, 4, 9]);
    }

    #[test]
    fn both_zst_vec() {
        #[derive(Debug)]
        struct Zst;

        let v = vec![(), (), (), ()];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|_| Zst);
        let ap = v.as_ptr() as *const ();

        assert_eq!(bp, ap); // still at same memory addr
    }

    #[test]
    fn nzst_to_zst_vec() {
        let v = vec![0, 1, 2, 3];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|_: u32| ());
        let ap = v.as_ptr() as *const ();

        assert!(bp != ap); // -- NOT -- still at same memory addr
    }

    #[test]
    #[should_panic]
    fn zst_to_nzst_vec() {
        let v = vec![(), (), (), ()];

        let bp = v.as_ptr() as *const ();
        let v = v.map_in_place(|_| 0usize);
        let ap = v.as_ptr() as *const ();

        assert_eq!(bp, ap); // still at same memory addr
    }
}
<|endoftext|>


<commit_before>//! Async WebSocket usage.
//!
//! This library is an implementation of WebSocket handshakes and streams. It
//! is based on the crate which implements all required WebSocket protocol
//! logic. So this crate basically just brings tokio support / tokio integration
//! to it.
//!
//! Each WebSocket stream implements the required `Stream` and `Sink` traits,
//! so the socket is just a stream of messages coming in and going out.
//!
//! This crate primarily exports this ability through two extension traits,
//! `ClientHandshakeExt` and `ServerHandshakeExt`. These traits augment the
//! functionality provided by the `tungestenite` crate, on which this crate is
//! built. Configuration is done through `tungestenite` crate as well.

#![deny(
    missing_docs,
    unused_must_use,
    unused_mut,
    unused_imports,
    unused_import_braces)]

extern crate futures;
extern crate tokio_io;
extern crate tungstenite;
extern crate url;

use std::io::ErrorKind;

use futures::{Poll, Future, Async, AsyncSink, Stream, Sink, StartSend};
use tokio_io::{AsyncRead, AsyncWrite};

use url::Url;

use tungstenite::handshake::client::ClientHandshake;
use tungstenite::handshake::server::ServerHandshake;
use tungstenite::handshake::{HandshakeRole, HandshakeError};
use tungstenite::protocol::{WebSocket, Message};
use tungstenite::error::Error as WsError;
use tungstenite::server;

/// A WebSocket request
pub struct Request<'a> {
    pub url: Url,
    pub headers: Vec<(&'a str, &'a str)>,
}

impl<'a> Request<'a> {
    /// Constructs a new WebSocket request with a URL or URL string
    pub fn new<U: Into<Url>>(url: U) -> Self {
        Request{url: url.into(), headers: vec![]}
    }

    /// Adds a WebSocket protocol to the request
    pub fn add_protocol(&mut self, protocol: &'a str) {
        self.headers.push(("Sec-WebSocket-Protocol", protocol));
    }

    /// Adds a custom header to the request
    pub fn add_header(&mut self, name: &'a str, value: &'a str) {
        self.headers.push((name, value));
    }
}

impl<'a, U: Into<Url>> From<U> for Request<'a> {
    fn from(u: U) -> Request<'a> {
        Request::new(u)
    }
}

/// Creates a WebSocket handshake from a request and a stream.
/// For convenience, the user may call this with a url string, a URL,
/// or a `Request`. Calling with `Request` allows the user to add
/// a WebSocket protocol or other custom headers.
///
/// Internally, this custom creates a handshake representation and returns
/// a future representing the resolution of the WebSocket handshake. The
/// returned future will resolve to either `WebSocketStream<S>` or `Error`
/// depending on whether the handshake is successful.
///
/// This is typically used for clients who have already established, for
/// example, a TCP connection to the remove server.
pub fn client_async<'a, R, S>(request: R, stream: S) -> ConnectAsync<S>
    where R: Into<Request<'a>>, S: AsyncRead + AsyncWrite {
    let Request{url, headers} = request.into();
    let tungstenite_request = tungstenite::handshake::client::Request{url: url, extra_headers: Some(&headers)};
    let handshake = ClientHandshake::start(stream, tungstenite_request).handshake();

    ConnectAsync {
        inner: MidHandshake {
            inner: Some(handshake)
        }
    }
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function will internally call `server::accept` to create a
/// handshake representation and returns a future representing the
/// resolution of the WebSocket handshake. The returned future will resolve
/// to either `WebSocketStream<S>` or `Error` depending if it's successful
/// or not.
///
/// This is typically used after a socket has been accepted from a
/// `TcpListener`. That socket is then passed to this function to perform
/// the server half of the accepting a client's websocket connection.
pub fn accept_async<S: AsyncRead + AsyncWrite>(stream: S) -> AcceptAsync<S> {
    AcceptAsync {
        inner: MidHandshake {
            inner: Some(server::accept(stream))
        }
    }
}

/// A wrapper around an underlying raw stream which implements the WebSocket
/// protocol.
///
/// A `WebSocketStream<S>` represents a handshake that has been completed
/// successfully and both the server and the client are ready for receiving
/// and sending data. Message from a `WebSocketStream<S>` are accessible
/// through the respective `Stream` and `Sink`. Check more information about
/// them in `futures-rs` crate documentation or have a look on the examples
/// and unit tests for this crate.
pub struct WebSocketStream<S> {
    inner: WebSocket<S>,
}

impl<T> Stream for WebSocketStream<T> where T: AsyncRead + AsyncWrite {
    type Item = Message;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Option<Message>, WsError> {
        self.inner.read_message().map(|m| Some(m)).to_async()
    }
}

impl<T> Sink for WebSocketStream<T> where T: AsyncRead + AsyncWrite {
    type SinkItem = Message;
    type SinkError = WsError;

    fn start_send(&mut self, item: Message) -> StartSend<Message, WsError> {
        try!(self.inner.write_message(item).to_async());
        Ok(AsyncSink::Ready)
    }

    fn poll_complete(&mut self) -> Poll<(), WsError> {
        self.inner.write_pending().to_async()
    }
}

/// Future returned from client_async() which will resolve
/// once the connection handshake has finished.
pub struct ConnectAsync<S> {
    inner: MidHandshake<S, ClientHandshake>,
}

impl<S: AsyncRead + AsyncWrite> Future for ConnectAsync<S> {
    type Item = WebSocketStream<S>;
    type Error = WsError;

    fn poll(&mut self) -> Poll<WebSocketStream<S>, WsError> {
        self.inner.poll()
    }
}

/// Future returned from accept_async() which will resolve
/// once the connection handshake has finished.
pub struct AcceptAsync<S> {
    inner: MidHandshake<S, ServerHandshake>,
}

impl<S: AsyncRead + AsyncWrite> Future for AcceptAsync<S> {
    type Item = WebSocketStream<S>;
    type Error = WsError;

    fn poll(&mut self) -> Poll<WebSocketStream<S>, WsError> {
        self.inner.poll()
    }
}

struct MidHandshake<S, R> {
    inner: Option<Result<WebSocket<S>, HandshakeError<S, R>>>,
}

impl<S: AsyncRead + AsyncWrite, R: HandshakeRole> Future for MidHandshake<S, R> {
    type Item = WebSocketStream<S>;
    type Error = WsError;

    fn poll(&mut self) -> Poll<WebSocketStream<S>, WsError> {
        match self.inner.take().expect("cannot poll MidHandshake twice") {
            Ok(stream) => Ok(WebSocketStream { inner: stream }.into()),
            Err(HandshakeError::Failure(e)) => Err(e),
            Err(HandshakeError::Interrupted(s)) => {
                match s.handshake() {
                    Ok(stream) => Ok(WebSocketStream { inner: stream }.into()),
                    Err(HandshakeError::Failure(e)) => Err(e),
                    Err(HandshakeError::Interrupted(s)) => {
                        self.inner = Some(Err(HandshakeError::Interrupted(s)));
                        Ok(Async::NotReady)
                    }
                }
            }
        }
    }
}

trait ToAsync {
    type T;
    type E;
    fn to_async(self) -> Result<Async<Self::T>, Self::E>;
}

impl<T> ToAsync for Result<T, WsError> {
    type T = T;
    type E = WsError;
    fn to_async(self) -> Result<Async<Self::T>, Self::E> {
        match self {
            Ok(x) => Ok(Async::Ready(x)),
            Err(error) => match error {
                WsError::Io(ref err) if err.kind() == ErrorKind::WouldBlock => Ok(Async::NotReady),
                err => Err(err),
            },
        }
    }
}

<commit_msg>Add missing documentation for Url struct<commit_after>//! Async WebSocket usage.
//!
//! This library is an implementation of WebSocket handshakes and streams. It
//! is based on the crate which implements all required WebSocket protocol
//! logic. So this crate basically just brings tokio support / tokio integration
//! to it.
//!
//! Each WebSocket stream implements the required `Stream` and `Sink` traits,
//! so the socket is just a stream of messages coming in and going out.
//!
//! This crate primarily exports this ability through two extension traits,
//! `ClientHandshakeExt` and `ServerHandshakeExt`. These traits augment the
//! functionality provided by the `tungestenite` crate, on which this crate is
//! built. Configuration is done through `tungestenite` crate as well.

#![deny(
    missing_docs,
    unused_must_use,
    unused_mut,
    unused_imports,
    unused_import_braces)]

extern crate futures;
extern crate tokio_io;
extern crate tungstenite;
extern crate url;

use std::io::ErrorKind;

use futures::{Poll, Future, Async, AsyncSink, Stream, Sink, StartSend};
use tokio_io::{AsyncRead, AsyncWrite};

use url::Url;

use tungstenite::handshake::client::ClientHandshake;
use tungstenite::handshake::server::ServerHandshake;
use tungstenite::handshake::{HandshakeRole, HandshakeError};
use tungstenite::protocol::{WebSocket, Message};
use tungstenite::error::Error as WsError;
use tungstenite::server;

/// A WebSocket request
pub struct Request<'a> {
    /// URL of the request.
    pub url: Url,
    /// Extra headers, if any.
    pub headers: Vec<(&'a str, &'a str)>,
}

impl<'a> Request<'a> {
    /// Constructs a new WebSocket request with a URL or URL string
    pub fn new<U: Into<Url>>(url: U) -> Self {
        Request{url: url.into(), headers: vec![]}
    }

    /// Adds a WebSocket protocol to the request
    pub fn add_protocol(&mut self, protocol: &'a str) {
        self.headers.push(("Sec-WebSocket-Protocol", protocol));
    }

    /// Adds a custom header to the request
    pub fn add_header(&mut self, name: &'a str, value: &'a str) {
        self.headers.push((name, value));
    }
}

impl<'a, U: Into<Url>> From<U> for Request<'a> {
    fn from(u: U) -> Request<'a> {
        Request::new(u)
    }
}

/// Creates a WebSocket handshake from a request and a stream.
/// For convenience, the user may call this with a url string, a URL,
/// or a `Request`. Calling with `Request` allows the user to add
/// a WebSocket protocol or other custom headers.
///
/// Internally, this custom creates a handshake representation and returns
/// a future representing the resolution of the WebSocket handshake. The
/// returned future will resolve to either `WebSocketStream<S>` or `Error`
/// depending on whether the handshake is successful.
///
/// This is typically used for clients who have already established, for
/// example, a TCP connection to the remove server.
pub fn client_async<'a, R, S>(request: R, stream: S) -> ConnectAsync<S>
    where R: Into<Request<'a>>, S: AsyncRead + AsyncWrite {
    let Request{url, headers} = request.into();
    let tungstenite_request = tungstenite::handshake::client::Request{url: url, extra_headers: Some(&headers)};
    let handshake = ClientHandshake::start(stream, tungstenite_request).handshake();

    ConnectAsync {
        inner: MidHandshake {
            inner: Some(handshake)
        }
    }
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function will internally call `server::accept` to create a
/// handshake representation and returns a future representing the
/// resolution of the WebSocket handshake. The returned future will resolve
/// to either `WebSocketStream<S>` or `Error` depending if it's successful
/// or not.
///
/// This is typically used after a socket has been accepted from a
/// `TcpListener`. That socket is then passed to this function to perform
/// the server half of the accepting a client's websocket connection.
pub fn accept_async<S: AsyncRead + AsyncWrite>(stream: S) -> AcceptAsync<S> {
    AcceptAsync {
        inner: MidHandshake {
            inner: Some(server::accept(stream))
        }
    }
}

/// A wrapper around an underlying raw stream which implements the WebSocket
/// protocol.
///
/// A `WebSocketStream<S>` represents a handshake that has been completed
/// successfully and both the server and the client are ready for receiving
/// and sending data. Message from a `WebSocketStream<S>` are accessible
/// through the respective `Stream` and `Sink`. Check more information about
/// them in `futures-rs` crate documentation or have a look on the examples
/// and unit tests for this crate.
pub struct WebSocketStream<S> {
    inner: WebSocket<S>,
}

impl<T> Stream for WebSocketStream<T> where T: AsyncRead + AsyncWrite {
    type Item = Message;
    type Error = WsError;

    fn poll(&mut self) -> Poll<Option<Message>, WsError> {
        self.inner.read_message().map(|m| Some(m)).to_async()
    }
}

impl<T> Sink for WebSocketStream<T> where T: AsyncRead + AsyncWrite {
    type SinkItem = Message;
    type SinkError = WsError;

    fn start_send(&mut self, item: Message) -> StartSend<Message, WsError> {
        try!(self.inner.write_message(item).to_async());
        Ok(AsyncSink::Ready)
    }

    fn poll_complete(&mut self) -> Poll<(), WsError> {
        self.inner.write_pending().to_async()
    }
}

/// Future returned from client_async() which will resolve
/// once the connection handshake has finished.
pub struct ConnectAsync<S> {
    inner: MidHandshake<S, ClientHandshake>,
}

impl<S: AsyncRead + AsyncWrite> Future for ConnectAsync<S> {
    type Item = WebSocketStream<S>;
    type Error = WsError;

    fn poll(&mut self) -> Poll<WebSocketStream<S>, WsError> {
        self.inner.poll()
    }
}

/// Future returned from accept_async() which will resolve
/// once the connection handshake has finished.
pub struct AcceptAsync<S> {
    inner: MidHandshake<S, ServerHandshake>,
}

impl<S: AsyncRead + AsyncWrite> Future for AcceptAsync<S> {
    type Item = WebSocketStream<S>;
    type Error = WsError;

    fn poll(&mut self) -> Poll<WebSocketStream<S>, WsError> {
        self.inner.poll()
    }
}

struct MidHandshake<S, R> {
    inner: Option<Result<WebSocket<S>, HandshakeError<S, R>>>,
}

impl<S: AsyncRead + AsyncWrite, R: HandshakeRole> Future for MidHandshake<S, R> {
    type Item = WebSocketStream<S>;
    type Error = WsError;

    fn poll(&mut self) -> Poll<WebSocketStream<S>, WsError> {
        match self.inner.take().expect("cannot poll MidHandshake twice") {
            Ok(stream) => Ok(WebSocketStream { inner: stream }.into()),
            Err(HandshakeError::Failure(e)) => Err(e),
            Err(HandshakeError::Interrupted(s)) => {
                match s.handshake() {
                    Ok(stream) => Ok(WebSocketStream { inner: stream }.into()),
                    Err(HandshakeError::Failure(e)) => Err(e),
                    Err(HandshakeError::Interrupted(s)) => {
                        self.inner = Some(Err(HandshakeError::Interrupted(s)));
                        Ok(Async::NotReady)
                    }
                }
            }
        }
    }
}

trait ToAsync {
    type T;
    type E;
    fn to_async(self) -> Result<Async<Self::T>, Self::E>;
}

impl<T> ToAsync for Result<T, WsError> {
    type T = T;
    type E = WsError;
    fn to_async(self) -> Result<Async<Self::T>, Self::E> {
        match self {
            Ok(x) => Ok(Async::Ready(x)),
            Err(error) => match error {
                WsError::Io(ref err) if err.kind() == ErrorKind::WouldBlock => Ok(Async::NotReady),
                err => Err(err),
            },
        }
    }
}

<|endoftext|>


<commit_before>//
// Copyright 2015 Joshua R. Rodgers
//
// 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.
//

#[macro_export]
macro_rules! context_match {
    ($value:expr, $context:pat => $result:expr) => {
        match $value {
            $context => $result,
            _ => panic!("Unexpected pattern context.")
        }
    }
}

#[macro_export]
macro_rules! query {
    ($($tokens:tt)*) => {
        query_from!($($tokens)*)
    };
}

#[macro_export]
macro_rules! query_from {
    (from $context:pat => $source:expr, $($remainder:tt)+) => {
        query_from!(match_none, $source, $context => $($remainder)+)
    };

    (match_none, $source:expr, $context:pat => from $newContext:pat => $newSource:expr, $($remainder:tt)+) => {{
        let source = $source.flat_map(|value| {
            let $context = value;
            $newSource
        });

        query_from!(match_none, source, $newContext => $($remainder)+)
    }};

    (match_context, $source:expr, $context:pat => from $newContext:pat => $newSource:expr, $($remainder:tt)+) => {{
        let source = $source.flat_map(|value| {
            context_match!(value, $context => $newSource.map(|value| { (value, Some(())) }))
        });

        query_from!(match_context, source, ($newContext, Some(())) => $($remainder)+)
    }};

    ($($tokens:tt)*) => {
        query_operator!($($tokens)*)
    };
}

#[macro_export]
macro_rules! query_where {
    (match_none, $source:expr, $context:pat => $filter:expr, $($remainder:tt)+) => {
        {
            let source = $source.filter(|&$context| { $filter });
            query!(match_none, source, $context => $($remainder)+)
        }
    };

    (match_context, $source:expr, $context:pat => $filter:expr, $($remainder:tt)+) => {
        {
            let source = $source.filter(|&value| { context_match!(value, $context => $filter) });
            query!(match_context, source, $context => $($remainder)+)
        }
    };
}

#[macro_export]
macro_rules! query_let {
    (match_none, $source:expr, $context:pat => $newContext:pat = $letValue:expr, $($remainder:tt)+) => {
        {
            let source = $source.map(|value| {
                let $context = value;
                (value, $letValue)
            });

            query!(match_none, source, ($context, $newContext) => $($remainder)+)
        }
    };
}

#[macro_export]
macro_rules! query_where_let {
    (match_none, $source:expr, $context:pat => $newContext:pat = $letValue:expr, $($remainder:tt)+) => {
        {
            let source = $source.filter_map(|&value| {
                let $context = value;
                if let $newContext = $letValue {
                    Some((value, $letValue))
                }
                else {
                    None
                }
            });

            query!(match_context, source, ($context, $newContext) => $($remainder)+)
        }
    };
}

#[macro_export]
macro_rules! query_operator {
    ($match_context:ident, $source:expr, $context:pat => where let $($remainder:tt)+) => {
        query_where_let!($match_context, $source, $context => $($remainder)+)
    };

    ($match_context:ident, $source:expr, $context:pat => where let $($remainder:tt)+) => {
        query_where_let!($match_context, $source, $context => $($remainder)+)
    };

    ($match_context:ident, $source:expr, $context:pat => where $($remainder:tt)+) => {
        {
            query_where!($match_context, $source, $context => $($remainder)+)
        }
    };

    ($match_context:ident, $source:expr, $context:pat => let $($remainder:tt)+) => {
        {
            query_let!($match_context, $source, $context => $($remainder)+)
        }
    };

    ($match_context:ident, $source:expr, $context:pat => do $action:stmt, $($remainder:tt)+) => {
        {
            let source = $source.inspect(|$context| { $action; });
            query!($match_context, source, $context => $($remainder)+)
        }
    };

    ($match_context:ident, $source:expr, $context:pat => from $($remainder:tt)+) => {
        {
            query_from!($match_context, $source, $context => from $($remainder)+)
        }
    };

    ($($tokens:tt)*) => {
        query_end!($($tokens)*)
    };
}

#[macro_export]
macro_rules! query_end {
    (match_context, $source:expr, $context:pat => select $selector:expr) => {
        $source.map(|value| { context_match!(value, $context => $selector) })
    };

    (match_none, $source:expr, $context:pat => select $selector:expr) => {
        $source.map(|$context| { $selector })
    };
}<commit_msg>Remove a redundant match clause in query_operator.<commit_after>//
// Copyright 2015 Joshua R. Rodgers
//
// 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.
//

#[macro_export]
macro_rules! context_match {
    ($value:expr, $context:pat => $result:expr) => {
        match $value {
            $context => $result,
            _ => panic!("Unexpected pattern context.")
        }
    }
}

#[macro_export]
macro_rules! query {
    ($($tokens:tt)*) => {
        query_from!($($tokens)*)
    };
}

#[macro_export]
macro_rules! query_from {
    (from $context:pat => $source:expr, $($remainder:tt)+) => {
        query_from!(match_none, $source, $context => $($remainder)+)
    };

    (match_none, $source:expr, $context:pat => from $newContext:pat => $newSource:expr, $($remainder:tt)+) => {{
        let source = $source.flat_map(|value| {
            let $context = value;
            $newSource
        });

        query_from!(match_none, source, $newContext => $($remainder)+)
    }};

    (match_context, $source:expr, $context:pat => from $newContext:pat => $newSource:expr, $($remainder:tt)+) => {{
        let source = $source.flat_map(|value| {
            context_match!(value, $context => $newSource.map(|value| { (value, Some(())) }))
        });

        query_from!(match_context, source, ($newContext, Some(())) => $($remainder)+)
    }};

    ($($tokens:tt)*) => {
        query_operator!($($tokens)*)
    };
}

#[macro_export]
macro_rules! query_where {
    (match_none, $source:expr, $context:pat => $filter:expr, $($remainder:tt)+) => {
        {
            let source = $source.filter(|&$context| { $filter });
            query!(match_none, source, $context => $($remainder)+)
        }
    };

    (match_context, $source:expr, $context:pat => $filter:expr, $($remainder:tt)+) => {
        {
            let source = $source.filter(|&value| { context_match!(value, $context => $filter) });
            query!(match_context, source, $context => $($remainder)+)
        }
    };
}

#[macro_export]
macro_rules! query_let {
    (match_none, $source:expr, $context:pat => $newContext:pat = $letValue:expr, $($remainder:tt)+) => {
        {
            let source = $source.map(|value| {
                let $context = value;
                (value, $letValue)
            });

            query!(match_none, source, ($context, $newContext) => $($remainder)+)
        }
    };
}

#[macro_export]
macro_rules! query_where_let {
    (match_none, $source:expr, $context:pat => $newContext:pat = $letValue:expr, $($remainder:tt)+) => {
        {
            let source = $source.filter_map(|&value| {
                let $context = value;
                if let $newContext = $letValue {
                    Some((value, $letValue))
                }
                else {
                    None
                }
            });

            query!(match_context, source, ($context, $newContext) => $($remainder)+)
        }
    };
}

#[macro_export]
macro_rules! query_operator {
    ($match_context:ident, $source:expr, $context:pat => where let $($remainder:tt)+) => {
        query_where_let!($match_context, $source, $context => $($remainder)+)
    };

    ($match_context:ident, $source:expr, $context:pat => where $($remainder:tt)+) => {
        {
            query_where!($match_context, $source, $context => $($remainder)+)
        }
    };

    ($match_context:ident, $source:expr, $context:pat => let $($remainder:tt)+) => {
        {
            query_let!($match_context, $source, $context => $($remainder)+)
        }
    };

    ($match_context:ident, $source:expr, $context:pat => do $action:stmt, $($remainder:tt)+) => {
        {
            let source = $source.inspect(|$context| { $action; });
            query!($match_context, source, $context => $($remainder)+)
        }
    };

    ($match_context:ident, $source:expr, $context:pat => from $($remainder:tt)+) => {
        {
            query_from!($match_context, $source, $context => from $($remainder)+)
        }
    };

    ($($tokens:tt)*) => {
        query_end!($($tokens)*)
    };
}

#[macro_export]
macro_rules! query_end {
    (match_context, $source:expr, $context:pat => select $selector:expr) => {
        $source.map(|value| { context_match!(value, $context => $selector) })
    };

    (match_none, $source:expr, $context:pat => select $selector:expr) => {
        $source.map(|$context| { $selector })
    };
}<|endoftext|>


<commit_before>#![feature(slicing_syntax)]
#![feature(globs)]

use std::io::File;
use std::slice::bytes::copy_memory;
use constants::{HEADER};
use utils::match_constant;
pub use error::{XmError, XmResult};

mod constants;
mod utils;
pub mod error;

pub struct XmModule {
    pub module_name: [u8, ..20],
    pub tracker_name: [u8, ..20],
}

pub fn parse(path: &Path) -> XmResult<XmModule> {
    let mut buffer = [0u8, ..500];
    let mut file = try!(File::open(path));
    try!(file.read(buffer[mut ..HEADER.len()]));
    try!(match_constant(buffer[], HEADER));

    try!(file.read(buffer[mut ..20]));
    let mut module_name = [0, ..20];
    copy_memory(module_name[mut], buffer[..20]);

    try!(file.read(buffer[mut ..1]));
    try!(match_constant(buffer[], b"\x1A"));

    try!(file.read(buffer[mut ..20]));
    let mut tracker_name = [0, ..20];
    copy_memory(tracker_name[mut], buffer[..20]);

    // Version check.
    try!(file.read(buffer[mut ..2]));
    if buffer[..2] != [1,4][] {
        return Err(XmError::WrongVersion(buffer[0],buffer[1]));
    }

    Ok(XmModule {
        module_name: module_name,
        tracker_name: tracker_name,
    })
}
<commit_msg>Replace [] slicing with taking a reference.<commit_after>#![feature(slicing_syntax)]
#![feature(globs)]

use std::io::File;
use std::slice::bytes::copy_memory;
use constants::{HEADER};
use utils::match_constant;
pub use error::{XmError, XmResult};

mod constants;
mod utils;
pub mod error;

pub struct XmModule {
    pub module_name: [u8, ..20],
    pub tracker_name: [u8, ..20],
}

pub fn parse(path: &Path) -> XmResult<XmModule> {
    let mut buffer = [0u8, ..500];
    let mut file = try!(File::open(path));
    try!(file.read(buffer[mut ..HEADER.len()]));
    try!(match_constant(&buffer, HEADER));

    try!(file.read(buffer[mut ..20]));
    let mut module_name = [0, ..20];
    copy_memory(module_name[mut], buffer[..20]);

    try!(file.read(buffer[mut ..1]));
    try!(match_constant(&buffer, b"\x1A"));

    try!(file.read(buffer[mut ..20]));
    let mut tracker_name = [0, ..20];
    copy_memory(tracker_name[mut], buffer[..20]);

    // Version check.
    try!(file.read(buffer[mut ..2]));
    if buffer[..2] != &[1,4] {
        return Err(XmError::WrongVersion(buffer[0],buffer[1]));
    }

    Ok(XmModule {
        module_name: module_name,
        tracker_name: tracker_name,
    })
}
<|endoftext|>


<commit_before>#![cfg(windows)]

extern crate winapi;

use com::{ComPtr, ToResult, HResult, as_ptr};
use std::ptr;
use winapi::shared::dxgi1_2::DXGI_SWAP_CHAIN_DESC1;
use winapi::shared::dxgi1_2::IDXGIFactory2;
use winapi::shared::minwindef::{TRUE, FALSE};
use winapi::shared::windef::HWND;
use winapi::shared::winerror::S_OK;
use winapi::um::d3d11::ID3D11Device;
use winapi::um::dcomp::IDCompositionDevice;
use winapi::um::dcomp::IDCompositionTarget;
use winapi::um::dcomp::IDCompositionVisual;

pub mod com;

pub struct DirectComposition {
    d3d_device: ComPtr<ID3D11Device>,
    dxgi_factory: ComPtr<IDXGIFactory2>,
    composition_device: ComPtr<IDCompositionDevice>,
    root_visual: ComPtr<IDCompositionVisual>,

    #[allow(unused)]  // Needs to be kept alive
    composition_target: ComPtr<IDCompositionTarget>,
}

impl DirectComposition {
    /// Initialize DirectComposition in the given window
    ///
    /// # Safety
    ///
    /// `hwnd` must be a valid handle to a window.
    pub unsafe fn new(hwnd: HWND) -> HResult<Self> {
        let mut feature_level_supported = 0;

        let d3d_device = ComPtr::new_with(|ptr_ptr| winapi::um::d3d11::D3D11CreateDevice(
            ptr::null_mut(),
            winapi::um::d3dcommon::D3D_DRIVER_TYPE_HARDWARE,
            ptr::null_mut(),
            winapi::um::d3d11::D3D11_CREATE_DEVICE_BGRA_SUPPORT |
            if cfg!(debug_assertions) {
                winapi::um::d3d11::D3D11_CREATE_DEVICE_DEBUG
            } else {
                0
            },
            ptr::null_mut(),
            0,
            winapi::um::d3d11::D3D11_SDK_VERSION,
            ptr_ptr,
            &mut feature_level_supported,
            ptr::null_mut(),
        ))?;

        let dxgi_device = d3d_device.cast::<winapi::shared::dxgi::IDXGIDevice>()?;

        // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404556(v=vs.85).aspx#code-snippet-1
        // “Because you can create a Direct3D device without creating a swap chain,
        //  you might need to retrieve the factory that is used to create the device
        //  in order to create a swap chain.”
        let adapter = ComPtr::new_with(|ptr_ptr| dxgi_device.GetAdapter(ptr_ptr))?;
        let dxgi_factory = ComPtr::<IDXGIFactory2>::new_with_uuid(|uuid, ptr_ptr| {
            adapter.GetParent(uuid, ptr_ptr)
        })?;

        // Create the DirectComposition device object.
        let composition_device = ComPtr::<IDCompositionDevice>::new_with_uuid(|uuid, ptr_ptr| {
            winapi::um::dcomp::DCompositionCreateDevice(&*dxgi_device, uuid,ptr_ptr)
        })?;

        // Create the composition target object based on the
        // specified application window.
        let composition_target = ComPtr::new_with(|ptr_ptr| {
            composition_device.CreateTargetForHwnd(hwnd, TRUE, ptr_ptr)
        })?;

        let root_visual = ComPtr::new_with(|ptr_ptr| composition_device.CreateVisual(ptr_ptr))?;
        composition_target.SetRoot(&*root_visual).to_result()?;

        Ok(DirectComposition {
            d3d_device, dxgi_factory, composition_device, composition_target, root_visual,
        })
    }

    /// Execute changes to the DirectComposition scene.
    pub fn commit(&self) -> HResult<()> {
        unsafe {
            self.composition_device.Commit().to_result()
        }
    }

    pub fn create_d3d_visual(&self, width: u32, height: u32) -> HResult<D3DVisual> {
        unsafe {
            let desc = DXGI_SWAP_CHAIN_DESC1 {
                Width: width,
                Height: height,
                Format: winapi::shared::dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
                Stereo: FALSE,
                SampleDesc: winapi::shared::dxgitype::DXGI_SAMPLE_DESC {
                    Count: 1,
                    Quality: 0,
                },
                BufferUsage: winapi::shared::dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
                BufferCount: 2,
                Scaling: winapi::shared::dxgi1_2::DXGI_SCALING_STRETCH,
                SwapEffect: winapi::shared::dxgi::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
                AlphaMode:  winapi::shared::dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED,
                Flags: 0,
            };
            let swap_chain = ComPtr::<winapi::shared::dxgi1_2::IDXGISwapChain1>::new_with(|ptr_ptr| {
                self.dxgi_factory.CreateSwapChainForComposition(
                    as_ptr(&self.d3d_device),
                    &desc,
                    ptr::null_mut(),
                    ptr_ptr,
                )
            })?;
            let visual = ComPtr::new_with(|ptr_ptr| self.composition_device.CreateVisual(ptr_ptr))?;
            visual.SetContent(&*****swap_chain).to_result()?;
            self.root_visual.AddVisual(&*visual, FALSE, ptr::null_mut()).to_result()?;

            Ok(D3DVisual { visual, swap_chain })
        }
    }
}

/// A DirectComposition "visual" configured for rendering with Direct3D.
pub struct D3DVisual {
    visual: ComPtr<IDCompositionVisual>,
    swap_chain: ComPtr<winapi::shared::dxgi1_2::IDXGISwapChain1>,
}

impl D3DVisual {
    pub fn set_offset_x(&self, offset_x: f32) -> HResult<()> {
        unsafe {
            self.visual.SetOffsetX_1(offset_x).to_result()
        }
    }

    pub fn set_offset_y(&self, offset_y: f32) -> HResult<()> {
        unsafe {
            self.visual.SetOffsetY_1(offset_y).to_result()
        }
    }

    pub fn render_and_present_solid_frame(&self, composition: &DirectComposition, rgba: &[f32; 4])
                                          -> HResult<()> {
        unsafe {
            let back_buffer = ComPtr::<winapi::um::d3d11::ID3D11Texture2D>::new_with_uuid(|uuid, ptr_ptr| {
                self.swap_chain.GetBuffer(0, uuid, ptr_ptr)
            })?;
            let render_target = ComPtr::new_with(|ptr_ptr| {
                composition.d3d_device.CreateRenderTargetView(
                    as_ptr(&back_buffer), ptr::null_mut(), ptr_ptr,
                )
            })?;
            let context = ComPtr::new_with(|ptr_ptr| {
                composition.d3d_device.GetImmediateContext(ptr_ptr);
                S_OK
            })?;

            // FIXME: arbitrary D3D rendering here?
            context.OMSetRenderTargets(1, &render_target.as_raw(), ptr::null_mut());
            context.ClearRenderTargetView(render_target.as_raw(), &rgba);

            self.swap_chain.Present(0, 0).to_result()
        }
    }
}
<commit_msg>OMSetRenderTargets appears to be unnecessary here<commit_after>#![cfg(windows)]

extern crate winapi;

use com::{ComPtr, ToResult, HResult, as_ptr};
use std::ptr;
use winapi::shared::dxgi1_2::DXGI_SWAP_CHAIN_DESC1;
use winapi::shared::dxgi1_2::IDXGIFactory2;
use winapi::shared::minwindef::{TRUE, FALSE};
use winapi::shared::windef::HWND;
use winapi::shared::winerror::S_OK;
use winapi::um::d3d11::ID3D11Device;
use winapi::um::dcomp::IDCompositionDevice;
use winapi::um::dcomp::IDCompositionTarget;
use winapi::um::dcomp::IDCompositionVisual;

pub mod com;

pub struct DirectComposition {
    d3d_device: ComPtr<ID3D11Device>,
    dxgi_factory: ComPtr<IDXGIFactory2>,
    composition_device: ComPtr<IDCompositionDevice>,
    root_visual: ComPtr<IDCompositionVisual>,

    #[allow(unused)]  // Needs to be kept alive
    composition_target: ComPtr<IDCompositionTarget>,
}

impl DirectComposition {
    /// Initialize DirectComposition in the given window
    ///
    /// # Safety
    ///
    /// `hwnd` must be a valid handle to a window.
    pub unsafe fn new(hwnd: HWND) -> HResult<Self> {
        let mut feature_level_supported = 0;

        let d3d_device = ComPtr::new_with(|ptr_ptr| winapi::um::d3d11::D3D11CreateDevice(
            ptr::null_mut(),
            winapi::um::d3dcommon::D3D_DRIVER_TYPE_HARDWARE,
            ptr::null_mut(),
            winapi::um::d3d11::D3D11_CREATE_DEVICE_BGRA_SUPPORT |
            if cfg!(debug_assertions) {
                winapi::um::d3d11::D3D11_CREATE_DEVICE_DEBUG
            } else {
                0
            },
            ptr::null_mut(),
            0,
            winapi::um::d3d11::D3D11_SDK_VERSION,
            ptr_ptr,
            &mut feature_level_supported,
            ptr::null_mut(),
        ))?;

        let dxgi_device = d3d_device.cast::<winapi::shared::dxgi::IDXGIDevice>()?;

        // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404556(v=vs.85).aspx#code-snippet-1
        // “Because you can create a Direct3D device without creating a swap chain,
        //  you might need to retrieve the factory that is used to create the device
        //  in order to create a swap chain.”
        let adapter = ComPtr::new_with(|ptr_ptr| dxgi_device.GetAdapter(ptr_ptr))?;
        let dxgi_factory = ComPtr::<IDXGIFactory2>::new_with_uuid(|uuid, ptr_ptr| {
            adapter.GetParent(uuid, ptr_ptr)
        })?;

        // Create the DirectComposition device object.
        let composition_device = ComPtr::<IDCompositionDevice>::new_with_uuid(|uuid, ptr_ptr| {
            winapi::um::dcomp::DCompositionCreateDevice(&*dxgi_device, uuid,ptr_ptr)
        })?;

        // Create the composition target object based on the
        // specified application window.
        let composition_target = ComPtr::new_with(|ptr_ptr| {
            composition_device.CreateTargetForHwnd(hwnd, TRUE, ptr_ptr)
        })?;

        let root_visual = ComPtr::new_with(|ptr_ptr| composition_device.CreateVisual(ptr_ptr))?;
        composition_target.SetRoot(&*root_visual).to_result()?;

        Ok(DirectComposition {
            d3d_device, dxgi_factory, composition_device, composition_target, root_visual,
        })
    }

    /// Execute changes to the DirectComposition scene.
    pub fn commit(&self) -> HResult<()> {
        unsafe {
            self.composition_device.Commit().to_result()
        }
    }

    pub fn create_d3d_visual(&self, width: u32, height: u32) -> HResult<D3DVisual> {
        unsafe {
            let desc = DXGI_SWAP_CHAIN_DESC1 {
                Width: width,
                Height: height,
                Format: winapi::shared::dxgiformat::DXGI_FORMAT_B8G8R8A8_UNORM,
                Stereo: FALSE,
                SampleDesc: winapi::shared::dxgitype::DXGI_SAMPLE_DESC {
                    Count: 1,
                    Quality: 0,
                },
                BufferUsage: winapi::shared::dxgitype::DXGI_USAGE_RENDER_TARGET_OUTPUT,
                BufferCount: 2,
                Scaling: winapi::shared::dxgi1_2::DXGI_SCALING_STRETCH,
                SwapEffect: winapi::shared::dxgi::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
                AlphaMode:  winapi::shared::dxgi1_2::DXGI_ALPHA_MODE_PREMULTIPLIED,
                Flags: 0,
            };
            let swap_chain = ComPtr::<winapi::shared::dxgi1_2::IDXGISwapChain1>::new_with(|ptr_ptr| {
                self.dxgi_factory.CreateSwapChainForComposition(
                    as_ptr(&self.d3d_device),
                    &desc,
                    ptr::null_mut(),
                    ptr_ptr,
                )
            })?;
            let visual = ComPtr::new_with(|ptr_ptr| self.composition_device.CreateVisual(ptr_ptr))?;
            visual.SetContent(&*****swap_chain).to_result()?;
            self.root_visual.AddVisual(&*visual, FALSE, ptr::null_mut()).to_result()?;

            Ok(D3DVisual { visual, swap_chain })
        }
    }
}

/// A DirectComposition "visual" configured for rendering with Direct3D.
pub struct D3DVisual {
    visual: ComPtr<IDCompositionVisual>,
    swap_chain: ComPtr<winapi::shared::dxgi1_2::IDXGISwapChain1>,
}

impl D3DVisual {
    pub fn set_offset_x(&self, offset_x: f32) -> HResult<()> {
        unsafe {
            self.visual.SetOffsetX_1(offset_x).to_result()
        }
    }

    pub fn set_offset_y(&self, offset_y: f32) -> HResult<()> {
        unsafe {
            self.visual.SetOffsetY_1(offset_y).to_result()
        }
    }

    pub fn render_and_present_solid_frame(&self, composition: &DirectComposition, rgba: &[f32; 4])
                                          -> HResult<()> {
        unsafe {
            let back_buffer = ComPtr::<winapi::um::d3d11::ID3D11Texture2D>::new_with_uuid(|uuid, ptr_ptr| {
                self.swap_chain.GetBuffer(0, uuid, ptr_ptr)
            })?;
            let render_target = ComPtr::new_with(|ptr_ptr| {
                composition.d3d_device.CreateRenderTargetView(
                    as_ptr(&back_buffer), ptr::null_mut(), ptr_ptr,
                )
            })?;
            let context = ComPtr::new_with(|ptr_ptr| {
                composition.d3d_device.GetImmediateContext(ptr_ptr);
                S_OK
            })?;

            // FIXME: arbitrary D3D rendering here?
            context.ClearRenderTargetView(render_target.as_raw(), &rgba);

            self.swap_chain.Present(0, 0).to_result()
        }
    }
}
<|endoftext|>


<commit_before>//! The library provides [special functions][1].
//!
//! [1]: https://en.wikipedia.org/wiki/Special_functions

#![feature(phase)]

extern crate libc;

pub use beta::{ln_beta, inc_beta, inv_inc_beta};

mod beta;

#[link_name = "m"]
mod m {
    use libc::{c_double, c_int};

    extern {
        pub fn erf(x: c_double) -> c_double;
        pub fn erfc(x: c_double) -> c_double;
        pub fn lgamma_r(x: c_double, sign: &mut c_int) -> c_double;
    }
}

/// Computes the error function.
#[inline]
pub fn erf(x: f64) -> f64 {
    unsafe { m::erf(x) }
}

/// Computes the complementary error function.
#[inline]
pub fn erfc(x: f64) -> f64 {
    unsafe { m::erfc(x) }
}

/// Computes the natural logarithm of the gamma function.
#[inline]
pub fn ln_gamma(x: f64) -> (f64, i32) {
    let mut sign: i32 = 0;
    let value = unsafe { m::lgamma_r(x, &mut sign) };
    (value, sign)
}
<commit_msg>Updated the description of the library<commit_after>//! [Special functions][1].
//!
//! [1]: https://en.wikipedia.org/wiki/Special_functions

#![feature(phase)]

extern crate libc;

pub use beta::{ln_beta, inc_beta, inv_inc_beta};

mod beta;

#[link_name = "m"]
mod m {
    use libc::{c_double, c_int};

    extern {
        pub fn erf(x: c_double) -> c_double;
        pub fn erfc(x: c_double) -> c_double;
        pub fn lgamma_r(x: c_double, sign: &mut c_int) -> c_double;
    }
}

/// Computes the error function.
#[inline]
pub fn erf(x: f64) -> f64 {
    unsafe { m::erf(x) }
}

/// Computes the complementary error function.
#[inline]
pub fn erfc(x: f64) -> f64 {
    unsafe { m::erfc(x) }
}

/// Computes the natural logarithm of the gamma function.
#[inline]
pub fn ln_gamma(x: f64) -> (f64, i32) {
    let mut sign: i32 = 0;
    let value = unsafe { m::lgamma_r(x, &mut sign) };
    (value, sign)
}
<|endoftext|>


<commit_before>extern crate conduit;
extern crate mime = "mime-types";
extern crate time;

use std::fmt::Show;
use std::collections::HashMap;
use std::io;
use std::io::fs::File;
use std::io::util::NullReader;
use conduit::{Request, Response, Handler};

pub struct Static {
    path: Path,
    types: mime::Types
}

impl Static {
    pub fn new(path: Path) -> Static {
        Static {
            path: path,
            types: mime::Types::new()
                .ok().expect("Couldn't load mime-types")
        }
    }
}

impl Handler for Static {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show>> {
        let request_path = request.path().slice_from(1);
        let path = self.path.join(request_path);

        if !self.path.is_ancestor_of(&path) {
            return Ok(not_found())
        }

        let mime = self.types.mime_for_path(&path);
        let mut file = match File::open(&path) {
            Ok(f) => f,
            Err(..) => return Ok(not_found()),
        };
        let stat = try!(file.stat().map_err(|e| box e as Box<Show>));
        match stat.kind {
            io::TypeDirectory => return Ok(not_found()),
            _ => {}
        }
        let ts = time::Timespec {
            sec: (stat.modified as i64) / 1000,
            nsec: (((stat.modified as u32) % 1000) as i32) * 1000000
        };
        let tm = time::at(ts).to_utc();

        let mut headers = HashMap::new();
        headers.insert("Content-Type".to_string(), vec![mime.to_string()]);
        headers.insert("Content-Length".to_string(), vec![stat.size.to_string()]);
        headers.insert("Last-Modified".to_string(),
                       vec![tm.strftime("%a, %d %b %Y %T GMT")]);

        Ok(Response {
            status: (200, "OK"),
            headers: headers,
            body: box file as Box<Reader + Send>
        })
    }
}

fn not_found() -> Response {
    Response {
        status: (404, "Not Found"),
        headers: HashMap::new(),
        body: box NullReader,
    }
}

#[cfg(test)]
mod tests {
    extern crate test = "conduit-test";

    use std::io::{fs, File, TempDir, UserRWX};

    use conduit;
    use conduit::Handler;
    use Static;

    #[test]
    fn test_static() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        let handler = Static::new(root.clone());
        File::create(&root.join("Cargo.toml")).write(b"[package]").unwrap();
        let mut req = test::MockRequest::new(conduit::Get, "/Cargo.toml");
        let mut res = handler.call(&mut req).ok().expect("No response");
        let body = res.body.read_to_string().ok().expect("No body");
        assert_eq!(body.as_slice(), "[package]");
        assert_eq!(res.headers.find_equiv(&"Content-Type"),
                   Some(&vec!("text/plain".to_string())));
        assert_eq!(res.headers.find_equiv(&"Content-Length"),
                   Some(&vec!["9".to_string()]));
    }

    #[test]
    fn test_mime_types() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        fs::mkdir(&root.join("src"), UserRWX).unwrap();
        File::create(&root.join("src/fixture.css")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/src/fixture.css");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.headers.find_equiv(&"Content-Type"),
                   Some(&vec!("text/css".to_string())));
        assert_eq!(res.headers.find_equiv(&"Content-Length"),
                   Some(&vec!["0".to_string()]));
    }

    #[test]
    fn test_missing() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/nope");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 404);
    }

    #[test]
    fn test_dir() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        fs::mkdir(&root.join("foo"), UserRWX).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/foo");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 404);
    }

    #[test]
    fn last_modified() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        File::create(&root.join("test")).unwrap();
        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/test");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 200);
        assert!(res.headers.find_equiv(&"Last-Modified").is_some());
    }
}
<commit_msg>Update to master<commit_after>extern crate conduit;
extern crate mime = "mime-types";
extern crate time;

use std::fmt::Show;
use std::collections::HashMap;
use std::io;
use std::io::fs::File;
use std::io::util::NullReader;
use conduit::{Request, Response, Handler};

pub struct Static {
    path: Path,
    types: mime::Types
}

impl Static {
    pub fn new(path: Path) -> Static {
        Static {
            path: path,
            types: mime::Types::new()
                .ok().expect("Couldn't load mime-types")
        }
    }
}

impl Handler for Static {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show + 'static>> {
        let request_path = request.path().slice_from(1);
        let path = self.path.join(request_path);

        if !self.path.is_ancestor_of(&path) {
            return Ok(not_found())
        }

        let mime = self.types.mime_for_path(&path);
        let mut file = match File::open(&path) {
            Ok(f) => f,
            Err(..) => return Ok(not_found()),
        };
        let stat = try!(file.stat().map_err(|e| box e as Box<Show>));
        match stat.kind {
            io::TypeDirectory => return Ok(not_found()),
            _ => {}
        }
        let ts = time::Timespec {
            sec: (stat.modified as i64) / 1000,
            nsec: (((stat.modified as u32) % 1000) as i32) * 1000000
        };
        let tm = time::at(ts).to_utc();

        let mut headers = HashMap::new();
        headers.insert("Content-Type".to_string(), vec![mime.to_string()]);
        headers.insert("Content-Length".to_string(), vec![stat.size.to_string()]);
        headers.insert("Last-Modified".to_string(),
                       vec![tm.strftime("%a, %d %b %Y %T GMT")]);

        Ok(Response {
            status: (200, "OK"),
            headers: headers,
            body: box file as Box<Reader + Send>
        })
    }
}

fn not_found() -> Response {
    Response {
        status: (404, "Not Found"),
        headers: HashMap::new(),
        body: box NullReader,
    }
}

#[cfg(test)]
mod tests {
    extern crate test = "conduit-test";

    use std::io::{fs, File, TempDir, UserRWX};

    use conduit;
    use conduit::Handler;
    use Static;

    #[test]
    fn test_static() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        let handler = Static::new(root.clone());
        File::create(&root.join("Cargo.toml")).write(b"[package]").unwrap();
        let mut req = test::MockRequest::new(conduit::Get, "/Cargo.toml");
        let mut res = handler.call(&mut req).ok().expect("No response");
        let body = res.body.read_to_string().ok().expect("No body");
        assert_eq!(body.as_slice(), "[package]");
        assert_eq!(res.headers.find_equiv(&"Content-Type"),
                   Some(&vec!("text/plain".to_string())));
        assert_eq!(res.headers.find_equiv(&"Content-Length"),
                   Some(&vec!["9".to_string()]));
    }

    #[test]
    fn test_mime_types() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        fs::mkdir(&root.join("src"), UserRWX).unwrap();
        File::create(&root.join("src/fixture.css")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/src/fixture.css");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.headers.find_equiv(&"Content-Type"),
                   Some(&vec!("text/css".to_string())));
        assert_eq!(res.headers.find_equiv(&"Content-Length"),
                   Some(&vec!["0".to_string()]));
    }

    #[test]
    fn test_missing() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/nope");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 404);
    }

    #[test]
    fn test_dir() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        fs::mkdir(&root.join("foo"), UserRWX).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/foo");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 404);
    }

    #[test]
    fn last_modified() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        File::create(&root.join("test")).unwrap();
        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/test");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 200);
        assert!(res.headers.find_equiv(&"Last-Modified").is_some());
    }
}
<|endoftext|>