<commit_before>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

//! Payloads are self-contained projects that encapsulate a specific
//! feature or system function. Think of them as reusable chunks of
//! code that can be run across multiple hosts. Any time you have a
//! task that you want to repeat, it should probably go into a
//! payload.
//!
//! For example, a payload could handle installing a specific
//! package, such as Nginx. Or, you could create a payload that
//! configures iptables.
//!
//! # Examples
//!
//! ```no_run
//! # use inapi::{Host, Payload};
#![cfg_attr(feature = "local-run", doc = "# let mut host = Host::local(Some(\"nodes/mynode.json\")).unwrap();")]
#![cfg_attr(feature = "remote-run", doc = "# let mut host = Host::connect(\"nodes/mynode.json\").unwrap();")]
//! let payload = Payload::new("nginx::install").unwrap(); // format is "payload::executable"
//! payload.run(&mut host, None).unwrap();
//! ```

pub mod config;
pub mod ffi;

use czmq::{ZMsg, ZPoller, ZSock, ZSockType, ZSys};
use error::{Error, Result};
use host::{Host,HostSendRecv};
use project::Language;
use self::config::Config;
use serde_json;
use std::env::{current_dir, set_current_dir};
use std::process;
use std::path::PathBuf;
use std::thread;
use zdaemon::ConfigFile;

/// Container for running a Payload.
pub struct Payload {
    /// Path to the payload directory.
    path: PathBuf,
    /// Name of the executable/source file to run.
    artifact: Option<String>,
    /// Language the payload is written in.
    language: Language,
}

impl Payload {
    /// Create a new Payload using the payload::artifact notation.
    /// This notation is simply "payload" + separator ("::") +
    /// "executable/source file". For example: "nginx::install".
    ///
    /// By default, payloads live in
    /// <project root>/payloads/<payload_name>. Thus the payload name
    /// "nginx" will resolve to <project root>/payloads/nginx/. You
    /// can also specify an absolute path to your payload, which will
    /// override the resolved path.
    ///
    /// ```no_run
    /// # use inapi::Payload;
    /// // Using standard payload/artifact notation...
    /// let payload = Payload::new("iptables::update").unwrap();
    ///
    /// // Using an absolute path...
    /// let payload = Payload::new("/mnt/intecture/payloads/iptables::update").unwrap();
    /// ```
    pub fn new(payload_artifact: &str) -> Result<Payload> {
        let mut parts: Vec<&str> = payload_artifact.split("::").collect();
        let payload = if parts.len() > 0 {
            parts.remove(0)
        } else {
            return Err(Error::Generic("Invalid payload string".into()));
        };

        let mut buf = PathBuf::from("payloads");
        buf.push(payload);

        buf.push("payload.json");
        let config = try!(Config::load(&buf));
        buf.pop();

        // Check dependencies
        if let Some(deps) = config.dependencies {
            try!(Self::check_deps(&deps));
        }

        Ok(Payload {
            path: buf,
            artifact: if parts.len() > 1 {
                Some(parts.remove(1).into())
            } else {
                None
            },
            language: config.language,
        })
    }

    /// Compile a payload's source code. This function is also called
    /// by Payload::run(), but is useful for precompiling payloads
    /// ahead of time to catch build errors early.
    ///
    /// Note that this is only useful for compiled languages. If this
    /// function is run on a payload that uses an interpreted
    /// language, it will safely be ignored.
    pub fn build(&self) -> Result<()> {
        let mut make_path = self.path.clone();
        make_path.push("Makefile");

        match self.language {
            Language::C | Language::Rust if make_path.exists() && make_path.is_file() => {
                let current_dir = try!(current_dir());
                try!(set_current_dir(&self.path));

                let output = try!(process::Command::new("make")
                                                   .stdout(process::Stdio::inherit())
                                                   .output());

                try!(set_current_dir(&current_dir));

                if !output.status.success() {
                    return Err(Error::BuildFailed(try!(String::from_utf8(output.stderr))).into());
                }
            },
            Language::Rust => {
                let manifest_path = format!("{}/Cargo.toml", self.path.to_str().unwrap());
                let output = try!(process::Command::new("cargo")
                                                   .args(&["build", "--release", "--manifest-path", &manifest_path])
                                                   .stdout(process::Stdio::inherit())
                                                   .output());
                if !output.status.success() {
                    return Err(Error::BuildFailed(try!(String::from_utf8(output.stderr))).into());
                }
            },
            _ => ()
        }

        Ok(())
    }

    /// Execute the payload's artifact.
    ///
    /// For compiled languages, the artifact will be executed
    /// directly. For interpreted languages, the artifact will be
    /// passed as an argument to the interpreter.
    ///
    /// ```no_run
    /// # use inapi::{Host, Payload};
    #[cfg_attr(feature = "local-run", doc = "# let mut host = Host::local(Some(\"nodes/mynode.json\")).unwrap();")]
    #[cfg_attr(feature = "remote-run", doc = "# let mut host = Host::connect(\"nodes/mynode.json\").unwrap();")]
    /// let payload = Payload::new("iptables::configure").unwrap();
    /// payload.run(&mut host, Some(vec![
    ///     "add_rule",
    ///     "..."
    /// ])).unwrap();
    /// ```
    pub fn run(&self, host: &mut Host, user_args: Option<Vec<&str>>) -> Result<()> {
        // XXX This ugly cloning is a wasteful solution. New ZMQ
        // socket types (SERVER & CLIENT) are threadsafe, which will
        // allow us to thread the ZMQ poller and avoid having to
        // clone half the world. When these are implemented, this
        // code should be changed.

        // Build payload to make sure it's up to date
        try!(self.build());

        let artifact_default = self.artifact.as_ref().map(|a| &**a).unwrap_or("main");
        let api_endpoint = format!("ipc://{}/{}_api.ipc", self.path.to_str().unwrap(), artifact_default);
        let mut api_pipe = ZSock::new(ZSockType::DEALER);
        try!(api_pipe.bind(&api_endpoint));

        let file_endpoint = format!("ipc://{}/{}_file.ipc", self.path.to_str().unwrap(), artifact_default);
        let mut file_pipe = ZSock::new(ZSockType::DEALER);
        try!(file_pipe.bind(&file_endpoint));

        let (mut parent, child) = try!(ZSys::create_pipe());
        let language = self.language.clone();
        let mut payload_path = self.path.clone();
        let artifact = self.artifact.clone();
        let user_args_c: Option<Vec<String>> = match user_args {
            Some(a) => Some(a.into_iter().map(|arg| String::from(arg)).collect()),
            None => None,
        };

        let handle = thread::spawn(move || {
            match language {
                Language::C => {
                    payload_path.push(artifact.as_ref().map(|a| &**a).unwrap_or("main"));

                    let mut args = vec![api_endpoint, file_endpoint];
                    if let Some(mut a) = user_args_c {
                        args.append(&mut a);
                    }

                    let output = try!(process::Command::new(payload_path.to_str().unwrap())
                                                       .args(&args)
                                                       .stdout(process::Stdio::inherit())
                                                       .output());

                    if !output.status.success() {
                        try!(child.signal(0));
                        return Err(Error::RunFailed(try!(String::from_utf8(output.stderr))).into());
                    }
                },
                Language::Php => {
                    payload_path.push("src");
                    payload_path.push(artifact.as_ref().map(|a| &**a).unwrap_or("main"));
                    if payload_path.extension().is_none() {
                        payload_path.set_extension("php");
                    }

                    let mut args = vec![payload_path.to_str().unwrap().into(), api_endpoint, file_endpoint];
                    if let Some(mut a) = user_args_c {
                        args.append(&mut a);
                    }

                    let output = try!(process::Command::new("php")
                                                       .args(&args)
                                                       .stdout(process::Stdio::inherit())
                                                       .output());

                    if !output.status.success() {
                        try!(child.signal(0));
                        return Err(Error::RunFailed(try!(String::from_utf8(output.stderr))).into());
                    }
                },
                Language::Rust => {
                    payload_path.push("Cargo.toml");

                    let mut args = vec![
                        "run".into(),
                        "--release".into(),
                        "--manifest-path".into(),
                        payload_path.to_str().unwrap().into()
                    ];

                    if let Some(a) = artifact {
                        args.push("--bin".into());
                        args.push(a);
                    }

                    args.push("--".into());
                    args.push(api_endpoint);
                    args.push(file_endpoint);

                    if let Some(mut a) = user_args_c {
                        args.append(&mut a);
                    }

                    let output = try!(process::Command::new("cargo")
                                                       .args(&args)
                                                       .stdout(process::Stdio::inherit())
                                                       .output());

                    if !output.status.success() {
                        try!(child.signal(0));
                        return Err(Error::RunFailed(try!(String::from_utf8(output.stderr))).into());
                    }
                }
            }

            try!(child.signal(0));
            Ok(())
        });

        // Send data to payload
        let json = try!(serde_json::to_string(host.data()));
        try!(api_pipe.send_str(&json));

        let mut poller = try!(ZPoller::new());
        try!(poller.add(&mut parent));
        try!(poller.add(&mut api_pipe));
        try!(poller.add(&mut file_pipe));

        loop {
            let sock: Option<ZSock> = poller.wait(None);
            if let Some(mut s) = sock {
                if s == api_pipe {
                    let req = try!(ZMsg::recv(&mut s));
                    try!(host.send(req));

                    let reply = try!(host.recv_raw());
                    try!(reply.send(&mut s));
                }
                else if s == file_pipe {
                    let req = try!(ZMsg::recv(&mut s));
                    try!(host.send_file(req));

                    let reply = try!(host.recv_file_raw());
                    try!(reply.send(&mut s));
                }
                else if s == parent {
                    break;
                } else {
                    unreachable!();
                }
            }

            if poller.terminated() {
                break;
            }
        }

        let cmd_result: Result<()> = try!(handle.join());
        try!(cmd_result);

        Ok(())
    }

    fn check_deps(payloads: &[String]) -> Result<()> {
        for payload in payloads {
            try!(Payload::new(payload));
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use czmq::{ZSock, ZSockType};
    use host::Host;
    use project::Language;
    use std::fs;
    use std::io::Write;
    use std::path::PathBuf;
    use std::process::Command;
    use std::thread;
    use super::*;
    use super::config::Config;
    use tempdir::TempDir;
    use zdaemon::ConfigFile;

    #[test]
    fn test_new_nodeps() {
        let _ = ::_MOCK_ENV.init();

        let tempdir = TempDir::new("test_payload_new_nodeps").unwrap();
        let mut buf = tempdir.path().to_owned();

        create_cargo_proj(&mut buf);

        let conf = Config {
            author: "Dr. Hibbert".into(),
            repository: "https://github.com/dhibbz/hehehe.git".into(),
            language: Language::Rust,
            dependencies: Some(vec!["missing_payload".into()]),
        };

        buf.push("payload.json");
        conf.save(&buf).unwrap();
        buf.pop();

        assert!(Payload::new(buf.to_str().unwrap()).is_err());
    }

    #[test]
    fn test_build_rust() {
        let _ = ::_MOCK_ENV.init();

        let tempdir = TempDir::new("test_payload_build_rust").unwrap();
        let mut buf = tempdir.path().to_owned();

        create_cargo_proj(&mut buf);

        let conf = Config {
            author: "Dr. Hibbert".into(),
            repository: "https://github.com/dhibbz/hehehe.git".into(),
            language: Language::Rust,
            dependencies: None,
        };

        buf.push("payload.json");
        conf.save(&buf).unwrap();
        buf.pop();

        let payload = Payload::new(buf.to_str().unwrap()).unwrap();
        payload.build().unwrap();
    }

    #[test]
    fn test_build_c() {
        let _ = ::_MOCK_ENV.init();

        let tempdir = TempDir::new("test_payload_build_c").unwrap();
        let mut buf = tempdir.path().to_owned();

        buf.push("Makefile");
        let mut fh = fs::File::create(&buf).unwrap();
        fh.write_all(b"all:
\ttouch test").unwrap();
        buf.pop();

        let conf = Config {
            author: "Dr. Hibbert".into(),
            repository: "https://github.com/dhibbz/hehehe.git".into(),
            language: Language::C,
            dependencies: None,
        };

        buf.push("payload.json");
        conf.save(&buf).unwrap();
        buf.pop();

        let payload = Payload::new(buf.to_str().unwrap()).unwrap();
        payload.build().unwrap();

        buf.push("test");
        assert!(buf.exists());
    }

    #[test]
    fn test_run() {
        let _ = ::_MOCK_ENV.init();

        let tempdir = TempDir::new("test_payload_run").unwrap();
        let mut buf = tempdir.path().to_owned();

        create_cargo_proj(&mut buf);

        let conf = Config {
            author: "Dr. Hibbert".into(),
            repository: "https://github.com/dhibbz/hehehe.git".into(),
            language: Language::Rust,
            dependencies: None,
        };

        buf.push("payload.json");
        conf.save(&buf).unwrap();
        buf.pop();

        let payload_name = buf.into_os_string().into_string().unwrap();
        let payload_name_clone = payload_name.clone();

        let handle = thread::spawn(move || {
            let s = ZSock::new(ZSockType::DEALER);
            s.connect(&format!("ipc://{}/main_api.ipc", payload_name_clone)).unwrap();
            s.recv_str().unwrap().unwrap();
        });

        let mut host = Host::test_new(None, None, None, None);
        let payload = Payload::new(&payload_name).unwrap();
        payload.run(&mut host, Some(vec!["abc"])).unwrap();

        handle.join().unwrap();
    }

    fn create_cargo_proj(buf: &mut PathBuf) {
        buf.push("payload");

        let status = Command::new("cargo")
                             .args(&["new", buf.to_str().unwrap(), "--bin"])
                             .status()
                             .expect("Failed to execute process");

        assert!(status.success());
    }
}
<commit_msg>Fixed bug retrieving artifact from payload::artifact string. Stopped using `cargo run` to prevent deadlocks building nested Cargo projects<commit_after>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

//! Payloads are self-contained projects that encapsulate a specific
//! feature or system function. Think of them as reusable chunks of
//! code that can be run across multiple hosts. Any time you have a
//! task that you want to repeat, it should probably go into a
//! payload.
//!
//! For example, a payload could handle installing a specific
//! package, such as Nginx. Or, you could create a payload that
//! configures iptables.
//!
//! # Examples
//!
//! ```no_run
//! # use inapi::{Host, Payload};
#![cfg_attr(feature = "local-run", doc = "# let mut host = Host::local(Some(\"nodes/mynode.json\")).unwrap();")]
#![cfg_attr(feature = "remote-run", doc = "# let mut host = Host::connect(\"nodes/mynode.json\").unwrap();")]
//! let payload = Payload::new("nginx::install").unwrap(); // format is "payload::executable"
//! payload.run(&mut host, None).unwrap();
//! ```

pub mod config;
pub mod ffi;

use czmq::{ZMsg, ZPoller, ZSock, ZSockType, ZSys};
use error::{Error, Result};
use host::{Host,HostSendRecv};
use project::Language;
use self::config::Config;
use serde_json;
use std::env::{current_dir, set_current_dir};
use std::process;
use std::path::PathBuf;
use std::thread;
use zdaemon::ConfigFile;

/// Container for running a Payload.
pub struct Payload {
    /// Path to the payload directory.
    path: PathBuf,
    /// Name of the executable/source file to run.
    artifact: Option<String>,
    /// Language the payload is written in.
    language: Language,
}

impl Payload {
    /// Create a new Payload using the payload::artifact notation.
    /// This notation is simply "payload" + separator ("::") +
    /// "executable/source file". For example: "nginx::install".
    ///
    /// By default, payloads live in
    /// <project root>/payloads/<payload_name>. Thus the payload name
    /// "nginx" will resolve to <project root>/payloads/nginx/. You
    /// can also specify an absolute path to your payload, which will
    /// override the resolved path.
    ///
    /// ```no_run
    /// # use inapi::Payload;
    /// // Using standard payload/artifact notation...
    /// let payload = Payload::new("iptables::update").unwrap();
    ///
    /// // Using an absolute path...
    /// let payload = Payload::new("/mnt/intecture/payloads/iptables::update").unwrap();
    /// ```
    pub fn new(payload_artifact: &str) -> Result<Payload> {
        let mut parts: Vec<&str> = payload_artifact.split("::").collect();
        let payload = if parts.len() > 0 {
            parts.remove(0)
        } else {
            return Err(Error::Generic("Invalid payload string".into()));
        };

        let mut buf = PathBuf::from("payloads");
        buf.push(payload);

        buf.push("payload.json");
        let config = try!(Config::load(&buf));
        buf.pop();

        // Check dependencies
        if let Some(deps) = config.dependencies {
            try!(Self::check_deps(&deps));
        }

        Ok(Payload {
            path: buf,
            artifact: if parts.len() > 0 {
                Some(parts.remove(0).into())
            } else {
                None
            },
            language: config.language,
        })
    }

    /// Compile a payload's source code. This function is also called
    /// by Payload::run(), but is useful for precompiling payloads
    /// ahead of time to catch build errors early.
    ///
    /// Note that this is only useful for compiled languages. If this
    /// function is run on a payload that uses an interpreted
    /// language, it will safely be ignored.
    pub fn build(&self) -> Result<()> {
        let mut make_path = self.path.clone();
        make_path.push("Makefile");

        match self.language {
            Language::C | Language::Rust if make_path.exists() && make_path.is_file() => {
                let current_dir = try!(current_dir());
                try!(set_current_dir(&self.path));

                let output = try!(process::Command::new("make")
                                                   .stdout(process::Stdio::inherit())
                                                   .output());

                try!(set_current_dir(&current_dir));

                if !output.status.success() {
                    return Err(Error::BuildFailed(try!(String::from_utf8(output.stderr))).into());
                }
            },
            Language::Rust => {
                let manifest_path = format!("{}/Cargo.toml", self.path.to_str().unwrap());
                let output = try!(process::Command::new("cargo")
                                                   .args(&["build", "--release", "--manifest-path", &manifest_path])
                                                   .stdout(process::Stdio::inherit())
                                                   .output());
                if !output.status.success() {
                    return Err(Error::BuildFailed(try!(String::from_utf8(output.stderr))).into());
                }
            },
            _ => ()
        }

        Ok(())
    }

    /// Execute the payload's artifact.
    ///
    /// For compiled languages, the artifact will be executed
    /// directly. For interpreted languages, the artifact will be
    /// passed as an argument to the interpreter.
    ///
    /// ```no_run
    /// # use inapi::{Host, Payload};
    #[cfg_attr(feature = "local-run", doc = "# let mut host = Host::local(Some(\"nodes/mynode.json\")).unwrap();")]
    #[cfg_attr(feature = "remote-run", doc = "# let mut host = Host::connect(\"nodes/mynode.json\").unwrap();")]
    /// let payload = Payload::new("iptables::configure").unwrap();
    /// payload.run(&mut host, Some(vec![
    ///     "add_rule",
    ///     "..."
    /// ])).unwrap();
    /// ```
    pub fn run(&self, host: &mut Host, user_args: Option<Vec<&str>>) -> Result<()> {
        // XXX This ugly cloning is a wasteful solution. New ZMQ
        // socket types (SERVER & CLIENT) are threadsafe, which will
        // allow us to thread the ZMQ poller and avoid having to
        // clone half the world. When these are implemented, this
        // code should be changed.

        // Build payload to make sure it's up to date
        try!(self.build());

        let artifact_default = self.artifact.as_ref().map(|a| &**a).unwrap_or("main");
        let api_endpoint = format!("ipc://{}/{}_api.ipc", self.path.to_str().unwrap(), artifact_default);
        let mut api_pipe = ZSock::new(ZSockType::DEALER);
        try!(api_pipe.bind(&api_endpoint));

        let file_endpoint = format!("ipc://{}/{}_file.ipc", self.path.to_str().unwrap(), artifact_default);
        let mut file_pipe = ZSock::new(ZSockType::DEALER);
        try!(file_pipe.bind(&file_endpoint));

        let (mut parent, child) = try!(ZSys::create_pipe());
        let language = self.language.clone();
        let mut payload_path = self.path.clone();
        let artifact = self.artifact.clone();
        let user_args_c: Option<Vec<String>> = match user_args {
            Some(a) => Some(a.into_iter().map(|arg| String::from(arg)).collect()),
            None => None,
        };

        let handle = thread::spawn(move || {
            match language {
                Language::C => {
                    payload_path.push(artifact.as_ref().map(|a| &**a).unwrap_or("main"));

                    let mut args = vec![api_endpoint, file_endpoint];
                    if let Some(mut a) = user_args_c {
                        args.append(&mut a);
                    }

                    let output = try!(process::Command::new(payload_path.to_str().unwrap())
                                                       .args(&args)
                                                       .stdout(process::Stdio::inherit())
                                                       .output());

                    if !output.status.success() {
                        try!(child.signal(0));
                        return Err(Error::RunFailed(try!(String::from_utf8(output.stderr))).into());
                    }
                },
                Language::Php => {
                    payload_path.push("src");
                    payload_path.push(artifact.as_ref().map(|a| &**a).unwrap_or("main"));
                    if payload_path.extension().is_none() {
                        payload_path.set_extension("php");
                    }

                    let mut args = vec![payload_path.to_str().unwrap().into(), api_endpoint, file_endpoint];
                    if let Some(mut a) = user_args_c {
                        args.append(&mut a);
                    }

                    let output = try!(process::Command::new("php")
                                                       .args(&args)
                                                       .stdout(process::Stdio::inherit())
                                                       .output());

                    if !output.status.success() {
                        try!(child.signal(0));
                        return Err(Error::RunFailed(try!(String::from_utf8(output.stderr))).into());
                    }
                },
                Language::Rust => {
                    if let Some(a) = artifact {
                        payload_path.push("target/release");
                        payload_path.push(a);
                    } else {
                        let dirname = try!(try!(payload_path.file_stem().ok_or(Error::RunFailed("Invalid payload path".into())))
                                                            .to_str().ok_or(Error::RunFailed("Invalid payload path".into())))
                                                            .to_owned();
                        payload_path.push("target/release");
                        payload_path.push(&dirname);
                    }

                    let mut args = vec![
                        api_endpoint,
                        file_endpoint
                    ];

                    if let Some(mut a) = user_args_c {
                        args.append(&mut a);
                    }

                    let output = try!(process::Command::new(&payload_path)
                                                       .args(&args)
                                                       .stdout(process::Stdio::inherit())
                                                       .output());

                    if !output.status.success() {
                        try!(child.signal(0));
                        return Err(Error::RunFailed(try!(String::from_utf8(output.stderr))).into());
                    }
                }
            }

            try!(child.signal(0));
            Ok(())
        });

        // Send data to payload
        let json = try!(serde_json::to_string(host.data()));
        try!(api_pipe.send_str(&json));

        let mut poller = try!(ZPoller::new());
        try!(poller.add(&mut parent));
        try!(poller.add(&mut api_pipe));
        try!(poller.add(&mut file_pipe));

        loop {
            let sock: Option<ZSock> = poller.wait(None);
            if let Some(mut s) = sock {
                if s == api_pipe {
                    let req = try!(ZMsg::recv(&mut s));
                    try!(host.send(req));

                    let reply = try!(host.recv_raw());
                    try!(reply.send(&mut s));
                }
                else if s == file_pipe {
                    let req = try!(ZMsg::recv(&mut s));
                    try!(host.send_file(req));

                    let reply = try!(host.recv_file_raw());
                    try!(reply.send(&mut s));
                }
                else if s == parent {
                    break;
                } else {
                    unreachable!();
                }
            }

            if poller.terminated() {
                break;
            }
        }

        let cmd_result: Result<()> = try!(handle.join());
        try!(cmd_result);

        Ok(())
    }

    fn check_deps(payloads: &[String]) -> Result<()> {
        for payload in payloads {
            try!(Payload::new(payload));
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use czmq::{ZSock, ZSockType};
    use host::Host;
    use project::Language;
    use std::fs;
    use std::io::Write;
    use std::path::PathBuf;
    use std::process::Command;
    use std::thread;
    use super::*;
    use super::config::Config;
    use tempdir::TempDir;
    use zdaemon::ConfigFile;

    #[test]
    fn test_new_nodeps() {
        let _ = ::_MOCK_ENV.init();

        let tempdir = TempDir::new("test_payload_new_nodeps").unwrap();
        let mut buf = tempdir.path().to_owned();

        create_cargo_proj(&mut buf);

        let conf = Config {
            author: "Dr. Hibbert".into(),
            repository: "https://github.com/dhibbz/hehehe.git".into(),
            language: Language::Rust,
            dependencies: Some(vec!["missing_payload".into()]),
        };

        buf.push("payload.json");
        conf.save(&buf).unwrap();
        buf.pop();

        assert!(Payload::new(buf.to_str().unwrap()).is_err());
    }

    #[test]
    fn test_build_rust() {
        let _ = ::_MOCK_ENV.init();

        let tempdir = TempDir::new("test_payload_build_rust").unwrap();
        let mut buf = tempdir.path().to_owned();

        create_cargo_proj(&mut buf);

        let conf = Config {
            author: "Dr. Hibbert".into(),
            repository: "https://github.com/dhibbz/hehehe.git".into(),
            language: Language::Rust,
            dependencies: None,
        };

        buf.push("payload.json");
        conf.save(&buf).unwrap();
        buf.pop();

        let payload = Payload::new(buf.to_str().unwrap()).unwrap();
        payload.build().unwrap();
    }

    #[test]
    fn test_build_c() {
        let _ = ::_MOCK_ENV.init();

        let tempdir = TempDir::new("test_payload_build_c").unwrap();
        let mut buf = tempdir.path().to_owned();

        buf.push("Makefile");
        let mut fh = fs::File::create(&buf).unwrap();
        fh.write_all(b"all:
\ttouch test").unwrap();
        buf.pop();

        let conf = Config {
            author: "Dr. Hibbert".into(),
            repository: "https://github.com/dhibbz/hehehe.git".into(),
            language: Language::C,
            dependencies: None,
        };

        buf.push("payload.json");
        conf.save(&buf).unwrap();
        buf.pop();

        let payload = Payload::new(buf.to_str().unwrap()).unwrap();
        payload.build().unwrap();

        buf.push("test");
        assert!(buf.exists());
    }

    #[test]
    fn test_run() {
        let _ = ::_MOCK_ENV.init();

        let tempdir = TempDir::new("test_payload_run").unwrap();
        let mut buf = tempdir.path().to_owned();

        create_cargo_proj(&mut buf);

        let conf = Config {
            author: "Dr. Hibbert".into(),
            repository: "https://github.com/dhibbz/hehehe.git".into(),
            language: Language::Rust,
            dependencies: None,
        };

        buf.push("payload.json");
        conf.save(&buf).unwrap();
        buf.pop();

        let payload_name = buf.into_os_string().into_string().unwrap();
        let payload_name_clone = payload_name.clone();

        let handle = thread::spawn(move || {
            let s = ZSock::new(ZSockType::DEALER);
            s.connect(&format!("ipc://{}/main_api.ipc", payload_name_clone)).unwrap();
            s.recv_str().unwrap().unwrap();
        });

        let mut host = Host::test_new(None, None, None, None);
        let payload = Payload::new(&payload_name).unwrap();
        payload.run(&mut host, Some(vec!["abc"])).unwrap();

        handle.join().unwrap();
    }

    fn create_cargo_proj(buf: &mut PathBuf) {
        buf.push("payload");

        let status = Command::new("cargo")
                             .args(&["new", buf.to_str().unwrap(), "--bin"])
                             .status()
                             .expect("Failed to execute process");

        assert!(status.success());
    }
}
<|endoftext|>


<commit_before>//! Defines types found in various posix_types.h files.
//!
//! If unsure, check include/uapi/asm-generic/posix_types.h **first**, then /arch/*/include/uapi/asm/posix_types.h
//!
//! For the best result, use http://lxr.free-electrons.com

#[cfg(any(target_arch="sparc", target_arch="parisc"))]
///A type that defines microseconds. Since you're using either SPARC or (pa)RISC, it is a c_int
pub type suseconds_t = ::c_int;

#[cfg(not(any(target_arch="sparc", target_arch="parisc")))]
///A type that defines microseconds. You're using a "regular" processor, so it is a c_long
pub type suseconds_t = ::c_long;

///A type that defines a clock ID. As of 4.1, this is always c_int
pub type clockid_t = ::c_int;

///A type that defines a Process or Thread Group ID
pub type pid_t = ::c_int;

///A type that defines a user ID
pub type uid_t = ::c_int;<commit_msg>Add gid_t<commit_after>//! Defines types found in various posix_types.h files.
//!
//! If unsure, check include/uapi/asm-generic/posix_types.h **first**, then /arch/*/include/uapi/asm/posix_types.h
//!
//! For the best result, use http://lxr.free-electrons.com

#[cfg(any(target_arch="sparc", target_arch="parisc"))]
///A type that defines microseconds. Since you're using either SPARC or (pa)RISC, it is a c_int
pub type suseconds_t = ::c_int;

#[cfg(not(any(target_arch="sparc", target_arch="parisc")))]
///A type that defines microseconds. You're using a "regular" processor, so it is a c_long
pub type suseconds_t = ::c_long;

///A type that defines a clock ID. As of 4.1, this is always c_int
pub type clockid_t = ::c_int;

///A type that defines a Process or Thread Group ID
pub type pid_t = ::c_int;

///A type that defines a user ID
pub type uid_t = ::c_uint;

///A type that defines a group ID
pub type gid_t = ::c_uint;<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Thread-local random number generator

use core::cell::UnsafeCell;
use std::rc::Rc;
use std::thread_local;

use super::std::Core;
use crate::rngs::adapter::ReseedingRng;
use crate::rngs::OsRng;
use crate::{CryptoRng, Error, RngCore, SeedableRng};

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.

// Number of generated bytes after which to reseed `ThreadRng`.
// According to benchmarks, reseeding has a noticable impact with thresholds
// of 32 kB and less. We choose 64 kB to avoid significant overhead.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;

/// A reference to the thread-local generator
///
/// An instance can be obtained via [`thread_rng`] or via `ThreadRng::default()`.
/// This handle is safe to use everywhere (including thread-local destructors)
/// but cannot be passed between threads (is not `Send` or `Sync`).
///
/// `ThreadRng` uses the same PRNG as [`StdRng`] for security and performance
/// and is automatically seeded from [`OsRng`].
///
/// Unlike `StdRng`, `ThreadRng` uses the  [`ReseedingRng`] wrapper to reseed
/// the PRNG from fresh entropy every 64 kiB of random data as well as after a
/// fork on Unix (though not quite immediately; see documentation of
/// [`ReseedingRng`]).
/// Note that the reseeding is done as an extra precaution against side-channel
/// attacks and mis-use (e.g. if somehow weak entropy were supplied initially).
/// The PRNG algorithms used are assumed to be secure.
///
/// [`ReseedingRng`]: crate::rngs::adapter::ReseedingRng
/// [`StdRng`]: crate::rngs::StdRng
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))]
#[derive(Clone, Debug)]
pub struct ThreadRng {
    // Rc is explictly !Send and !Sync
    rng: Rc<UnsafeCell<ReseedingRng<Core, OsRng>>>,
}

thread_local!(
    // We require Rc<..> to avoid premature freeing when thread_rng is used
    // within thread-local destructors. See #968.
    static THREAD_RNG_KEY: Rc<UnsafeCell<ReseedingRng<Core, OsRng>>> = {
        let r = Core::from_rng(OsRng).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    OsRng);
        Rc::new(UnsafeCell::new(rng))
    }
);

/// Retrieve the lazily-initialized thread-local random number generator,
/// seeded by the system. Intended to be used in method chaining style,
/// e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.  Invoked by the `Default` trait, making
/// `ThreadRng::default()` equivalent.
///
/// For more information see [`ThreadRng`].
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))]
pub fn thread_rng() -> ThreadRng {
    let rng = THREAD_RNG_KEY.with(|t| t.clone());
    ThreadRng { rng }
}

impl Default for ThreadRng {
    fn default() -> ThreadRng {
        crate::prelude::thread_rng()
    }
}

impl ThreadRng {
    #[inline(always)]
    fn rng(&mut self) -> &mut ReseedingRng<Core, OsRng> {
        unsafe { &mut *self.rng.get() }
    }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        self.rng().next_u32()
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        self.rng().next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.rng().fill_bytes(dest)
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.rng().try_fill_bytes(dest)
    }
}

impl CryptoRng for ThreadRng {}

#[cfg(test)]
mod test {
    #[test]
    fn test_thread_rng() {
        use crate::Rng;
        let mut r = crate::thread_rng();
        r.gen::<i32>();
        assert_eq!(r.gen_range(0..1), 0);
    }
}
<commit_msg>Get rid of `ThreadRng::rng`<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Thread-local random number generator

use core::cell::UnsafeCell;
use std::rc::Rc;
use std::thread_local;

use super::std::Core;
use crate::rngs::adapter::ReseedingRng;
use crate::rngs::OsRng;
use crate::{CryptoRng, Error, RngCore, SeedableRng};

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.

// Number of generated bytes after which to reseed `ThreadRng`.
// According to benchmarks, reseeding has a noticable impact with thresholds
// of 32 kB and less. We choose 64 kB to avoid significant overhead.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 1024 * 64;

/// A reference to the thread-local generator
///
/// An instance can be obtained via [`thread_rng`] or via `ThreadRng::default()`.
/// This handle is safe to use everywhere (including thread-local destructors)
/// but cannot be passed between threads (is not `Send` or `Sync`).
///
/// `ThreadRng` uses the same PRNG as [`StdRng`] for security and performance
/// and is automatically seeded from [`OsRng`].
///
/// Unlike `StdRng`, `ThreadRng` uses the  [`ReseedingRng`] wrapper to reseed
/// the PRNG from fresh entropy every 64 kiB of random data as well as after a
/// fork on Unix (though not quite immediately; see documentation of
/// [`ReseedingRng`]).
/// Note that the reseeding is done as an extra precaution against side-channel
/// attacks and mis-use (e.g. if somehow weak entropy were supplied initially).
/// The PRNG algorithms used are assumed to be secure.
///
/// [`ReseedingRng`]: crate::rngs::adapter::ReseedingRng
/// [`StdRng`]: crate::rngs::StdRng
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))]
#[derive(Clone, Debug)]
pub struct ThreadRng {
    // Rc is explictly !Send and !Sync
    rng: Rc<UnsafeCell<ReseedingRng<Core, OsRng>>>,
}

thread_local!(
    // We require Rc<..> to avoid premature freeing when thread_rng is used
    // within thread-local destructors. See #968.
    static THREAD_RNG_KEY: Rc<UnsafeCell<ReseedingRng<Core, OsRng>>> = {
        let r = Core::from_rng(OsRng).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    OsRng);
        Rc::new(UnsafeCell::new(rng))
    }
);

/// Retrieve the lazily-initialized thread-local random number generator,
/// seeded by the system. Intended to be used in method chaining style,
/// e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.  Invoked by the `Default` trait, making
/// `ThreadRng::default()` equivalent.
///
/// For more information see [`ThreadRng`].
#[cfg_attr(doc_cfg, doc(cfg(all(feature = "std", feature = "std_rng"))))]
pub fn thread_rng() -> ThreadRng {
    let rng = THREAD_RNG_KEY.with(|t| t.clone());
    ThreadRng { rng }
}

impl Default for ThreadRng {
    fn default() -> ThreadRng {
        crate::prelude::thread_rng()
    }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        // SAFETY: We must make sure to stop using `rng` before anyone else
        // creates another mutable reference
        let rng = unsafe { &mut *self.rng.get() };
        rng.next_u32()
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        // SAFETY: We must make sure to stop using `rng` before anyone else
        // creates another mutable reference
        let rng = unsafe { &mut *self.rng.get() };
        rng.next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        // SAFETY: We must make sure to stop using `rng` before anyone else
        // creates another mutable reference
        let rng = unsafe { &mut *self.rng.get() };
        rng.fill_bytes(dest)
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        // SAFETY: We must make sure to stop using `rng` before anyone else
        // creates another mutable reference
        let rng = unsafe { &mut *self.rng.get() };
        rng.try_fill_bytes(dest)
    }
}

impl CryptoRng for ThreadRng {}

#[cfg(test)]
mod test {
    #[test]
    fn test_thread_rng() {
        use crate::Rng;
        let mut r = crate::thread_rng();
        r.gen::<i32>();
        assert_eq!(r.gen_range(0..1), 0);
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Thread-local random number generator

use std::cell::UnsafeCell;

use {RngCore, CryptoRng, SeedableRng, Error};
use rngs::adapter::ReseedingRng;
use rngs::OsRng;
use rand_hc::Hc128Core;

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.
//
// The additional `Rc` is not strictly neccesary, and could be removed. For now
// it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`.

// Number of generated bytes after which to reseed `TreadRng`.
//
// The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB.
// We pick a treshold here that is large enough to not reduce the average
// performance too much, but also small enough to not make reseeding something
// that basically never happens.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB

/// The type returned by [`thread_rng`], essentially just a reference to the
/// PRNG in thread-local memory.
///
/// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`],
/// which is reseeded after generating 32 MiB of random data. A single instance
/// is cached per thread and the returned `ThreadRng` is a reference to this
/// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use
/// within a single thread. This RNG is seeded and reseeded via [`OsRng`]
/// as required.
///
/// Note that the reseeding is done as an extra precaution against entropy
/// leaks and is in theory unnecessary — to predict `ThreadRng`'s output, an
/// attacker would have to either determine most of the RNG's seed or internal
/// state, or crack the algorithm used.
///
/// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current
/// algorithm used is [HC-128], which is an array-based PRNG that trades memory
/// usage for better performance. This makes it similar to ISAAC, the algorithm
/// used in `ThreadRng` before rand 0.5.
///
/// Cloning this handle just produces a new reference to the same thread-local
/// generator.
///
/// [`ReseedingRng`]: crate::rngs::adapter::ReseedingRng
/// [`StdRng`]: crate::rngs::StdRng
/// [HC-128]: rand_hc::Hc128Rng
#[derive(Clone, Debug)]
pub struct ThreadRng {
    // use of raw pointer implies type is neither Send nor Sync
    rng: *mut ReseedingRng<Hc128Core, OsRng>,
}

thread_local!(
    static THREAD_RNG_KEY: UnsafeCell<ReseedingRng<Hc128Core, OsRng>> = {
        let r = Hc128Core::from_rng(OsRng).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    OsRng);
        UnsafeCell::new(rng)
    }
);

/// Retrieve the lazily-initialized thread-local random number generator,
/// seeded by the system. Intended to be used in method chaining style,
/// e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.  Invoked by the `Default` trait, making
/// `ThreadRng::default()` equivelent.
///
/// For more information see [`ThreadRng`].
pub fn thread_rng() -> ThreadRng {
    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.get()) }
}

impl Default for ThreadRng {
    fn default() -> ThreadRng {
        ::prelude::thread_rng()
    }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        unsafe { (*self.rng).next_u32() }
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        unsafe { (*self.rng).next_u64() }
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        unsafe { (*self.rng).fill_bytes(dest) }
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        unsafe { (*self.rng).try_fill_bytes(dest) }
    }
}

impl CryptoRng for ThreadRng {}

#[cfg(test)]
mod test {
    #[test]
    fn test_thread_rng() {
        use Rng;
        let mut r = ::thread_rng();
        r.gen::<i32>();
        assert_eq!(r.gen_range(0, 1), 0);
    }
}
<commit_msg>Fix typo in docstring<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Thread-local random number generator

use std::cell::UnsafeCell;

use {RngCore, CryptoRng, SeedableRng, Error};
use rngs::adapter::ReseedingRng;
use rngs::OsRng;
use rand_hc::Hc128Core;

// Rationale for using `UnsafeCell` in `ThreadRng`:
//
// Previously we used a `RefCell`, with an overhead of ~15%. There will only
// ever be one mutable reference to the interior of the `UnsafeCell`, because
// we only have such a reference inside `next_u32`, `next_u64`, etc. Within a
// single thread (which is the definition of `ThreadRng`), there will only ever
// be one of these methods active at a time.
//
// A possible scenario where there could be multiple mutable references is if
// `ThreadRng` is used inside `next_u32` and co. But the implementation is
// completely under our control. We just have to ensure none of them use
// `ThreadRng` internally, which is nonsensical anyway. We should also never run
// `ThreadRng` in destructors of its implementation, which is also nonsensical.
//
// The additional `Rc` is not strictly neccesary, and could be removed. For now
// it ensures `ThreadRng` stays `!Send` and `!Sync`, and implements `Clone`.

// Number of generated bytes after which to reseed `TreadRng`.
//
// The time it takes to reseed HC-128 is roughly equivalent to generating 7 KiB.
// We pick a treshold here that is large enough to not reduce the average
// performance too much, but also small enough to not make reseeding something
// that basically never happens.
const THREAD_RNG_RESEED_THRESHOLD: u64 = 32*1024*1024; // 32 MiB

/// The type returned by [`thread_rng`], essentially just a reference to the
/// PRNG in thread-local memory.
///
/// `ThreadRng` uses [`ReseedingRng`] wrapping the same PRNG as [`StdRng`],
/// which is reseeded after generating 32 MiB of random data. A single instance
/// is cached per thread and the returned `ThreadRng` is a reference to this
/// instance — hence `ThreadRng` is neither `Send` nor `Sync` but is safe to use
/// within a single thread. This RNG is seeded and reseeded via [`OsRng`]
/// as required.
///
/// Note that the reseeding is done as an extra precaution against entropy
/// leaks and is in theory unnecessary — to predict `ThreadRng`'s output, an
/// attacker would have to either determine most of the RNG's seed or internal
/// state, or crack the algorithm used.
///
/// Like [`StdRng`], `ThreadRng` is a cryptographically secure PRNG. The current
/// algorithm used is [HC-128], which is an array-based PRNG that trades memory
/// usage for better performance. This makes it similar to ISAAC, the algorithm
/// used in `ThreadRng` before rand 0.5.
///
/// Cloning this handle just produces a new reference to the same thread-local
/// generator.
///
/// [`ReseedingRng`]: crate::rngs::adapter::ReseedingRng
/// [`StdRng`]: crate::rngs::StdRng
/// [HC-128]: rand_hc::Hc128Rng
#[derive(Clone, Debug)]
pub struct ThreadRng {
    // use of raw pointer implies type is neither Send nor Sync
    rng: *mut ReseedingRng<Hc128Core, OsRng>,
}

thread_local!(
    static THREAD_RNG_KEY: UnsafeCell<ReseedingRng<Hc128Core, OsRng>> = {
        let r = Hc128Core::from_rng(OsRng).unwrap_or_else(|err|
                panic!("could not initialize thread_rng: {}", err));
        let rng = ReseedingRng::new(r,
                                    THREAD_RNG_RESEED_THRESHOLD,
                                    OsRng);
        UnsafeCell::new(rng)
    }
);

/// Retrieve the lazily-initialized thread-local random number generator,
/// seeded by the system. Intended to be used in method chaining style,
/// e.g. `thread_rng().gen::<i32>()`, or cached locally, e.g.
/// `let mut rng = thread_rng();`.  Invoked by the `Default` trait, making
/// `ThreadRng::default()` equivalent.
///
/// For more information see [`ThreadRng`].
pub fn thread_rng() -> ThreadRng {
    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.get()) }
}

impl Default for ThreadRng {
    fn default() -> ThreadRng {
        ::prelude::thread_rng()
    }
}

impl RngCore for ThreadRng {
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        unsafe { (*self.rng).next_u32() }
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        unsafe { (*self.rng).next_u64() }
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        unsafe { (*self.rng).fill_bytes(dest) }
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        unsafe { (*self.rng).try_fill_bytes(dest) }
    }
}

impl CryptoRng for ThreadRng {}

#[cfg(test)]
mod test {
    #[test]
    fn test_thread_rng() {
        use Rng;
        let mut r = ::thread_rng();
        r.gen::<i32>();
        assert_eq!(r.gen_range(0, 1), 0);
    }
}
<|endoftext|>


<commit_before>//! DPLL Algorithm implementation with unit-clause propagation and
//! pure literal assignment.

use satyrs::cnf::{CNF, Assignment, PartialAssignment};
use satyrs::heuristics::jw;

#[allow(non_snake_case)]
pub fn DPLL(cnf: &CNF, verbose: bool) -> Option<(Assignment,PartialAssignment)> {
    let mut p_assn = PartialAssignment::new(cnf.nvar as usize);
    match _dpll(cnf, &mut p_assn, verbose) {
        Some(assn) => {
            Some((assn.assignment
                     .iter()
                     .map(|a| {
                         match *a {
                             Some(a) => a,
                             None => true,
                         }
                     })
                     .collect(),
                     assn))
        }
        None => None,
    }
}

fn _dpll(cnf: &CNF, p_assn: &mut PartialAssignment, verbose: bool) -> Option<PartialAssignment> {
    if verbose {
        println!("====DPLL====\n");
        println!("{}\n{}", cnf, p_assn);
    }
    // If consistent set of literals, return True
    if cnf.clauses.is_empty() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);  // Display optional value
    }

    // If contains an empty clause return None
    for clause in cnf.clauses.values() {
        if clause.is_empty() {
            return None;
        }
    }

    // For every unit-clause, unit-propagate
    let mut _cnf = cnf.clone();
    let mut units = cnf.units.clone();
    while !units.is_empty() {
        if verbose { println!("Simplifying unit clause(s): {:?}", units) }
        for unit in units.iter() {
            // Previous versions of this for loop could have unit-propagated and
            // remove the unit clause here, so it's not necessary that the unit clause id
            // still exists in the clauses.
            let mut propagate: bool = false;
            if let Some(clause) = _cnf.clauses.get(&unit) {
                // Then via unit propagation we've created an empty clause; no solution down this path
                if clause.is_empty() {
                    return None;
                }
                let lit: i32 = zeroth!(clause);
                p_assn.assign_literal(lit);
                propagate=true;
                // TODO: Could have check for empty clauses in unit_propagate
            }
            if propagate { _cnf.unit_propagate(*unit); } // Only propagate in the clone
        }
        units = _cnf.units.clone();
    }
    println!("After cascade: {}", cnf);
    // Pure literal elimination
    // We can iterate through old cnf occurrences and propagate on new _cnf
    for lit in cnf.occurrences.keys() {
        let neg = *lit ^ 1;
        if !cnf.occurrences.contains_key(&neg) {
            p_assn.assign_literal(*lit);
            _cnf.propagate(*lit);
        }
    }

    // Clone for the right literal, since we're going to propagate _cnf with the left literal
    let mut r_cnf = _cnf.clone();

    // Choose literal L for split
    // Heuristics don't do random checks for empty occurrences.
    // If there are no occurrences,
    if _cnf.occurrences.is_empty() {
        // FIXME: horrible hack
        // Bookkeeping is not implemented perfectly, we can get to this state and (just from
        // empirics) clauses will either be EMPTY or will have any number of empty clauses.
        // Intutition: if clauses is EMPTY, then there are no occurrences but also no clauses, so
        // we're good to go. If clauses is NOT empty, then there are no occurrences but there are
        // clauses, so the clauses are empty, so we return none.
        if _cnf.clauses.is_empty() {
            // Good
            let _p_assn = p_assn.clone();
            return Some(_p_assn);
        } else {
            // Bad
            return None;
        }
    }
    let lit = jw(&_cnf);

    if verbose {
        if lit & 1 == 0 {
            // True
            println!("Splitting on {}", lit / 2);
        } else {
            // False
            println!("Splitting on -{}", lit / 2);
        }
    }
    // Propagate literal
    _cnf.propagate(lit);

    // Return DPLL with L and -L
    p_assn.assign_literal(lit);

    if verbose {
        println!("Trying left");
    }
    let left = _dpll(&_cnf, p_assn, verbose);
    // If this branch works, return left.
    if left.is_some() {
        return left;
    }

    // Otherwise, unassign this literal, assign its negation, and try the subsequent formula.
    let neg = lit ^ 1;
    p_assn.unassign_literal(lit);
    p_assn.assign_literal(neg);

    r_cnf.propagate(neg);
    if verbose {
        println!("Trying right");
    }
    _dpll(&r_cnf, p_assn, verbose)
}
<commit_msg>Fixed cascading bug<commit_after>//! DPLL Algorithm implementation with unit-clause propagation and
//! pure literal assignment.

use satyrs::cnf::{CNF, Assignment, PartialAssignment};
use satyrs::heuristics::jw;

#[allow(non_snake_case)]
pub fn DPLL(cnf: &CNF, verbose: bool) -> Option<(Assignment,PartialAssignment)> {
    let mut p_assn = PartialAssignment::new(cnf.nvar as usize);
    match _dpll(cnf, &mut p_assn, verbose) {
        Some(assn) => {
            Some((assn.assignment
                     .iter()
                     .map(|a| {
                         match *a {
                             Some(a) => a,
                             None => true,
                         }
                     })
                     .collect(),
                     assn))
        }
        None => None,
    }
}

fn _dpll(cnf: &CNF, p_assn: &mut PartialAssignment, verbose: bool) -> Option<PartialAssignment> {
    if verbose {
        println!("====DPLL====\n");
        println!("{}\n{}", cnf, p_assn);
    }
    // If consistent set of literals, return True
    if cnf.clauses.is_empty() {
        let _p_assn = p_assn.clone();
        return Some(_p_assn);  // Display optional value
    }

    // If contains an empty clause return None
    for clause in cnf.clauses.values() {
        if clause.is_empty() {
            return None;
        }
    }

    // For every unit-clause, unit-propagate
    let mut _cnf = cnf.clone();
    let mut units = _cnf.units.clone();
    while !units.is_empty() {
        if verbose { println!("Simplifying unit clause(s): {:?}", units) }
        for unit in units.iter() {
            // Previous versions of this for loop could have unit-propagated and
            // remove the unit clause here, so it's not necessary that the unit clause id
            // still exists in the clauses.
            if let Some(clause) = _cnf.clauses.get(&unit) {
                // Then via unit propagation we've created an empty clause; no solution down this path
                if clause.is_empty() {
                    return None;
                }
                let lit: i32 = zeroth!(clause);
                p_assn.assign_literal(lit);
                // TODO: Could have check for empty clauses in unit_propagate
            }
            _cnf.unit_propagate(*unit); // Only propagate in the clone
        }
        units = _cnf.units.clone();
    }
    // Pure literal elimination
    // We can iterate through old cnf occurrences and propagate on new _cnf
    for lit in cnf.occurrences.keys() {
        let neg = *lit ^ 1;
        if !cnf.occurrences.contains_key(&neg) {
            p_assn.assign_literal(*lit);
            _cnf.propagate(*lit);
        }
    }

    // Clone for the right literal, since we're going to propagate _cnf with the left literal
    let mut r_cnf = _cnf.clone();

    // Choose literal L for split
    // Heuristics don't do random checks for empty occurrences.
    // If there are no occurrences,
    if _cnf.occurrences.is_empty() {
        // FIXME: horrible hack
        // Bookkeeping is not implemented perfectly, we can get to this state and (just from
        // empirics) clauses will either be EMPTY or will have any number of empty clauses.
        // Intutition: if clauses is EMPTY, then there are no occurrences but also no clauses, so
        // we're good to go. If clauses is NOT empty, then there are no occurrences but there are
        // clauses, so the clauses are empty, so we return none.
        if _cnf.clauses.is_empty() {
            // Good
            let _p_assn = p_assn.clone();
            return Some(_p_assn);
        } else {
            // Bad
            return None;
        }
    }
    let lit = jw(&_cnf);

    if verbose {
        if lit & 1 == 0 {
            // True
            println!("Splitting on {}", lit / 2);
        } else {
            // False
            println!("Splitting on -{}", lit / 2);
        }
    }
    // Propagate literal
    _cnf.propagate(lit);

    // Return DPLL with L and -L
    p_assn.assign_literal(lit);

    if verbose {
        println!("Trying left");
    }
    let left = _dpll(&_cnf, p_assn, verbose);
    // If this branch works, return left.
    if left.is_some() {
        return left;
    }

    // Otherwise, unassign this literal, assign its negation, and try the subsequent formula.
    let neg = lit ^ 1;
    p_assn.unassign_literal(lit);
    p_assn.assign_literal(neg);

    r_cnf.propagate(neg);
    if verbose {
        println!("Trying right");
    }
    _dpll(&r_cnf, p_assn, verbose)
}
<|endoftext|>


<commit_before>use stats::LogProb;

pub mod evidence {
    /// Scale of evidence as defined by
    /// [Kass and Raftery 1995](http://www.andrew.cmu.edu/user/kk3n/simplicity/KassRaftery1995.pdf).
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
    pub enum KassRaftery {
        None,
        Barely,
        Positive,
        Strong,
        VeryStrong,
    }
}

custom_derive! {
    /// A newtype for Bayes factors.
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug,
    )]
    pub struct BayesFactor(pub f64);
}

impl BayesFactor {
    /// Calculate Bayes factor from given probabilities.
    pub fn new(a: LogProb, b: LogProb) -> Self {
        BayesFactor((a - b).exp())
    }

    /// Calculate strength of evidence as defined by
    /// [Kass and Raftery 1995](http://www.andrew.cmu.edu/user/kk3n/simplicity/KassRaftery1995.pdf).
    pub fn evidence_kass_raftery(&self) -> evidence::KassRaftery {
        let k = **self;
        if k >= 1.0 && k <= 3.0 {
            evidence::KassRaftery::Barely
        } else if k <= 20.0 {
            evidence::KassRaftery::Positive
        } else if k <= 150.0 {
            evidence::KassRaftery::Strong
        } else {
            evidence::KassRaftery::VeryStrong
        }
    }
}

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

    #[test]
    fn test_bayes_factor() {
        let bf = BayesFactor::new(LogProb(0.5_f64.ln()), LogProb(0.1_f64.ln()));
        assert_relative_eq!(*bf, 5.0, epsilon = 1e-9);
        assert_eq!(bf.evidence_kass_raftery(), evidence::KassRaftery::Positive);
    }
}
<commit_msg>implement FromStr for KassRaftery.<commit_after>use stats::LogProb;

pub mod evidence {
    use std::str::FromStr;

    /// Scale of evidence as defined by
    /// [Kass and Raftery 1995](http://www.andrew.cmu.edu/user/kk3n/simplicity/KassRaftery1995.pdf).
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
    pub enum KassRaftery {
        None,
        Barely,
        Positive,
        Strong,
        VeryStrong,
    }

    impl FromStr for KassRaftery {
        type Err = ParseError;

        fn from_str(s: &str) -> Result<Self, Self::Err> {
            match s {
                "none" => Ok(KassRaftery::None),
                "barely" => Ok(KassRaftery::Barely),
                "positive" => Ok(KassRaftery::Positive),
                "strong" => Ok(KassRaftery::Strong),
                "very-strong" => Ok(KassRaftery::VeryStrong),
                _ => Err(ParseError::Some),
            }
        }
    }

    quick_error! {
        #[derive(Debug)]
        pub enum ParseError {
            Some {
                description("unable to parse Kass Raftery score")
                display("valid values are none, barely, positive, strong, very-strong")
            }
        }
    }
}

custom_derive! {
    /// A newtype for Bayes factors.
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug,
    )]
    pub struct BayesFactor(pub f64);
}

impl BayesFactor {
    /// Calculate Bayes factor from given probabilities.
    pub fn new(a: LogProb, b: LogProb) -> Self {
        BayesFactor((a - b).exp())
    }

    /// Calculate strength of evidence as defined by
    /// [Kass and Raftery 1995](http://www.andrew.cmu.edu/user/kk3n/simplicity/KassRaftery1995.pdf).
    pub fn evidence_kass_raftery(&self) -> evidence::KassRaftery {
        let k = **self;
        if k >= 1.0 && k <= 3.0 {
            evidence::KassRaftery::Barely
        } else if k <= 20.0 {
            evidence::KassRaftery::Positive
        } else if k <= 150.0 {
            evidence::KassRaftery::Strong
        } else {
            evidence::KassRaftery::VeryStrong
        }
    }
}

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

    #[test]
    fn test_bayes_factor() {
        let bf = BayesFactor::new(LogProb(0.5_f64.ln()), LogProb(0.1_f64.ln()));
        assert_relative_eq!(*bf, 5.0, epsilon = 1e-9);
        assert_eq!(bf.evidence_kass_raftery(), evidence::KassRaftery::Positive);
    }
}
<|endoftext|>


<commit_before>use std::ptr;
use std::collections::HashMap;
use glib::Error;
use glib::glib_container::GlibContainer;
use glib::object::{Wrapper, Ref, Object, Upcast};
use glib::types::{StaticType, Type};
use glib::translate::*;
use secret_service::SecretService;
use secret_value::SecretValue;
use SecretResult;
use ffi;

/// SecretItem represents a secret item stored in the Secret Service.
/// Each item has a value, represented by a SecretValue, which can be retrieved by `get_secret()` or set by `set_secret()` (TODO). The item is only available when the item is not locked.
/// Items can be locked or unlocked using the `Lock::lock()` or `Lock::unlock()` functions. The Lock trait is implemented by SecretItem. The Secret Service may not be able to unlock individual items, and may unlock an entire collection when a single item is unlocked.
/// Each item has a set of attributes, which are used to locate the item later. These are not stored or transferred in a secure manner. Each attribute has a string name and a string value. Use `SecretService::search()` to search for items based on their attributes, and `set_attributes()` (TODO) to change the attributes associated with an item.
/// Items can be created with `create()` (TODO) or `SecretService::store()`.
pub struct SecretItem(Ref);

impl SecretItem {

    /// Delete this secret item.
    pub fn delete(&self) -> SecretResult<()> {
        let mut err = ptr::null_mut();
        unsafe{ffi::secret_item_delete_sync(self.to_glib_none().0, ptr::null_mut(), &mut err)};
        if err.is_null() {
            Ok(())
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Get the name of the attribute schema.
    pub fn get_schema_name(&self) -> String {
        unsafe {
            let ptr = ffi::secret_item_get_schema_name(self.to_glib_none().0);
            from_glib_full(ptr)
        }
    }

    /// Get the created date and time of the item.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_created(&self) -> u64 {
        unsafe {ffi::secret_item_get_created(self.to_glib_none().0)}
    }

    /// Get the modified date and time of the item.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_modified(&self) -> u64 {
        unsafe {ffi::secret_item_get_modified(self.to_glib_none().0)}
    }

    /// Get the label of the item.
    pub fn get_label(&self) -> String {
        unsafe {
            let ptr = ffi::secret_item_get_label(self.to_glib_none().0);
            from_glib_full(ptr)
        }
    }

    /// Get the SecretService this item was created with.
    pub fn get_service(&self) -> SecretService {
        unsafe {
            let ptr = ffi::secret_item_get_service(self.to_glib_none().0);
            from_glib_none(ptr)
        }
    }

    /// Ensure that the SecretValue of this item is loaded.
    pub fn load_secret(&self) -> SecretResult<()> {
        let mut err = ptr::null_mut();
        unsafe{ffi::secret_item_load_secret_sync(self.to_glib_none().0, ptr::null_mut(), &mut err)};
        if err.is_null() {
            Ok(())
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Get the SecretValue of this item. The item must be unlocked and the value must be loaded.
    pub fn get_secret(&self) -> Option<SecretValue> {
        unsafe {
            let ptr = ffi::secret_item_get_secret(self.to_glib_none().0);
            if ptr.is_null() {
                None
            } else {
                Some(SecretValue::from_glib_full(ptr))
            }
        }
    }

    /// Get the attributes of this item.
    pub fn get_attributes(&self) -> HashMap<String, String> {
        unsafe {
            let ptr = ffi::secret_item_get_attributes(self.to_glib_none().0);
            HashMap::from_glib_full(ptr)
        }
    }
}

impl StaticType for SecretItem {
    fn static_type() -> Type{
        unsafe { from_glib(ffi::secret_item_get_type()) }
    }
}

unsafe impl Upcast<Object> for SecretItem { }

impl Wrapper for SecretItem {
    type GlibType = ffi::SecretItem;
    unsafe fn wrap(r: Ref) -> Self{
        SecretItem(r)
    }

    fn as_ref(&self) -> &Ref{
        &self.0
    }

    fn unwrap(self) -> Ref{
        self.0
    }
}
<commit_msg>Implement several new methods for SecretItem<commit_after>use std::ptr;
use std::collections::HashMap;
use glib::Error;
use glib::glib_container::GlibContainer;
use glib::object::{Wrapper, Ref, Object, Upcast};
use glib::types::{StaticType, Type};
use glib::translate::*;
use secret_service::SecretService;
use secret_collection::SecretCollection;
use secret_value::SecretValue;
use SecretResult;
use ffi;

/// SecretItem represents a secret item stored in the Secret Service.
/// Each item has a value, represented by a SecretValue, which can be retrieved by `get_secret()` or set by `set_secret()`. The item is only available when the item is not locked.
/// Items can be locked or unlocked using the `Lock::lock()` or `Lock::unlock()` functions. The Lock trait is implemented by SecretItem. The Secret Service may not be able to unlock individual items, and may unlock an entire collection when a single item is unlocked.
/// Each item has a set of attributes, which are used to locate the item later. These are not stored or transferred in a secure manner. Each attribute has a string name and a string value. Use `SecretService::search()` to search for items based on their attributes, and `set_attributes()` to change the attributes associated with an item.
/// Items can be created with `create()` or `SecretService::store()`.
pub struct SecretItem(Ref);

impl SecretItem {

    /// Create a new item in the secret service.
    /// collection: a secret collection to create this item in
    /// attributes: attributes for the new item.
    /// label: label for the new item
    /// value: secret value for the new item
    pub fn create(collection: &SecretCollection, attributes: &HashMap<String, String>, label: &str, value: &SecretValue) -> SecretResult<SecretItem> {
        let mut err = ptr::null_mut();
        unsafe {
            let item = ffi::secret_item_create_sync(collection.to_glib_none().0, ptr::null(), attributes.to_glib_none().0, label.to_glib_none().0, value.to_glib_none(), SECRET_ITEM_CREATE_NONE, ptr::null_mut(), &mut err);
            if err.is_null() { //TODO for all patterns like this: This if does not need to be in the unsafe block. Fix pls.
                Ok(from_glib_full(item))
            } else {
                Err(Error::wrap(err))
            }
        }
    }

    /// Delete this secret item.
    pub fn delete(&self) -> SecretResult<()> {
        let mut err = ptr::null_mut();
        unsafe{ffi::secret_item_delete_sync(self.to_glib_none().0, ptr::null_mut(), &mut err)};
        if err.is_null() {
            Ok(())
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Get the name of the attribute schema.
    pub fn get_schema_name(&self) -> String {
        unsafe {
            let ptr = ffi::secret_item_get_schema_name(self.to_glib_none().0);
            from_glib_full(ptr)
        }
    }

    /// Get the created date and time of the item.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_created(&self) -> u64 {
        unsafe {ffi::secret_item_get_created(self.to_glib_none().0)}
    }

    /// Get the modified date and time of the item.
    /// The return value is the number of seconds since the unix epoch, January 1st 1970.
    pub fn get_modified(&self) -> u64 {
        unsafe {ffi::secret_item_get_modified(self.to_glib_none().0)}
    }

    /// Get the label of the item.
    pub fn get_label(&self) -> String {
        unsafe {
            let ptr = ffi::secret_item_get_label(self.to_glib_none().0);
            from_glib_full(ptr)
        }
    }

    /// Get the SecretService this item was created with.
    pub fn get_service(&self) -> SecretService {
        unsafe {
            let ptr = ffi::secret_item_get_service(self.to_glib_none().0);
            from_glib_none(ptr)
        }
    }

    /// Ensure that the SecretValue of this item is loaded.
    pub fn load_secret(&self) -> SecretResult<()> {
        let mut err = ptr::null_mut();
        unsafe{ffi::secret_item_load_secret_sync(self.to_glib_none().0, ptr::null_mut(), &mut err)};
        if err.is_null() {
            Ok(())
        } else {
            Err(Error::wrap(err))
        }
    }

    /// Get the SecretValue of this item. The item must be unlocked and the value must be loaded.
    pub fn get_secret(&self) -> Option<SecretValue> {
        unsafe {
            let ptr = ffi::secret_item_get_secret(self.to_glib_none().0);
            if ptr.is_null() {
                None
            } else {
                Some(SecretValue::from_glib_full(ptr))
            }
        }
    }

    /// Set the secret value of this item.
    /// Each item has a single secret which might be a password or some other secret binary value (not supported yet).
    pub fn set_secret(&self, value: &SecretValue) -> SecretResult<()> {
        let mut err = ptr::null_mut();
        unsafe {
            ffi::secret_item_set_secret_sync(self.to_glib_none().0, value.to_glib_none(), ptr::null_mut(), &mut err);
            if err.is_null() {
                Ok(())
            } else {
                Err(Error::wrap(err))
            }
        }
    }

    /// Get the attributes of this item.
    pub fn get_attributes(&self) -> HashMap<String, String> {
        unsafe {
            let ptr = ffi::secret_item_get_attributes(self.to_glib_none().0);
            HashMap::from_glib_full(ptr)
        }
    }

    /// Set the attributes of this item.
    pub fn set_attributes(&self, attributes: &HashMap<String, String>) -> SecretResult<()> {
        let mut err = ptr::null_mut();
        unsafe {
            ffi::secret_item_set_attributes_sync(self.to_glib_none().0, ptr::null(), attributes.to_glib_none().0, ptr::null_mut(), &mut err);
            if err.is_null() {
                Ok(())
            } else {
                Err(Error::wrap(err))
            }
        }
    }
}

impl StaticType for SecretItem {
    fn static_type() -> Type{
        unsafe { from_glib(ffi::secret_item_get_type()) }
    }
}

unsafe impl Upcast<Object> for SecretItem { }

impl Wrapper for SecretItem {
    type GlibType = ffi::SecretItem;
    unsafe fn wrap(r: Ref) -> Self{
        SecretItem(r)
    }

    fn as_ref(&self) -> &Ref{
        &self.0
    }

    fn unwrap(self) -> Ref{
        self.0
    }
}

const SECRET_ITEM_CREATE_NONE: i32        = 0;
#[allow(dead_code)]
const SECRET_ITEM_CREATE_REPLACE: i32     = 1 << 1;
<|endoftext|>


<commit_before>//! Indirect system call
//!
use libc::c_int;

pub use self::arch::*;

#[cfg(target_arch = "x86_64")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 155;
    pub static MEMFD_CREATE: Syscall = 319;
}

#[cfg(target_arch = "x86")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 217;
    pub static MEMFD_CREATE: Syscall = 356;
}

#[cfg(target_arch = "aarch64")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 41;
    pub static MEMFD_CREATE: Syscall = 279;
}

#[cfg(target_arch = "arm")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 218;
    pub static MEMFD_CREATE: Syscall = 385;
}

#[cfg(target_arch = "mips")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 216;
    pub static MEMFD_CREATE: Syscall = 354;
}

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 203;
    pub static MEMFD_CREATE: Syscall = 360;
}

#[cfg(target_arch = "s390x")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 217;
    pub static MEMFD_CREATE: Syscall = 350;
}

extern {
    pub fn syscall(num: Syscall, ...) -> c_int;
}
<commit_msg>Support syscalls on mips64<commit_after>//! Indirect system call
//!
use libc::c_int;

pub use self::arch::*;

#[cfg(target_arch = "x86_64")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 155;
    pub static MEMFD_CREATE: Syscall = 319;
}

#[cfg(target_arch = "x86")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 217;
    pub static MEMFD_CREATE: Syscall = 356;
}

#[cfg(target_arch = "aarch64")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 41;
    pub static MEMFD_CREATE: Syscall = 279;
}

#[cfg(target_arch = "arm")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 218;
    pub static MEMFD_CREATE: Syscall = 385;
}

// Rust on mips uses the N32 ABI
#[cfg(target_arch = "mips")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 216;
    pub static MEMFD_CREATE: Syscall = 354;
}

// Rust on mips64 uses the N64 ABI
#[cfg(target_arch = "mips64")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 151;
    pub static MEMFD_CREATE: Syscall = 314;
}

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 203;
    pub static MEMFD_CREATE: Syscall = 360;
}

#[cfg(target_arch = "s390x")]
mod arch {
    use libc::c_long;

    pub type Syscall = c_long;

    pub static SYSPIVOTROOT: Syscall = 217;
    pub static MEMFD_CREATE: Syscall = 350;
}

extern {
    pub fn syscall(num: Syscall, ...) -> c_int;
}
<|endoftext|>