<commit_before>// Copyright 2014-2015 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.

use io::{self, Error, ErrorKind};
use libc::{self, c_int, gid_t, pid_t, uid_t};
use ptr;

use sys::cvt;
use sys::process::process_common::*;

////////////////////////////////////////////////////////////////////////////////
// Command
////////////////////////////////////////////////////////////////////////////////

impl Command {
    pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
                 -> io::Result<(Process, StdioPipes)> {
        use sys;

        const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";

        let envp = self.capture_env();

        if self.saw_nul() {
            return Err(io::Error::new(ErrorKind::InvalidInput,
                                      "nul byte found in provided data"));
        }

        let (ours, theirs) = self.setup_io(default, needs_stdin)?;

        if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
            return Ok((ret, ours))
        }

        let (input, output) = sys::pipe::anon_pipe()?;

        let pid = unsafe {
            match cvt(libc::fork())? {
                0 => {
                    drop(input);
                    let err = self.do_exec(theirs, envp.as_ref());
                    let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;
                    let bytes = [
                        (errno >> 24) as u8,
                        (errno >> 16) as u8,
                        (errno >>  8) as u8,
                        (errno >>  0) as u8,
                        CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1],
                        CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3]
                    ];
                    // pipe I/O up to PIPE_BUF bytes should be atomic, and then
                    // we want to be sure we *don't* run at_exit destructors as
                    // we're being torn down regardless
                    assert!(output.write(&bytes).is_ok());
                    libc::_exit(1)
                }
                n => n,
            }
        };

        let mut p = Process { pid: pid, status: None };
        drop(output);
        let mut bytes = [0; 8];

        // loop to handle EINTR
        loop {
            match input.read(&mut bytes) {
                Ok(0) => return Ok((p, ours)),
                Ok(8) => {
                    assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]),
                            "Validation on the CLOEXEC pipe failed: {:?}", bytes);
                    let errno = combine(&bytes[0.. 4]);
                    assert!(p.wait().is_ok(),
                            "wait() should either return Ok or panic");
                    return Err(Error::from_raw_os_error(errno))
                }
                Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
                Err(e) => {
                    assert!(p.wait().is_ok(),
                            "wait() should either return Ok or panic");
                    panic!("the CLOEXEC pipe failed: {:?}", e)
                },
                Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
                    assert!(p.wait().is_ok(),
                            "wait() should either return Ok or panic");
                    panic!("short read on the CLOEXEC pipe")
                }
            }
        }

        fn combine(arr: &[u8]) -> i32 {
            let a = arr[0] as u32;
            let b = arr[1] as u32;
            let c = arr[2] as u32;
            let d = arr[3] as u32;

            ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32
        }
    }

    pub fn exec(&mut self, default: Stdio) -> io::Error {
        let envp = self.capture_env();

        if self.saw_nul() {
            return io::Error::new(ErrorKind::InvalidInput,
                                  "nul byte found in provided data")
        }

        match self.setup_io(default, true) {
            Ok((_, theirs)) => unsafe { self.do_exec(theirs, envp.as_ref()) },
            Err(e) => e,
        }
    }

    // And at this point we've reached a special time in the life of the
    // child. The child must now be considered hamstrung and unable to
    // do anything other than syscalls really. Consider the following
    // scenario:
    //
    //      1. Thread A of process 1 grabs the malloc() mutex
    //      2. Thread B of process 1 forks(), creating thread C
    //      3. Thread C of process 2 then attempts to malloc()
    //      4. The memory of process 2 is the same as the memory of
    //         process 1, so the mutex is locked.
    //
    // This situation looks a lot like deadlock, right? It turns out
    // that this is what pthread_atfork() takes care of, which is
    // presumably implemented across platforms. The first thing that
    // threads to *before* forking is to do things like grab the malloc
    // mutex, and then after the fork they unlock it.
    //
    // Despite this information, libnative's spawn has been witnessed to
    // deadlock on both macOS and FreeBSD. I'm not entirely sure why, but
    // all collected backtraces point at malloc/free traffic in the
    // child spawned process.
    //
    // For this reason, the block of code below should contain 0
    // invocations of either malloc of free (or their related friends).
    //
    // As an example of not having malloc/free traffic, we don't close
    // this file descriptor by dropping the FileDesc (which contains an
    // allocation). Instead we just close it manually. This will never
    // have the drop glue anyway because this code never returns (the
    // child will either exec() or invoke libc::exit)
    unsafe fn do_exec(
        &mut self,
        stdio: ChildPipes,
        maybe_envp: Option<&CStringArray>
    ) -> io::Error {
        use sys::{self, cvt_r};

        macro_rules! t {
            ($e:expr) => (match $e {
                Ok(e) => e,
                Err(e) => return e,
            })
        }

        if let Some(fd) = stdio.stdin.fd() {
            t!(cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO)));
        }
        if let Some(fd) = stdio.stdout.fd() {
            t!(cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO)));
        }
        if let Some(fd) = stdio.stderr.fd() {
            t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO)));
        }

        if cfg!(not(any(target_os = "l4re"))) {
            if let Some(u) = self.get_gid() {
                t!(cvt(libc::setgid(u as gid_t)));
            }
            if let Some(u) = self.get_uid() {
                // When dropping privileges from root, the `setgroups` call
                // will remove any extraneous groups. If we don't call this,
                // then even though our uid has dropped, we may still have
                // groups that enable us to do super-user things. This will
                // fail if we aren't root, so don't bother checking the
                // return value, this is just done as an optimistic
                // privilege dropping function.
                let _ = libc::setgroups(0, ptr::null());

                t!(cvt(libc::setuid(u as uid_t)));
            }
        }
        if let Some(ref cwd) = *self.get_cwd() {
            t!(cvt(libc::chdir(cwd.as_ptr())));
        }
        if let Some(envp) = maybe_envp {
            *sys::os::environ() = envp.as_ptr();
        }

        // emscripten has no signal support.
        #[cfg(not(any(target_os = "emscripten")))]
        {
            use mem;
            // Reset signal handling so the child process starts in a
            // standardized state. libstd ignores SIGPIPE, and signal-handling
            // libraries often set a mask. Child processes inherit ignored
            // signals and the signal mask from their parent, but most
            // UNIX programs do not reset these things on their own, so we
            // need to clean things up now to avoid confusing the program
            // we're about to run.
            let mut set: libc::sigset_t = mem::uninitialized();
            if cfg!(target_os = "android") {
                // Implementing sigemptyset allow us to support older Android
                // versions. See the comment about Android and sig* functions in
                // process_common.rs
                libc::memset(&mut set as *mut _ as *mut _,
                             0,
                             mem::size_of::<libc::sigset_t>());
            } else {
                t!(cvt(libc::sigemptyset(&mut set)));
            }
            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set,
                                         ptr::null_mut())));
            let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
            if ret == libc::SIG_ERR {
                return io::Error::last_os_error()
            }
        }

        for callback in self.get_closures().iter_mut() {
            t!(callback());
        }

        libc::execvp(self.get_argv()[0], self.get_argv().as_ptr());
        io::Error::last_os_error()
    }

    #[cfg(not(any(target_os = "freebsd")))]
    fn posix_spawn(&mut self, _stdio: &ChildPipes, _envp: Option<&CStringArray>)
        -> io::Result<Option<Process>>
    {
        Ok(None)
    }

    #[cfg(any(target_os = "freebsd"))]
    fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
        -> io::Result<Option<Process>>
    {
        use mem;
        use sys;

        if self.get_cwd().is_some() ||
            self.get_gid().is_some() ||
            self.get_uid().is_some() ||
            self.get_closures().len() != 0 {
            return Ok(None)
        }

        let mut p = Process { pid: 0, status: None };

        struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);

        impl Drop for PosixSpawnFileActions {
            fn drop(&mut self) {
                unsafe {
                    libc::posix_spawn_file_actions_destroy(&mut self.0);
                }
            }
        }

        struct PosixSpawnattr(libc::posix_spawnattr_t);

        impl Drop for PosixSpawnattr {
            fn drop(&mut self) {
                unsafe {
                    libc::posix_spawnattr_destroy(&mut self.0);
                }
            }
        }

        unsafe {
            let mut file_actions = PosixSpawnFileActions(mem::uninitialized());
            let mut attrs = PosixSpawnattr(mem::uninitialized());

            libc::posix_spawnattr_init(&mut attrs.0);
            libc::posix_spawn_file_actions_init(&mut file_actions.0);

            if let Some(fd) = stdio.stdin.fd() {
                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
                                                           fd,
                                                           libc::STDIN_FILENO))?;
            }
            if let Some(fd) = stdio.stdout.fd() {
                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
                                                           fd,
                                                           libc::STDOUT_FILENO))?;
            }
            if let Some(fd) = stdio.stderr.fd() {
                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
                                                           fd,
                                                           libc::STDERR_FILENO))?;
            }

            let mut set: libc::sigset_t = mem::uninitialized();
            cvt(libc::sigemptyset(&mut set))?;
            cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0,
                                                 &set))?;
            cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?;
            cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0,
                                                    &set))?;

            let flags = libc::POSIX_SPAWN_SETSIGDEF |
                libc::POSIX_SPAWN_SETSIGMASK;
            cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?;

            let envp = envp.map(|c| c.as_ptr())
                .unwrap_or(*sys::os::environ() as *const _);
            let ret = libc::posix_spawnp(
                &mut p.pid,
                self.get_argv()[0],
                &file_actions.0,
                &attrs.0,
                self.get_argv().as_ptr() as *const _,
                envp as *const _,
            );
            if ret == 0 {
                Ok(Some(p))
            } else {
                Err(io::Error::from_raw_os_error(ret))
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// Processes
////////////////////////////////////////////////////////////////////////////////

/// The unique id of the process (this should never be negative).
pub struct Process {
    pid: pid_t,
    status: Option<ExitStatus>,
}

impl Process {
    pub fn id(&self) -> u32 {
        self.pid as u32
    }

    pub fn kill(&mut self) -> io::Result<()> {
        // If we've already waited on this process then the pid can be recycled
        // and used for another process, and we probably shouldn't be killing
        // random processes, so just return an error.
        if self.status.is_some() {
            Err(Error::new(ErrorKind::InvalidInput,
                           "invalid argument: can't kill an exited process"))
        } else {
            cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(|_| ())
        }
    }

    pub fn wait(&mut self) -> io::Result<ExitStatus> {
        use sys::cvt_r;
        if let Some(status) = self.status {
            return Ok(status)
        }
        let mut status = 0 as c_int;
        cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
        self.status = Some(ExitStatus::new(status));
        Ok(ExitStatus::new(status))
    }

    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
        if let Some(status) = self.status {
            return Ok(Some(status))
        }
        let mut status = 0 as c_int;
        let pid = cvt(unsafe {
            libc::waitpid(self.pid, &mut status, libc::WNOHANG)
        })?;
        if pid == 0 {
            Ok(None)
        } else {
            self.status = Some(ExitStatus::new(status));
            Ok(Some(ExitStatus::new(status)))
        }
    }
}
<commit_msg>posix_spawn() on OSX supports returning ENOENT.<commit_after>// Copyright 2014-2015 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.

use io::{self, Error, ErrorKind};
use libc::{self, c_int, gid_t, pid_t, uid_t};
use ptr;

use sys::cvt;
use sys::process::process_common::*;

////////////////////////////////////////////////////////////////////////////////
// Command
////////////////////////////////////////////////////////////////////////////////

impl Command {
    pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
                 -> io::Result<(Process, StdioPipes)> {
        use sys;

        const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";

        let envp = self.capture_env();

        if self.saw_nul() {
            return Err(io::Error::new(ErrorKind::InvalidInput,
                                      "nul byte found in provided data"));
        }

        let (ours, theirs) = self.setup_io(default, needs_stdin)?;

        if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
            return Ok((ret, ours))
        }

        let (input, output) = sys::pipe::anon_pipe()?;

        let pid = unsafe {
            match cvt(libc::fork())? {
                0 => {
                    drop(input);
                    let err = self.do_exec(theirs, envp.as_ref());
                    let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32;
                    let bytes = [
                        (errno >> 24) as u8,
                        (errno >> 16) as u8,
                        (errno >>  8) as u8,
                        (errno >>  0) as u8,
                        CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1],
                        CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3]
                    ];
                    // pipe I/O up to PIPE_BUF bytes should be atomic, and then
                    // we want to be sure we *don't* run at_exit destructors as
                    // we're being torn down regardless
                    assert!(output.write(&bytes).is_ok());
                    libc::_exit(1)
                }
                n => n,
            }
        };

        let mut p = Process { pid: pid, status: None };
        drop(output);
        let mut bytes = [0; 8];

        // loop to handle EINTR
        loop {
            match input.read(&mut bytes) {
                Ok(0) => return Ok((p, ours)),
                Ok(8) => {
                    assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]),
                            "Validation on the CLOEXEC pipe failed: {:?}", bytes);
                    let errno = combine(&bytes[0.. 4]);
                    assert!(p.wait().is_ok(),
                            "wait() should either return Ok or panic");
                    return Err(Error::from_raw_os_error(errno))
                }
                Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
                Err(e) => {
                    assert!(p.wait().is_ok(),
                            "wait() should either return Ok or panic");
                    panic!("the CLOEXEC pipe failed: {:?}", e)
                },
                Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
                    assert!(p.wait().is_ok(),
                            "wait() should either return Ok or panic");
                    panic!("short read on the CLOEXEC pipe")
                }
            }
        }

        fn combine(arr: &[u8]) -> i32 {
            let a = arr[0] as u32;
            let b = arr[1] as u32;
            let c = arr[2] as u32;
            let d = arr[3] as u32;

            ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32
        }
    }

    pub fn exec(&mut self, default: Stdio) -> io::Error {
        let envp = self.capture_env();

        if self.saw_nul() {
            return io::Error::new(ErrorKind::InvalidInput,
                                  "nul byte found in provided data")
        }

        match self.setup_io(default, true) {
            Ok((_, theirs)) => unsafe { self.do_exec(theirs, envp.as_ref()) },
            Err(e) => e,
        }
    }

    // And at this point we've reached a special time in the life of the
    // child. The child must now be considered hamstrung and unable to
    // do anything other than syscalls really. Consider the following
    // scenario:
    //
    //      1. Thread A of process 1 grabs the malloc() mutex
    //      2. Thread B of process 1 forks(), creating thread C
    //      3. Thread C of process 2 then attempts to malloc()
    //      4. The memory of process 2 is the same as the memory of
    //         process 1, so the mutex is locked.
    //
    // This situation looks a lot like deadlock, right? It turns out
    // that this is what pthread_atfork() takes care of, which is
    // presumably implemented across platforms. The first thing that
    // threads to *before* forking is to do things like grab the malloc
    // mutex, and then after the fork they unlock it.
    //
    // Despite this information, libnative's spawn has been witnessed to
    // deadlock on both macOS and FreeBSD. I'm not entirely sure why, but
    // all collected backtraces point at malloc/free traffic in the
    // child spawned process.
    //
    // For this reason, the block of code below should contain 0
    // invocations of either malloc of free (or their related friends).
    //
    // As an example of not having malloc/free traffic, we don't close
    // this file descriptor by dropping the FileDesc (which contains an
    // allocation). Instead we just close it manually. This will never
    // have the drop glue anyway because this code never returns (the
    // child will either exec() or invoke libc::exit)
    unsafe fn do_exec(
        &mut self,
        stdio: ChildPipes,
        maybe_envp: Option<&CStringArray>
    ) -> io::Error {
        use sys::{self, cvt_r};

        macro_rules! t {
            ($e:expr) => (match $e {
                Ok(e) => e,
                Err(e) => return e,
            })
        }

        if let Some(fd) = stdio.stdin.fd() {
            t!(cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO)));
        }
        if let Some(fd) = stdio.stdout.fd() {
            t!(cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO)));
        }
        if let Some(fd) = stdio.stderr.fd() {
            t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO)));
        }

        if cfg!(not(any(target_os = "l4re"))) {
            if let Some(u) = self.get_gid() {
                t!(cvt(libc::setgid(u as gid_t)));
            }
            if let Some(u) = self.get_uid() {
                // When dropping privileges from root, the `setgroups` call
                // will remove any extraneous groups. If we don't call this,
                // then even though our uid has dropped, we may still have
                // groups that enable us to do super-user things. This will
                // fail if we aren't root, so don't bother checking the
                // return value, this is just done as an optimistic
                // privilege dropping function.
                let _ = libc::setgroups(0, ptr::null());

                t!(cvt(libc::setuid(u as uid_t)));
            }
        }
        if let Some(ref cwd) = *self.get_cwd() {
            t!(cvt(libc::chdir(cwd.as_ptr())));
        }
        if let Some(envp) = maybe_envp {
            *sys::os::environ() = envp.as_ptr();
        }

        // emscripten has no signal support.
        #[cfg(not(any(target_os = "emscripten")))]
        {
            use mem;
            // Reset signal handling so the child process starts in a
            // standardized state. libstd ignores SIGPIPE, and signal-handling
            // libraries often set a mask. Child processes inherit ignored
            // signals and the signal mask from their parent, but most
            // UNIX programs do not reset these things on their own, so we
            // need to clean things up now to avoid confusing the program
            // we're about to run.
            let mut set: libc::sigset_t = mem::uninitialized();
            if cfg!(target_os = "android") {
                // Implementing sigemptyset allow us to support older Android
                // versions. See the comment about Android and sig* functions in
                // process_common.rs
                libc::memset(&mut set as *mut _ as *mut _,
                             0,
                             mem::size_of::<libc::sigset_t>());
            } else {
                t!(cvt(libc::sigemptyset(&mut set)));
            }
            t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set,
                                         ptr::null_mut())));
            let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
            if ret == libc::SIG_ERR {
                return io::Error::last_os_error()
            }
        }

        for callback in self.get_closures().iter_mut() {
            t!(callback());
        }

        libc::execvp(self.get_argv()[0], self.get_argv().as_ptr());
        io::Error::last_os_error()
    }

    #[cfg(not(any(target_os = "macos", target_os = "freebsd")))]
    fn posix_spawn(&mut self, _stdio: &ChildPipes, _envp: Option<&CStringArray>)
        -> io::Result<Option<Process>>
    {
        Ok(None)
    }

    #[cfg(any(target_os = "macos", target_os = "freebsd"))]
    fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
        -> io::Result<Option<Process>>
    {
        use mem;
        use sys;

        if self.get_cwd().is_some() ||
            self.get_gid().is_some() ||
            self.get_uid().is_some() ||
            self.get_closures().len() != 0 {
            return Ok(None)
        }

        let mut p = Process { pid: 0, status: None };

        struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);

        impl Drop for PosixSpawnFileActions {
            fn drop(&mut self) {
                unsafe {
                    libc::posix_spawn_file_actions_destroy(&mut self.0);
                }
            }
        }

        struct PosixSpawnattr(libc::posix_spawnattr_t);

        impl Drop for PosixSpawnattr {
            fn drop(&mut self) {
                unsafe {
                    libc::posix_spawnattr_destroy(&mut self.0);
                }
            }
        }

        unsafe {
            let mut file_actions = PosixSpawnFileActions(mem::uninitialized());
            let mut attrs = PosixSpawnattr(mem::uninitialized());

            libc::posix_spawnattr_init(&mut attrs.0);
            libc::posix_spawn_file_actions_init(&mut file_actions.0);

            if let Some(fd) = stdio.stdin.fd() {
                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
                                                           fd,
                                                           libc::STDIN_FILENO))?;
            }
            if let Some(fd) = stdio.stdout.fd() {
                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
                                                           fd,
                                                           libc::STDOUT_FILENO))?;
            }
            if let Some(fd) = stdio.stderr.fd() {
                cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
                                                           fd,
                                                           libc::STDERR_FILENO))?;
            }

            let mut set: libc::sigset_t = mem::uninitialized();
            cvt(libc::sigemptyset(&mut set))?;
            cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0,
                                                 &set))?;
            cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?;
            cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0,
                                                    &set))?;

            let flags = libc::POSIX_SPAWN_SETSIGDEF |
                libc::POSIX_SPAWN_SETSIGMASK;
            cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?;

            let envp = envp.map(|c| c.as_ptr())
                .unwrap_or(*sys::os::environ() as *const _);
            let ret = libc::posix_spawnp(
                &mut p.pid,
                self.get_argv()[0],
                &file_actions.0,
                &attrs.0,
                self.get_argv().as_ptr() as *const _,
                envp as *const _,
            );
            if ret == 0 {
                Ok(Some(p))
            } else {
                Err(io::Error::from_raw_os_error(ret))
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// Processes
////////////////////////////////////////////////////////////////////////////////

/// The unique id of the process (this should never be negative).
pub struct Process {
    pid: pid_t,
    status: Option<ExitStatus>,
}

impl Process {
    pub fn id(&self) -> u32 {
        self.pid as u32
    }

    pub fn kill(&mut self) -> io::Result<()> {
        // If we've already waited on this process then the pid can be recycled
        // and used for another process, and we probably shouldn't be killing
        // random processes, so just return an error.
        if self.status.is_some() {
            Err(Error::new(ErrorKind::InvalidInput,
                           "invalid argument: can't kill an exited process"))
        } else {
            cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(|_| ())
        }
    }

    pub fn wait(&mut self) -> io::Result<ExitStatus> {
        use sys::cvt_r;
        if let Some(status) = self.status {
            return Ok(status)
        }
        let mut status = 0 as c_int;
        cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) })?;
        self.status = Some(ExitStatus::new(status));
        Ok(ExitStatus::new(status))
    }

    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
        if let Some(status) = self.status {
            return Ok(Some(status))
        }
        let mut status = 0 as c_int;
        let pid = cvt(unsafe {
            libc::waitpid(self.pid, &mut status, libc::WNOHANG)
        })?;
        if pid == 0 {
            Ok(None)
        } else {
            self.status = Some(ExitStatus::new(status));
            Ok(Some(ExitStatus::new(status)))
        }
    }
}
<|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.

//! Helper functions for implementing `RngCore` functions.
//!
//! For cross-platform reproducibility, these functions all use Little Endian:
//! least-significant part first. For example, `next_u64_via_u32` takes `u32`
//! values `x, y`, then outputs `(y << 32) | x`. To implement `next_u32`
//! from `next_u64` in little-endian order, one should use `next_u64() as u32`.
//!
//! Byte-swapping (like the std `to_le` functions) is only needed to convert
//! to/from byte sequences, and since its purpose is reproducibility,
//! non-reproducible sources (e.g. `OsRng`) need not bother with it.

use crate::RngCore;
use core::cmp::min;

/// Implement `next_u64` via `next_u32`, little-endian order.
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    // Use LE; we explicitly generate one value before the next.
    let x = u64::from(rng.next_u32());
    let y = u64::from(rng.next_u32());
    (y << 32) | x
}

/// Implement `fill_bytes` via `next_u64` and `next_u32`, little-endian order.
///
/// The fastest way to fill a slice is usually to work as long as possible with
/// integers. That is why this method mostly uses `next_u64`, and only when
/// there are 4 or less bytes remaining at the end of the slice it uses
/// `next_u32` once.
pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
    let mut left = dest;
    while left.len() >= 8 {
        let (l, r) = { left }.split_at_mut(8);
        left = r;
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        l.copy_from_slice(&chunk);
    }
    let n = left.len();
    if n > 4 {
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    } else if n > 0 {
        let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    }
}

macro_rules! fill_via_chunks {
    ($src:expr, $dst:expr, $ty:ty) => {{
        const SIZE: usize = core::mem::size_of::<$ty>();
        let chunk_size_u8 = min($src.len() * SIZE, $dst.len());
        let chunk_size = (chunk_size_u8 + SIZE - 1) / SIZE;

        let mut iter_src = $src.iter();
        let mut chunks = $dst.chunks_exact_mut(SIZE);
        for (chunk, n) in (&mut chunks).zip(&mut iter_src) {
            chunk.copy_from_slice(&n.to_le_bytes());
        }
        let rem = chunks.into_remainder();
        if let Some(n) = iter_src.next() {
            rem.copy_from_slice(&n.to_le_bytes()[..rem.len()]);
        }

        (chunk_size, chunk_size_u8)
    }};
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u32, filled_u8)`.
///
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u32` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 4` rounded up.
///
/// # Example
/// (from `IsaacRng`)
///
/// ```ignore
/// fn fill_bytes(&mut self, dest: &mut [u8]) {
///     let mut read_len = 0;
///     while read_len < dest.len() {
///         if self.index >= self.rsl.len() {
///             self.isaac();
///         }
///
///         let (consumed_u32, filled_u8) =
///             impls::fill_via_u32_chunks(&mut self.rsl[self.index..],
///                                        &mut dest[read_len..]);
///
///         self.index += consumed_u32;
///         read_len += filled_u8;
///     }
/// }
/// ```
pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u32)
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u64, filled_u8)`.
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u64` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 8` rounded up.
///
/// See `fill_via_u32_chunks` for an example.
pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u64)
}

/// Implement `next_u32` via `fill_bytes`, little-endian order.
pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
    let mut buf = [0; 4];
    rng.fill_bytes(&mut buf);
    u32::from_ne_bytes(buf)
}

/// Implement `next_u64` via `fill_bytes`, little-endian order.
pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    let mut buf = [0; 8];
    rng.fill_bytes(&mut buf);
    u64::from_ne_bytes(buf)
}

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

    #[test]
    fn test_fill_via_u32_chunks() {
        let src = [1, 2, 3];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 11));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]);

        let mut dst = [0u8; 13];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 12));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (2, 5));
        assert_eq!(dst, [1, 0, 0, 0, 2]);
    }

    #[test]
    fn test_fill_via_u64_chunks() {
        let src = [1, 2];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 11));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);

        let mut dst = [0u8; 17];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 16));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (1, 5));
        assert_eq!(dst, [1, 0, 0, 0, 0]);
    }
}
<commit_msg>Restore unsafe `fill_via_chunks` implementation for performance<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.

//! Helper functions for implementing `RngCore` functions.
//!
//! For cross-platform reproducibility, these functions all use Little Endian:
//! least-significant part first. For example, `next_u64_via_u32` takes `u32`
//! values `x, y`, then outputs `(y << 32) | x`. To implement `next_u32`
//! from `next_u64` in little-endian order, one should use `next_u64() as u32`.
//!
//! Byte-swapping (like the std `to_le` functions) is only needed to convert
//! to/from byte sequences, and since its purpose is reproducibility,
//! non-reproducible sources (e.g. `OsRng`) need not bother with it.

use crate::RngCore;
use core::cmp::min;

/// Implement `next_u64` via `next_u32`, little-endian order.
pub fn next_u64_via_u32<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    // Use LE; we explicitly generate one value before the next.
    let x = u64::from(rng.next_u32());
    let y = u64::from(rng.next_u32());
    (y << 32) | x
}

/// Implement `fill_bytes` via `next_u64` and `next_u32`, little-endian order.
///
/// The fastest way to fill a slice is usually to work as long as possible with
/// integers. That is why this method mostly uses `next_u64`, and only when
/// there are 4 or less bytes remaining at the end of the slice it uses
/// `next_u32` once.
pub fn fill_bytes_via_next<R: RngCore + ?Sized>(rng: &mut R, dest: &mut [u8]) {
    let mut left = dest;
    while left.len() >= 8 {
        let (l, r) = { left }.split_at_mut(8);
        left = r;
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        l.copy_from_slice(&chunk);
    }
    let n = left.len();
    if n > 4 {
        let chunk: [u8; 8] = rng.next_u64().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    } else if n > 0 {
        let chunk: [u8; 4] = rng.next_u32().to_le_bytes();
        left.copy_from_slice(&chunk[..n]);
    }
}

macro_rules! fill_via_chunks {
    ($src:expr, $dst:expr, $ty:ty) => {{
        const SIZE: usize = core::mem::size_of::<$ty>();
        let chunk_size_u8 = min($src.len() * SIZE, $dst.len());
        let chunk_size = (chunk_size_u8 + SIZE - 1) / SIZE;

        if cfg!(target_endian = "little") {
            unsafe {
                core::ptr::copy_nonoverlapping(
                    $src.as_ptr() as *const u8,
                    $dst.as_mut_ptr(),
                    chunk_size_u8);
            }
        } else {
            for (&n, chunk) in $src.iter().zip($dst.chunks_mut(SIZE)) {
                let tmp = n.to_le();
                let src_ptr = &tmp as *const $ty as *const u8;
                unsafe {
                    core::ptr::copy_nonoverlapping(
                        src_ptr,
                        chunk.as_mut_ptr(),
                        chunk.len());
                }
            }
        }

        // The following code is a safe replacement, but unfortunately ca. 8%
        // slower.
        /*
        let mut iter_src = $src.iter();
        let mut chunks = $dst.chunks_exact_mut(SIZE);
        for (chunk, n) in (&mut chunks).zip(&mut iter_src) {
            chunk.copy_from_slice(&n.to_le_bytes());
        }
        let rem = chunks.into_remainder();
        if let Some(n) = iter_src.next() {
            rem.copy_from_slice(&n.to_le_bytes()[..rem.len()]);
        }
        */

        (chunk_size, chunk_size_u8)
    }};
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u32, filled_u8)`.
///
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u32` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 4` rounded up.
///
/// # Example
/// (from `IsaacRng`)
///
/// ```ignore
/// fn fill_bytes(&mut self, dest: &mut [u8]) {
///     let mut read_len = 0;
///     while read_len < dest.len() {
///         if self.index >= self.rsl.len() {
///             self.isaac();
///         }
///
///         let (consumed_u32, filled_u8) =
///             impls::fill_via_u32_chunks(&mut self.rsl[self.index..],
///                                        &mut dest[read_len..]);
///
///         self.index += consumed_u32;
///         read_len += filled_u8;
///     }
/// }
/// ```
pub fn fill_via_u32_chunks(src: &[u32], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u32)
}

/// Implement `fill_bytes` by reading chunks from the output buffer of a block
/// based RNG.
///
/// The return values are `(consumed_u64, filled_u8)`.
/// `filled_u8` is the number of filled bytes in `dest`, which may be less than
/// the length of `dest`.
/// `consumed_u64` is the number of words consumed from `src`, which is the same
/// as `filled_u8 / 8` rounded up.
///
/// See `fill_via_u32_chunks` for an example.
pub fn fill_via_u64_chunks(src: &[u64], dest: &mut [u8]) -> (usize, usize) {
    fill_via_chunks!(src, dest, u64)
}

/// Implement `next_u32` via `fill_bytes`, little-endian order.
pub fn next_u32_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u32 {
    let mut buf = [0; 4];
    rng.fill_bytes(&mut buf);
    u32::from_ne_bytes(buf)
}

/// Implement `next_u64` via `fill_bytes`, little-endian order.
pub fn next_u64_via_fill<R: RngCore + ?Sized>(rng: &mut R) -> u64 {
    let mut buf = [0; 8];
    rng.fill_bytes(&mut buf);
    u64::from_ne_bytes(buf)
}

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

    #[test]
    fn test_fill_via_u32_chunks() {
        let src = [1, 2, 3];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 11));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0]);

        let mut dst = [0u8; 13];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (3, 12));
        assert_eq!(dst, [1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u32_chunks(&src, &mut dst), (2, 5));
        assert_eq!(dst, [1, 0, 0, 0, 2]);
    }

    #[test]
    fn test_fill_via_u64_chunks() {
        let src = [1, 2];
        let mut dst = [0u8; 11];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 11));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0]);

        let mut dst = [0u8; 17];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (2, 16));
        assert_eq!(dst, [1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]);

        let mut dst = [0u8; 5];
        assert_eq!(fill_via_u64_chunks(&src, &mut dst), (1, 5));
        assert_eq!(dst, [1, 0, 0, 0, 0]);
    }
}
<|endoftext|>


<commit_before>//! Solve linear problem using LU decomposition

use super::*;
use crate::{error::*, layout::MatrixLayout};
use cauchy::*;
use num_traits::{ToPrimitive, Zero};

pub trait Solve_: Scalar + Sized {
    /// Computes the LU factorization of a general `m x n` matrix `a` using
    /// partial pivoting with row interchanges.
    ///
    /// $ PA = LU $
    ///
    /// Error
    /// ------
    /// - `LapackComputationalFailure { return_code }` when the matrix is singular
    ///   - Division by zero will occur if it is used to solve a system of equations
    ///     because `U[(return_code-1, return_code-1)]` is exactly zero.
    fn lu(l: MatrixLayout, a: &mut [Self]) -> Result<Pivot>;

    fn inv(l: MatrixLayout, a: &mut [Self], p: &Pivot) -> Result<()>;

    fn solve(l: MatrixLayout, t: Transpose, a: &[Self], p: &Pivot, b: &mut [Self]) -> Result<()>;
}

macro_rules! impl_solve {
    ($scalar:ty, $getrf:path, $getri:path, $getrs:path) => {
        impl Solve_ for $scalar {
            fn lu(l: MatrixLayout, a: &mut [Self]) -> Result<Pivot> {
                let (row, col) = l.size();
                assert_eq!(a.len() as i32, row * col);
                let k = ::std::cmp::min(row, col);
                let mut ipiv = vec![0; k as usize];
                let mut info = 0;
                unsafe { $getrf(l.lda(), l.len(), a, l.lda(), &mut ipiv, &mut info) };
                info.as_lapack_result()?;
                Ok(ipiv)
            }

            fn inv(l: MatrixLayout, a: &mut [Self], ipiv: &Pivot) -> Result<()> {
                let (n, _) = l.size();

                // calc work size
                let mut info = 0;
                let mut work_size = [Self::zero()];
                unsafe { $getri(n, a, l.lda(), ipiv, &mut work_size, -1, &mut info) };
                info.as_lapack_result()?;

                // actual
                let lwork = work_size[0].to_usize().unwrap();
                let mut work = vec![Self::zero(); lwork];
                unsafe {
                    $getri(
                        l.len(),
                        a,
                        l.lda(),
                        ipiv,
                        &mut work,
                        lwork as i32,
                        &mut info,
                    )
                };
                info.as_lapack_result()?;

                Ok(())
            }

            fn solve(
                l: MatrixLayout,
                t: Transpose,
                a: &[Self],
                ipiv: &Pivot,
                b: &mut [Self],
            ) -> Result<()> {
                let t = match l {
                    MatrixLayout::C { .. } => match t {
                        Transpose::No => Transpose::Transpose,
                        Transpose::Transpose | Transpose::Hermite => Transpose::No,
                    },
                    _ => t,
                };
                let (n, _) = l.size();
                let nrhs = 1;
                let ldb = l.lda();
                let mut info = 0;
                unsafe { $getrs(t as u8, n, nrhs, a, l.lda(), ipiv, b, ldb, &mut info) };
                info.as_lapack_result()?;
                Ok(())
            }
        }
    };
} // impl_solve!

impl_solve!(f64, lapack::dgetrf, lapack::dgetri, lapack::dgetrs);
impl_solve!(f32, lapack::sgetrf, lapack::sgetri, lapack::sgetrs);
impl_solve!(c64, lapack::zgetrf, lapack::zgetri, lapack::zgetrs);
impl_solve!(c32, lapack::cgetrf, lapack::cgetri, lapack::cgetrs);
<commit_msg>Handling empty matrix case<commit_after>//! Solve linear problem using LU decomposition

use super::*;
use crate::{error::*, layout::MatrixLayout};
use cauchy::*;
use num_traits::{ToPrimitive, Zero};

pub trait Solve_: Scalar + Sized {
    /// Computes the LU factorization of a general `m x n` matrix `a` using
    /// partial pivoting with row interchanges.
    ///
    /// $ PA = LU $
    ///
    /// Error
    /// ------
    /// - `LapackComputationalFailure { return_code }` when the matrix is singular
    ///   - Division by zero will occur if it is used to solve a system of equations
    ///     because `U[(return_code-1, return_code-1)]` is exactly zero.
    fn lu(l: MatrixLayout, a: &mut [Self]) -> Result<Pivot>;

    fn inv(l: MatrixLayout, a: &mut [Self], p: &Pivot) -> Result<()>;

    fn solve(l: MatrixLayout, t: Transpose, a: &[Self], p: &Pivot, b: &mut [Self]) -> Result<()>;
}

macro_rules! impl_solve {
    ($scalar:ty, $getrf:path, $getri:path, $getrs:path) => {
        impl Solve_ for $scalar {
            fn lu(l: MatrixLayout, a: &mut [Self]) -> Result<Pivot> {
                let (row, col) = l.size();
                assert_eq!(a.len() as i32, row * col);
                if row == 0 || col == 0 {
                    // Do nothing for empty matrix
                    return Ok(Vec::new());
                }
                let k = ::std::cmp::min(row, col);
                let mut ipiv = vec![0; k as usize];
                let mut info = 0;
                unsafe { $getrf(l.lda(), l.len(), a, l.lda(), &mut ipiv, &mut info) };
                info.as_lapack_result()?;
                Ok(ipiv)
            }

            fn inv(l: MatrixLayout, a: &mut [Self], ipiv: &Pivot) -> Result<()> {
                let (n, _) = l.size();

                // calc work size
                let mut info = 0;
                let mut work_size = [Self::zero()];
                unsafe { $getri(n, a, l.lda(), ipiv, &mut work_size, -1, &mut info) };
                info.as_lapack_result()?;

                // actual
                let lwork = work_size[0].to_usize().unwrap();
                let mut work = vec![Self::zero(); lwork];
                unsafe {
                    $getri(
                        l.len(),
                        a,
                        l.lda(),
                        ipiv,
                        &mut work,
                        lwork as i32,
                        &mut info,
                    )
                };
                info.as_lapack_result()?;

                Ok(())
            }

            fn solve(
                l: MatrixLayout,
                t: Transpose,
                a: &[Self],
                ipiv: &Pivot,
                b: &mut [Self],
            ) -> Result<()> {
                let t = match l {
                    MatrixLayout::C { .. } => match t {
                        Transpose::No => Transpose::Transpose,
                        Transpose::Transpose | Transpose::Hermite => Transpose::No,
                    },
                    _ => t,
                };
                let (n, _) = l.size();
                let nrhs = 1;
                let ldb = l.lda();
                let mut info = 0;
                unsafe { $getrs(t as u8, n, nrhs, a, l.lda(), ipiv, b, ldb, &mut info) };
                info.as_lapack_result()?;
                Ok(())
            }
        }
    };
} // impl_solve!

impl_solve!(f64, lapack::dgetrf, lapack::dgetri, lapack::dgetrs);
impl_solve!(f32, lapack::sgetrf, lapack::sgetri, lapack::sgetrs);
impl_solve!(c64, lapack::zgetrf, lapack::zgetri, lapack::zgetrs);
impl_solve!(c32, lapack::cgetrf, lapack::cgetri, lapack::cgetrs);
<|endoftext|>


<commit_before>// Portion that builds and runs tests.  Assumes that this can be
// done via a call to `make build` and `make test`.  Compiler failure
// is assumed to be communicated by return value.  Tests are assumed
// to have the following output format:
//
// some test name: <PASS|FAIL>
//
// ...where each test result is on its own line.  If multiple tests
// have the same name, then only the last test is recorded.

use std::io::{BufferedReader, RefReader, IoResult, IoError, OtherIoError};
use std::io::pipe::PipeStream;
use std::io::process::{Command, Process, ExitStatus, ExitSignal};
use std::collections::HashMap;

/// Peforms builds and testing via abstract requests.
trait Builder<A : Tester> {
    /// Gets everything in order for testing to be performed.
    /// After calling this, it is assumed that we are ready
    /// to call make
    fn setup_env(&self);

    /// Makes a tester.  This should be the only way
    /// to make a tester.  Avoids situations where we
    /// tried to call `make test` without a successful
    /// `make build`
    fn make_tester(&self) -> A;

    fn build_timeout(&self) -> u64;

    fn test_timeout(&self) -> u64;

    /// runs make build
    fn do_build(&self) -> IoResult<A> {
        Command::new("make").arg("build")
            .spawn().and_then(|mut process| {
                process.set_timeout(Some(self.build_timeout()));
                process.wait().and_then(|res| match res {
                    ExitStatus(0) => Ok(self.make_tester()),
                    ExitStatus(x) => Err(
                        IoError {
                            kind: OtherIoError,
                            desc: "Non-zero exit code",
                            detail: Some(x.to_string())
                        }),
                    ExitSignal(x) => Err(
                        IoError {
                            kind: OtherIoError,
                            desc: "Exit signal",
                            detail: Some(x.to_string())
                        })
                })
            })
    }
} // trait Builder

enum TestResult {
    Pass,
    Fail
}

struct ProcessReader {
    p: Process
}

impl ProcessReader {
    fn new(cmd: &Command) -> IoResult<ProcessReader> {
        cmd.spawn().map(|p| ProcessReader { p: p })
    }

    fn output_reader<'a>(&'a mut self) -> BufferedReader<RefReader<'a, PipeStream>> {
        // unwrap should be ok - the documentation says `Some` is the default,
        // and we are not messing with any of the defaults
        BufferedReader::new(
            Reader::by_ref(
                self.p.stdout.as_mut().unwrap()))
    }
}

trait Tester {
    fn parse_test_result(line: &str) -> IoResult<TestResult> {
        match line {
            "PASS" => Ok(Pass),
            "FAIL" => Ok(Fail),
            _ => Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Malformed test result",
                    detail: Some(line.to_string())
                })
        }
    }

    fn parse_line(line: &str) -> IoResult<(String, TestResult)> {
        let results: Vec<&str> = line.split_str(":").collect();
        if results.len() == 2 {
            Tester::parse_test_result(results[1]).map(|res| {
                (results[0].to_string(), res)
            })
        } else {
            Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Malformed test string",
                    detail: Some(line.to_string())
                })
        }
    }

    fn do_testing(&self) -> IoResult<HashMap<String, TestResult>> {
        match ProcessReader::new(&*Command::new("make").arg("test")) {
            Ok(mut reader) => {
                let mut map = HashMap::new();
                for op_line in reader.output_reader().lines() {
                    match op_line {
                        Ok(line) => {
                            match Tester::parse_line(line.as_slice()) {
                                Ok((k, v)) => {
                                    map.insert(k, v);
                                }
                                Err(s) => { return Err(s); }
                            }
                        }
                        Err(s) => { return Err(s); }
                    }
                }
                Ok(map)

            }
            Err(s) => { return Err(s); }
        }
    }
}

/// Encapsulates a request to perform a build and begin test execution.
/// In the future, this may include information for spinning up Docker
/// and pulling from GitHub, though for the moment this is just a directory
/// to go to.
struct BuildRequest {
    dir: String, // directory where the build is to be performed
    makefile_loc: String // where the makefile is located
}

<commit_msg>Refactored errors to be simpler.  Now different stages (hopefully) enforced via phantom types.<commit_after>// Portion that builds and runs tests.  Assumes that this can be
// done via a call to `make build` and `make test`.  Compiler failure
// is assumed to be communicated by return value.  Tests are assumed
// to have the following output format:
//
// some test name: <PASS|FAIL>
//
// ...where each test result is on its own line.  If multiple tests
// have the same name, then only the last test is recorded.

use std::io::{BufferedReader, RefReader, IoResult, IoError, OtherIoError};
use std::io::pipe::PipeStream;
use std::io::process::{Command, Process, ExitStatus, ExitSignal,
                       ProcessExit};
use std::collections::HashMap;

struct BuilderState<A>(A);

struct InitialState;
struct EnvDone;
struct BuildDone;
struct TestDone;

fn spawn_with_timeout(c: &Command, timeout: Option<u64>) -> IoResult<Process> {
    match c.spawn() {
        Ok(mut p) => {
            p.set_timeout(timeout);
            Ok(p)
        },
        Err(e) => Err(e)
    }
}

/// Runs the given command with the given timeout, ignoring the output.
/// If it returns non-zero, then it's a failure, as with a signal.
/// Takes what it should return on success.
fn run_command<A>(c: &Command, timeout: Option<u64>, on_success: A) -> IoResult<A> {
    // would like to use `and_then` here, but we get problems with capturing
    // on_success, seemingly because the compiler cannot enforce that
    // the closure passed to `and_then` only calls it once
    match spawn_with_timeout(c, timeout) {
        Ok(mut p) => {
            match p.wait() {
                Ok(mut res) => res.if_ok(on_success),
                Err(e) => Err(e)
            }
        },
        Err(e) => Err(e)
    }
}

trait ErrorSimplifier {
    fn if_ok<A>(&self, ret_this: A) -> IoResult<A>;
}

impl ErrorSimplifier for ProcessExit {
    fn if_ok<A>(&self, ret_this: A) -> IoResult<A> {
        match *self {
            ExitStatus(0) => Ok(ret_this),
            ExitStatus(x) => Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Non-zero exit code",
                    detail: Some(x.to_string())
                }),
            ExitSignal(x) => Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Exit signal",
                    detail: Some(x.to_string())
                })
        }
    }
}

trait EnvSetup {
    fn timeout(&self) -> Option<u64>;

    fn command(&self) -> Command;

    /// Gets everything in order for testing to be performed.
    /// After calling this, it is assumed that we are ready
    /// to call make
    fn setup_env(&self) -> IoResult<BuilderState<EnvDone>> {
        run_command(&self.command(), self.timeout(),
                    BuilderState(EnvDone))
    }
}

trait BuildSetup {
    fn timeout(&self) -> Option<u64>;

    fn command(&self) -> Command;

    fn do_build(&self) -> IoResult<BuilderState<BuildDone>> {
        run_command(&self.command(), self.timeout(),
                    BuilderState(BuildDone))
    }
}

enum TestResult {
    Pass,
    Fail
}

struct ProcessReader {
    p: Process
}

impl ProcessReader {
    fn new(cmd: &Command) -> IoResult<ProcessReader> {
        cmd.spawn().map(|p| ProcessReader { p: p })
    }

    fn output_reader<'a>(&'a mut self) -> BufferedReader<RefReader<'a, PipeStream>> {
        // unwrap should be ok - the documentation says `Some` is the default,
        // and we are not messing with any of the defaults
        BufferedReader::new(
            Reader::by_ref(
                self.p.stdout.as_mut().unwrap()))
    }
}

trait Tester {
    fn parse_test_result(line: &str) -> IoResult<TestResult> {
        match line {
            "PASS" => Ok(Pass),
            "FAIL" => Ok(Fail),
            _ => Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Malformed test result",
                    detail: Some(line.to_string())
                })
        }
    }

    fn parse_line(line: &str) -> IoResult<(String, TestResult)> {
        let results: Vec<&str> = line.split_str(":").collect();
        if results.len() == 2 {
            Tester::parse_test_result(results[1]).map(|res| {
                (results[0].to_string(), res)
            })
        } else {
            Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Malformed test string",
                    detail: Some(line.to_string())
                })
        }
    }

    fn test_command(&self) -> Command;

    fn do_testing(&self) -> IoResult<HashMap<String, TestResult>> {
        // TODO: without do syntax this becomes nightmarish in
        // functional style, and I had issues with closures capturing
        // too much
        match ProcessReader::new(&self.test_command()) {
            Ok(mut reader) => {
                let mut map = HashMap::new();
                for op_line in reader.output_reader().lines() {
                    match op_line {
                        Ok(line) => {
                            match Tester::parse_line(line.as_slice()) {
                                Ok((k, v)) => {
                                    map.insert(k, v);
                                }
                                Err(s) => { return Err(s); }
                            }
                        }
                        Err(s) => { return Err(s); }
                    }
                }
                Ok(map)

            }
            Err(s) => { return Err(s); }
        }
    }
}

struct TestingRequest {
    dir: String, // directory where the build is to be performed
    makefile_loc: String // where the makefile is located
}
<|endoftext|>


<commit_before>//! # Functions and types used by generated protobuf code
//!
//! These are not considered to be public API of rust-protobuf,
//! so they can be changed any time (provided compatibility with
//! previously generated code is preserved).

pub use crate::cached_size::CachedSize;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::Enum;
use crate::error::Result;
pub use crate::lazy::Lazy;
pub use crate::wire_format::WireType;
use crate::zigzag::*;
use crate::EnumOrUnknown;
use crate::Message;
use crate::MessageField;

pub(crate) mod map;
pub(crate) mod repeated;
pub(crate) mod unsorted;
pub use map::compute_map_size;
pub use map::read_map_into;
pub use map::write_map_with_cached_sizes;
pub use repeated::read_repeated_packed_enum_or_unknown_into;
pub use unsorted::read_unknown_or_skip_group;
pub use unsorted::unknown_fields_size;

use crate::varint::encode::encoded_varint64_len;

/// Given `u64` value compute varint encoded length.
pub fn compute_raw_varint64_size(value: u64) -> u64 {
    encoded_varint64_len(value) as u64
}

/// Given `u32` value compute varint encoded length.
pub(crate) fn compute_raw_varint32_size(value: u32) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Fixed size integers.
pub trait ProtobufFixed {
    /// Size of this fixed type in bytes.
    const LEN: u32;
}

/// Helper trait implemented by integer types which could be encoded as varint.
pub trait ProtobufVarint {
    /// Size of self when encoded as varint.
    fn len_varint(&self) -> u64;
}

/// Helper trait implemented by integer types which could be encoded as zigzag varint.
pub trait ProtobufVarintZigzag {
    /// Size of self when encoded as zigzag varint.
    fn len_varint_zigzag(&self) -> u64;
}

impl ProtobufVarint for u64 {
    fn len_varint(&self) -> u64 {
        compute_raw_varint64_size(*self)
    }
}

impl ProtobufVarint for u32 {
    fn len_varint(&self) -> u64 {
        (*self as u64).len_varint()
    }
}

impl ProtobufVarint for i64 {
    fn len_varint(&self) -> u64 {
        // same as length of u64
        (*self as u64).len_varint()
    }
}

impl ProtobufVarintZigzag for i64 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint64_size(encode_zig_zag_64(*self))
    }
}

impl ProtobufVarint for i32 {
    fn len_varint(&self) -> u64 {
        // sign-extend and then compute
        (*self as i64).len_varint()
    }
}

impl ProtobufVarintZigzag for i32 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint32_size(encode_zig_zag_32(*self))
    }
}

impl ProtobufVarint for bool {
    fn len_varint(&self) -> u64 {
        1
    }
}

impl ProtobufFixed for u32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for i32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for u64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for i64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for f32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for f64 {
    const LEN: u32 = 8;
}

/// Technically `bool` is not fixed, but it can be considered as fixed
/// for the purpose of encoding.
impl ProtobufFixed for bool {
    const LEN: u32 = 1;
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter().map(|v| v.len_varint() as u64).sum()
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter().map(|v| v.len_varint_zigzag()).sum()
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .sum()
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute tag size. Size of tag does not depend on wire type.
pub fn tag_size(field_number: u32) -> u64 {
    encoded_varint64_len((field_number as u64) << 3) as u64
}

/// Size of encoded `sint32` value.
pub fn sint32_size_no_tag(value: i32) -> u64 {
    compute_raw_varint32_size(encode_zig_zag_32(value))
}

/// Size of encoded `sint64` value.
pub fn sint64_size_no_tag(value: i64) -> u64 {
    compute_raw_varint64_size(encode_zig_zag_64(value))
}

/// Size of encoded `int32` value.
pub fn int32_size_no_tag(value: i32) -> u64 {
    value.len_varint()
}

/// Size of encoded `int64` value.
pub fn int64_size_no_tag(value: i64) -> u64 {
    value.len_varint()
}

/// Size of encoded `uint32` value.
pub fn uint32_size_no_tag(value: u32) -> u64 {
    value.len_varint()
}

/// Size of encoded `uint64` value.
pub fn uint64_size_no_tag(value: u64) -> u64 {
    value.len_varint()
}

/// Size of encoded bytes field.
pub fn bytes_size_no_tag(bytes: &[u8]) -> u64 {
    compute_raw_varint64_size(bytes.len() as u64) + bytes.len() as u64
}

/// Size of encoded string field.
pub fn string_size_no_tag(s: &str) -> u64 {
    bytes_size_no_tag(s.as_bytes())
}

/// Read singular `message` field.
pub fn read_singular_message_into_field<M>(
    is: &mut CodedInputStream,
    target: &mut MessageField<M>,
) -> Result<()>
where
    M: Message,
{
    let mut m = M::new();
    is.merge_message(&mut m)?;
    *target = MessageField::some(m);
    Ok(())
}

/// Write message with field number and length to the stream.
pub fn write_message_field_with_cached_size<M>(
    field_number: u32,
    message: &M,
    os: &mut CodedOutputStream,
) -> Result<()>
where
    M: Message,
{
    os.write_tag(field_number, WireType::LengthDelimited)?;
    os.write_raw_varint32(message.cached_size())?;
    message.write_to_with_cached_sizes(os)
}
<commit_msg>Revert "Code cleanup"<commit_after>//! # Functions and types used by generated protobuf code
//!
//! These are not considered to be public API of rust-protobuf,
//! so they can be changed any time (provided compatibility with
//! previously generated code is preserved).

pub use crate::cached_size::CachedSize;
use crate::coded_input_stream::CodedInputStream;
use crate::coded_output_stream::CodedOutputStream;
use crate::enums::Enum;
use crate::error::Result;
pub use crate::lazy::Lazy;
pub use crate::wire_format::WireType;
use crate::zigzag::*;
use crate::EnumOrUnknown;
use crate::Message;
use crate::MessageField;

pub(crate) mod map;
pub(crate) mod repeated;
pub(crate) mod unsorted;
pub use map::compute_map_size;
pub use map::read_map_into;
pub use map::write_map_with_cached_sizes;
pub use repeated::read_repeated_packed_enum_or_unknown_into;
pub use unsorted::read_unknown_or_skip_group;
pub use unsorted::unknown_fields_size;

use crate::varint::encode::encoded_varint64_len;

/// Given `u64` value compute varint encoded length.
pub fn compute_raw_varint64_size(value: u64) -> u64 {
    encoded_varint64_len(value) as u64
}

/// Given `u32` value compute varint encoded length.
pub(crate) fn compute_raw_varint32_size(value: u32) -> u64 {
    compute_raw_varint64_size(value as u64)
}

/// Fixed size integers.
pub trait ProtobufFixed {
    /// Size of this fixed type in bytes.
    const LEN: u32;
}

/// Helper trait implemented by integer types which could be encoded as varint.
pub trait ProtobufVarint {
    /// Size of self when encoded as varint.
    fn len_varint(&self) -> u64;
}

/// Helper trait implemented by integer types which could be encoded as zigzag varint.
pub trait ProtobufVarintZigzag {
    /// Size of self when encoded as zigzag varint.
    fn len_varint_zigzag(&self) -> u64;
}

impl ProtobufVarint for u64 {
    fn len_varint(&self) -> u64 {
        compute_raw_varint64_size(*self)
    }
}

impl ProtobufVarint for u32 {
    fn len_varint(&self) -> u64 {
        (*self as u64).len_varint()
    }
}

impl ProtobufVarint for i64 {
    fn len_varint(&self) -> u64 {
        // same as length of u64
        (*self as u64).len_varint()
    }
}

impl ProtobufVarintZigzag for i64 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint64_size(encode_zig_zag_64(*self))
    }
}

impl ProtobufVarint for i32 {
    fn len_varint(&self) -> u64 {
        // sign-extend and then compute
        (*self as i64).len_varint()
    }
}

impl ProtobufVarintZigzag for i32 {
    fn len_varint_zigzag(&self) -> u64 {
        compute_raw_varint32_size(encode_zig_zag_32(*self))
    }
}

impl ProtobufVarint for bool {
    fn len_varint(&self) -> u64 {
        1
    }
}

impl ProtobufFixed for u32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for i32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for u64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for i64 {
    const LEN: u32 = 8;
}

impl ProtobufFixed for f32 {
    const LEN: u32 = 4;
}

impl ProtobufFixed for f64 {
    const LEN: u32 = 8;
}

/// Technically `bool` is not fixed, but it can be considered as fixed
/// for the purpose of encoding.
impl ProtobufFixed for bool {
    const LEN: u32 = 1;
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint() as u64)
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed field, excluding length and tag.
pub fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint_zigzag())
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .fold(0, |a, i| a + i)
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute tag size. Size of tag does not depend on wire type.
pub fn tag_size(field_number: u32) -> u64 {
    encoded_varint64_len((field_number as u64) << 3) as u64
}

/// Size of encoded `sint32` value.
pub fn sint32_size_no_tag(value: i32) -> u64 {
    compute_raw_varint32_size(encode_zig_zag_32(value))
}

/// Size of encoded `sint64` value.
pub fn sint64_size_no_tag(value: i64) -> u64 {
    compute_raw_varint64_size(encode_zig_zag_64(value))
}

/// Size of encoded `int32` value.
pub fn int32_size_no_tag(value: i32) -> u64 {
    value.len_varint()
}

/// Size of encoded `int64` value.
pub fn int64_size_no_tag(value: i64) -> u64 {
    value.len_varint()
}

/// Size of encoded `uint32` value.
pub fn uint32_size_no_tag(value: u32) -> u64 {
    value.len_varint()
}

/// Size of encoded `uint64` value.
pub fn uint64_size_no_tag(value: u64) -> u64 {
    value.len_varint()
}

/// Size of encoded bytes field.
pub fn bytes_size_no_tag(bytes: &[u8]) -> u64 {
    compute_raw_varint64_size(bytes.len() as u64) + bytes.len() as u64
}

/// Size of encoded string field.
pub fn string_size_no_tag(s: &str) -> u64 {
    bytes_size_no_tag(s.as_bytes())
}

/// Read singular `message` field.
pub fn read_singular_message_into_field<M>(
    is: &mut CodedInputStream,
    target: &mut MessageField<M>,
) -> Result<()>
where
    M: Message,
{
    let mut m = M::new();
    is.merge_message(&mut m)?;
    *target = MessageField::some(m);
    Ok(())
}

/// Write message with field number and length to the stream.
pub fn write_message_field_with_cached_size<M>(
    field_number: u32,
    message: &M,
    os: &mut CodedOutputStream,
) -> Result<()>
where
    M: Message,
{
    os.write_tag(field_number, WireType::LengthDelimited)?;
    os.write_raw_varint32(message.cached_size())?;
    message.write_to_with_cached_sizes(os)
}
<|endoftext|>


<commit_before>use ffi::*;
use std::ptr;
use std::thread;
use std::mem;
use std::cell::RefCell;
use std::os::raw::c_void;

unsafe impl Sync for MainLoop {}
unsafe impl Send for MainLoop {}

pub struct MainLoop{
	gst_loop: *mut GMainLoop,
	running: bool
}

impl Drop for MainLoop{
	fn drop(&mut self){
		unsafe{
			if self.running {
				self.quit();
			}
			g_main_loop_unref(mem::transmute(self.gst_loop));
		}
	}
}

impl MainLoop{
	pub fn new() -> MainLoop{
		unsafe{
			MainLoop{ gst_loop: g_main_loop_new(mem::transmute(ptr::null::<c_void>()), 0), running: false }
		}
	}

	pub fn spawn(&mut self){
		if !self.running {
			self.running = true;
			let gst_loop: u64 = unsafe{ mem::transmute(self.gst_loop) };
			thread::spawn( move|| {
				unsafe{
					g_main_loop_run ( mem::transmute(gst_loop) );
				}
				/*loop{
					g_main_context_iteration(gst_loop,1);
				}*/
			});
		}
	}

	pub fn run(&mut self){
		unsafe{
			if !self.running {
				self.running = true;
				let gst_loop = self.gst_loop.clone();
				g_main_loop_run ( mem::transmute(gst_loop) );
			}
		}
	}

	pub fn quit(&mut self){
		unsafe{
			if self.running{
				self.running = false;
				g_main_loop_quit(mem::transmute(self.gst_loop));
			}
		}
	}
}

thread_local!(static LOOP: RefCell<MainLoop> = RefCell::new(MainLoop::new()));

pub fn spawn(){
	LOOP.with(|mainloop| mainloop.borrow_mut().spawn());
}

pub fn run(){
	LOOP.with(|mainloop| mainloop.borrow_mut().run());
}

pub fn quit(){
	LOOP.with(|mainloop| mainloop.borrow_mut().quit());
}
<commit_msg>mainloop: cast pointer to usize so it works on any platform<commit_after>use ffi::*;
use std::ptr;
use std::thread;
use std::mem;
use std::cell::RefCell;
use std::os::raw::c_void;

unsafe impl Sync for MainLoop {}
unsafe impl Send for MainLoop {}

pub struct MainLoop{
	gst_loop: *mut GMainLoop,
	running: bool
}

impl Drop for MainLoop{
	fn drop(&mut self){
		unsafe{
			if self.running {
				self.quit();
			}
			g_main_loop_unref(mem::transmute(self.gst_loop));
		}
	}
}

impl MainLoop{
	pub fn new() -> MainLoop{
		unsafe{
			MainLoop{ gst_loop: g_main_loop_new(mem::transmute(ptr::null::<c_void>()), 0), running: false }
		}
	}

	pub fn spawn(&mut self){
		if !self.running {
			self.running = true;
			let gst_loop: usize = unsafe{ mem::transmute(self.gst_loop) };
			thread::spawn( move|| {
				unsafe{
					g_main_loop_run ( mem::transmute(gst_loop) );
				}
				/*loop{
					g_main_context_iteration(gst_loop,1);
				}*/
			});
		}
	}

	pub fn run(&mut self){
		unsafe{
			if !self.running {
				self.running = true;
				let gst_loop = self.gst_loop.clone();
				g_main_loop_run ( mem::transmute(gst_loop) );
			}
		}
	}

	pub fn quit(&mut self){
		unsafe{
			if self.running{
				self.running = false;
				g_main_loop_quit(mem::transmute(self.gst_loop));
			}
		}
	}
}

thread_local!(static LOOP: RefCell<MainLoop> = RefCell::new(MainLoop::new()));

pub fn spawn(){
	LOOP.with(|mainloop| mainloop.borrow_mut().spawn());
}

pub fn run(){
	LOOP.with(|mainloop| mainloop.borrow_mut().run());
}

pub fn quit(){
	LOOP.with(|mainloop| mainloop.borrow_mut().quit());
}
<|endoftext|>


<commit_before>/// Determines the minimum number of edits required to transform
/// the first string into the second, using a matrix-driven
/// version of the Levenshtein distance algorithm.
///
fn edit_distance(first: &str, second: &str) -> usize {
    // Initialize a matrix we'll use to track the
    // edit distances as we step through both strings.
    let width = first.chars().count()+1;
    let height = second.chars().count()+1;
    let mut distances: Vec<usize> = Vec::with_capacity(width*height);

    // We want to be able to index values immediately,
    // without having to push data (usizes default to zero).
    unsafe { distances.set_len(width*height); }

    // Initialize first row and column values, when we come
    // across them, which is the distance from nothing to
    // every zero-index substring of the other word.
    // e.g. ("" -> "hou", "" -> "houn", "" -> "hound")
    for row in (0..height) {
        distances[row*width] = row;
    }
    for column in (0..width) {
        distances[column] = column;
    }

    // We need to manage indices manually; strings don't have an
    // index + character iterator, since indexing UTF-8 strings
    // doesn't work beyond the ASCII set. We, however, need to track
    // each substring combination, so they're useful in this scenario.
    let mut row = 1;
    let mut column = 1;
    for row_char in second.chars() {
        for column_char in first.chars() {
            if column_char == row_char {
                // When the strings share a common character, there's
                // no additional cost; we carry forward the optimum edit
                // distance we calculated without having considered it.
                distances[row*width + column] = distances[(row-1)*width + (column-1)];
            } else {
                distances[row*width + column] = *[
                    // Cost of removing a character from the first word.
                    distances[(row-1)*width + column] + 1,

                    // Cost of adding a character to the first word.
                    distances[row*width + (column-1)] + 1,

                    // Cost of substituting the character for another.
                    distances[(row-1)*width + (column-1)] + 1
                ].iter().min().unwrap();
            }
            column += 1;
        }
        row += 1;
        column = 1;
    }

    // The optimal edit distance is always in the
    // lower-right corner of the distance matrix.
    return distances[width*height-1]
}

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

    #[test]
    fn edit_distance_is_correct_for_removing_a_character() {
        assert_eq!(edit_distance("hound", "hounds"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_adding_a_character() {
        assert_eq!(edit_distance("hounds", "hound"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_substitutions() {
        assert_eq!(edit_distance("hound", "mound"), 1);
    }
}
<commit_msg>Implement matching::find function.<commit_after>pub struct Result {
    pub path: Path,
    score: usize,
}

/// Given a set of paths, `find` returns a set of `Result` objects
/// ordered by increasing score values (first values are closest matches).
/// If the result set is larger than `max_results`, the set is reduced to
/// that size.
///
/// # Examples
///
/// ```rust
/// use bloodhound::matching::find;
///
/// let paths = vec![Path::new("bloodhound.rs"), Path::new("lib.rs")];
/// let matches = find("lib", paths, 1);
///
/// assert_eq!(matches[0].path.as_str().unwrap(), "lib.rs");
/// ```
pub fn find(needle: &str, haystack: Vec<Path>, max_results: usize) -> Vec<Result> {
    let mut results = Vec::new();

    // Calculate a score for each of the haystack entries.
    for path in haystack.iter() {
        results.push(Result{ path: path.clone(), score: edit_distance(needle, path.as_str().unwrap()) });
    }

    // Sort the results in ascending order (higher values are worse).
    results.sort_by(|a, b| a.score.cmp(&b.score));

    // Make sure we don't exceed the specified result limit.
    results.truncate(max_results);

    results
}

/// Determines the minimum number of edits required to transform
/// the first string into the second, using a matrix-driven
/// version of the Levenshtein distance algorithm.
///
fn edit_distance(first: &str, second: &str) -> usize {
    // Initialize a matrix we'll use to track the
    // edit distances as we step through both strings.
    let width = first.chars().count()+1;
    let height = second.chars().count()+1;
    let mut distances: Vec<usize> = Vec::with_capacity(width*height);

    // We want to be able to index values immediately,
    // without having to push data (usizes default to zero).
    unsafe { distances.set_len(width*height); }

    // Initialize first row and column values, when we come
    // across them, which is the distance from nothing to
    // every zero-index substring of the other word.
    // e.g. ("" -> "hou", "" -> "houn", "" -> "hound")
    for row in (0..height) {
        distances[row*width] = row;
    }
    for column in (0..width) {
        distances[column] = column;
    }

    // We need to manage indices manually; strings don't have an
    // index + character iterator, since indexing UTF-8 strings
    // doesn't work beyond the ASCII set. We, however, need to track
    // each substring combination, so they're useful in this scenario.
    let mut row = 1;
    let mut column = 1;
    for row_char in second.chars() {
        for column_char in first.chars() {
            if column_char == row_char {
                // When the strings share a common character, there's
                // no additional cost; we carry forward the optimum edit
                // distance we calculated without having considered it.
                distances[row*width + column] = distances[(row-1)*width + (column-1)];
            } else {
                distances[row*width + column] = *[
                    // Cost of removing a character from the first word.
                    distances[(row-1)*width + column] + 1,

                    // Cost of adding a character to the first word.
                    distances[row*width + (column-1)] + 1,

                    // Cost of substituting the character for another.
                    distances[(row-1)*width + (column-1)] + 1
                ].iter().min().unwrap();
            }
            column += 1;
        }
        row += 1;
        column = 1;
    }

    // The optimal edit distance is always in the
    // lower-right corner of the distance matrix.
    return distances[width*height-1]
}

#[cfg(test)]
mod tests {
    use super::find;
    use super::edit_distance;
    use super::Result;

    #[test]
    fn find_returns_a_correctly_ordered_set_of_results() {
        let haystack = vec![Path::new("src/hound.rs"),
            Path::new("lib/hounds.rs"), Path::new("Houndfile")];
        let expected_results = vec![Path::new("Houndfile"), Path::new("src/hound.rs")];
        let results = find("Hound", haystack, 2);
        for i in 0..2 {
            assert_eq!(results[i].path, expected_results[i]);
        }
    }

    #[test]
    fn find_returns_a_correctly_limited_set_of_results() {
        let haystack = vec![Path::new("src/hound.rs"),
            Path::new("lib/hounds.rs"), Path::new("Houndfile")];
        let expected_results = vec![Path::new("Houndfile"), Path::new("src/hound.rs")];
        let results = find("Hound", haystack, 2);
        assert_eq!(results.len(), 2);
    }

    #[test]
    fn edit_distance_is_correct_for_removing_a_character() {
        assert_eq!(edit_distance("hound", "hounds"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_adding_a_character() {
        assert_eq!(edit_distance("hounds", "hound"), 1);
    }

    #[test]
    fn edit_distance_is_correct_for_substitutions() {
        assert_eq!(edit_distance("hound", "mound"), 1);
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::path::Path;

use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc::session::config;
use rustc::ty::TyCtxt;
use rustc_codegen_ssa::METADATA_FILENAME;
use rustc_data_structures::owning_ref::{self, OwningRef};
use rustc_data_structures::rustc_erase_owner;
use rustc_target::spec::Target;

use crate::backend::WriteMetadata;

pub struct CraneliftMetadataLoader;

impl MetadataLoader for CraneliftMetadataLoader {
    fn get_rlib_metadata(
        &self,
        _target: &Target,
        path: &Path,
    ) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> {
        let mut archive = ar::Archive::new(File::open(path).map_err(|e| format!("{:?}", e))?);
        // Iterate over all entries in the archive:
        while let Some(entry_result) = archive.next_entry() {
            let mut entry = entry_result.map_err(|e| format!("{:?}", e))?;
            if entry.header().identifier() == METADATA_FILENAME.as_bytes() {
                let mut buf = Vec::new();
                ::std::io::copy(&mut entry, &mut buf).map_err(|e| format!("{:?}", e))?;
                let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
                return Ok(rustc_erase_owner!(buf.map_owner_box()));
            }
        }

        Err("couldn't find metadata entry".to_string())
        //self.get_dylib_metadata(target, path)
    }

    fn get_dylib_metadata(
        &self,
        _target: &Target,
        path: &Path,
    ) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> {
        use object::Object;
        let file = std::fs::read(path).map_err(|e| format!("read:{:?}", e))?;
        let file = object::File::parse(&file).map_err(|e| format!("parse: {:?}", e))?;
        let buf = file
            .section_data_by_name(".rustc")
            .ok_or("no .rustc section")?
            .into_owned();
        let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
        Ok(rustc_erase_owner!(buf.map_owner_box()))
    }
}

// Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
pub fn write_metadata<P: WriteMetadata>(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata {
    use flate2::write::DeflateEncoder;
    use flate2::Compression;
    use std::io::Write;

    #[derive(PartialEq, Eq, PartialOrd, Ord)]
    enum MetadataKind {
        None,
        Uncompressed,
        Compressed,
    }

    let kind = tcx
        .sess
        .crate_types
        .borrow()
        .iter()
        .map(|ty| match *ty {
            config::CrateType::Executable
            | config::CrateType::Staticlib
            | config::CrateType::Cdylib => MetadataKind::None,

            config::CrateType::Rlib => MetadataKind::Uncompressed,

            config::CrateType::Dylib | config::CrateType::ProcMacro => MetadataKind::Compressed,
        })
        .max()
        .unwrap_or(MetadataKind::None);

    if kind == MetadataKind::None {
        return EncodedMetadata::new();
    }

    let metadata = tcx.encode_metadata();
    if kind == MetadataKind::Uncompressed {
        return metadata;
    }

    assert!(kind == MetadataKind::Compressed);
    let mut compressed = tcx.metadata_encoding_version();
    DeflateEncoder::new(&mut compressed, Compression::fast())
        .write_all(&metadata.raw_data)
        .unwrap();

    product.add_rustc_section(
        rustc::middle::exported_symbols::metadata_symbol_name(tcx),
        compressed,
        tcx.sess.target.target.options.is_like_osx,
    );

    metadata
}
<commit_msg>Pre-allocate vec for rlib metadata reading<commit_after>use std::convert::TryFrom;
use std::fs::File;
use std::path::Path;

use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc::session::config;
use rustc::ty::TyCtxt;
use rustc_codegen_ssa::METADATA_FILENAME;
use rustc_data_structures::owning_ref::{self, OwningRef};
use rustc_data_structures::rustc_erase_owner;
use rustc_target::spec::Target;

use crate::backend::WriteMetadata;

pub struct CraneliftMetadataLoader;

impl MetadataLoader for CraneliftMetadataLoader {
    fn get_rlib_metadata(
        &self,
        _target: &Target,
        path: &Path,
    ) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> {
        let mut archive = ar::Archive::new(File::open(path).map_err(|e| format!("{:?}", e))?);
        // Iterate over all entries in the archive:
        while let Some(entry_result) = archive.next_entry() {
            let mut entry = entry_result.map_err(|e| format!("{:?}", e))?;
            if entry.header().identifier() == METADATA_FILENAME.as_bytes() {
                let mut buf = Vec::with_capacity(
                    usize::try_from(entry.header().size())
                        .expect("Rlib metadata file too big to load into memory.")
                );
                ::std::io::copy(&mut entry, &mut buf).map_err(|e| format!("{:?}", e))?;
                let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
                return Ok(rustc_erase_owner!(buf.map_owner_box()));
            }
        }

        Err("couldn't find metadata entry".to_string())
        //self.get_dylib_metadata(target, path)
    }

    fn get_dylib_metadata(
        &self,
        _target: &Target,
        path: &Path,
    ) -> Result<owning_ref::ErasedBoxRef<[u8]>, String> {
        use object::Object;
        let file = std::fs::read(path).map_err(|e| format!("read:{:?}", e))?;
        let file = object::File::parse(&file).map_err(|e| format!("parse: {:?}", e))?;
        let buf = file
            .section_data_by_name(".rustc")
            .ok_or("no .rustc section")?
            .into_owned();
        let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
        Ok(rustc_erase_owner!(buf.map_owner_box()))
    }
}

// Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
pub fn write_metadata<P: WriteMetadata>(tcx: TyCtxt<'_>, product: &mut P) -> EncodedMetadata {
    use flate2::write::DeflateEncoder;
    use flate2::Compression;
    use std::io::Write;

    #[derive(PartialEq, Eq, PartialOrd, Ord)]
    enum MetadataKind {
        None,
        Uncompressed,
        Compressed,
    }

    let kind = tcx
        .sess
        .crate_types
        .borrow()
        .iter()
        .map(|ty| match *ty {
            config::CrateType::Executable
            | config::CrateType::Staticlib
            | config::CrateType::Cdylib => MetadataKind::None,

            config::CrateType::Rlib => MetadataKind::Uncompressed,

            config::CrateType::Dylib | config::CrateType::ProcMacro => MetadataKind::Compressed,
        })
        .max()
        .unwrap_or(MetadataKind::None);

    if kind == MetadataKind::None {
        return EncodedMetadata::new();
    }

    let metadata = tcx.encode_metadata();
    if kind == MetadataKind::Uncompressed {
        return metadata;
    }

    assert!(kind == MetadataKind::Compressed);
    let mut compressed = tcx.metadata_encoding_version();
    DeflateEncoder::new(&mut compressed, Compression::fast())
        .write_all(&metadata.raw_data)
        .unwrap();

    product.add_rustc_section(
        rustc::middle::exported_symbols::metadata_symbol_name(tcx),
        compressed,
        tcx.sess.target.target.options.is_like_osx,
    );

    metadata
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;

pub fn compare(input: uint, test: uint) -> Ordering {
    if input < test {
        Ordering::Less
    }
    else if input > test {
        Ordering::Greater
    }
    else {
        Ordering::Equal
    }
}
<commit_msg>`uint` -> `usize`<commit_after>use std::cmp::Ordering;

pub fn compare(input: usize, test: usize) -> Ordering {
    if input < test {
        Ordering::Less
    }
    else if input > test {
        Ordering::Greater
    }
    else {
        Ordering::Equal
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc::{TryRecvError, channel};
use std::time::Duration;
use std::io;

use byteorder::{ByteOrder, LittleEndian};

use net::EventLoop;

#[test]
fn get_packet_length_correct() {
    let mut m_number: [u8; 4] = [0; 4];
    LittleEndian::write_u32(&mut m_number, super::NET_MAGIC_NUMBER);
    let mut intended_length: [u8; 2] = [0; 2];
    LittleEndian::write_u16(&mut intended_length, 10);
    let length = super::get_packet_length([m_number[0],
                                           m_number[1],
                                           m_number[2],
                                           m_number[3],
                                           intended_length[0],
                                           intended_length[1]])
                     .expect("get_packet_length wrongly checks NET_MAGIC_NUMBER");
    assert_eq!(length, 10);
}

#[test]
fn get_packet_length_bad_magic_number() {
    let length: Option<u16> = super::get_packet_length([0xFE, 0xF0, 0xF6, 0xFD, 0, 10]);
    assert_eq!(length, None);
}

#[test]
fn handler_new() {
    super::Handler::new(super::MAX_CONNECTIONS);
}

#[test]
fn event_loop_impl_new() {
    super::EventLoopImpl::new(super::MAX_CONNECTIONS).unwrap();
}

#[test]
fn event_loop_impl_shutdown() {
    let (tx, rx) = channel::<Result<(), io::Error>>();
    let mut event_loop = super::EventLoopImpl::new(super::MAX_CONNECTIONS).unwrap();
    let event_loop_ref: super::EventLoopImplRef = (&mut event_loop).into();
    let thread = thread::spawn(move || tx.send(event_loop.run()).unwrap());
    event_loop_ref.shutdown();
    thread::sleep(Duration::from_millis(250));
    // This may, once in a very long time, fail. It really shouldn't, but it is possible.
    // Just raise the number or try again if it fails.
    match rx.try_recv() {
        Err(TryRecvError::Empty) => panic!("EventLoopImpl did not stop after calling shutdown()"),
        Err(TryRecvError::Disconnected) => {
            panic!("EventLoop somehow disconnected it's channel without stopping")
        }
        Ok(res) => res,
    }
    .unwrap();
    thread.join().unwrap();
}
<commit_msg>Unit test for adding a TcpListener to an EventLoopImpl<commit_after>use std::thread;
use std::sync::mpsc::{TryRecvError, channel};
use std::time::Duration;
use std::io;
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};

use byteorder::{ByteOrder, LittleEndian};
use mio::tcp::TcpListener;

use net::EventLoop;

#[test]
fn get_packet_length_correct() {
    let mut m_number: [u8; 4] = [0; 4];
    LittleEndian::write_u32(&mut m_number, super::NET_MAGIC_NUMBER);
    let mut intended_length: [u8; 2] = [0; 2];
    LittleEndian::write_u16(&mut intended_length, 10);
    let length = super::get_packet_length([m_number[0],
                                           m_number[1],
                                           m_number[2],
                                           m_number[3],
                                           intended_length[0],
                                           intended_length[1]])
                     .expect("get_packet_length wrongly checks NET_MAGIC_NUMBER");
    assert_eq!(length, 10);
}

#[test]
fn get_packet_length_bad_magic_number() {
    let length: Option<u16> = super::get_packet_length([0xFE, 0xF0, 0xF6, 0xFD, 0, 10]);
    assert_eq!(length, None);
}

#[test]
fn handler_new() {
    super::Handler::new(super::MAX_CONNECTIONS);
}

#[test]
fn event_loop_impl_new() {
    super::EventLoopImpl::new(super::MAX_CONNECTIONS).unwrap();
}

#[test]
fn event_loop_impl_shutdown() {
    let (tx, rx) = channel::<Result<(), io::Error>>();
    let mut event_loop = super::EventLoopImpl::new(super::MAX_CONNECTIONS).unwrap();
    let event_loop_ref: super::EventLoopImplRef = (&mut event_loop).into();
    let thread = thread::spawn(move || tx.send(event_loop.run()).unwrap());
    event_loop_ref.shutdown();
    thread::sleep(Duration::from_millis(250));
    // This may, once in a very long time, fail. It really shouldn't, but it is possible.
    // Just raise the number or try again if it fails.
    match rx.try_recv() {
        Err(TryRecvError::Empty) => {
            panic!("EventLoopImpl did not stop after calling shutdown()! This fact is depended on \
                    by other unit tests, so ctrl+c here")
        }
        Err(TryRecvError::Disconnected) => {
            panic!("EventLoop somehow disconnected it's channel without stopping! This fact is \
                    depended on by other unit tests, so ctrl+c here")
        }
        Ok(res) => res,
    }
    .unwrap();
    thread.join().unwrap();
}

#[test]
fn event_loop_impl_add_listener() {
    let mut event_loop = super::EventLoopImpl::new(super::MAX_CONNECTIONS).unwrap();
    let event_loop_ref: super::EventLoopImplRef = (&mut event_loop).into();
    let listener = TcpListener::bind(&SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0),
                                                                       25567)))
                       .unwrap();
    let thread = thread::spawn(move || {
        event_loop.run().unwrap();
        event_loop
    });
    event_loop_ref.add_listener(listener);
    event_loop_ref.shutdown();
    let event_loop = thread.join().unwrap();
    assert_eq!(event_loop.handler.listeners.len(), 1);
}
<|endoftext|>