<commit_before>//! A small library meant to be used as a build dependency with Cargo for easily
//! integrating [ISPC](https://ispc.github.io/) code into Rust projects.
//!
//! # Using ispc-rs
//!
//! You'll want to add a build script to your crate (`build.rs`), tell Cargo about it and add this crate
//! as a build dependency.
//!
//! ```toml
//! # Cargo.toml
//! [package]
//! # ...
//! build = "build.rs"
//!
//! [build-dependencies]
//! ispc = "0.0.1"
//! ```
//!
//! Now you can use `ispc` to compile your code into a static library:
//!
//! ```rust
//! extern crate ispc;
//!
//! fn main() {
//!     let ispc_files = vec!["src/simple.ispc"];
//!     // Optional: Only re-run the build script if the ISPC files have been changed
//!     for s in &ispc_files[..] {
//!         println!("cargo:rerun-if-changed={}", s);
//!     }
//! 	// Compile our ISPC library and make sure it went ok
//!     if !ispc::compile_library("simple", &ispc_files[..]) {
//!         panic!("Failed to compile ISPC library 'simple'");
//!     }
//! }
//! ```
//!
//! Running `cargo build` should now build your ISPC files into a library and link your Rust
//! application with it. For extra convenience the `ispc_module` macro is provided to import
//! bindings to the library generated with [rust-bindgen](https://github.com/crabtw/rust-bindgen)
//! into a module of the same name. Note that all the functions imported will be unsafe as they're
//! the raw C bindings to your lib.
//!
//! ```rust
//! #[macro_use]
//! extern crate ispc;
//!
//! // Functions exported from simple will be callable under simple::*
//! ispc_module!(simple);
//! ```
//!
//! Some more complete examples can be found in the
//! [examples/](https://github.com/Twinklebear/ispc-rs/tree/master/examples) folder.
//!
//! # Compile-time Requirements
//!
//! Both the [ISPC compiler](https://ispc.github.io/) and [libclang](http://clang.llvm.org/)
//! (for [rust-bindgen](https://github.com/crabtw/rust-bindgen)) must be available in your path.
//!
//! ## Windows Users
//!
//! You'll need Visual Studio and will have to use the MSVC ABI version of Rust since ISPC
//! and Clang link with MSVC on Windows. For bindgen to find libclang you'll need to copy
//! `libclang.lib` to `clang.lib` and place it in your path.
//!
//! I've also had issues with multiple definition link errors coming up when compiling multiple
//! ISPC files into a library on MSVC, I haven't figured out the cause yet. On Linux the repeated
//! symbols are defined in each object as well but the linker doesn't seem to mind.

#![allow(dead_code)]

extern crate bindgen;
extern crate gcc;

use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;
use std::process::{Command, ExitStatus};
use std::env;

/// Convenience macro for generating the module to hold the raw/unsafe ISPC bindings.
///
/// In addition to building the library with ISPC we use rust-bindgen to generate
/// a rust module containing bindings to the functions exported from ISPC. These
/// can be imported by passing the name of your library to the `ispc_module` macro.
///
/// # Example
///
/// ```rust
/// #[macro_use]
/// extern crate ispc;
///
/// // Functions exported from foo will be callable under foo::*
/// ispc_module!(foo);
/// ```
#[macro_export]
macro_rules! ispc_module {
    ($lib:ident) => (
        #[allow(dead_code, non_camel_case_types)]
        mod $lib {
            include!(concat!(env!("OUT_DIR"), "/", stringify!($lib), ".rs"));
        }
    )
}

/// Compile the list of ISPC files into a static library and generate bindings
/// using bindgen.
///
/// Returns true if compilation and binding generation
/// succeeded, will panic or return false depending on what operations failed.
/// If compilation fails your build script would likely want to panic to show the
/// compilation errors.
///
/// The library name should not contain a lib prefix or a lib extension like
/// '.a' or '.lib', the appropriate prefix and suffix wil be added based on
/// the compilation target.
///
/// # Example
/// ```no_run
/// ispc::compile_library("foo", &["src/foo.ispc", "src/bar.ispc"]);
/// ```
pub fn compile_library(lib: &str, files: &[&str]) -> bool {
    let mut cfg = Config::new();
    for f in &files[..] {
        cfg.file(*f);
    }
    cfg.compile(lib)
}

/// Extra configuration to be passed to ISPC
pub struct Config {
    ispc_files: Vec<PathBuf>,
    objects: Vec<PathBuf>,
    headers: Vec<PathBuf>,
    include_directories: Vec<PathBuf>,
    // We need to generate a single header so we have one header to give bindgen
    bindgen_header: PathBuf,
    // These options are set from the environment if not set by the user
    out_dir: Option<PathBuf>,
    debug: Option<bool>,
    opt_level: Option<u32>,
    target: Option<String>,
    cargo_metadata: bool,
}

impl Config {
    pub fn new() -> Config {
        Config {
            ispc_files: Vec::new(),
            objects: Vec::new(),
            headers: Vec::new(),
            include_directories: Vec::new(),
            bindgen_header: PathBuf::new(),
            out_dir: None,
            debug: None,
            opt_level: None,
            target: None,
            cargo_metadata: true,
        }
    }
    /// Add an ISPC file to be compiled
    pub fn file<P: AsRef<Path>>(&mut self, p: P) -> &mut Config {
        self.ispc_files.push(p.as_ref().to_path_buf());
        self
    }
    /// Set the output directory to override the default of `env!("OUT_DIR")`
    pub fn out_dir<P: AsRef<Path>>(&mut self, p: P) -> &mut Config {
        self.out_dir = Some(p.as_ref().to_path_buf());
        self
    }
    /// Set whether debug symbols should be generated, symbols are generated by
    /// default if `env!("DEBUG") == "true"`
    pub fn debug(&mut self, debug: bool) -> &mut Config {
        self.debug = Some(debug);
        self
    }
    /// Set the optimization level to override the default of `env!("OPT_LEVEL")`
    pub fn opt_level(&mut self, opt_level: u32) -> &mut Config {
        self.opt_level = Some(opt_level);
        self
    }
    /// Set the target triple to compile for, overriding the default of `env!("TARGET")`
    pub fn target(&mut self, target: &str) -> &mut Config {
        self.target = Some(target.to_string());
        self
    }
    /// Set whether Cargo metadata should be emitted to link to the compiled library
    pub fn cargo_metadata(&mut self, metadata: bool) -> &mut Config {
        self.cargo_metadata = metadata;
        self
    }
    /// Run the compiler, producing the library `lib`. Returns false
    /// if compilation fails, in a build script to see ISPC compilation
    /// errors the caller should panic in this case as they'll be logged to stderr
    ///
    /// The library name should not have any prefix or suffix, e.g. instead of
    /// `libexample.a` or `example.lib` simply pass `example`
    pub fn compile(&mut self, lib: &str) -> bool {
        let dst = self.get_out_dir();
        println!("dst = {}", dst.display());
        let default_args = self.default_args();
        for s in &self.ispc_files[..] {
            let fname = s.file_stem().expect("ISPC source files must be files")
                .to_str().expect("ISPC source file names must be valid UTF-8");

            let ispc_fname = String::from(fname) + "_ispc";
            let object = dst.join(ispc_fname.clone()).with_extension("o");
            let header = dst.join(ispc_fname).with_extension("h");
            let status = Command::new("ispc").args(&default_args[..])
                .arg(s).arg("-o").arg(&object).arg("-h").arg(&header)
                .status().unwrap();

            if !status.success() {
                return false;
            }
            self.objects.push(object);
            self.headers.push(header);
        }
        if !self.assemble(lib).success() {
            return false;
        }
        // Now generate a header we can give to bindgen and generate bindings
        self.generate_bindgen_header(lib);
        let mut bindings = bindgen::builder();
        bindings.forbid_unknown_types()
            .header(self.bindgen_header.to_str().unwrap())
            .link_static(lib);
        let bindgen_file = dst.join(lib).with_extension("rs");
        match bindings.generate() {
            Ok(b) => b.write_to_file(bindgen_file).unwrap(),
            Err(_) => return false,
        };
        // Tell cargo where to find the library we just built if we're running
        // in a build script
        self.print(&format!("cargo:rustc-link-search=native={}", dst.display()));
        true
    }
    /// Link the ISPC code into a static library on Unix using `ar`
    #[cfg(unix)]
    fn assemble(&self, lib: &str) -> ExitStatus {
        Command::new("ar").arg("crus")
            .arg(format!("lib{}.a", lib))
            .args(&self.objects[..])
            .current_dir(&self.get_out_dir())
            .status().unwrap()
    }
    /// Link the ISPC code into a static library on Windows using `lib.exe`
    #[cfg(windows)]
    fn assemble(&self, lib: &str) -> ExitStatus {
        let target = self.get_target();
        let mut lib_cmd = gcc::windows_registry::find_tool(&target[..], "lib.exe")
            .expect("Failed to find lib.exe for MSVC toolchain, aborting")
            .to_command();
        lib_cmd.arg(format!("/OUT:{}.lib", lib))
            .args(&self.objects[..])
            .current_dir(&self.get_out_dir())
            .status().unwrap()
    }
    /// Generate a single header that includes all of our ISPC headers which we can
    /// pass to bindgen
    fn generate_bindgen_header(&mut self, lib: &str) {
        self.bindgen_header = self.get_out_dir().join(format!("_{}_ispc_bindgen_header.h", lib));
        let mut include_file = File::create(&self.bindgen_header).unwrap();
        for h in &self.headers[..] {
            write!(include_file, "#include \"{}\"\n", h.display()).unwrap();
        }
    }
    /// Build up list of basic args for each target, debug, opt level, etc.
    fn default_args(&self) -> Vec<String> {
        let mut ispc_args = Vec::new();
        if self.get_debug() {
            ispc_args.push(String::from("-g"));
        }
        let opt_level = self.get_opt_level();
        if opt_level == 0 {
            ispc_args.push(String::from("-O0"));
        } else if opt_level == 1 {
            ispc_args.push(String::from("-O1"));
        } else if opt_level == 2 {
            ispc_args.push(String::from("-O2"));
        } else if opt_level == 3 {
            ispc_args.push(String::from("-O3"));
        }
        // If we're on Unix we need position independent code
        if cfg!(unix) {
            ispc_args.push(String::from("--pic"));
        }
        ispc_args
    }
    /// Returns the user-set output directory if they've set one, otherwise
    /// returns env("OUT_DIR")
    fn get_out_dir(&self) -> PathBuf {
        self.out_dir.clone().unwrap_or_else(|| {
            // TODO: The */out part is incorrectly interpreted as the file name so append a /
            env::var_os("OUT_DIR").map(PathBuf::from).unwrap()
        })
    }
    /// Returns the user-set debug flag if they've set one, otherwise returns
    /// env("DEBUG")
    fn get_debug(&self) -> bool {
        self.debug.unwrap_or_else(|| {
            env::var("DEBUG").map(|x| x == "true").unwrap()
        })
    }
    /// Returns the user-set optimization level if they've set one, otherwise
    /// returns env("OPT_LEVEL")
    fn get_opt_level(&self) -> u32 {
        self.opt_level.unwrap_or_else(|| {
            let opt = env::var("OPT_LEVEL").unwrap();
            opt.parse::<u32>().unwrap()
        })
    }
    /// Returns the user-set target triple if they're set one, otherwise
    /// returns env("TARGET")
    fn get_target(&self) -> String {
        self.target.clone().unwrap_or_else(|| {
            env::var("TARGET").unwrap()
        })
    }
    /// Print out cargo metadata if enabled
    fn print(&self, s: &str) {
        if self.cargo_metadata {
            println!("{}", s);
        }
    }
}

<commit_msg>Add option to make the ISPC module functions public<commit_after>//! A small library meant to be used as a build dependency with Cargo for easily
//! integrating [ISPC](https://ispc.github.io/) code into Rust projects.
//!
//! # Using ispc-rs
//!
//! You'll want to add a build script to your crate (`build.rs`), tell Cargo about it and add this crate
//! as a build dependency.
//!
//! ```toml
//! # Cargo.toml
//! [package]
//! # ...
//! build = "build.rs"
//!
//! [build-dependencies]
//! ispc = "0.0.1"
//! ```
//!
//! Now you can use `ispc` to compile your code into a static library:
//!
//! ```rust
//! extern crate ispc;
//!
//! fn main() {
//!     let ispc_files = vec!["src/simple.ispc"];
//!     // Optional: Only re-run the build script if the ISPC files have been changed
//!     for s in &ispc_files[..] {
//!         println!("cargo:rerun-if-changed={}", s);
//!     }
//! 	// Compile our ISPC library and make sure it went ok
//!     if !ispc::compile_library("simple", &ispc_files[..]) {
//!         panic!("Failed to compile ISPC library 'simple'");
//!     }
//! }
//! ```
//!
//! Running `cargo build` should now build your ISPC files into a library and link your Rust
//! application with it. For extra convenience the `ispc_module` macro is provided to import
//! bindings to the library generated with [rust-bindgen](https://github.com/crabtw/rust-bindgen)
//! into a module of the same name. Note that all the functions imported will be unsafe as they're
//! the raw C bindings to your lib.
//!
//! ```rust
//! #[macro_use]
//! extern crate ispc;
//!
//! // Functions exported from simple will be callable under simple::*
//! ispc_module!(simple);
//! ```
//!
//! Some more complete examples can be found in the
//! [examples/](https://github.com/Twinklebear/ispc-rs/tree/master/examples) folder.
//!
//! # Compile-time Requirements
//!
//! Both the [ISPC compiler](https://ispc.github.io/) and [libclang](http://clang.llvm.org/)
//! (for [rust-bindgen](https://github.com/crabtw/rust-bindgen)) must be available in your path.
//!
//! ## Windows Users
//!
//! You'll need Visual Studio and will have to use the MSVC ABI version of Rust since ISPC
//! and Clang link with MSVC on Windows. For bindgen to find libclang you'll need to copy
//! `libclang.lib` to `clang.lib` and place it in your path.
//!
//! I've also had issues with multiple definition link errors coming up when compiling multiple
//! ISPC files into a library on MSVC, I haven't figured out the cause yet. On Linux the repeated
//! symbols are defined in each object as well but the linker doesn't seem to mind.

#![allow(dead_code)]

extern crate bindgen;
extern crate gcc;

use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;
use std::process::{Command, ExitStatus};
use std::env;

/// Convenience macro for generating the module to hold the raw/unsafe ISPC bindings.
///
/// In addition to building the library with ISPC we use rust-bindgen to generate
/// a rust module containing bindings to the functions exported from ISPC. These
/// can be imported by passing the name of your library to the `ispc_module` macro.
///
/// # Example
///
/// ```rust
/// #[macro_use]
/// extern crate ispc;
///
/// // Functions exported from foo will be callable under foo::*
/// ispc_module!(foo);
/// ```
#[macro_export]
macro_rules! ispc_module {
    ($lib:ident) => (
        #[allow(dead_code, non_camel_case_types)]
        mod $lib {
            include!(concat!(env!("OUT_DIR"), "/", stringify!($lib), ".rs"));
        }
    );
    (pub $lib:ident) => (
        #[allow(dead_code, non_camel_case_types)]
        pub mod $lib {
            include!(concat!(env!("OUT_DIR"), "/", stringify!($lib), ".rs"));
        }
    )
}

/// Compile the list of ISPC files into a static library and generate bindings
/// using bindgen.
///
/// Returns true if compilation and binding generation
/// succeeded, will panic or return false depending on what operations failed.
/// If compilation fails your build script would likely want to panic to show the
/// compilation errors.
///
/// The library name should not contain a lib prefix or a lib extension like
/// '.a' or '.lib', the appropriate prefix and suffix wil be added based on
/// the compilation target.
///
/// # Example
/// ```no_run
/// ispc::compile_library("foo", &["src/foo.ispc", "src/bar.ispc"]);
/// ```
pub fn compile_library(lib: &str, files: &[&str]) -> bool {
    let mut cfg = Config::new();
    for f in &files[..] {
        cfg.file(*f);
    }
    cfg.compile(lib)
}

/// Extra configuration to be passed to ISPC
pub struct Config {
    ispc_files: Vec<PathBuf>,
    objects: Vec<PathBuf>,
    headers: Vec<PathBuf>,
    include_directories: Vec<PathBuf>,
    // We need to generate a single header so we have one header to give bindgen
    bindgen_header: PathBuf,
    // These options are set from the environment if not set by the user
    out_dir: Option<PathBuf>,
    debug: Option<bool>,
    opt_level: Option<u32>,
    target: Option<String>,
    cargo_metadata: bool,
}

impl Config {
    pub fn new() -> Config {
        Config {
            ispc_files: Vec::new(),
            objects: Vec::new(),
            headers: Vec::new(),
            include_directories: Vec::new(),
            bindgen_header: PathBuf::new(),
            out_dir: None,
            debug: None,
            opt_level: None,
            target: None,
            cargo_metadata: true,
        }
    }
    /// Add an ISPC file to be compiled
    pub fn file<P: AsRef<Path>>(&mut self, p: P) -> &mut Config {
        self.ispc_files.push(p.as_ref().to_path_buf());
        self
    }
    /// Set the output directory to override the default of `env!("OUT_DIR")`
    pub fn out_dir<P: AsRef<Path>>(&mut self, p: P) -> &mut Config {
        self.out_dir = Some(p.as_ref().to_path_buf());
        self
    }
    /// Set whether debug symbols should be generated, symbols are generated by
    /// default if `env!("DEBUG") == "true"`
    pub fn debug(&mut self, debug: bool) -> &mut Config {
        self.debug = Some(debug);
        self
    }
    /// Set the optimization level to override the default of `env!("OPT_LEVEL")`
    pub fn opt_level(&mut self, opt_level: u32) -> &mut Config {
        self.opt_level = Some(opt_level);
        self
    }
    /// Set the target triple to compile for, overriding the default of `env!("TARGET")`
    pub fn target(&mut self, target: &str) -> &mut Config {
        self.target = Some(target.to_string());
        self
    }
    /// Set whether Cargo metadata should be emitted to link to the compiled library
    pub fn cargo_metadata(&mut self, metadata: bool) -> &mut Config {
        self.cargo_metadata = metadata;
        self
    }
    /// Run the compiler, producing the library `lib`. Returns false
    /// if compilation fails, in a build script to see ISPC compilation
    /// errors the caller should panic in this case as they'll be logged to stderr
    ///
    /// The library name should not have any prefix or suffix, e.g. instead of
    /// `libexample.a` or `example.lib` simply pass `example`
    pub fn compile(&mut self, lib: &str) -> bool {
        let dst = self.get_out_dir();
        println!("dst = {}", dst.display());
        let default_args = self.default_args();
        for s in &self.ispc_files[..] {
            let fname = s.file_stem().expect("ISPC source files must be files")
                .to_str().expect("ISPC source file names must be valid UTF-8");

            let ispc_fname = String::from(fname) + "_ispc";
            let object = dst.join(ispc_fname.clone()).with_extension("o");
            let header = dst.join(ispc_fname).with_extension("h");
            let status = Command::new("ispc").args(&default_args[..])
                .arg(s).arg("-o").arg(&object).arg("-h").arg(&header)
                .status().unwrap();

            if !status.success() {
                return false;
            }
            self.objects.push(object);
            self.headers.push(header);
        }
        if !self.assemble(lib).success() {
            return false;
        }
        // Now generate a header we can give to bindgen and generate bindings
        self.generate_bindgen_header(lib);
        let mut bindings = bindgen::builder();
        bindings.forbid_unknown_types()
            .header(self.bindgen_header.to_str().unwrap())
            .link_static(lib);
        let bindgen_file = dst.join(lib).with_extension("rs");
        match bindings.generate() {
            Ok(b) => b.write_to_file(bindgen_file).unwrap(),
            Err(_) => return false,
        };
        // Tell cargo where to find the library we just built if we're running
        // in a build script
        self.print(&format!("cargo:rustc-link-search=native={}", dst.display()));
        true
    }
    /// Link the ISPC code into a static library on Unix using `ar`
    #[cfg(unix)]
    fn assemble(&self, lib: &str) -> ExitStatus {
        Command::new("ar").arg("crus")
            .arg(format!("lib{}.a", lib))
            .args(&self.objects[..])
            .current_dir(&self.get_out_dir())
            .status().unwrap()
    }
    /// Link the ISPC code into a static library on Windows using `lib.exe`
    #[cfg(windows)]
    fn assemble(&self, lib: &str) -> ExitStatus {
        let target = self.get_target();
        let mut lib_cmd = gcc::windows_registry::find_tool(&target[..], "lib.exe")
            .expect("Failed to find lib.exe for MSVC toolchain, aborting")
            .to_command();
        lib_cmd.arg(format!("/OUT:{}.lib", lib))
            .args(&self.objects[..])
            .current_dir(&self.get_out_dir())
            .status().unwrap()
    }
    /// Generate a single header that includes all of our ISPC headers which we can
    /// pass to bindgen
    fn generate_bindgen_header(&mut self, lib: &str) {
        self.bindgen_header = self.get_out_dir().join(format!("_{}_ispc_bindgen_header.h", lib));
        let mut include_file = File::create(&self.bindgen_header).unwrap();
        for h in &self.headers[..] {
            write!(include_file, "#include \"{}\"\n", h.display()).unwrap();
        }
    }
    /// Build up list of basic args for each target, debug, opt level, etc.
    fn default_args(&self) -> Vec<String> {
        let mut ispc_args = Vec::new();
        if self.get_debug() {
            ispc_args.push(String::from("-g"));
        }
        let opt_level = self.get_opt_level();
        if opt_level == 0 {
            ispc_args.push(String::from("-O0"));
        } else if opt_level == 1 {
            ispc_args.push(String::from("-O1"));
        } else if opt_level == 2 {
            ispc_args.push(String::from("-O2"));
        } else if opt_level == 3 {
            ispc_args.push(String::from("-O3"));
        }
        // If we're on Unix we need position independent code
        if cfg!(unix) {
            ispc_args.push(String::from("--pic"));
        }
        ispc_args
    }
    /// Returns the user-set output directory if they've set one, otherwise
    /// returns env("OUT_DIR")
    fn get_out_dir(&self) -> PathBuf {
        self.out_dir.clone().unwrap_or_else(|| {
            // TODO: The */out part is incorrectly interpreted as the file name so append a /
            env::var_os("OUT_DIR").map(PathBuf::from).unwrap()
        })
    }
    /// Returns the user-set debug flag if they've set one, otherwise returns
    /// env("DEBUG")
    fn get_debug(&self) -> bool {
        self.debug.unwrap_or_else(|| {
            env::var("DEBUG").map(|x| x == "true").unwrap()
        })
    }
    /// Returns the user-set optimization level if they've set one, otherwise
    /// returns env("OPT_LEVEL")
    fn get_opt_level(&self) -> u32 {
        self.opt_level.unwrap_or_else(|| {
            let opt = env::var("OPT_LEVEL").unwrap();
            opt.parse::<u32>().unwrap()
        })
    }
    /// Returns the user-set target triple if they're set one, otherwise
    /// returns env("TARGET")
    fn get_target(&self) -> String {
        self.target.clone().unwrap_or_else(|| {
            env::var("TARGET").unwrap()
        })
    }
    /// Print out cargo metadata if enabled
    fn print(&self, s: &str) {
        if self.cargo_metadata {
            println!("{}", s);
        }
    }
}

<|endoftext|>


<commit_before>//! Use this library to open a path or URL using the program configured on the system.
//!
//! # Usage
//!
//! The following should open the given URL in a web browser
//!
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::that("http://rust-lang.org").unwrap();
//! # }
//! ```
//!
//! # Notes
//!
//! As an operating system program is used, chances are that the open operation fails.
//! Therefore, you are advised to at least check the result with `.is_err()` and
//! behave accordingly, e.g. by letting the user know what you tried to open, and failed.
//!
//! ```
//! # fn doit() {
//! match open::that("http://rust-lang.org") {
//!     Ok(exit_status) => {
//!         if exit_status.success() {
//!             println!("Look at your browser!");
//!         } else {
//!             if let Some(code) = exit_status.code() {
//!                 println!("Command returned non-zero exit status {}!", code);
//!             } else {
//!                 println!("Command returned with unknown exit status!");
//!             }
//!         }
//!     }
//!     Err(why) => println!("Failure to execute command: {}", why),
//! }
//! # }
//! ```
#[cfg(windows)]
extern crate winapi;

#[cfg(not(target_os = "windows"))]
use std::process::{Command, Stdio};

use std::ffi::OsStr;
use std::io;
use std::process::ExitStatus;

#[cfg(not(any(target_os = "windows", target_os = "macos")))]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    let path_ref = path.as_ref();
    let mut last_err: io::Error = io::Error::from_raw_os_error(0);
    for program in &["xdg-open", "gnome-open", "kde-open"] {
        match Command::new(program)
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .arg(path_ref)
            .spawn()
        {
            Ok(mut child) => return child.wait(),
            Err(err) => {
                last_err = err;
                continue;
            }
        }
    }
    Err(last_err)
}

#[cfg(target_os = "windows")]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    use std::os::windows::ffi::OsStrExt;
    use std::os::windows::process::ExitStatusExt;
    use std::ptr;
    use winapi::ctypes::c_int;
    use winapi::um::shellapi::ShellExecuteW;

    const SW_SHOW: c_int = 5;

    let path = windows::convert_path(path.as_ref())?;
    let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
    let result = unsafe {
        ShellExecuteW(
            ptr::null_mut(),
            operation.as_ptr(),
            path.as_ptr(),
            ptr::null(),
            ptr::null(),
            SW_SHOW,
        )
    };
    if result as c_int > 32 {
        Ok(ExitStatus::from_raw(0))
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(target_os = "macos")]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    Command::new("open")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .arg(path.as_ref())
        .spawn()?
        .wait()
}

#[cfg(windows)]
mod windows {
    use std::ffi::OsStr;
    use std::io;
    use std::os::windows::ffi::OsStrExt;

    pub fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
        let mut maybe_result: Vec<_> = path.encode_wide().collect();
        if maybe_result.iter().any(|&u| u == 0) {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "path contains NUL byte(s)",
            ));
        }
        maybe_result.push(0);
        Ok(maybe_result)
    }
}
<commit_msg>Add support for Linux in WSL through wslu/wslview<commit_after>//! Use this library to open a path or URL using the program configured on the system.
//!
//! # Usage
//!
//! The following should open the given URL in a web browser
//!
//! ```test_harness,no_run
//! extern crate open;
//!
//! # #[test]
//! # fn doit() {
//! open::that("http://rust-lang.org").unwrap();
//! # }
//! ```
//!
//! # Notes
//!
//! As an operating system program is used, chances are that the open operation fails.
//! Therefore, you are advised to at least check the result with `.is_err()` and
//! behave accordingly, e.g. by letting the user know what you tried to open, and failed.
//!
//! ```
//! # fn doit() {
//! match open::that("http://rust-lang.org") {
//!     Ok(exit_status) => {
//!         if exit_status.success() {
//!             println!("Look at your browser!");
//!         } else {
//!             if let Some(code) = exit_status.code() {
//!                 println!("Command returned non-zero exit status {}!", code);
//!             } else {
//!                 println!("Command returned with unknown exit status!");
//!             }
//!         }
//!     }
//!     Err(why) => println!("Failure to execute command: {}", why),
//! }
//! # }
//! ```
#[cfg(windows)]
extern crate winapi;

#[cfg(not(target_os = "windows"))]
use std::process::{Command, Stdio};

use std::ffi::OsStr;
use std::io;
use std::process::ExitStatus;

#[cfg(not(any(target_os = "windows", target_os = "macos")))]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    let path_ref = path.as_ref();
    let mut last_err: io::Error = io::Error::from_raw_os_error(0);
    for program in &["wslopen", "xdg-open", "gnome-open", "kde-open"] {
        match Command::new(program)
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .arg(path_ref)
            .spawn()
        {
            Ok(mut child) => return child.wait(),
            Err(err) => {
                last_err = err;
                continue;
            }
        }
    }
    Err(last_err)
}

#[cfg(target_os = "windows")]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    use std::os::windows::ffi::OsStrExt;
    use std::os::windows::process::ExitStatusExt;
    use std::ptr;
    use winapi::ctypes::c_int;
    use winapi::um::shellapi::ShellExecuteW;

    const SW_SHOW: c_int = 5;

    let path = windows::convert_path(path.as_ref())?;
    let operation: Vec<u16> = OsStr::new("open\0").encode_wide().collect();
    let result = unsafe {
        ShellExecuteW(
            ptr::null_mut(),
            operation.as_ptr(),
            path.as_ptr(),
            ptr::null(),
            ptr::null(),
            SW_SHOW,
        )
    };
    if result as c_int > 32 {
        Ok(ExitStatus::from_raw(0))
    } else {
        Err(io::Error::last_os_error())
    }
}

#[cfg(target_os = "macos")]
pub fn that<T: AsRef<OsStr> + Sized>(path: T) -> io::Result<ExitStatus> {
    Command::new("open")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .arg(path.as_ref())
        .spawn()?
        .wait()
}

#[cfg(windows)]
mod windows {
    use std::ffi::OsStr;
    use std::io;
    use std::os::windows::ffi::OsStrExt;

    pub fn convert_path(path: &OsStr) -> io::Result<Vec<u16>> {
        let mut maybe_result: Vec<_> = path.encode_wide().collect();
        if maybe_result.iter().any(|&u| u == 0) {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "path contains NUL byte(s)",
            ));
        }
        maybe_result.push(0);
        Ok(maybe_result)
    }
}
<|endoftext|>


<commit_before>#![feature(test)]
#![feature(core_simd)]
#![feature(step_by)]

mod vector_types;
use vector_types::*;
extern crate test;
use test::Bencher;
use std::simd::f32x4;

pub fn add_one(data: &mut DataVector)
{
	let increment_vector = f32x4(1.0, 1.0, 1.0, 1.0);
	let data_length = data.len();
	let scalar_length = data_length % 4;
	let vectorization_length = data_length - scalar_length;
	let mut array = &mut data.data;
	for i in (0..vectorization_length).step_by(4)
	{
		let vector = f32x4(array[i], array[i+1], array[i+2], array[i+3]);
		let incremted = vector + increment_vector;
		array[i] = incremted.0;
		array[i + 1] = incremted.1;
		array[i + 2] = incremted.2;
		array[i + 3] = incremted.3;
	}

	for i in vectorization_length..data_length
	{
		array[i] = array[i] + 1.0;
	}
}

pub fn add_one_scalar(data: &mut DataVector)
{
	let data_length = data.len();
	let mut array = &mut data.data;
	for i in 0..data_length
	{
		array[i] = array[i] + 1.0;
	}
}

#[test]
fn add_one_test()
{
	let mut data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
	let mut result = DataVector::new(&mut data);
	add_one(&mut result);
	assert_eq!(result.data, [2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]);
}

#[test]
fn add_one_test_odd_number_of_elements()
{
	let mut data = [1.0, 2.0, 3.0];
	let mut result = DataVector::new(&mut data);
	add_one(&mut result);
	assert_eq!(result.data, [2.0, 3.0, 4.0]);
}

#[bench]
fn add_one_benchmark(b: &mut Bencher)
{
	let mut data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
	let mut result = DataVector::new(&mut data);
	b.iter(|| {
		add_one(&mut result);
		return result.data[0];
		});
}

#[bench]
fn add_one_scalar_benchmark(b: &mut Bencher)
{
	let mut data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
	let mut result = DataVector::new(&mut data);
	b.iter(|| {
		add_one_scalar(&mut result);
		return result.data[0];
		});
}<commit_msg>Ignoring warnings for now: The warnings are valid and should be treated correctly but for now I just want to run some tests and so it's okay to ignore them.<commit_after>#![feature(test)]
#![feature(core_simd)]
#![feature(step_by)]
mod vector_types;
use vector_types::*;
extern crate test;
#[allow(unused_imports)]
use test::Bencher;
#[allow(deprecated)]
use std::simd::f32x4;

#[allow(deprecated)]
pub fn add_one(data: &mut DataVector)
{
	let increment_vector = f32x4(1.0, 1.0, 1.0, 1.0);
	let data_length = data.len();
	let scalar_length = data_length % 4;
	let vectorization_length = data_length - scalar_length;
	let mut array = &mut data.data;
	for i in (0..vectorization_length).step_by(4)
	{
		let vector = f32x4(array[i], array[i+1], array[i+2], array[i+3]);
		let incremted = vector + increment_vector;
		array[i] = incremted.0;
		array[i + 1] = incremted.1;
		array[i + 2] = incremted.2;
		array[i + 3] = incremted.3;
	}

	for i in vectorization_length..data_length
	{
		array[i] = array[i] + 1.0;
	}
}

pub fn add_one_scalar(data: &mut DataVector)
{
	let data_length = data.len();
	let mut array = &mut data.data;
	for i in 0..data_length
	{
		array[i] = array[i] + 1.0;
	}
}

#[test]
fn add_one_test()
{
	let mut data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
	let mut result = DataVector::new(&mut data);
	add_one(&mut result);
	assert_eq!(result.data, [2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]);
}

#[test]
fn add_one_test_odd_number_of_elements()
{
	let mut data = [1.0, 2.0, 3.0];
	let mut result = DataVector::new(&mut data);
	add_one(&mut result);
	assert_eq!(result.data, [2.0, 3.0, 4.0]);
}

#[bench]
fn add_one_benchmark(b: &mut Bencher)
{
	let mut data = [0.0; 20000];
	let mut result = DataVector::new(&mut data);
	b.iter(|| {
		add_one(&mut result);
		return result.data[0];
		});
}

#[bench]
fn add_one_scalar_benchmark(b: &mut Bencher)
{
	let mut data = [0.0; 20000];
	let mut result = DataVector::new(&mut data);
	b.iter(|| {
		add_one_scalar(&mut result);
		return result.data[0];
		});
}<|endoftext|>


<commit_before>//! This crate provides safe bindings to
//! [wlroots](https://github.com/swaywm/wlroots).
//!
//! Start your [Compositor](struct.Compositor.html) by implementing an [input
//! manager](manager/struct.InputManager.html) and an [output
//! manager](manager/struct.OutputManager.html) on two separate structs.
//!
//! # Example
//! ```rust,no_run
//! extern crate wlroots;
//!
//! struct InputManager;
//! struct OutputManager;
//!
//! impl wlroots::OutputManagerHandler for OutputManager {}
//! impl wlroots::InputManagerHandler for InputManager {}
//!
//! fn main() {
//!     wlroots::CompositorBuilder::new()
//!          .build_auto((), // Dummy state
//!                      Box::new(InputManager),
//!                      Box::new(OutputManager))
//!          .run()
//! }
//! ```

#![allow(unused_unsafe)]
#[macro_use]
extern crate bitflags;
extern crate lazy_static;
extern crate libc;
#[macro_use]
pub extern crate wayland_sys;
pub extern crate wlroots_sys;
pub extern crate xkbcommon;

#[macro_use]
mod macros;
mod manager;
mod compositor;
mod errors;
pub mod events;
pub mod types;
pub mod extensions;
pub mod render;
pub mod utils;

pub use self::compositor::{terminate, Compositor, CompositorBuilder};
pub use self::events::{key_events, pointer_events, wl_shell_events};
pub use self::manager::{InputManagerHandler, KeyboardHandler, OutputBuilder, OutputBuilderResult,
                        OutputHandler, OutputManagerHandler, PointerHandler, WlShellHandler,
                        WlShellManagerHandler};
pub use self::types::area::*;
pub use self::types::cursor::*;
pub use self::types::input_device::*;
pub use self::types::keyboard::*;
pub use self::types::output::output::*;
pub use self::types::output::output_layout::*;
pub use self::types::pointer::*;
pub use self::types::seat::*;
pub use self::types::shell::*;
pub use self::types::surface::*;
pub use key_events::Key;
pub use pointer_events::ButtonState;

pub use self::errors::*;
<commit_msg>Fixed doc test<commit_after>//! This crate provides safe bindings to
//! [wlroots](https://github.com/swaywm/wlroots).
//!
//! Start your [Compositor](struct.Compositor.html) by implementing an [input
//! manager](manager/struct.InputManager.html) and an [output
//! manager](manager/struct.OutputManager.html) on two separate structs.
//!
//! # Example
//! ```rust,no_run
//! extern crate wlroots;
//!
//! fn main() {
//!     wlroots::CompositorBuilder::new()
//!          .build_auto((), // Dummy state
//!                      None, None, None)
//!          .run()
//! }
//! ```

#![allow(unused_unsafe)]
#[macro_use]
extern crate bitflags;
extern crate lazy_static;
extern crate libc;
#[macro_use]
pub extern crate wayland_sys;
pub extern crate wlroots_sys;
pub extern crate xkbcommon;

#[macro_use]
mod macros;
mod manager;
mod compositor;
mod errors;
pub mod events;
pub mod types;
pub mod extensions;
pub mod render;
pub mod utils;

pub use self::compositor::{terminate, Compositor, CompositorBuilder};
pub use self::events::{key_events, pointer_events, wl_shell_events};
pub use self::manager::{InputManagerHandler, KeyboardHandler, OutputBuilder, OutputBuilderResult,
                        OutputHandler, OutputManagerHandler, PointerHandler, WlShellHandler,
                        WlShellManagerHandler};
pub use self::types::area::*;
pub use self::types::cursor::*;
pub use self::types::input_device::*;
pub use self::types::keyboard::*;
pub use self::types::output::output::*;
pub use self::types::output::output_layout::*;
pub use self::types::pointer::*;
pub use self::types::seat::*;
pub use self::types::shell::*;
pub use self::types::surface::*;
pub use key_events::Key;
pub use pointer_events::ButtonState;

pub use self::errors::*;
<|endoftext|>


<commit_before>extern crate hyper;

mod contentlength;
pub mod http_version;
pub mod download;

/// Represents a byte, in `u64`.
type Byte = u64;
<commit_msg>Add new custom types, import new mods<commit_after>extern crate hyper;

use std::sync::{Arc, Mutex};

pub mod client;
mod contentlength;
pub mod download;
pub mod http_version;

/// Represents a number of bytes, in `u64`.
type Byte = u64;
/// Represents a 'chunk', which is just a piece of bytes.
type Chunk = Vec<u8>;
/// Represents a list of chunks
type Chunks = Vec<Chunk>;
/// Represents a shared mutable reference of chunks
type SChunks = Arc<Mutex<Chunks>>;
<|endoftext|>


<commit_before>/**
 * adi_screen - Aldaron's Device Interface - Screen - "lib.rs"
 * Copyright 2017 (c) Jeron Lau - Licensed under the MIT LICENSE
**/

/// The version of adi_screen that's being used
pub const VERSION : &'static str = "adi_screen 0.1.0";

mod image;
mod renderer;
mod input;

mod window;
mod sprite;
mod style;
mod gui;

pub use input::keyboard::Key;
pub use input::joystick::Button;
pub use input::{ Input };
pub use window::{ Window };
pub use sprite::{ Sprite, Transform };
pub use style::Style;
pub use gui::Button as GuiButton;

extern crate ami;

pub extern crate adi_clock;
<commit_msg>Fix constant.<commit_after>/**
 * adi_screen - Aldaron's Device Interface - Screen - "lib.rs"
 * Copyright 2017 (c) Jeron Lau - Licensed under the MIT LICENSE
**/

/// The version of adi_screen that's being used
pub const VERSION : &'static str = "adi_screen 0.2.1";

mod image;
mod renderer;
mod input;

mod window;
mod sprite;
mod style;
mod gui;

pub use input::keyboard::Key;
pub use input::joystick::Button;
pub use input::{ Input };
pub use window::{ Window };
pub use sprite::{ Sprite, Transform };
pub use style::Style;
pub use gui::Button as GuiButton;

extern crate ami;

pub extern crate adi_clock;
<|endoftext|>


<commit_before>use std::fs::{File};
use std::string::String;
use std::path::Path;
use std::convert::{From, AsRef};
use std::io::{Read, BufReader, Write};
use std::vec::Vec;
use std::num::ParseIntError;
use std::mem;

#[derive(Debug)]
pub enum Error {
    IO,
    Parse,
    DataType,
    FieldType,
    Malformed,
    NotImplemented
}

impl From<std::io::Error> for Error {
    fn from(_: std::io::Error) -> Error {
        Error::IO
    }
}

impl From<ParseIntError> for Error {
    fn from(_: ParseIntError) -> Error {
        Error::Parse
    }
}

#[derive(Debug)]
pub enum DataType {
    XDRFloat,
    FloatLE,
    Byte,
}

impl DataType {
    fn from_str(s: &str) -> Result<DataType, Error> {
        match s {
            "float_le" => Ok(DataType::FloatLE),
            "xdr_float" => Ok(DataType::XDRFloat),
            "byte" => Ok(DataType::Byte),
            _ => Err(Error::DataType)
        }
    }

    fn num_bytes(self: &Self) -> usize {
        match *self {
            DataType::XDRFloat => 4usize,
            DataType::FloatLE => 4usize,
            DataType::Byte => 1usize,
        }
    }

    fn convert_to_f32(self: &Self, buf: &[u8]) -> f32 {
        match *self {
            DataType::XDRFloat => {
                let b = [buf[3], buf[2], buf[1], buf[0]];
                unsafe { mem::transmute(b) }
            },
            DataType::FloatLE => {
                let b = [buf[0], buf[1], buf[2], buf[3]];
                unsafe { mem::transmute(b) }
            },
            DataType::Byte => {
                buf[0] as f32
            },
        }
    }
}

#[derive(Debug)]
pub enum FieldType {
    Uniform
}

impl FieldType {
    fn from_str(s: &str) -> Result<FieldType, Error> {
        match s {
            "uniform" => Ok(FieldType::Uniform),
            _ => Err(Error::FieldType)
        }
    }
}

pub struct AVSFile {
    pub ndim: usize,
    pub sizes: Vec<usize>,
    pub data_type: DataType,
    pub field_type: FieldType,
    reader: Box<Read>
}

impl AVSFile {
    pub fn write<W: Write, T>(
                writer: &mut W, dims: &[usize], data: &[T])
                    -> Result<(), Error> {
        // header
        let ndim = dims.len();
        try!(writer.write_fmt(format_args!("# AVS FLD file (written by avsfldrs github.com/greyhill/avsfldrs)\n")));
        try!(writer.write_fmt(format_args!("ndim={}\n", ndim)));
        try!(writer.write_fmt(format_args!("veclen=1\n")));
        try!(writer.write_fmt(format_args!("nspace={}\n", ndim)));
        try!(writer.write_fmt(format_args!("field=uniform\n")));
        try!(writer.write_fmt(format_args!("data=float_le\n"))); // TODO
        for (id, size) in dims.iter().enumerate() {
            try!(writer.write_fmt(format_args!("dim{}={}\n", id+1, size)));
        }
        try!(writer.write_fmt(format_args!("{}{}", 12 as char, 12 as char)));
        let b: &[u8] = unsafe {
            std::slice::from_raw_parts(data.as_ptr() as *const u8,
                                       data.len()*mem::size_of::<T>())
        };
        try!(writer.write_all(b));
        Ok(())
    }

    pub fn read_to_f32(self: &mut Self) -> Result<Vec<f32>, Error> {
        println!("{:?}", self.sizes);
        let size = self.sizes.iter().fold(1 as usize, |l, r| l * *r);
        let mut buf_u8 = Vec::<u8>::with_capacity(size * self.data_type.num_bytes());
        let mut buf_tr = Vec::<f32>::with_capacity(size);
        try!(self.reader.read_to_end(&mut buf_u8));

        for n in 0 .. size {
            let off0 = n*self.data_type.num_bytes();
            let off1 = (n+1)*self.data_type.num_bytes();
            buf_tr.push(self.data_type.convert_to_f32(&buf_u8[off0 .. off1]));
        }

        Ok(buf_tr)
    }

    pub fn read<T>(self: &mut Self) -> Result<Vec<T>, Error> {
        let size = self.sizes.iter().fold(1 as usize, |l, r| l * *r);
        let mut buf_u8 = Vec::<u8>::with_capacity(mem::size_of::<T>()*size);
        try!(self.reader.read_to_end(&mut buf_u8));
        let buf: Vec<T> = unsafe {
            let ptr = buf_u8.as_mut_ptr();
            let cap = buf_u8.capacity();
            Vec::<T>::from_raw_parts(
                mem::transmute(ptr),
                size,
                cap / mem::size_of::<T>())
        };
        Ok(buf)
    }

    pub fn open<P: AsRef<Path>>(p: &P) -> Result<AVSFile, Error> {
        let path = p.as_ref();
        let mut reader = BufReader::new(try!(File::open(path)));

        let mut ndim: Option<usize> = None;
        let mut sizes = Vec::<Option<usize>>::new();
        let mut data_type: Option<DataType> = None;
        let mut field_type: Option<FieldType> = None;
        let mut external: Option<String> = None;

        let mut line = String::new();
        let mut last_char: u8 = 0;
        loop {
            let mut new_char_buf: [u8;1] = [ 0u8 ];
            try!(reader.read(&mut new_char_buf));

            // break on two chr 14s
            let new_char = new_char_buf[0];
            if (new_char, last_char) == (12u8, 12u8) {
                break;
            }
            last_char = new_char;

            line.push(new_char as char);

            // new line; process the line and discard
            if new_char == 10 {
                let tokens: Vec<&str> = line.split('=')
                    .map(|s| s.trim()).collect();
                match tokens[0] {
                    "ndim" => {
                        let nd = try!(tokens[1].parse::<usize>());
                        ndim = Some(nd);
                        for _ in 0..nd {
                            sizes.push(None);
                        }
                    },
                    "dim1" => sizes[0] = Some(try!(tokens[1].parse::<usize>())),
                    "dim2" => sizes[1] = Some(try!(tokens[1].parse::<usize>())),
                    "dim3" => sizes[2] = Some(try!(tokens[1].parse::<usize>())),
                    "dim4" => sizes[3] = Some(try!(tokens[1].parse::<usize>())),
                    "dim5" => sizes[4] = Some(try!(tokens[1].parse::<usize>())),
                    "dim6" => sizes[5] = Some(try!(tokens[1].parse::<usize>())),
                    "dim7" => sizes[6] = Some(try!(tokens[1].parse::<usize>())),
                    "data" =>
                        data_type = Some(try!(DataType::from_str(tokens[1]))),
                    "field" =>
                        field_type = Some(try!(FieldType::from_str(tokens[1]))),
                    "variable 1 file" =>
                        external = Some(tokens[1].to_string()),
                    _ => {}
                }
            }
            // hack?  code smell?  need borrow in previous block to expire
            if new_char == 10 {
                line.clear();
            }
        }

        match external {
            None => {
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
            Some(path) => {
                let new_reader = BufReader::new(try!(File::open(&path)));
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(new_reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
        }
    }
}

<commit_msg>fix memory bug<commit_after>use std::fs::{File};
use std::string::String;
use std::path::Path;
use std::convert::{From, AsRef};
use std::io::{Read, BufReader, Write};
use std::vec::Vec;
use std::num::ParseIntError;
use std::mem;

#[derive(Debug)]
pub enum Error {
    IO,
    Parse,
    DataType,
    FieldType,
    Malformed,
    NotImplemented
}

impl From<std::io::Error> for Error {
    fn from(_: std::io::Error) -> Error {
        Error::IO
    }
}

impl From<ParseIntError> for Error {
    fn from(_: ParseIntError) -> Error {
        Error::Parse
    }
}

#[derive(Debug)]
pub enum DataType {
    XDRFloat,
    FloatLE,
    Byte,
}

impl DataType {
    fn from_str(s: &str) -> Result<DataType, Error> {
        match s {
            "float_le" => Ok(DataType::FloatLE),
            "xdr_float" => Ok(DataType::XDRFloat),
            "byte" => Ok(DataType::Byte),
            _ => Err(Error::DataType)
        }
    }

    fn num_bytes(self: &Self) -> usize {
        match *self {
            DataType::XDRFloat => 4usize,
            DataType::FloatLE => 4usize,
            DataType::Byte => 1usize,
        }
    }

    fn convert_to_f32(self: &Self, buf: &[u8]) -> f32 {
        match *self {
            DataType::XDRFloat => {
                let b = [buf[3], buf[2], buf[1], buf[0]];
                unsafe { mem::transmute(b) }
            },
            DataType::FloatLE => {
                let b = [buf[0], buf[1], buf[2], buf[3]];
                unsafe { mem::transmute(b) }
            },
            DataType::Byte => {
                buf[0] as f32
            },
        }
    }
}

#[derive(Debug)]
pub enum FieldType {
    Uniform
}

impl FieldType {
    fn from_str(s: &str) -> Result<FieldType, Error> {
        match s {
            "uniform" => Ok(FieldType::Uniform),
            _ => Err(Error::FieldType)
        }
    }
}

pub struct AVSFile {
    pub ndim: usize,
    pub sizes: Vec<usize>,
    pub data_type: DataType,
    pub field_type: FieldType,
    reader: Box<Read>
}

impl AVSFile {
    pub fn write<W: Write, T>(
                writer: &mut W, dims: &[usize], data: &[T])
                    -> Result<(), Error> {
        // header
        let ndim = dims.len();
        try!(writer.write_fmt(format_args!("# AVS FLD file (written by avsfldrs github.com/greyhill/avsfldrs)\n")));
        try!(writer.write_fmt(format_args!("ndim={}\n", ndim)));
        try!(writer.write_fmt(format_args!("veclen=1\n")));
        try!(writer.write_fmt(format_args!("nspace={}\n", ndim)));
        try!(writer.write_fmt(format_args!("field=uniform\n")));
        try!(writer.write_fmt(format_args!("data=float_le\n"))); // TODO
        for (id, size) in dims.iter().enumerate() {
            try!(writer.write_fmt(format_args!("dim{}={}\n", id+1, size)));
        }
        try!(writer.write_fmt(format_args!("{}{}", 12 as char, 12 as char)));
        let b: &[u8] = unsafe {
            std::slice::from_raw_parts(data.as_ptr() as *const u8,
                                       data.len()*mem::size_of::<T>())
        };
        try!(writer.write_all(b));
        Ok(())
    }

    pub fn read_to_f32(self: &mut Self) -> Result<Vec<f32>, Error> {
        let size = self.sizes.iter().fold(1 as usize, |l, r| l * *r);
        let mut buf_u8 = Vec::<u8>::with_capacity(size * self.data_type.num_bytes());
        let mut buf_tr = Vec::<f32>::with_capacity(size);
        try!(self.reader.read_to_end(&mut buf_u8));

        for n in 0 .. size {
            let off0 = n*self.data_type.num_bytes();
            let off1 = (n+1)*self.data_type.num_bytes();
            buf_tr.push(self.data_type.convert_to_f32(&buf_u8[off0 .. off1]));
        }

        Ok(buf_tr)
    }

    pub fn read<T>(self: &mut Self) -> Result<Vec<T>, Error> {
        let size = self.sizes.iter().fold(1 as usize, |l, r| l * *r);
        let mut buf_u8 = Vec::<u8>::with_capacity(mem::size_of::<T>()*size);
        try!(self.reader.read_to_end(&mut buf_u8));
        let buf: Vec<T> = unsafe {
            let ptr = buf_u8.as_mut_ptr();
            let cap = buf_u8.capacity();
            mem::forget(buf_u8);
            Vec::<T>::from_raw_parts(
                mem::transmute(ptr),
                size,
                cap / mem::size_of::<T>())
        };
        Ok(buf)
    }

    pub fn open<P: AsRef<Path>>(p: &P) -> Result<AVSFile, Error> {
        let path = p.as_ref();
        let mut reader = BufReader::new(try!(File::open(path)));

        let mut ndim: Option<usize> = None;
        let mut sizes = Vec::<Option<usize>>::new();
        let mut data_type: Option<DataType> = None;
        let mut field_type: Option<FieldType> = None;
        let mut external: Option<String> = None;

        let mut line = String::new();
        let mut last_char: u8 = 0;
        loop {
            let mut new_char_buf: [u8;1] = [ 0u8 ];
            try!(reader.read(&mut new_char_buf));

            // break on two chr 14s
            let new_char = new_char_buf[0];
            if (new_char, last_char) == (12u8, 12u8) {
                break;
            }
            last_char = new_char;

            line.push(new_char as char);

            // new line; process the line and discard
            if new_char == 10 {
                let tokens: Vec<&str> = line.split('=')
                    .map(|s| s.trim()).collect();
                match tokens[0] {
                    "ndim" => {
                        let nd = try!(tokens[1].parse::<usize>());
                        ndim = Some(nd);
                        for _ in 0..nd {
                            sizes.push(None);
                        }
                    },
                    "dim1" => sizes[0] = Some(try!(tokens[1].parse::<usize>())),
                    "dim2" => sizes[1] = Some(try!(tokens[1].parse::<usize>())),
                    "dim3" => sizes[2] = Some(try!(tokens[1].parse::<usize>())),
                    "dim4" => sizes[3] = Some(try!(tokens[1].parse::<usize>())),
                    "dim5" => sizes[4] = Some(try!(tokens[1].parse::<usize>())),
                    "dim6" => sizes[5] = Some(try!(tokens[1].parse::<usize>())),
                    "dim7" => sizes[6] = Some(try!(tokens[1].parse::<usize>())),
                    "data" =>
                        data_type = Some(try!(DataType::from_str(tokens[1]))),
                    "field" =>
                        field_type = Some(try!(FieldType::from_str(tokens[1]))),
                    "variable 1 file" =>
                        external = Some(tokens[1].to_string()),
                    _ => {}
                }
            }
            // hack?  code smell?  need borrow in previous block to expire
            if new_char == 10 {
                line.clear();
            }
        }

        match external {
            None => {
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
            Some(path) => {
                let new_reader = BufReader::new(try!(File::open(&path)));
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(new_reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
        }
    }
}

<|endoftext|>


<commit_before>//! An implementation of Google Protobuf's Variable-Length Integers

/// The maximum number of bytes used by a 32-bit Varint
pub const VARINT_32_MAX_BYTES: u8 = 5;

/// The maximum number of bytes used by a 32-bit Varint
pub const VARINT_64_MAX_BYTES: u8 = 10;

/// Checks to see if the most signifigant bit exists in the specified byte
pub fn most_signifigant_bit_exists(input: u8) -> bool {
    input & 0b10000000 != 0
}

/// A struct defining a variable-length integer
#[derive(Clone, Debug)]
pub struct Varint {

    /// The internal data representation
    pub data: Vec<u8>

}

impl Varint {

    /// Gets the number of bytes currently contained by this Varint
    pub fn number_of_bytes(&self) -> usize {
        self.data.len()
    }

}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn test_new_varint_has_no_bytes() {

        let abc: Varint = Varint { data: Vec::new() };

        assert_eq!(0, abc.number_of_bytes());

    }

    #[test]
    fn test_most_signifigant_bit() {
        let mut value: u8 = 1;

        assert!(most_signifigant_bit_exists(value) == false);

        value = 120;

        assert!(most_signifigant_bit_exists(value) == false);

        value = 128;

        assert!(most_signifigant_bit_exists(value) == true);

        value = 129;

        assert!(most_signifigant_bit_exists(value) == true);
    }

}<commit_msg>Get unsigned Varint encoding done<commit_after>//! An implementation of Google Protobuf's Variable-Length Integers

/// The maximum number of bytes used by a 32-bit Varint
pub const VARINT_32_MAX_BYTES: u8 = 5;

/// The maximum number of bytes used by a 32-bit Varint
pub const VARINT_64_MAX_BYTES: u8 = 10;

/// Checks to see if the most signifigant bit exists in the specified byte
pub fn most_signifigant_bit_exists(input: u8) -> bool {
    input & 0b10000000 != 0
}

/// A struct defining a variable-length integer
#[derive(Clone, Debug)]
pub struct Varint {

    /// The internal data representation
    pub data: Vec<u8>

}

impl Varint {

    /// Gets the number of bytes currently contained by this Varint
    pub fn number_of_bytes(&self) -> usize {
        self.data.len()
    }

}

/// Gets the number of bytes required to store an unsigned value in a Varint
pub fn unsigned_varint_bytes_required(input: usize) -> u8 {

    let mut value: u64 = input as u64;

    let mut returnable: u8 = 0;

    if value == 0 {
        return 1;
    }

    while value >= 1 {

        value >>= 7;

        returnable += 1;
    }

    returnable

}

///Encodes an unsigned value as a Varint.
pub fn encode_unsigned_varint(input: usize) -> Varint {

    let mut returnable: Varint = Varint { data: Vec::<u8>::new() };

    let mut value: u64 = input as u64;

    if value == 0 {
        returnable.data.push(0);
        return returnable;
    } else {

        while value >= 1 {
            let mut next_byte: u8 = (value & 0b01111111) as u8;

            value >>= 7;

            if value >= 1 {
                next_byte |= 0b10000000;
            }

            returnable.data.push(next_byte);
        }

        return returnable;
    }

}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn test_varint_bytes_required() {
        let mut abc: usize = 0;

        assert_eq!(1, unsigned_varint_bytes_required(abc));

        abc = 120;

        assert_eq!(1, unsigned_varint_bytes_required(abc));

        abc = 128;

        assert_eq!(2, unsigned_varint_bytes_required(abc));

        abc = 300;

        assert_eq!(2, unsigned_varint_bytes_required(abc));

        abc = 0b000111111101010110101100;

        assert_eq!(3, unsigned_varint_bytes_required(abc));

        abc = 0b011111111101010110101100;

        assert_eq!(4, unsigned_varint_bytes_required(abc));

        abc = 4147110142;

        assert_eq!(5, unsigned_varint_bytes_required(abc));
    }

    #[test]
    fn test_new_varint_has_no_bytes() {

        let abc: Varint = Varint { data: Vec::<u8>::new() };

        assert_eq!(0, abc.number_of_bytes());

    }

    #[test]
    fn test_most_signifigant_bit() {
        let mut value: u8 = 1;

        assert!(most_signifigant_bit_exists(value) == false);

        value = 120;

        assert!(most_signifigant_bit_exists(value) == false);

        value = 128;

        assert!(most_signifigant_bit_exists(value) == true);

        value = 129;

        assert!(most_signifigant_bit_exists(value) == true);
    }

}<|endoftext|>


<commit_before>#![feature(optin_builtin_traits)]
#![feature(unsafe_destructor)]
#![feature(core)]
#![feature(std_misc)]
extern crate time;

use std::cell::UnsafeCell;
pub use std::sync::{
    TryLockError,
    LockResult,
    TryLockResult,
    PoisonError,
};
use std::thread;
use std::ops::{Deref, DerefMut};

use std::sync::atomic::{Ordering, AtomicUsize};

// Panic guards, taken from std::sync

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

struct Flag { failed: UnsafeCell<bool> }
unsafe impl Send for Flag {}
unsafe impl Sync for Flag {}

impl Flag {
    #[inline]
    fn new() -> Flag {
        Flag { failed : UnsafeCell { value : false }}
    }

    #[inline]
    fn borrow(&self) -> LockResult<Guard> {
        let ret = Guard { panicking: thread::panicking() };
        if unsafe { *self.failed.get() } {
            Err(PoisonError::new(ret))
        } else {
            Ok(ret)
        }
    }

    #[inline]
    fn done(&self, guard: &Guard) {
        if !guard.panicking && thread::panicking() {
            unsafe { *self.failed.get() = true; }
        }
    }

    #[inline]
    fn get(&self) -> bool {
        unsafe { *self.failed.get() }
    }
}

struct Guard {
    panicking: bool,
}

fn map_result<T, U, F>(result: LockResult<T>, f: F)
                           -> LockResult<U>
                           where F: FnOnce(T) -> U {
    match result {
        Ok(t) => Ok(f(t)),
        Err(err) => Err(PoisonError::new(f(err.into_inner())))
    }
}

// SpinLock implementation
//
const SHARED : usize = 0x80000000;
const EXCLWAIT : usize = 0x00100000;
const MAXWAIT : u64 = 2_000_000_000;
const SPIN_COUNT : u32 = 0xFF;

pub struct SpinLock<T> {
    count : AtomicUsize,
    data : UnsafeCell<T>,
    poison : Flag,
}

unsafe impl<T: Send + Sync> Send for SpinLock<T> {}
unsafe impl<T: Send + Sync> Sync for SpinLock<T> {}

impl<T : Send + Sync> SpinLock<T> {
    pub fn new(data : T) -> SpinLock<T> {
        SpinLock {
            count : AtomicUsize::new(0),
            data : UnsafeCell::new(data),
            poison : Flag::new(),
        }
    }

    #[inline]
    pub fn write(&self) -> LockResult<SpinLockWriteGuard<T>> {
        if self.count.fetch_add(1, Ordering::AcqRel) != 0 {
            return self.write_contested()
        }
        SpinLockWriteGuard::new(self, &self.data)
    }

    pub fn write_contested(&self) -> LockResult<SpinLockWriteGuard<T>> {
        let mut base_time : u64 = 0;
        let mut time : u64;
        let mut i = 0u32;

        self.count.fetch_add(EXCLWAIT - 1, Ordering::AcqRel);
        self.count.fetch_and(! SHARED, Ordering::AcqRel);
        loop {
            let count = self.count.load(Ordering::Acquire);
            if count & (EXCLWAIT - 1) == 0 &&
                self.count.compare_and_swap(count, (count & !EXCLWAIT) | 1, Ordering::AcqRel) == count {
                    break;
                }

            if i >= SPIN_COUNT  {
                time = time::precise_time_ns();
                if base_time == 0 {
                    base_time = time;
                } else if time - base_time > MAXWAIT {
                    // FIXME : not 100% sure about what happens if there are multiple EXCL requests pending
                    self.count.fetch_and(! EXCLWAIT, Ordering::AcqRel);
                    panic!("Spinning on a spin lock for too long")
                }
                thread::yield_now();
            } else {
                i += 1;
            }
        }
        SpinLockWriteGuard::new(self, &self.data)
    }

    #[inline]
    pub fn read(&self) -> LockResult<SpinLockReadGuard<T>> {
        if self.count.compare_and_swap(0, SHARED | 1, Ordering::AcqRel) == 0 {
            return self.read_contested()
        }
        SpinLockReadGuard::new(self, &self.data)
    }

    pub fn read_contested(&self) -> LockResult<SpinLockReadGuard<T>> {
        let mut i = 0u32;
        let mut base_time : u64 = 0;
        let mut time : u64;
        loop {
            let count = self.count.load(Ordering::Acquire);
            if count == 0 {
                if self.count.compare_and_swap(0, SHARED | 1, Ordering::AcqRel) == 0 {
                    break
                }
            } else if count & SHARED == SHARED {
                if self.count.compare_and_swap(count, count + 1, Ordering::AcqRel) == count {
                    break
                }
            }
            if i >= SPIN_COUNT  {
                time = time::precise_time_ns();
                if base_time == 0 {
                    base_time = time;
                } else if time - base_time > MAXWAIT {
                    panic!("Spinning on a spin lock for too long")
                }
                thread::yield_now();
            } else {
                i+=1;
            }
        }
        SpinLockReadGuard::new(self, &self.data)
    }

    #[inline]
    pub fn try_read(&self) -> TryLockResult<SpinLockReadGuard<T>> {
        if self.count.compare_and_swap(0, 1 | SHARED, Ordering::AcqRel) == 0 {
            return Ok(try!(SpinLockReadGuard::new(self, &self.data)))
        } else {
            let count = self.count.load(Ordering::Acquire);
            if self.count.compare_and_swap(count, count + 1, Ordering::AcqRel) == count {
                return Ok(try!(SpinLockReadGuard::new(self, &self.data)))
            }
            return Err(TryLockError::WouldBlock)
        }
    }

    pub fn try_write(&self) -> TryLockResult<SpinLockWriteGuard<T>> {
        if self.count.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
            Ok(try!(SpinLockWriteGuard::new(self, &self.data)))
        } else {
            Err(TryLockError::WouldBlock)
        }
    }

    #[inline]
    pub fn is_poisonned(&self) -> bool {
        self.poison.get()
    }

}

impl<T> SpinLock<T> {

    #[inline]
    fn read_unlock(&self) {
        self.count.fetch_sub(1, Ordering::AcqRel);

        while self.count.load(Ordering::Acquire) == SHARED {
            if self.count.compare_and_swap(SHARED, 0, Ordering::AcqRel) == SHARED {
                break
            }
        }
    }

    fn write_unlock(&self) {
        self.count.fetch_sub(1, Ordering::AcqRel);
    }
}

#[must_use]
pub struct SpinLockReadGuard<'a, T : 'a> {
    lock : &'a SpinLock<T>,
    data : &'a UnsafeCell<T>,
}

impl<'a, T> !Send for SpinLockReadGuard<'a, T> {}

impl<'a, T> SpinLockReadGuard<'a, T> {
    fn new(lock : &'a SpinLock<T>, data : &'a UnsafeCell<T>) -> LockResult<SpinLockReadGuard<'a, T>> {
        map_result(lock.poison.borrow(), |_| {
            SpinLockReadGuard {
                lock : lock,
                data : data,
            }
        })
    }
}

impl<'a, T> Deref for SpinLockReadGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &T { unsafe { &*self.data.get() } }
}

#[unsafe_destructor]
impl<'a, T> Drop for SpinLockReadGuard<'a, T> {
    fn drop(&mut self) {
        self.lock.read_unlock();
    }
}

#[must_use]
pub struct SpinLockWriteGuard<'a, T : 'a> {
    lock : &'a SpinLock<T>,
    data : &'a UnsafeCell<T>,
    poison :  Guard,
}

impl<'a, T> !Send for SpinLockWriteGuard<'a, T> {}

impl<'a, T> SpinLockWriteGuard<'a, T> {
    fn new(lock : &'a SpinLock<T>, data : &'a UnsafeCell<T>) -> LockResult<SpinLockWriteGuard<'a, T>> {
        map_result(lock.poison.borrow(), |guard| {
            SpinLockWriteGuard {
                lock : lock,
                data : data,
                poison : guard,
            }
        })
    }
}

impl<'a, T> Deref for SpinLockWriteGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &T { unsafe { &*self.data.get() } }
}

impl<'a, T> DerefMut for SpinLockWriteGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.data.get() } }
}

#[unsafe_destructor]
impl<'a, T> Drop for SpinLockWriteGuard<'a, T> {
    fn drop(&mut self) {
        self.lock.poison.done(&self.poison);
        self.lock.write_unlock();
    }
}

#[cfg(test)]
mod tests;
<commit_msg>Fix try_read() when the shared count is to be increased<commit_after>#![feature(optin_builtin_traits)]
#![feature(unsafe_destructor)]
#![feature(core)]
#![feature(std_misc)]
extern crate time;

use std::cell::UnsafeCell;
pub use std::sync::{
    TryLockError,
    LockResult,
    TryLockResult,
    PoisonError,
};
use std::thread;
use std::ops::{Deref, DerefMut};

use std::sync::atomic::{Ordering, AtomicUsize};

// Panic guards, taken from std::sync

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

struct Flag { failed: UnsafeCell<bool> }
unsafe impl Send for Flag {}
unsafe impl Sync for Flag {}

impl Flag {
    #[inline]
    fn new() -> Flag {
        Flag { failed : UnsafeCell { value : false }}
    }

    #[inline]
    fn borrow(&self) -> LockResult<Guard> {
        let ret = Guard { panicking: thread::panicking() };
        if unsafe { *self.failed.get() } {
            Err(PoisonError::new(ret))
        } else {
            Ok(ret)
        }
    }

    #[inline]
    fn done(&self, guard: &Guard) {
        if !guard.panicking && thread::panicking() {
            unsafe { *self.failed.get() = true; }
        }
    }

    #[inline]
    fn get(&self) -> bool {
        unsafe { *self.failed.get() }
    }
}

struct Guard {
    panicking: bool,
}

fn map_result<T, U, F>(result: LockResult<T>, f: F)
                           -> LockResult<U>
                           where F: FnOnce(T) -> U {
    match result {
        Ok(t) => Ok(f(t)),
        Err(err) => Err(PoisonError::new(f(err.into_inner())))
    }
}

// SpinLock implementation
//
const SHARED : usize = 0x80000000;
const EXCLWAIT : usize = 0x00100000;
const MAXWAIT : u64 = 2_000_000_000;
const SPIN_COUNT : u32 = 0xFF;

pub struct SpinLock<T> {
    count : AtomicUsize,
    data : UnsafeCell<T>,
    poison : Flag,
}

unsafe impl<T: Send + Sync> Send for SpinLock<T> {}
unsafe impl<T: Send + Sync> Sync for SpinLock<T> {}

impl<T : Send + Sync> SpinLock<T> {
    pub fn new(data : T) -> SpinLock<T> {
        SpinLock {
            count : AtomicUsize::new(0),
            data : UnsafeCell::new(data),
            poison : Flag::new(),
        }
    }

    #[inline]
    pub fn write(&self) -> LockResult<SpinLockWriteGuard<T>> {
        if self.count.fetch_add(1, Ordering::AcqRel) != 0 {
            return self.write_contested()
        }
        SpinLockWriteGuard::new(self, &self.data)
    }

    pub fn write_contested(&self) -> LockResult<SpinLockWriteGuard<T>> {
        let mut base_time : u64 = 0;
        let mut time : u64;
        let mut i = 0u32;

        self.count.fetch_add(EXCLWAIT - 1, Ordering::AcqRel);
        self.count.fetch_and(! SHARED, Ordering::AcqRel);
        loop {
            let count = self.count.load(Ordering::Acquire);
            if count & (EXCLWAIT - 1) == 0 &&
                self.count.compare_and_swap(count, (count & !EXCLWAIT) | 1, Ordering::AcqRel) == count {
                    break;
                }

            if i >= SPIN_COUNT  {
                time = time::precise_time_ns();
                if base_time == 0 {
                    base_time = time;
                } else if time - base_time > MAXWAIT {
                    // FIXME : not 100% sure about what happens if there are multiple EXCL requests pending
                    self.count.fetch_and(! EXCLWAIT, Ordering::AcqRel);
                    panic!("Spinning on a spin lock for too long")
                }
                thread::yield_now();
            } else {
                i += 1;
            }
        }
        SpinLockWriteGuard::new(self, &self.data)
    }

    #[inline]
    pub fn read(&self) -> LockResult<SpinLockReadGuard<T>> {
        if self.count.compare_and_swap(0, SHARED | 1, Ordering::AcqRel) == 0 {
            return self.read_contested()
        }
        SpinLockReadGuard::new(self, &self.data)
    }

    pub fn read_contested(&self) -> LockResult<SpinLockReadGuard<T>> {
        let mut i = 0u32;
        let mut base_time : u64 = 0;
        let mut time : u64;
        loop {
            let count = self.count.load(Ordering::Acquire);
            if count == 0 {
                if self.count.compare_and_swap(0, SHARED | 1, Ordering::AcqRel) == 0 {
                    break
                }
            } else if count & SHARED == SHARED {
                if self.count.compare_and_swap(count, count + 1, Ordering::AcqRel) == count {
                    break
                }
            }
            if i >= SPIN_COUNT  {
                time = time::precise_time_ns();
                if base_time == 0 {
                    base_time = time;
                } else if time - base_time > MAXWAIT {
                    panic!("Spinning on a spin lock for too long")
                }
                thread::yield_now();
            } else {
                i+=1;
            }
        }
        SpinLockReadGuard::new(self, &self.data)
    }

    #[inline]
    pub fn try_read(&self) -> TryLockResult<SpinLockReadGuard<T>> {
        if self.count.compare_and_swap(0, 1 | SHARED, Ordering::AcqRel) == 0 {
            return Ok(try!(SpinLockReadGuard::new(self, &self.data)))
        } else {
            let count = self.count.load(Ordering::Acquire);
            if count & SHARED == SHARED &&
                self.count.compare_and_swap(count, count + 1, Ordering::AcqRel) == count {
                return Ok(try!(SpinLockReadGuard::new(self, &self.data)))
            }
            return Err(TryLockError::WouldBlock)
        }
    }

    pub fn try_write(&self) -> TryLockResult<SpinLockWriteGuard<T>> {
        if self.count.compare_and_swap(0, 1, Ordering::AcqRel) == 0 {
            Ok(try!(SpinLockWriteGuard::new(self, &self.data)))
        } else {
            Err(TryLockError::WouldBlock)
        }
    }

    #[inline]
    pub fn is_poisonned(&self) -> bool {
        self.poison.get()
    }

}

impl<T> SpinLock<T> {

    #[inline]
    fn read_unlock(&self) {
        self.count.fetch_sub(1, Ordering::AcqRel);

        while self.count.load(Ordering::Acquire) == SHARED {
            if self.count.compare_and_swap(SHARED, 0, Ordering::AcqRel) == SHARED {
                break
            }
        }
    }

    fn write_unlock(&self) {
        self.count.fetch_sub(1, Ordering::AcqRel);
    }
}

#[must_use]
pub struct SpinLockReadGuard<'a, T : 'a> {
    lock : &'a SpinLock<T>,
    data : &'a UnsafeCell<T>,
}

impl<'a, T> !Send for SpinLockReadGuard<'a, T> {}

impl<'a, T> SpinLockReadGuard<'a, T> {
    fn new(lock : &'a SpinLock<T>, data : &'a UnsafeCell<T>) -> LockResult<SpinLockReadGuard<'a, T>> {
        map_result(lock.poison.borrow(), |_| {
            SpinLockReadGuard {
                lock : lock,
                data : data,
            }
        })
    }
}

impl<'a, T> Deref for SpinLockReadGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &T { unsafe { &*self.data.get() } }
}

#[unsafe_destructor]
impl<'a, T> Drop for SpinLockReadGuard<'a, T> {
    fn drop(&mut self) {
        self.lock.read_unlock();
    }
}

#[must_use]
pub struct SpinLockWriteGuard<'a, T : 'a> {
    lock : &'a SpinLock<T>,
    data : &'a UnsafeCell<T>,
    poison :  Guard,
}

impl<'a, T> !Send for SpinLockWriteGuard<'a, T> {}

impl<'a, T> SpinLockWriteGuard<'a, T> {
    fn new(lock : &'a SpinLock<T>, data : &'a UnsafeCell<T>) -> LockResult<SpinLockWriteGuard<'a, T>> {
        map_result(lock.poison.borrow(), |guard| {
            SpinLockWriteGuard {
                lock : lock,
                data : data,
                poison : guard,
            }
        })
    }
}

impl<'a, T> Deref for SpinLockWriteGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &T { unsafe { &*self.data.get() } }
}

impl<'a, T> DerefMut for SpinLockWriteGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.data.get() } }
}

#[unsafe_destructor]
impl<'a, T> Drop for SpinLockWriteGuard<'a, T> {
    fn drop(&mut self) {
        self.lock.poison.done(&self.poison);
        self.lock.write_unlock();
    }
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>//!
//! # Libinput bindings for rust
//!
//! These bindings closely follow libinput's concepts and it's original API.
//! Please refer to the [libinput documentation](https://wayland.freedesktop.org/libinput/doc/latest/)
//! to understand the general structure and concepts.
//!
//! ## Differences to the C-Library:
//!
//! - Refcounting does not need to be done manually. Just call `clone` when you need an additional reference.
//! - Logging cannot be customized the same way as in libinput. Instead the [`log` crate](https://github.com/rust-lang-nursery/log) is used for maximum compatibility with the rust ecosystem.
//!
//! ## Userdata handling
//!
//! Multiple types in the libinput library allow to attach a pointer of an arbitrary type, so called `userdata`.
//! Using this data is unsafe as there is no way to find out what type is stored in the libinput struct.
//! Additionally multiple references to the same libinput object may exist and userdata may be shared mutably.
//!
//! This is why using and setting userdata is an unsafe operation (except when creating an object).
//!
//! If you heavily rely on userdata, you should always stored them wrapped in a `Mutex` and use the same
//! type for every userdata access to further simplify usage.
//!
//! You need to be especially cautious when initializing libinput types from raw pointers, you obtained
//! from other libraries which may set their own userdata. If accessing their userdata make sure no shared
//! mutable access may happen and don't store something else instead, if the library does not explicitly
//! allow this.
//!
//! Generally usage of this api is error-prone and discouraged if not needed.
//!
//! ## Getting started
//!
//! To get started check out the [`Libinput` struct](./struct.Libinput.html).
//!

#![deny(missing_docs)]
#![cfg_attr(feature="cargo-clippy", deny(clippy))]
#![cfg_attr(feature="cargo-clippy", allow(doc_markdown))]

extern crate input_sys;
extern crate libc;

use std::{mem, ptr};

/// Unsafe c-api.
pub mod ffi {
    pub use input_sys::*;
}

/// Trait for types that allow to optain the underlying raw libinput pointer.
pub trait AsRaw<T> {
    /// Receive a raw pointer representing this type.
    fn as_raw(&self) -> *const T;
    #[doc(hidden)]
    fn as_raw_mut(&self) -> *mut T {
        self.as_raw() as *mut _
    }
}

/// Trait for types that allow to be initialized from a raw pointer
pub trait FromRaw<T> {
    /// Create a new instance of this type from a raw pointer.
    ///
    /// ## Warning
    ///
    /// If you make use of [`Userdata`](./trait.Userdata.html) make sure you use the correct types
    /// to allow receiving the set userdata. When dealing with raw pointers initialized by other
    /// libraries this must be done extra carefully to select a correct representation.
    ///
    /// If unsure using `()` is always a safe option..
    ///
    /// ## Unsafety
    ///
    /// If the pointer is pointing to a different struct, invalid memory or `NULL` the returned
    /// struct may panic on use or cause other undefined behavior.
    ///
    unsafe fn from_raw(*mut T) -> Self;
}

/// Trait to deal with userdata attached to this struct.
pub trait Userdata {
    /// Receive a reference to the attached userdata, if one exists.
    ///
    /// ## Unsafety
    ///
    /// Receiving userdata is unsafe as multiple references to the same underlying libinput struct
    /// may exist. As such any reference may become invalid if changed using `set_userdata`.
    ///
    unsafe fn userdata<T: 'static>(&self) -> Option<&T> {
        self.userdata_raw().as_ref()
    }

    /// Receive a mutable reference to the attached userdata, if one exists.
    ///
    /// ## Unsafety
    ///
    /// Receiving userdata is unsafe as multiple references to the same underlying libinput struct
    /// may exist. As such any reference may become invalid if changed using `set_userdata`.
    ///
    /// Additionally multiple mutable references may be created through the existance of multiple
    /// structs using the same libinput reference. If you have control over the userdata make sure
    /// to store `Mutex` to be on the safe side.
    ///
    unsafe fn userdata_mut<T: 'static>(&mut self) -> Option<&mut T> {
        self.userdata_raw().as_mut()
    }

    /// Set userdata and receive the currently set userdata
    ///
    /// Sets new userdata or nothing in place of any existing one and returns the currently set
    /// userdata if one exists.
    ///
    /// ## Unsafety
    ///
    /// Multiple references to the same underlying libinput struct may exist. As such this function
    /// allows for shared mutable access, which is unsafe. Also this means this function
    /// might invalidate references to the currently set userdata, once dropped.
    ///
    /// Use a `Mutex` when storing new userdata to mitiage some of these problems.
    ///
    /// ## Note
    ///
    /// Stored userdata is dropped correctly, if the last reference is hold by rust and goes out of scope normally.
    unsafe fn set_userdata<T: 'static, U: 'static>(&mut self, new: Option<T>) -> Option<U> {
        let old = {
            let ptr = self.userdata_raw();
            if !ptr.is_null() {
                Some(Box::from_raw(ptr as *mut U))
            } else {
                None
            }
        };
        let mut boxed = Box::new(new);
        self.set_userdata_raw(match (*boxed).as_mut() {
            Some(value) => value as *mut T,
            None => ptr::null_mut(),
        });
        mem::forget(boxed);
        old.map(|x| *x)
    }

    #[doc(hidden)]
    unsafe fn userdata_raw<T: 'static>(&self) -> *mut T;
    #[doc(hidden)]
    unsafe fn set_userdata_raw<T: 'static>(&self, ptr: *mut T);
}

macro_rules! ffi_struct {
    ($(#[$attr:meta])* struct $struct_name:ident, $ffi_name:path) => (
        #[derive(Eq)]
        $(#[$attr])*
        pub struct $struct_name
        {
            ffi: *mut $ffi_name,
        }

        impl ::std::fmt::Debug for $struct_name {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                write!(f, "$struct_name @{:p}", self.as_raw())
            }
        }

        impl FromRaw<$ffi_name> for $struct_name
        {
            unsafe fn from_raw(ffi: *mut $ffi_name) -> Self {
                $struct_name {
                    ffi: ffi,
                }
            }
        }

        impl AsRaw<$ffi_name> for $struct_name
        {
            fn as_raw(&self) -> *const $ffi_name {
                self.ffi as *const _
            }
        }

        impl Clone for $struct_name {
            fn clone(&self) -> Self {
                unsafe { $struct_name::from_raw(self.as_raw_mut()) }
            }
        }

        impl PartialEq for $struct_name {
            fn eq(&self, other: &Self) -> bool {
                self.as_raw() == other.as_raw()
            }
        }

        impl ::std::hash::Hash for $struct_name {
            fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
                self.as_raw().hash(state);
            }
        }
    )
}

macro_rules! ffi_ref_struct {
    ($(#[$attr:meta])* struct $struct_name:ident, $ffi_name:path, $ref_fn:path, $unref_fn:path, $get_userdata_fn:path, $set_userdata_fn:path) => (
        #[derive(Eq)]
        $(#[$attr])*
        pub struct $struct_name
        {
            ffi: *mut $ffi_name,
        }

        impl ::std::fmt::Debug for $struct_name {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                write!(f, "$struct_name @{:p}", self.as_raw())
            }
        }

        impl FromRaw<$ffi_name> for $struct_name
        {
            unsafe fn from_raw(ffi: *mut $ffi_name) -> Self {
                $struct_name {
                    ffi: $ref_fn(ffi),
                }
            }
        }

        impl AsRaw<$ffi_name> for $struct_name
        {
            fn as_raw(&self) -> *const $ffi_name {
                self.ffi as *const _
            }
        }

        impl Userdata for $struct_name {
            unsafe fn userdata_raw<T: 'static>(&self) -> *mut T {
                $get_userdata_fn(self.as_raw_mut()) as *mut T
            }
            unsafe fn set_userdata_raw<T: 'static>(&self, ptr: *mut T) {
                $set_userdata_fn(self.as_raw_mut(), ptr as *mut libc::c_void);
            }
        }

        impl Clone for $struct_name {
            fn clone(&self) -> Self {
                unsafe { $struct_name::from_raw(self.as_raw_mut()) }
            }
        }

        impl Drop for $struct_name
        {
            fn drop(&mut self) {
                unsafe {
                    let userdata_ref = $get_userdata_fn(self.as_raw_mut());
                    if $unref_fn(self.ffi).is_null() {
                        let _ = Box::from_raw(userdata_ref);
                    }
                }
            }
        }

        impl PartialEq for $struct_name {
            fn eq(&self, other: &Self) -> bool {
                self.as_raw() == other.as_raw()
            }
        }

        impl ::std::hash::Hash for $struct_name {
            fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
                self.as_raw().hash(state);
            }
        }
    )
}

macro_rules! ffi_func {
    ($(#[$attr:meta])* fn $name:ident, $ffi_fn:path, bool) => (
        $(#[$attr])*
        fn $name(&self) -> bool {
            unsafe { $ffi_fn(self.as_raw_mut()) != 0 }
        }
    );
    ($(#[$attr:meta])* pub fn $name:ident, $ffi_fn:path, bool) => (
        $(#[$attr])*
        pub fn $name(&self) -> bool {
            unsafe { $ffi_fn(self.as_raw_mut()) != 0 }
        }
    );
    ($(#[$attr:meta])* fn $name:ident, $ffi_fn:path, $return_type:ty) => (
        $(#[$attr])*
        fn $name(&self) -> $return_type {
            unsafe { $ffi_fn(self.as_raw_mut()) as $return_type }
        }
    );
    ($(#[$attr:meta])* pub fn $name:ident, $ffi_fn:path, $return_type:ty) => (
        $(#[$attr])*
        pub fn $name(&self) -> $return_type {
            unsafe { $ffi_fn(self.as_raw_mut()) as $return_type }
        }
    );
}

mod context;
mod device;
pub mod event;
mod seat;

pub use context::*;
pub use device::*;
pub use seat::*;
pub use event::Event;
<commit_msg>Fix docs on logging<commit_after>//!
//! # Libinput bindings for rust
//!
//! These bindings closely follow libinput's concepts and it's original API.
//! Please refer to the [libinput documentation](https://wayland.freedesktop.org/libinput/doc/latest/)
//! to understand the general structure and concepts.
//!
//! ## Differences to the C-Library:
//!
//! - Refcounting does not need to be done manually. Just call `clone` when you need an additional reference.
//! - Libinput logging cannot (currently) not be customized.
//!
//! ## Userdata handling
//!
//! Multiple types in the libinput library allow to attach a pointer of an arbitrary type, so called `userdata`.
//! Using this data is unsafe as there is no way to find out what type is stored in the libinput struct.
//! Additionally multiple references to the same libinput object may exist and userdata may be shared mutably.
//!
//! This is why using and setting userdata is an unsafe operation (except when creating an object).
//!
//! If you heavily rely on userdata, you should always stored them wrapped in a `Mutex` and use the same
//! type for every userdata access to further simplify usage.
//!
//! You need to be especially cautious when initializing libinput types from raw pointers, you obtained
//! from other libraries which may set their own userdata. If accessing their userdata make sure no shared
//! mutable access may happen and don't store something else instead, if the library does not explicitly
//! allow this.
//!
//! Generally usage of this api is error-prone and discouraged if not needed.
//!
//! ## Getting started
//!
//! To get started check out the [`Libinput` struct](./struct.Libinput.html).
//!

#![deny(missing_docs)]
#![cfg_attr(feature="cargo-clippy", deny(clippy))]
#![cfg_attr(feature="cargo-clippy", allow(doc_markdown))]

extern crate input_sys;
extern crate libc;

use std::{mem, ptr};

/// Unsafe c-api.
pub mod ffi {
    pub use input_sys::*;
}

/// Trait for types that allow to optain the underlying raw libinput pointer.
pub trait AsRaw<T> {
    /// Receive a raw pointer representing this type.
    fn as_raw(&self) -> *const T;
    #[doc(hidden)]
    fn as_raw_mut(&self) -> *mut T {
        self.as_raw() as *mut _
    }
}

/// Trait for types that allow to be initialized from a raw pointer
pub trait FromRaw<T> {
    /// Create a new instance of this type from a raw pointer.
    ///
    /// ## Warning
    ///
    /// If you make use of [`Userdata`](./trait.Userdata.html) make sure you use the correct types
    /// to allow receiving the set userdata. When dealing with raw pointers initialized by other
    /// libraries this must be done extra carefully to select a correct representation.
    ///
    /// If unsure using `()` is always a safe option..
    ///
    /// ## Unsafety
    ///
    /// If the pointer is pointing to a different struct, invalid memory or `NULL` the returned
    /// struct may panic on use or cause other undefined behavior.
    ///
    unsafe fn from_raw(*mut T) -> Self;
}

/// Trait to deal with userdata attached to this struct.
pub trait Userdata {
    /// Receive a reference to the attached userdata, if one exists.
    ///
    /// ## Unsafety
    ///
    /// Receiving userdata is unsafe as multiple references to the same underlying libinput struct
    /// may exist. As such any reference may become invalid if changed using `set_userdata`.
    ///
    unsafe fn userdata<T: 'static>(&self) -> Option<&T> {
        self.userdata_raw().as_ref()
    }

    /// Receive a mutable reference to the attached userdata, if one exists.
    ///
    /// ## Unsafety
    ///
    /// Receiving userdata is unsafe as multiple references to the same underlying libinput struct
    /// may exist. As such any reference may become invalid if changed using `set_userdata`.
    ///
    /// Additionally multiple mutable references may be created through the existance of multiple
    /// structs using the same libinput reference. If you have control over the userdata make sure
    /// to store `Mutex` to be on the safe side.
    ///
    unsafe fn userdata_mut<T: 'static>(&mut self) -> Option<&mut T> {
        self.userdata_raw().as_mut()
    }

    /// Set userdata and receive the currently set userdata
    ///
    /// Sets new userdata or nothing in place of any existing one and returns the currently set
    /// userdata if one exists.
    ///
    /// ## Unsafety
    ///
    /// Multiple references to the same underlying libinput struct may exist. As such this function
    /// allows for shared mutable access, which is unsafe. Also this means this function
    /// might invalidate references to the currently set userdata, once dropped.
    ///
    /// Use a `Mutex` when storing new userdata to mitiage some of these problems.
    ///
    /// ## Note
    ///
    /// Stored userdata is dropped correctly, if the last reference is hold by rust and goes out of scope normally.
    unsafe fn set_userdata<T: 'static, U: 'static>(&mut self, new: Option<T>) -> Option<U> {
        let old = {
            let ptr = self.userdata_raw();
            if !ptr.is_null() {
                Some(Box::from_raw(ptr as *mut U))
            } else {
                None
            }
        };
        let mut boxed = Box::new(new);
        self.set_userdata_raw(match (*boxed).as_mut() {
            Some(value) => value as *mut T,
            None => ptr::null_mut(),
        });
        mem::forget(boxed);
        old.map(|x| *x)
    }

    #[doc(hidden)]
    unsafe fn userdata_raw<T: 'static>(&self) -> *mut T;
    #[doc(hidden)]
    unsafe fn set_userdata_raw<T: 'static>(&self, ptr: *mut T);
}

macro_rules! ffi_struct {
    ($(#[$attr:meta])* struct $struct_name:ident, $ffi_name:path) => (
        #[derive(Eq)]
        $(#[$attr])*
        pub struct $struct_name
        {
            ffi: *mut $ffi_name,
        }

        impl ::std::fmt::Debug for $struct_name {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                write!(f, "$struct_name @{:p}", self.as_raw())
            }
        }

        impl FromRaw<$ffi_name> for $struct_name
        {
            unsafe fn from_raw(ffi: *mut $ffi_name) -> Self {
                $struct_name {
                    ffi: ffi,
                }
            }
        }

        impl AsRaw<$ffi_name> for $struct_name
        {
            fn as_raw(&self) -> *const $ffi_name {
                self.ffi as *const _
            }
        }

        impl Clone for $struct_name {
            fn clone(&self) -> Self {
                unsafe { $struct_name::from_raw(self.as_raw_mut()) }
            }
        }

        impl PartialEq for $struct_name {
            fn eq(&self, other: &Self) -> bool {
                self.as_raw() == other.as_raw()
            }
        }

        impl ::std::hash::Hash for $struct_name {
            fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
                self.as_raw().hash(state);
            }
        }
    )
}

macro_rules! ffi_ref_struct {
    ($(#[$attr:meta])* struct $struct_name:ident, $ffi_name:path, $ref_fn:path, $unref_fn:path, $get_userdata_fn:path, $set_userdata_fn:path) => (
        #[derive(Eq)]
        $(#[$attr])*
        pub struct $struct_name
        {
            ffi: *mut $ffi_name,
        }

        impl ::std::fmt::Debug for $struct_name {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                write!(f, "$struct_name @{:p}", self.as_raw())
            }
        }

        impl FromRaw<$ffi_name> for $struct_name
        {
            unsafe fn from_raw(ffi: *mut $ffi_name) -> Self {
                $struct_name {
                    ffi: $ref_fn(ffi),
                }
            }
        }

        impl AsRaw<$ffi_name> for $struct_name
        {
            fn as_raw(&self) -> *const $ffi_name {
                self.ffi as *const _
            }
        }

        impl Userdata for $struct_name {
            unsafe fn userdata_raw<T: 'static>(&self) -> *mut T {
                $get_userdata_fn(self.as_raw_mut()) as *mut T
            }
            unsafe fn set_userdata_raw<T: 'static>(&self, ptr: *mut T) {
                $set_userdata_fn(self.as_raw_mut(), ptr as *mut libc::c_void);
            }
        }

        impl Clone for $struct_name {
            fn clone(&self) -> Self {
                unsafe { $struct_name::from_raw(self.as_raw_mut()) }
            }
        }

        impl Drop for $struct_name
        {
            fn drop(&mut self) {
                unsafe {
                    let userdata_ref = $get_userdata_fn(self.as_raw_mut());
                    if $unref_fn(self.ffi).is_null() {
                        let _ = Box::from_raw(userdata_ref);
                    }
                }
            }
        }

        impl PartialEq for $struct_name {
            fn eq(&self, other: &Self) -> bool {
                self.as_raw() == other.as_raw()
            }
        }

        impl ::std::hash::Hash for $struct_name {
            fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
                self.as_raw().hash(state);
            }
        }
    )
}

macro_rules! ffi_func {
    ($(#[$attr:meta])* fn $name:ident, $ffi_fn:path, bool) => (
        $(#[$attr])*
        fn $name(&self) -> bool {
            unsafe { $ffi_fn(self.as_raw_mut()) != 0 }
        }
    );
    ($(#[$attr:meta])* pub fn $name:ident, $ffi_fn:path, bool) => (
        $(#[$attr])*
        pub fn $name(&self) -> bool {
            unsafe { $ffi_fn(self.as_raw_mut()) != 0 }
        }
    );
    ($(#[$attr:meta])* fn $name:ident, $ffi_fn:path, $return_type:ty) => (
        $(#[$attr])*
        fn $name(&self) -> $return_type {
            unsafe { $ffi_fn(self.as_raw_mut()) as $return_type }
        }
    );
    ($(#[$attr:meta])* pub fn $name:ident, $ffi_fn:path, $return_type:ty) => (
        $(#[$attr])*
        pub fn $name(&self) -> $return_type {
            unsafe { $ffi_fn(self.as_raw_mut()) as $return_type }
        }
    );
}

mod context;
mod device;
pub mod event;
mod seat;

pub use context::*;
pub use device::*;
pub use seat::*;
pub use event::Event;
<|endoftext|>