<commit_before><commit_msg>Use clap subcommand_required setting<commit_after><|endoftext|>


<commit_before>//! Standard symbolic constants and types
//!
use {Error, Result, NixPath, from_ffi};
use errno::Errno;
use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{c_char, c_void, c_int, size_t, pid_t, off_t};
use std::mem;
use std::ffi::CString;
use std::os::unix::io::RawFd;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

mod ffi {
    use libc::{c_char, c_int, size_t};
    pub use libc::{close, read, write, pipe, ftruncate, unlink};
    pub use libc::funcs::posix88::unistd::{fork, getpid, getppid};

    extern {
        // duplicate a file descriptor
        // doc: http://man7.org/linux/man-pages/man2/dup.2.html
        pub fn dup(oldfd: c_int) -> c_int;
        pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int;

        // change working directory
        // doc: http://man7.org/linux/man-pages/man2/chdir.2.html
        pub fn chdir(path: *const c_char) -> c_int;

        // Execute PATH with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execv.3.html
        pub fn execv (path: *const c_char, argv: *const *const c_char) -> c_int;

        // execute program
        // doc: http://man7.org/linux/man-pages/man2/execve.2.html
        pub fn execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // Execute FILE, searching in the `PATH' environment variable if it contains
        // no slashes, with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execvp.3.html
        pub fn execvp(filename: *const c_char, argv: *const *const c_char) -> c_int;

        // doc: http://man7.org/linux/man-pages/man3/exec.3.html
        #[cfg(any(target_os = "linux", target_os = "android"))]
        #[cfg(feature = "execvpe")]
        pub fn execvpe(filename: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // run the current process in the background
        // doc: http://man7.org/linux/man-pages/man3/daemon.3.html
        pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int;

        // sets the hostname to the value given
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn gethostname(name: *mut c_char, len: size_t) -> c_int;

        // gets the hostname
        // doc: http://man7.org/linux/man-pages/man2/sethostname.2.html
        pub fn sethostname(name: *const c_char, len: size_t) -> c_int;

        // change root directory
        // doc: http://man7.org/linux/man-pages/man2/chroot.2.html
        pub fn chroot(path: *const c_char) -> c_int;

        // synchronize a file's in-core state with storage device
        // doc: http://man7.org/linux/man-pages/man2/fsync.2.html
        pub fn fsync(fd: c_int) -> c_int;
        pub fn fdatasync(fd: c_int) -> c_int;
    }
}

#[derive(Clone, Copy)]
pub enum Fork {
    Parent(pid_t),
    Child
}

impl Fork {
    pub fn is_child(&self) -> bool {
        match *self {
            Fork::Child => true,
            _ => false
        }
    }

    pub fn is_parent(&self) -> bool {
        match *self {
            Fork::Parent(_) => true,
            _ => false
        }
    }
}

pub fn fork() -> Result<Fork> {
    use self::Fork::*;

    let res = unsafe { ffi::fork() };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    } else if res == 0 {
        Ok(Child)
    } else {
        Ok(Parent(res))
    }
}

#[inline]
pub fn getpid() -> pid_t {
    unsafe { ffi::getpid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn getppid() -> pid_t {
    unsafe { ffi::getppid() } // no error handling, according to man page: "These functions are always successful."
}

#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup(oldfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup2(oldfd, newfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    dup3_polyfill(oldfd, newfd, flags)
}

#[inline]
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    use errno::EINVAL;

    if oldfd == newfd {
        return Err(Error::Sys(Errno::EINVAL));
    }

    let fd = try!(dup2(oldfd, newfd));

    if flags.contains(O_CLOEXEC) {
        if let Err(e) = fcntl(fd, F_SETFD(FD_CLOEXEC)) {
            let _ = close(fd);
            return Err(e);
        }
    }

    Ok(fd)
}

#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chdir(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(())
}

fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
    use std::ptr;
    use libc::c_char;

    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
    args_p.push(ptr::null());
    args_p
}

#[inline]
pub fn execv(path: &CString, argv: &[CString]) -> Result<()> {
    let args_p = to_exec_array(argv);

    unsafe {
        ffi::execv(path.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);
    let env_p = to_exec_array(env);

    unsafe {
        ffi::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execvp(filename: &CString, args: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);

    unsafe {
        ffi::execvp(filename.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
    let res = unsafe { ffi::daemon(nochdir as c_int, noclose as c_int) };
    from_ffi(res)
}

pub fn sethostname(name: &[u8]) -> Result<()> {
    let ptr = name.as_ptr() as *const c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::sethostname(ptr, len) };
    from_ffi(res)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
    let ptr = name.as_mut_ptr() as *mut c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::gethostname(ptr, len) };
    from_ffi(res)
}

pub fn close(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::close(fd) };
    from_ffi(res)
}

pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
    let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
    let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn pipe() -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok((fds[0], fds[1]))
    }
}

pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        try!(pipe2_setflags(fds[0], fds[1], flags));

        Ok((fds[0], fds[1]))
    }
}

fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
    let mut res = Ok(0);

    if flags.contains(O_CLOEXEC) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC)))
            .and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC)));
    }

    if flags.contains(O_NONBLOCK) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK)))
            .and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK)));
    }

    match res {
        Ok(_) => Ok(()),
        Err(e) => {
            let _ = close(fd1);
            let _ = close(fd2);
            return Err(e);
        }
    }
}

pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
    if unsafe { ffi::ftruncate(fd, len) } < 0 {
        Err(Error::Sys(Errno::last()))
    } else {
        Ok(())
    }
}

pub fn isatty(fd: RawFd) -> Result<bool> {
    use libc;

    if unsafe { libc::isatty(fd) } == 1 {
        Ok(true)
    } else {
        match Errno::last() {
            // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
            // we return `Ok(false)`
            Errno::ENOTTY => Ok(false),
            err => Err(Error::Sys(err))
        }
    }
}

pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
    unsafe {
        ffi::unlink(cstr.as_ptr())
    }
    }));
    from_ffi(res)
}

#[inline]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chroot(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[inline]
pub fn fsync(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::fsync(fd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[inline]
pub fn fdatasync(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::fdatasync(fd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
    use sys::syscall::{syscall, SYSPIVOTROOT};
    use errno::Errno;
    use {Error, Result, NixPath};

    #[cfg(feature = "execvpe")]
    use std::ffi::CString;

    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
            new_root: &P1, put_old: &P2) -> Result<()> {
        let res = try!(try!(new_root.with_nix_path(|new_root| {
            put_old.with_nix_path(|put_old| {
                unsafe {
                    syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr())
                }
            })
        })));

        if res != 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok(())
    }

    #[inline]
    #[cfg(feature = "execvpe")]
    pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
        use std::ptr;
        use libc::c_char;

        let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
        args_p.push(ptr::null());

        let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
        env_p.push(ptr::null());

        unsafe {
            super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
        };

        Err(Error::Sys(Errno::last()))
    }
}
<commit_msg>add an implementation of setpgid<commit_after>//! Standard symbolic constants and types
//!
use {Error, Result, NixPath, from_ffi};
use errno::Errno;
use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
use libc::{c_char, c_void, c_int, size_t, pid_t, off_t};
use std::mem;
use std::ffi::CString;
use std::os::unix::io::RawFd;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::linux::*;

mod ffi {
    use libc::{c_char, c_int, size_t};
    pub use libc::{close, read, write, pipe, ftruncate, unlink, setpgid};
    pub use libc::funcs::posix88::unistd::{fork, getpid, getppid};

    extern {
        // duplicate a file descriptor
        // doc: http://man7.org/linux/man-pages/man2/dup.2.html
        pub fn dup(oldfd: c_int) -> c_int;
        pub fn dup2(oldfd: c_int, newfd: c_int) -> c_int;

        // change working directory
        // doc: http://man7.org/linux/man-pages/man2/chdir.2.html
        pub fn chdir(path: *const c_char) -> c_int;

        // Execute PATH with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execv.3.html
        pub fn execv (path: *const c_char, argv: *const *const c_char) -> c_int;

        // execute program
        // doc: http://man7.org/linux/man-pages/man2/execve.2.html
        pub fn execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // Execute FILE, searching in the `PATH' environment variable if it contains
        // no slashes, with arguments ARGV and environment from `environ'.
        // doc: http://man7.org/linux/man-pages/man3/execvp.3.html
        pub fn execvp(filename: *const c_char, argv: *const *const c_char) -> c_int;

        // doc: http://man7.org/linux/man-pages/man3/exec.3.html
        #[cfg(any(target_os = "linux", target_os = "android"))]
        #[cfg(feature = "execvpe")]
        pub fn execvpe(filename: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> c_int;

        // run the current process in the background
        // doc: http://man7.org/linux/man-pages/man3/daemon.3.html
        pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int;

        // sets the hostname to the value given
        // doc: http://man7.org/linux/man-pages/man2/gethostname.2.html
        pub fn gethostname(name: *mut c_char, len: size_t) -> c_int;

        // gets the hostname
        // doc: http://man7.org/linux/man-pages/man2/sethostname.2.html
        pub fn sethostname(name: *const c_char, len: size_t) -> c_int;

        // change root directory
        // doc: http://man7.org/linux/man-pages/man2/chroot.2.html
        pub fn chroot(path: *const c_char) -> c_int;

        // synchronize a file's in-core state with storage device
        // doc: http://man7.org/linux/man-pages/man2/fsync.2.html
        pub fn fsync(fd: c_int) -> c_int;
        pub fn fdatasync(fd: c_int) -> c_int;
    }
}

#[derive(Clone, Copy)]
pub enum Fork {
    Parent(pid_t),
    Child
}

impl Fork {
    pub fn is_child(&self) -> bool {
        match *self {
            Fork::Child => true,
            _ => false
        }
    }

    pub fn is_parent(&self) -> bool {
        match *self {
            Fork::Parent(_) => true,
            _ => false
        }
    }
}

pub fn fork() -> Result<Fork> {
    use self::Fork::*;

    let res = unsafe { ffi::fork() };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    } else if res == 0 {
        Ok(Child)
    } else {
        Ok(Parent(res))
    }
}

#[inline]
pub fn getpid() -> pid_t {
    unsafe { ffi::getpid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn getppid() -> pid_t {
    unsafe { ffi::getppid() } // no error handling, according to man page: "These functions are always successful."
}
#[inline]
pub fn setpgid(pid: pid_t, pgid: pid_t) -> Result<()> {
    let res = unsafe { ffi::setpgid(pid, pgid) };
    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }
    Ok(())
}

#[inline]
pub fn dup(oldfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup(oldfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

#[inline]
pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
    let res = unsafe { ffi::dup2(oldfd, newfd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(res)
}

pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    dup3_polyfill(oldfd, newfd, flags)
}

#[inline]
fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
    use errno::EINVAL;

    if oldfd == newfd {
        return Err(Error::Sys(Errno::EINVAL));
    }

    let fd = try!(dup2(oldfd, newfd));

    if flags.contains(O_CLOEXEC) {
        if let Err(e) = fcntl(fd, F_SETFD(FD_CLOEXEC)) {
            let _ = close(fd);
            return Err(e);
        }
    }

    Ok(fd)
}

#[inline]
pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chdir(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(())
}

fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
    use std::ptr;
    use libc::c_char;

    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
    args_p.push(ptr::null());
    args_p
}

#[inline]
pub fn execv(path: &CString, argv: &[CString]) -> Result<()> {
    let args_p = to_exec_array(argv);

    unsafe {
        ffi::execv(path.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);
    let env_p = to_exec_array(env);

    unsafe {
        ffi::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

#[inline]
pub fn execvp(filename: &CString, args: &[CString]) -> Result<()> {
    let args_p = to_exec_array(args);

    unsafe {
        ffi::execvp(filename.as_ptr(), args_p.as_ptr())
    };

    Err(Error::Sys(Errno::last()))
}

pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
    let res = unsafe { ffi::daemon(nochdir as c_int, noclose as c_int) };
    from_ffi(res)
}

pub fn sethostname(name: &[u8]) -> Result<()> {
    let ptr = name.as_ptr() as *const c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::sethostname(ptr, len) };
    from_ffi(res)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
    let ptr = name.as_mut_ptr() as *mut c_char;
    let len = name.len() as size_t;

    let res = unsafe { ffi::gethostname(ptr, len) };
    from_ffi(res)
}

pub fn close(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::close(fd) };
    from_ffi(res)
}

pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
    let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
    let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    return Ok(res as usize)
}

pub fn pipe() -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok((fds[0], fds[1]))
    }
}

pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
    unsafe {
        let mut fds: [c_int; 2] = mem::uninitialized();

        let res = ffi::pipe(fds.as_mut_ptr());

        if res < 0 {
            return Err(Error::Sys(Errno::last()));
        }

        try!(pipe2_setflags(fds[0], fds[1], flags));

        Ok((fds[0], fds[1]))
    }
}

fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
    let mut res = Ok(0);

    if flags.contains(O_CLOEXEC) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFD(FD_CLOEXEC)))
            .and_then(|_| fcntl(fd2, F_SETFD(FD_CLOEXEC)));
    }

    if flags.contains(O_NONBLOCK) {
        res = res
            .and_then(|_| fcntl(fd1, F_SETFL(O_NONBLOCK)))
            .and_then(|_| fcntl(fd2, F_SETFL(O_NONBLOCK)));
    }

    match res {
        Ok(_) => Ok(()),
        Err(e) => {
            let _ = close(fd1);
            let _ = close(fd2);
            return Err(e);
        }
    }
}

pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
    if unsafe { ffi::ftruncate(fd, len) } < 0 {
        Err(Error::Sys(Errno::last()))
    } else {
        Ok(())
    }
}

pub fn isatty(fd: RawFd) -> Result<bool> {
    use libc;

    if unsafe { libc::isatty(fd) } == 1 {
        Ok(true)
    } else {
        match Errno::last() {
            // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
            // we return `Ok(false)`
            Errno::ENOTTY => Ok(false),
            err => Err(Error::Sys(err))
        }
    }
}

pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
    unsafe {
        ffi::unlink(cstr.as_ptr())
    }
    }));
    from_ffi(res)
}

#[inline]
pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe { ffi::chroot(cstr.as_ptr()) }
    }));

    if res != 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[inline]
pub fn fsync(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::fsync(fd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[inline]
pub fn fdatasync(fd: RawFd) -> Result<()> {
    let res = unsafe { ffi::fdatasync(fd) };

    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

#[cfg(any(target_os = "linux", target_os = "android"))]
mod linux {
    use sys::syscall::{syscall, SYSPIVOTROOT};
    use errno::Errno;
    use {Error, Result, NixPath};

    #[cfg(feature = "execvpe")]
    use std::ffi::CString;

    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
            new_root: &P1, put_old: &P2) -> Result<()> {
        let res = try!(try!(new_root.with_nix_path(|new_root| {
            put_old.with_nix_path(|put_old| {
                unsafe {
                    syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr())
                }
            })
        })));

        if res != 0 {
            return Err(Error::Sys(Errno::last()));
        }

        Ok(())
    }

    #[inline]
    #[cfg(feature = "execvpe")]
    pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> {
        use std::ptr;
        use libc::c_char;

        let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
        args_p.push(ptr::null());

        let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect();
        env_p.push(ptr::null());

        unsafe {
            super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
        };

        Err(Error::Sys(Errno::last()))
    }
}
<|endoftext|>


<commit_before>//! Arithmetic on **Iterator** *.size_hint()* values.
//!

use std::usize;
use std::cmp;

/// **SizeHint** is the return type of **Iterator::size_hint()**.
pub type SizeHint = (usize, Option<usize>);

/// Add **SizeHint** correctly.
#[inline]
pub fn add(a: SizeHint, b: SizeHint) -> SizeHint {
    let min = a.0.checked_add(b.0).unwrap_or(usize::MAX);
    let max = match (a.1, b.1) {
        (Some(x), Some(y)) => x.checked_add(y),
        _ => None,
    };

    (min, max)
}

/// Add **x** correctly to a **SizeHint**.
#[inline]
pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint {
    let (mut low, mut hi) = sh;
    low = low.saturating_add(x);
    hi = hi.and_then(|elt| elt.checked_add(x));
    (low, hi)
}

/// Sbb **x** correctly to a **SizeHint**.
#[inline]
pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint {
    let (mut low, mut hi) = sh;
    low = low.saturating_sub(x);
    hi = hi.map(|elt| elt.saturating_sub(x));
    (low, hi)
}

/// Multiply **SizeHint** correctly
///
/// ```ignore
/// use std::usize;
/// use itertools::size_hint;
///
/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))),
///            (9, Some(16)));
///
/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)),
///            (usize::MAX, None));
///
/// assert_eq!(size_hint::mul((3, None), (0, Some(0))),
///            (0, Some(0)));
/// ```
#[inline]
pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint {
    let low = a.0.checked_mul(b.0).unwrap_or(usize::MAX);
    let hi = match (a.1, b.1) {
        (Some(x), Some(y)) => x.checked_mul(y),
        (Some(0), None) | (None, Some(0)) => Some(0),
        _ => None,
    };
    (low, hi)
}

/// Return the maximum
#[inline]
pub fn max(a: SizeHint, b: SizeHint) -> SizeHint {
    let (a_lower, a_upper) = a;
    let (b_lower, b_upper) = b;

    let lower = cmp::max(a_lower, b_lower);

    let upper = match (a_upper, b_upper) {
        (Some(x), Some(y)) => Some(cmp::max(x, y)),
        _ => None,
    };

    (lower, upper)
}

/// Return the minimum
#[inline]
pub fn min(a: SizeHint, b: SizeHint) -> SizeHint {
    let (a_lower, a_upper) = a;
    let (b_lower, b_upper) = b;
    let lower = cmp::min(a_lower, b_lower);
    let upper = match (a_upper, b_upper) {
        (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
        _ => a_upper.or(b_upper),
    };
    (lower, upper)
}
<commit_msg>Add #[allow(dead_code)] to sub_scalar.<commit_after>//! Arithmetic on **Iterator** *.size_hint()* values.
//!

use std::usize;
use std::cmp;

/// **SizeHint** is the return type of **Iterator::size_hint()**.
pub type SizeHint = (usize, Option<usize>);

/// Add **SizeHint** correctly.
#[inline]
pub fn add(a: SizeHint, b: SizeHint) -> SizeHint {
    let min = a.0.checked_add(b.0).unwrap_or(usize::MAX);
    let max = match (a.1, b.1) {
        (Some(x), Some(y)) => x.checked_add(y),
        _ => None,
    };

    (min, max)
}

/// Add **x** correctly to a **SizeHint**.
#[inline]
pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint {
    let (mut low, mut hi) = sh;
    low = low.saturating_add(x);
    hi = hi.and_then(|elt| elt.checked_add(x));
    (low, hi)
}

/// Sbb **x** correctly to a **SizeHint**.
#[inline]
#[allow(dead_code)]
pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint {
    let (mut low, mut hi) = sh;
    low = low.saturating_sub(x);
    hi = hi.map(|elt| elt.saturating_sub(x));
    (low, hi)
}

/// Multiply **SizeHint** correctly
///
/// ```ignore
/// use std::usize;
/// use itertools::size_hint;
///
/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))),
///            (9, Some(16)));
///
/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)),
///            (usize::MAX, None));
///
/// assert_eq!(size_hint::mul((3, None), (0, Some(0))),
///            (0, Some(0)));
/// ```
#[inline]
pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint {
    let low = a.0.checked_mul(b.0).unwrap_or(usize::MAX);
    let hi = match (a.1, b.1) {
        (Some(x), Some(y)) => x.checked_mul(y),
        (Some(0), None) | (None, Some(0)) => Some(0),
        _ => None,
    };
    (low, hi)
}

/// Return the maximum
#[inline]
pub fn max(a: SizeHint, b: SizeHint) -> SizeHint {
    let (a_lower, a_upper) = a;
    let (b_lower, b_upper) = b;

    let lower = cmp::max(a_lower, b_lower);

    let upper = match (a_upper, b_upper) {
        (Some(x), Some(y)) => Some(cmp::max(x, y)),
        _ => None,
    };

    (lower, upper)
}

/// Return the minimum
#[inline]
pub fn min(a: SizeHint, b: SizeHint) -> SizeHint {
    let (a_lower, a_upper) = a;
    let (b_lower, b_upper) = b;
    let lower = cmp::min(a_lower, b_lower);
    let upper = match (a_upper, b_upper) {
        (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
        _ => a_upper.or(b_upper),
    };
    (lower, upper)
}
<|endoftext|>


<commit_before>//! Write las points.
//!
//! A `Writer` uses a `Header` for its configuration:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Writer, Header};
//! let mut header = Header::from((1, 4));
//! let writer = Writer::new(Cursor::new(Vec::new()), header).unwrap();
//! ```
//!
//! The set of optional fields on the point format and the points must match exactly:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Builder, Writer, Point};
//! use las::point::Format;
//! use las::Color;
//!
//! let mut builder = Builder::default();
//! builder.point_format = Format::new(1).unwrap();
//! let mut writer = Writer::new(Cursor::new(Vec::new()), builder.into_header().unwrap()).unwrap();
//!
//! let mut point = Point::default(); // default points don't have any optional attributes
//! assert!(writer.write(point.clone()).is_err());
//!
//! point.gps_time = Some(42.); // point format 1 requires gps time
//! writer.write(point.clone()).unwrap();
//!
//! point.color = Some(Color::new(1, 2, 3));
//! assert!(writer.write(point).is_err()); // the point's color would be lost
//! ```

use {Header, Point, Result};
use point::Format;
use std::fs::File;
use std::io::{BufWriter, Seek, SeekFrom, Write};
use std::path::Path;

quick_error! {
    /// Writer errors.
    #[derive(Debug)]
    pub enum Error {
        /// The writer is closed.
        Closed {
            description("the writer is closed")
        }
        /// The attributes of the point format and point do not match.
        PointAttributes(format: Format, point: Point) {
            description("the attributes of the point format and point do not match")
            display("the attributes of point format {:?} does not match point {:?}", format, point)
        }
    }
}

/// Writes LAS data.
///
/// The LAS header needs to be re-written when the writer closes. For convenience, this is done via
/// the `Drop` implementation of the writer. One consequence is that if the header re-write fails
/// during the drop, a panic will result. If you want to check for errors instead of panicing, use
/// `close` explicitly.
///
/// ```
/// use std::io::Cursor;
/// use las::Writer;
/// {
///     let mut writer = Writer::default();
///     writer.close().unwrap();
/// } // <- `close` is not called
/// ```
#[derive(Debug)]
pub struct Writer<W: Seek + Write> {
    closed: bool,
    header: Header,
    write: W,
}

impl<W: Seek + Write> Writer<W> {
    /// Creates a new writer.
    ///
    /// The header that is passed in will have various fields zero'd, e.g. bounds, number of
    /// points, etc.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// use las::Writer;
    /// let writer = Writer::new(Cursor::new(Vec::new()), Default::default());
    /// ```
    pub fn new(mut write: W, mut header: Header) -> Result<Writer<W>> {
        header.clear();
        header.clone().into_raw().and_then(|raw_header| {
            raw_header.write_to(&mut write)
        })?;
        for vlr in header.vlrs() {
            (*vlr).clone().into_raw().and_then(|raw_vlr| {
                raw_vlr.write_to(&mut write)
            })?;
        }
        if !header.vlr_padding().is_empty() {
            write.write_all(&header.vlr_padding())?;
        }
        Ok(Writer {
            closed: false,
            header: header,
            write: write,
        })
    }

    /// Writes a point.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// use las::Writer;
    ///
    /// let mut writer = Writer::default();
    /// writer.write(Default::default()).unwrap();
    /// ```
    pub fn write(&mut self, point: Point) -> Result<()> {
        if self.closed {
            return Err(Error::Closed.into());
        }
        if !point.matches(self.header.point_format()) {
            return Err(
                Error::PointAttributes(self.header.point_format(), point).into(),
            );
        }
        self.header.add_point(&point);
        point.into_raw(self.header.transforms()).and_then(
            |raw_point| {
                raw_point.write_to(&mut self.write, self.header.point_format())
            },
        )?;
        Ok(())
    }

    /// Close this writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// use las::Writer;
    /// let mut writer = Writer::default();
    /// writer.close().unwrap();
    /// assert!(writer.close().is_err());
    /// ```
    pub fn close(&mut self) -> Result<()> {
        if self.closed {
            return Err(Error::Closed.into());
        }
        for raw_evlr in self.header.evlrs().into_iter().map(|evlr| {
            evlr.clone().into_raw()
        })
        {
            raw_evlr?.write_to(&mut self.write)?;
        }
        // TODO support writers that aren't at the beginning of their write
        self.write.seek(SeekFrom::Start(0))?;
        self.header.clone().into_raw().and_then(|raw_header| {
            raw_header.write_to(&mut self.write)
        })?;
        self.closed = true;
        Ok(())
    }
}

impl<W: Write + Seek + Clone> Writer<W> {
    /// Closes this writer and returns its inner `Write`, seeked to the beginning of the las data.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::Writer;
    /// let writer = Writer::default();
    /// let cursor = writer.into_inner().unwrap();
    /// ```
    pub fn into_inner(mut self) -> Result<W> {
        if !self.closed {
            self.close()?;
        }
        let mut write = self.write.clone();
        // TODO writers that aren't at the beginning of their write
        write.seek(SeekFrom::Start(0))?;
        Ok(write)
    }
}

impl Writer<BufWriter<File>> {
    /// Creates a new writer for a path.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::Writer;
    /// let writer = Writer::from_path("/dev/null", Default::default());
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P, header: Header) -> Result<Writer<BufWriter<File>>> {
        File::create(path).map_err(::Error::from).and_then(|file| {
            Writer::new(BufWriter::new(file), header)
        })
    }
}

impl Default for Writer<Cursor<Vec<u8>>> {
    fn default() -> Writer<Cursor<Vec<u8>>> {
        Writer::new(Cursor::new(Vec::new()), Header::default()).unwrap()
    }
}

impl<W: Seek + Write> Drop for Writer<W> {
    fn drop(&mut self) {
        if !self.closed {
            self.close().expect("Error when dropping the writer");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use Version;
    use byteorder::{LittleEndian, ReadBytesExt};
    use header::Builder;
    use point::Format;
    use std::io::Cursor;

    fn writer(format: Format, version: Version) -> Writer<Cursor<Vec<u8>>> {
        let mut builder = Builder::default();
        builder.point_format = format;
        builder.version = version;
        Writer::new(Cursor::new(Vec::new()), builder.into_header().unwrap()).unwrap()
    }

    #[test]
    fn las_1_0_point_data_start_signature() {
        let mut builder = Builder::default();
        builder.version = (1, 0).into();
        builder.vlrs.push(Default::default());
        let mut writer = Writer::new(Cursor::new(Vec::new()), builder.into_header().unwrap())
            .unwrap();
        writer.write(Default::default()).unwrap();
        let mut cursor = writer.into_inner().unwrap();
        cursor.set_position(281);
        assert_eq!(0xCCDD, cursor.read_u16::<LittleEndian>().unwrap());
    }

    #[test]
    fn already_closed() {
        let mut writer = Writer::default();
        writer.close().unwrap();
        assert!(writer.close().is_err());
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_extra_bytes() {
        let format = Format {
            extra_bytes: 1,
            ..Default::default()
        };
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_gps_time() {
        let format = Format::new(1).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_color() {
        let format = Format::new(2).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_nir() {
        let format = Format::new(8).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        let point = Point {
            gps_time: Some(0.),
            color: Some(Default::default()),
            ..Default::default()
        };
        assert!(writer.write(point).is_err());
    }

    #[test]
    fn missing_waveform() {
        let format = Format::new(4).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }
}
<commit_msg>Permit writers that aren't at their start<commit_after>//! Write las points.
//!
//! A `Writer` uses a `Header` for its configuration:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Writer, Header};
//! let mut header = Header::from((1, 4));
//! let writer = Writer::new(Cursor::new(Vec::new()), header).unwrap();
//! ```
//!
//! The set of optional fields on the point format and the points must match exactly:
//!
//! ```
//! use std::io::Cursor;
//! use las::{Builder, Writer, Point};
//! use las::point::Format;
//! use las::Color;
//!
//! let mut builder = Builder::default();
//! builder.point_format = Format::new(1).unwrap();
//! let mut writer = Writer::new(Cursor::new(Vec::new()), builder.into_header().unwrap()).unwrap();
//!
//! let mut point = Point::default(); // default points don't have any optional attributes
//! assert!(writer.write(point.clone()).is_err());
//!
//! point.gps_time = Some(42.); // point format 1 requires gps time
//! writer.write(point.clone()).unwrap();
//!
//! point.color = Some(Color::new(1, 2, 3));
//! assert!(writer.write(point).is_err()); // the point's color would be lost
//! ```

use {Header, Point, Result};
use point::Format;
use std::fs::File;
use std::io::{BufWriter, Cursor, Seek, SeekFrom, Write};
use std::path::Path;

quick_error! {
    /// Writer errors.
    #[derive(Debug)]
    pub enum Error {
        /// The writer is closed.
        Closed {
            description("the writer is closed")
        }
        /// The attributes of the point format and point do not match.
        PointAttributes(format: Format, point: Point) {
            description("the attributes of the point format and point do not match")
            display("the attributes of point format {:?} does not match point {:?}", format, point)
        }
    }
}

/// Writes LAS data.
///
/// The LAS header needs to be re-written when the writer closes. For convenience, this is done via
/// the `Drop` implementation of the writer. One consequence is that if the header re-write fails
/// during the drop, a panic will result. If you want to check for errors instead of panicing, use
/// `close` explicitly.
///
/// ```
/// use std::io::Cursor;
/// use las::Writer;
/// {
///     let mut writer = Writer::default();
///     writer.close().unwrap();
/// } // <- `close` is not called
/// ```
#[derive(Debug)]
pub struct Writer<W: Seek + Write> {
    closed: bool,
    header: Header,
    start: u64,
    write: W,
}

impl<W: Seek + Write> Writer<W> {
    /// Creates a new writer.
    ///
    /// The header that is passed in will have various fields zero'd, e.g. bounds, number of
    /// points, etc.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// use las::Writer;
    /// let writer = Writer::new(Cursor::new(Vec::new()), Default::default());
    /// ```
    pub fn new(mut write: W, mut header: Header) -> Result<Writer<W>> {
        let start = write.seek(SeekFrom::Current(0))?;
        header.clear();
        header.clone().into_raw().and_then(|raw_header| {
            raw_header.write_to(&mut write)
        })?;
        for vlr in header.vlrs() {
            (*vlr).clone().into_raw().and_then(|raw_vlr| {
                raw_vlr.write_to(&mut write)
            })?;
        }
        if !header.vlr_padding().is_empty() {
            write.write_all(&header.vlr_padding())?;
        }
        Ok(Writer {
            closed: false,
            header: header,
            start: start,
            write: write,
        })
    }

    /// Writes a point.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// use las::Writer;
    ///
    /// let mut writer = Writer::default();
    /// writer.write(Default::default()).unwrap();
    /// ```
    pub fn write(&mut self, point: Point) -> Result<()> {
        if self.closed {
            return Err(Error::Closed.into());
        }
        if !point.matches(self.header.point_format()) {
            return Err(
                Error::PointAttributes(self.header.point_format(), point).into(),
            );
        }
        self.header.add_point(&point);
        point.into_raw(self.header.transforms()).and_then(
            |raw_point| {
                raw_point.write_to(&mut self.write, self.header.point_format())
            },
        )?;
        Ok(())
    }

    /// Close this writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// use las::Writer;
    /// let mut writer = Writer::default();
    /// writer.close().unwrap();
    /// assert!(writer.close().is_err());
    /// ```
    pub fn close(&mut self) -> Result<()> {
        if self.closed {
            return Err(Error::Closed.into());
        }
        for raw_evlr in self.header.evlrs().into_iter().map(|evlr| {
            evlr.clone().into_raw()
        })
        {
            raw_evlr?.write_to(&mut self.write)?;
        }
        self.write.seek(SeekFrom::Start(self.start))?;
        self.header.clone().into_raw().and_then(|raw_header| {
            raw_header.write_to(&mut self.write)
        })?;
        self.write.seek(SeekFrom::Start(self.start))?;
        self.closed = true;
        Ok(())
    }
}

impl<W: Write + Seek + Clone> Writer<W> {
    /// Closes this writer and returns its inner `Write`, seeked to the beginning of the las data.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::Writer;
    /// let writer = Writer::default();
    /// let cursor = writer.into_inner().unwrap();
    /// ```
    pub fn into_inner(mut self) -> Result<W> {
        if !self.closed {
            self.close()?;
        }
        self.write.seek(SeekFrom::Start(self.start))?;
        Ok(self.write.clone())
    }
}

impl Writer<BufWriter<File>> {
    /// Creates a new writer for a path.
    ///
    /// # Examples
    ///
    /// ```
    /// use las::Writer;
    /// let writer = Writer::from_path("/dev/null", Default::default());
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P, header: Header) -> Result<Writer<BufWriter<File>>> {
        File::create(path).map_err(::Error::from).and_then(|file| {
            Writer::new(BufWriter::new(file), header)
        })
    }
}

impl Default for Writer<Cursor<Vec<u8>>> {
    fn default() -> Writer<Cursor<Vec<u8>>> {
        Writer::new(Cursor::new(Vec::new()), Header::default()).unwrap()
    }
}

impl<W: Seek + Write> Drop for Writer<W> {
    fn drop(&mut self) {
        if !self.closed {
            self.close().expect("Error when dropping the writer");
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use Version;
    use byteorder::{LittleEndian, ReadBytesExt};
    use header::Builder;
    use point::Format;
    use std::io::Cursor;

    fn writer(format: Format, version: Version) -> Writer<Cursor<Vec<u8>>> {
        let mut builder = Builder::default();
        builder.point_format = format;
        builder.version = version;
        Writer::new(Cursor::new(Vec::new()), builder.into_header().unwrap()).unwrap()
    }

    #[test]
    fn las_1_0_point_data_start_signature() {
        let mut builder = Builder::default();
        builder.version = (1, 0).into();
        builder.vlrs.push(Default::default());
        let mut writer = Writer::new(Cursor::new(Vec::new()), builder.into_header().unwrap())
            .unwrap();
        writer.write(Default::default()).unwrap();
        let mut cursor = writer.into_inner().unwrap();
        cursor.set_position(281);
        assert_eq!(0xCCDD, cursor.read_u16::<LittleEndian>().unwrap());
    }

    #[test]
    fn already_closed() {
        let mut writer = Writer::default();
        writer.close().unwrap();
        assert!(writer.close().is_err());
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_extra_bytes() {
        let format = Format {
            extra_bytes: 1,
            ..Default::default()
        };
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_gps_time() {
        let format = Format::new(1).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_color() {
        let format = Format::new(2).unwrap();
        let mut writer = writer(format, Version::new(1, 2));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn missing_nir() {
        let format = Format::new(8).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        let point = Point {
            gps_time: Some(0.),
            color: Some(Default::default()),
            ..Default::default()
        };
        assert!(writer.write(point).is_err());
    }

    #[test]
    fn missing_waveform() {
        let format = Format::new(4).unwrap();
        let mut writer = writer(format, Version::new(1, 4));
        assert!(writer.write(Default::default()).is_err());
    }

    #[test]
    fn write_not_at_start() {
        use Reader;
        use byteorder::WriteBytesExt;

        let mut cursor = Cursor::new(Vec::new());
        cursor.write_u8(42).unwrap();
        let mut writer = Writer::new(cursor, Default::default()).unwrap();
        let point = Point::default();
        writer.write(point.clone()).unwrap();
        let mut reader = Reader::new(writer.into_inner().unwrap()).unwrap();
        assert_eq!(point, reader.read().unwrap().unwrap());
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("hello, world");
    println!("> Primitives");
    primitives();
    println!("> Tuples");
    tuples();
    println!("> Arrays");
    arrays();
    println!("> Structs");
    structs();
    println!("> References");
    references();
    println!("> Enums");
    enums();
}

fn primitives() {
    // List of Rust primitive types
    // https://doc.rust-lang.org/book/primitive-types.html
    println!("1 + 2 = {}", 1 + 2);
    println!("1 - 2 = {}", 1 - 2);
    println!("true and true = {}", true && true);
    let x:char = 'x';
    println!("x = {}", x);
    let y:f32 = 3.14;
    println!("y = {}", y);
}

fn tuples() {
    fn reverse(pair: (i32, i32)) -> (i32, i32) {
        let (x, y) = pair;
        (y, x)
    }
    let pair = (3, 2);
    let reversed = reverse(pair);
    println!("reversed: ({}, {})", reversed.0, reversed.1);
}

fn arrays() {
    fn sum(slice:&[i32]) -> i32 {
        let mut total = 0;
        for i in 0..slice.len() {
            total += slice[i]
        }
        total
    }
    let x = [1, 2, 3];
    println!("total: {}", sum(&x));
    let y = [1, 2, 3, 4, 5];
    println!("total: {}", sum(&y));
}

fn structs() {
    struct Point {
        x: i32,
        y: i32
    }
    fn add(p1: Point, p2: Point) -> Point {
        Point {
            x: p1.x + p2.x,
            y: p1.y + p2.y
        }
    }
    fn print_point(p: Point) {
        println!("({} ,{})", p.x, p.y);
    }
    let p1 = Point { x: 1, y: 2 };
    let p2 = Point { x: 4, y: 5 };
    let p3 = add(p1, p2);
    print_point(p3);
}

fn references() {
    // testing mutable reference.
    let mut x:i32 = 5;
    println!("x: {}", x);
    fn increment(x: &mut i32) {
        *x = *x + 1;
    }
    increment(&mut x);
    println!("x: {}", x);
    // testing immutable references
    fn print_twice(x: &i32) {
        println!("first:  {}", x);
        println!("second: {}", x);
    }
    print_twice(&3);
    print_twice(&x);
    /*
    this code does not compile - taking multiple mutable references.
    {
        let y = &mut x;
        let z = &mut x;
    }
    */
    /*
    this code does not compile - taking mutable & immutable references (they form read-write-lock).
    {
        let y = & x;
        let z = &mut x;
    }
    */
}

fn enums() {
    // standard enum.
    enum Color {
        RED,
        GREEN,
        BLACK
    };
    fn categorize_color(c: Color) {
        match c {
            Color::RED => println!("color is red!"),
            Color::GREEN => println!("color is green!"),
            _ =>
                println!("Unknown color.")
        }
    }
    categorize_color(Color::RED);
    categorize_color(Color::GREEN);
    categorize_color(Color::BLACK);
    // pattern matching enum.
    enum Option {
        None,
        Some(i32)
    }
    fn app(o: Option, function: fn(i32) -> i32) -> Option {
        match o {
            Option::None => Option::None,
            Option::Some(x) => Option::Some(function(x))
        }
    }
    fn add_one(x:i32) -> i32 {
        x + 1
    }
    fn print_value(x:i32) -> i32 {
        println!("value: {}", x);
        return 0;
    }
    app(app(Option::Some(10), add_one), print_value);
    app(app(Option::None, add_one), print_value);
}
<commit_msg>Add trait support<commit_after>use std::ops::Add;

fn main() {
    println!("hello, world");
    println!("> Primitives");
    primitives();
    println!("> Tuples");
    tuples();
    println!("> Arrays");
    arrays();
    println!("> Structs");
    structs();
    println!("> References");
    references();
    println!("> Enums");
    enums();
}

fn primitives() {
    // List of Rust primitive types
    // https://doc.rust-lang.org/book/primitive-types.html
    println!("1 + 2 = {}", 1 + 2);
    println!("1 - 2 = {}", 1 - 2);
    println!("true and true = {}", true && true);
    let x:char = 'x';
    println!("x = {}", x);
    let y:f32 = 3.14;
    println!("y = {}", y);
}

fn tuples() {
    fn reverse(pair: (i32, i32)) -> (i32, i32) {
        let (x, y) = pair;
        (y, x)
    }
    let pair = (3, 2);
    let reversed = reverse(pair);
    println!("reversed: ({}, {})", reversed.0, reversed.1);
}

fn arrays() {
    fn sum(slice:&[i32]) -> i32 {
        let mut total = 0;
        for i in 0..slice.len() {
            total += slice[i]
        }
        total
    }
    let x = [1, 2, 3];
    println!("total: {}", sum(&x));
    let y = [1, 2, 3, 4, 5];
    println!("total: {}", sum(&y));
}

fn structs() {
    // this is used to override move semantics.
    #[derive(Copy, Clone)]
    struct Point {
        x: i32,
        y: i32
    }
    fn add(p1: Point, p2: Point) -> Point {
        Point {
            x: p1.x + p2.x,
            y: p1.y + p2.y
        }
    }
    impl Add for Point {
        // operator overloading!
        type Output = Point;
        fn add(self, other: Point) -> Point {
            Point { x: self.x + other.x, y: self.y + other.y }
        }
    }

    fn print_point(p: Point) {
        println!("({} ,{})", p.x, p.y);
    }
    let p1 = Point { x: 1, y: 2 };
    let p2 = Point { x: 4, y: 5 };
    let p3 = add(p1, p2);
    let p4 = p1 + p2;
    print_point(p3);
    print_point(p4);
}

fn references() {
    // testing mutable reference.
    let mut x:i32 = 5;
    println!("x: {}", x);
    fn increment(x: &mut i32) {
        *x = *x + 1;
    }
    increment(&mut x);
    println!("x: {}", x);
    // testing immutable references
    fn print_twice(x: &i32) {
        println!("first:  {}", x);
        println!("second: {}", x);
    }
    print_twice(&3);
    print_twice(&x);
    /*
    this code does not compile - taking multiple mutable references.
    {
        let y = &mut x;
        let z = &mut x;
    }
    */
    /*
    this code does not compile - taking mutable & immutable references (they form read-write-lock).
    {
        let y = & x;
        let z = &mut x;
    }
    */
}

fn enums() {
    // standard enum.
    enum Color {
        RED,
        GREEN,
        BLACK
    };
    fn categorize_color(c: Color) {
        match c {
            Color::RED => println!("color is red!"),
            Color::GREEN => println!("color is green!"),
            _ =>
                println!("Unknown color.")
        }
    }
    categorize_color(Color::RED);
    categorize_color(Color::GREEN);
    categorize_color(Color::BLACK);
    // pattern matching enum.
    enum Option {
        None,
        Some(i32)
    }
    fn app(o: Option, function: fn(i32) -> i32) -> Option {
        match o {
            Option::None => Option::None,
            Option::Some(x) => Option::Some(function(x))
        }
    }
    fn add_one(x:i32) -> i32 {
        x + 1
    }
    fn print_value(x:i32) -> i32 {
        println!("value: {}", x);
        return 0;
    }
    app(app(Option::Some(10), add_one), print_value);
    app(app(Option::None, add_one), print_value);
}
<|endoftext|>


<commit_before>use error;
use std::io;
use value;

pub struct RawSource<R>(io::Lines<io::BufReader<R>>) where R: io::Read;

pub struct RawSink<W>(io::LineWriter<W>) where W: io::Write;

#[inline]
pub fn source<R>(r: R) -> RawSource<R> where R: io::Read
{
    use std::io::BufRead;
    RawSource(io::BufReader::new(r).lines())
}

#[inline]
pub fn sink<W>(w: W) -> RawSink<W> where W: io::Write
{
    RawSink(io::LineWriter::new(w))
}

impl<R> value::Source for RawSource<R> where R: io::Read
{
    #[inline]
    fn read(&mut self) -> error::Result<Option<value::Value>> {
        match self.0.next() {
            Some(Ok(v)) => Ok(Some(value::Value::String(v))),
            Some(Err(e)) => Err(error::Error::from(e)),
            None => Ok(None),
        }
    }
}

impl<W> value::Sink for RawSink<W> where W: io::Write
{
    #[inline]
    fn write(&mut self, value: value::Value) -> error::Result<()> {
        use std::io::Write;
        match value {
            value::Value::String(s) => {
                self.0.write(s.as_bytes())?;
                self.0.write(b"\n")?;
                Ok(())
            }
            _ => bail!("raw can only output strings")
        }
    }
}
<commit_msg>Improve error message<commit_after>use error;
use std::io;
use value;

pub struct RawSource<R>(io::Lines<io::BufReader<R>>) where R: io::Read;

pub struct RawSink<W>(io::LineWriter<W>) where W: io::Write;

#[inline]
pub fn source<R>(r: R) -> RawSource<R> where R: io::Read
{
    use std::io::BufRead;
    RawSource(io::BufReader::new(r).lines())
}

#[inline]
pub fn sink<W>(w: W) -> RawSink<W> where W: io::Write
{
    RawSink(io::LineWriter::new(w))
}

impl<R> value::Source for RawSource<R> where R: io::Read
{
    #[inline]
    fn read(&mut self) -> error::Result<Option<value::Value>> {
        match self.0.next() {
            Some(Ok(v)) => Ok(Some(value::Value::String(v))),
            Some(Err(e)) => Err(error::Error::from(e)),
            None => Ok(None),
        }
    }
}

impl<W> value::Sink for RawSink<W> where W: io::Write
{
    #[inline]
    fn write(&mut self, value: value::Value) -> error::Result<()> {
        use std::io::Write;
        match value {
            value::Value::String(s) => {
                self.0.write(s.as_bytes())?;
                self.0.write(b"\n")?;
                Ok(())
            }
            x => bail!("raw can only output strings, got: {:?}", x)
        }
    }
}
<|endoftext|>


<commit_before>use bvh::*;
use bounding_hierarchy::BHShape;
use aabb::AABB;
use std::collections::HashSet;

// TODO Consider: Instead of getting the scene's shapes passed, let leaf nodes store an AABB
// that is updated from the outside, perhaps by passing not only the indices of the changed
// shapes, but also their new AABBs into optimize().

impl BVH {
    /// Optimizes the `BVH` by batch-reorganizing updated nodes.
    /// Based on https://github.com/jeske/SimpleScene/blob/master/SimpleScene/Util/ssBVH/ssBVH.cs
    ///
    /// Needs all the scene's shapes, plus the indices of the shapes that were updated.
    ///
    pub fn optimize<Shape: BHShape>(&mut self,
                                    refit_shape_indices: &HashSet<usize>,
                                    shapes: &[Shape]) {
        let mut refit_node_indices: HashSet<usize> = refit_shape_indices.iter()
            .map(|x| shapes[*x].bh_node_index())
            .collect();

        // As long as we have refit nodes left, take the list of refit nodes
        // with the highest depth (sweep nodes) and try to rotate them all
        while refit_node_indices.len() > 0 {
            let mut max_depth = 0;
            let mut sweep_node_indices: Vec<usize> = Vec::new();

            // Find max_depth and sweep_node_indices in one iteration
            for refit_node_index in refit_node_indices.iter() {
                let depth = match self.nodes[*refit_node_index] {
                    BVHNode::Node { depth, .. } => depth,
                    BVHNode::Leaf { depth, .. } => depth,
                    BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
                };

                if depth > max_depth {
                    max_depth = depth;
                    sweep_node_indices.clear();
                    sweep_node_indices.push(*refit_node_index);
                } else if depth == max_depth {
                    sweep_node_indices.push(*refit_node_index);
                }
            }

            // Try to find a useful tree rotation with all nodes previously found
            for sweep_node_index in sweep_node_indices.iter() {
                // This node does not need to be checked again
                refit_node_indices.remove(&sweep_node_index);

                let new_refit_node_index = self.try_rotate(*sweep_node_index, shapes);

                // Instead of finding a useful tree rotation, we found another node
                // that we should check, so we add its index to the refit_node_indices.
                if let Some(index) = new_refit_node_index {
                    refit_node_indices.insert(index);
                }
            }
        }
    }

    /// Checks if there is a way to rotate a child and a grandchild (or two grandchildren) of
    /// the given node (specified by `node_index`) that would improve the `BVH`.
    /// If there is, the best rotation found is performed.
    /// Relies on the children and transitive children of the given node having correct AABBs.
    ///
    /// Returns Some(index_of_node) if a new node was found that should be used for optimization.
    ///
    fn try_rotate<Shape: BHShape>(&mut self, node_index: usize, shapes: &[Shape]) -> Option<usize> {
        let mut nodes = &mut self.nodes;

        let node_clone = nodes[node_index].clone();

        // Contains the surface area that would result from applying the currently favored rotation.
        // The rotation with the smallest SA will be applied in the end.
        // The value is calculated by child_l_aabb.surface_area() + child_r_aabb.surface_area()
        let mut best_surface_area = 0f32;

        // TODO Re-implement without mutability
        let mut parent_index: usize = 0;

        #[derive(Debug, Copy, Clone)]
        struct NodeData {
            index: usize,
            aabb: AABB,
        }

        macro_rules! get_children_node_data {
            ($node_index:expr) => ({
                let node = &nodes[$node_index];
                match *node {
                    BVHNode::Node { child_l, child_r, child_l_aabb, child_r_aabb, .. } => {
                        Some((NodeData{ index: child_l, aabb: child_l_aabb},
                            NodeData{ index: child_r, aabb: child_r_aabb}))
                    }
                    BVHNode::Leaf { .. } => {
                        None
                    }
                    BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
                }
            });
        }

        macro_rules! get_child_aabb {
            ($node_index:expr) => ({
                let node = &nodes[$node_index];
                match *node {
                    BVHNode::Node { child_l_aabb, child_r_aabb, .. } => {
                        child_l_aabb.join(&child_r_aabb)
                    }
                    BVHNode::Leaf { shape, .. } => {
                        shapes[shape].aabb()
                    }
                    BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
                }
            });
        }

        // If this node is not a grandparent, update the AABB,
        // queue the parent for refitting, and bail out.
        // If it is a grandparent, calculate the current best_surface_area.
        let (child_l, child_r) = match node_clone {
            BVHNode::Node { parent, child_l, child_r, child_l_aabb, child_r_aabb, .. } => {
                if let BVHNode::Leaf { shape, .. } = nodes[child_l] {
                    let shape_l_index = shape;
                    if let BVHNode::Leaf { shape, .. } = nodes[child_r] {
                        let shape_r_index = shape;

                        // Update the AABBs saved for the children
                        // since at least one of them changed.
                        let mut node = &mut nodes[node_index];
                        match node {
                            &mut BVHNode::Node { ref mut child_l_aabb,
                                                 ref mut child_r_aabb,
                                                 .. } => {
                                *child_l_aabb = shapes[shape_l_index].aabb();
                                *child_r_aabb = shapes[shape_r_index].aabb();
                            }
                            _ => unreachable!(),
                        }

                        return Some(parent);
                    }
                }

                // Recalculate AABBs for the children since at least one of them changed.
                // Don't update the AABBs yet because they're still subject to change
                // during potential upcoming rotations.
                let aabb_l = get_child_aabb!(child_l);
                let aabb_r = get_child_aabb!(child_r);

                parent_index = parent;
                best_surface_area = child_l_aabb.surface_area() + child_r_aabb.surface_area();
                (NodeData {
                     index: child_l,
                     aabb: aabb_l,
                 },
                 NodeData {
                     index: child_r,
                     aabb: aabb_r,
                 })
            }
            BVHNode::Leaf { parent, .. } => {
                return Some(parent);
            }
            BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
        };

        // Stores the Rotation that would result in the surface area best_surface_area,
        // thus being the favored rotation that will be executed after considering all rotations.
        let mut best_rotation: Option<(usize, usize)> = None;

        macro_rules! consider_rotation {
            ($a:expr, $b:expr, $sa:expr) => {
                if $sa < best_surface_area {
                    best_surface_area = $sa;
                    best_rotation = Some(($a.index, $b.index));
                }
            };
        }

        // Get indices and AABBs of all grandchildren
        let left_children_nodes = {
            let node_data: NodeData = child_l;
            let index = node_data.index;
            get_children_node_data!(index)
        };
        let right_children_nodes = {
            let node_data: NodeData = child_r;
            let index = node_data.index;
            get_children_node_data!(index)
        };

        // Child to grandchild rotations
        if let Some((child_rl, child_rr)) = right_children_nodes {
            consider_rotation!(child_l,
                               child_rl,
                               child_rl.aabb.surface_area() +
                               child_l.aabb.join(&child_rr.aabb).surface_area());
            consider_rotation!(child_l,
                               child_rr,
                               child_rr.aabb.surface_area() +
                               child_l.aabb.join(&child_rl.aabb).surface_area());
        }
        if let Some((child_ll, child_lr)) = left_children_nodes {
            consider_rotation!(child_r,
                               child_ll,
                               child_ll.aabb.surface_area() +
                               child_r.aabb.join(&child_lr.aabb).surface_area());
            consider_rotation!(child_r,
                               child_lr,
                               child_lr.aabb.surface_area() +
                               child_r.aabb.join(&child_ll.aabb).surface_area());

            // Grandchild to grandchild rotations
            if let Some((child_rl, child_rr)) = right_children_nodes {
                consider_rotation!(child_ll,
                                   child_rl,
                                   child_rl.aabb.join(&child_lr.aabb).surface_area() +
                                   child_ll.aabb.join(&child_rr.aabb).surface_area());
                consider_rotation!(child_ll,
                                   child_rr,
                                   child_ll.aabb.join(&child_rl.aabb).surface_area() +
                                   child_lr.aabb.join(&child_rr.aabb).surface_area());
            }
        }

        let new_refit_node_index = if parent_index > 0 {
            Some(parent_index)
        } else {
            None
        };

        if let Some(rotation) = best_rotation {
            BVH::rotate(nodes, rotation.0, rotation.1);

            // TODO Update all changed node AABBs

            // Return parent node's index for upcoming refitting,
            // since this node just changed its AABB
            new_refit_node_index
        } else {
            // Update this node's AABBs (child_l_aabb, child_r_aabb)
            // according to the children nodes' AABBs.
            let mut node = &mut nodes[node_index];
            match node {
                &mut BVHNode::Node { ref mut child_l_aabb, ref mut child_r_aabb, .. } => {
                    *child_l_aabb = child_l.aabb;
                    *child_r_aabb = child_r.aabb;
                }
                _ => unreachable!(),
            }

            // Even with no rotation being useful for this node, a parent node's rotation
            // could be beneficial, so queue the parent sometimes.
            // TODO Return None most of the time, randomly
            // (see https://github.com/jeske/SimpleScene/blob/master/SimpleScene/Util/ssBVH/ssBVH_Node.cs#L307)
            new_refit_node_index
        }
    }

    /// Switch two nodes by rewiring the involved indices (not by moving them in the nodes slice).
    fn rotate(nodes: &mut Vec<BVHNode>, node_a_index: usize, node_b_index: usize) {
        // This function is not defined with a self parameter to make it easier to call
        // without running into borrow checker issues.
        macro_rules! should_not_happen {
            () => ( panic!("While rotating BVH nodes, something unexpected happened."); );
            ($s:expr) => ( panic!("While rotating BVH nodes, something unexpected happened: {}", $s); );
        }

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn get_parent_index(nodes: &Vec<BVHNode>, node_index: usize) -> usize {
            let node = &nodes[node_index];

            match *node {
                BVHNode::Node { parent, .. } |
                BVHNode::Leaf { parent, .. } => parent,
                _ => should_not_happen!(),
            }
        }

        // Get parent indices
        let node_a_parent_index = get_parent_index(nodes, node_a_index);
        let node_b_parent_index = get_parent_index(nodes, node_b_index);

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn get_is_left_child(nodes: &Vec<BVHNode>,
                             node_index: usize,
                             node_parent_index: usize)
                             -> bool {
            let node_parent = &nodes[node_parent_index];

            match *node_parent {
                BVHNode::Node { child_l, .. } => child_l == node_index,
                _ => should_not_happen!(),
            }
        }

        // Get info about the nodes being a left or right child
        let node_a_is_left_child = get_is_left_child(nodes, node_a_index, node_a_parent_index);
        let node_b_is_left_child = get_is_left_child(nodes, node_b_index, node_b_parent_index);

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn connect_nodes(nodes: &mut Vec<BVHNode>,
                         child_index: usize,
                         parent_index: usize,
                         left_child: bool) {
            // Set parent's child and get its depth
            let parent_depth = {
                let mut parent = &mut nodes[parent_index];
                match parent {
                    &mut BVHNode::Node { ref mut child_l, ref mut child_r, depth, .. } => {
                        if left_child {
                            *child_l = child_index;
                        } else {
                            *child_r = child_index;
                        }
                        depth
                    }
                    _ => should_not_happen!(),
                }
            };

            // Set child's parent and depth
            {
                let mut child = &mut nodes[child_index];
                match child {
                    &mut BVHNode::Node { ref mut parent, ref mut depth, .. } |
                    &mut BVHNode::Leaf { ref mut parent, ref mut depth, .. } => {
                        *parent = parent_index;
                        *depth = parent_depth + 1;
                    }
                    _ => should_not_happen!(),
                };
            }
        }

        // Perform the switch
        connect_nodes(nodes,
                      node_a_index,
                      node_b_parent_index,
                      node_b_is_left_child);
        connect_nodes(nodes,
                      node_b_index,
                      node_a_parent_index,
                      node_a_is_left_child);
    }
}

#[cfg(test)]
pub mod tests {
    use bvh::BVH;
    use std::collections::HashSet;
    use testbase::build_some_bh;

    #[test]
    /// Tests if the optimize function tries to change a fresh BVH even though it shouldn't
    fn test_optimizing_new_bvh() {
        let (mut shapes, mut bvh) = build_some_bh::<BVH>();

        let refit_shape_indices: HashSet<usize> = (0..shapes.len()).collect();
        bvh.optimize(&refit_shape_indices, &mut shapes);
    }

    // TODO Add tests for:
    // * correct parent
    // * correct depth
    // * correct BVH after optimizing
    // * correct parent and depth after optimizing
}
<commit_msg>Add minor fixes and Todo<commit_after>use bvh::*;
use bounding_hierarchy::BHShape;
use aabb::AABB;
use std::collections::HashSet;

// TODO Consider: Instead of getting the scene's shapes passed, let leaf nodes store an AABB
// that is updated from the outside, perhaps by passing not only the indices of the changed
// shapes, but also their new AABBs into optimize().

impl BVH {
    /// Optimizes the `BVH` by batch-reorganizing updated nodes.
    /// Based on https://github.com/jeske/SimpleScene/blob/master/SimpleScene/Util/ssBVH/ssBVH.cs
    ///
    /// Needs all the scene's shapes, plus the indices of the shapes that were updated.
    ///
    pub fn optimize<Shape: BHShape>(&mut self,
                                    refit_shape_indices: &HashSet<usize>,
                                    shapes: &[Shape]) {
        let mut refit_node_indices: HashSet<usize> = refit_shape_indices.iter()
            .map(|x| shapes[*x].bh_node_index())
            .collect();

        // As long as we have refit nodes left, take the list of refit nodes
        // with the highest depth (sweep nodes) and try to rotate them all
        while refit_node_indices.len() > 0 {
            let mut max_depth = 0;
            let mut sweep_node_indices: Vec<usize> = Vec::new();

            // Find max_depth and sweep_node_indices in one iteration
            for refit_node_index in refit_node_indices.iter() {
                let depth = match self.nodes[*refit_node_index] {
                    BVHNode::Node { depth, .. } => depth,
                    BVHNode::Leaf { depth, .. } => depth,
                    BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
                };

                if depth > max_depth {
                    max_depth = depth;
                    sweep_node_indices.clear();
                    sweep_node_indices.push(*refit_node_index);
                } else if depth == max_depth {
                    sweep_node_indices.push(*refit_node_index);
                }
            }

            // Try to find a useful tree rotation with all nodes previously found
            for sweep_node_index in sweep_node_indices.iter() {
                // This node does not need to be checked again
                refit_node_indices.remove(&sweep_node_index);

                // TODO There might be multithreading potential here
                let new_refit_node_index = self.try_rotate(*sweep_node_index, shapes);

                // Instead of finding a useful tree rotation, we found another node
                // that we should check, so we add its index to the refit_node_indices.
                if let Some(index) = new_refit_node_index {
                    refit_node_indices.insert(index);
                }
            }
        }
    }

    /// Checks if there is a way to rotate a child and a grandchild (or two grandchildren) of
    /// the given node (specified by `node_index`) that would improve the `BVH`.
    /// If there is, the best rotation found is performed.
    /// Relies on the children and transitive children of the given node having correct AABBs.
    ///
    /// Returns Some(index_of_node) if a new node was found that should be used for optimization.
    ///
    fn try_rotate<Shape: BHShape>(&mut self, node_index: usize, shapes: &[Shape]) -> Option<usize> {
        let mut nodes = &mut self.nodes;

        let node_clone = nodes[node_index].clone();

        // Contains the surface area that would result from applying the currently favored rotation.
        // The rotation with the smallest SA will be applied in the end.
        // The value is calculated by child_l_aabb.surface_area() + child_r_aabb.surface_area()
        let mut best_surface_area = 0f32;

        // TODO Re-implement without mutability
        let mut parent_index: usize = 0;

        #[derive(Debug, Copy, Clone)]
        struct NodeData {
            index: usize,
            aabb: AABB,
        }

        macro_rules! get_children_node_data {
            ($node_index:expr) => ({
                let node = nodes[$node_index].clone();
                match node {
                    BVHNode::Node { child_l, child_r, child_l_aabb, child_r_aabb, .. } => {
                        Some((NodeData{ index: child_l, aabb: child_l_aabb },
                            NodeData{ index: child_r, aabb: child_r_aabb }))
                    }
                    BVHNode::Leaf { .. } => {
                        None
                    }
                    BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
                }
            });
        }

        macro_rules! get_node_aabb {
            ($node_index:expr) => ({
                let node = &nodes[$node_index];
                match *node {
                    BVHNode::Node { child_l_aabb, child_r_aabb, .. } => {
                        child_l_aabb.join(&child_r_aabb)
                    }
                    BVHNode::Leaf { shape, .. } => {
                        shapes[shape].aabb()
                    }
                    BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
                }
            });
        }

        // If this node is not a grandparent, update the AABB,
        // queue the parent for refitting, and bail out.
        // If it is a grandparent, calculate the current best_surface_area.
        let (child_l, child_r) = match node_clone {
            BVHNode::Node { parent, child_l, child_r, child_l_aabb, child_r_aabb, .. } => {
                if let BVHNode::Leaf { shape, .. } = nodes[child_l] {
                    let shape_l_index = shape;
                    if let BVHNode::Leaf { shape, .. } = nodes[child_r] {
                        let shape_r_index = shape;

                        // Update the AABBs saved for the children
                        // since at least one of them changed.
                        let mut node = &mut nodes[node_index];
                        match node {
                            &mut BVHNode::Node { ref mut child_l_aabb,
                                                 ref mut child_r_aabb,
                                                 .. } => {
                                *child_l_aabb = shapes[shape_l_index].aabb();
                                *child_r_aabb = shapes[shape_r_index].aabb();
                            }
                            _ => unreachable!(),
                        }

                        return Some(parent);
                    }
                }

                // Recalculate AABBs for the children since at least one of them changed.
                // Don't update the AABBs yet because they're still subject to change
                // during potential upcoming rotations.
                let aabb_l = get_node_aabb!(child_l);
                let aabb_r = get_node_aabb!(child_r);

                parent_index = parent;
                best_surface_area = child_l_aabb.surface_area() + child_r_aabb.surface_area();
                (NodeData {
                     index: child_l,
                     aabb: aabb_l,
                 },
                 NodeData {
                     index: child_r,
                     aabb: aabb_r,
                 })
            }
            BVHNode::Leaf { parent, .. } => {
                return Some(parent);
            }
            BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
        };

        // Stores the Rotation that would result in the surface area best_surface_area,
        // thus being the favored rotation that will be executed after considering all rotations.
        let mut best_rotation: Option<(usize, usize)> = None;

        macro_rules! consider_rotation {
            ($a:expr, $b:expr, $sa:expr) => {
                if $sa < best_surface_area {
                    best_surface_area = $sa;
                    best_rotation = Some(($a.index, $b.index));
                }
            };
        }

        // Get indices and AABBs of all grandchildren
        let left_children_nodes = {
            let node_data: NodeData = child_l;
            let index = node_data.index;
            get_children_node_data!(index)
        };
        let right_children_nodes = {
            let node_data: NodeData = child_r;
            let index = node_data.index;
            get_children_node_data!(index)
        };

        // Child to grandchild rotations
        if let Some((child_rl, child_rr)) = right_children_nodes {
            consider_rotation!(child_l,
                               child_rl,
                               child_rl.aabb.surface_area() +
                               child_l.aabb.join(&child_rr.aabb).surface_area());
            consider_rotation!(child_l,
                               child_rr,
                               child_rr.aabb.surface_area() +
                               child_l.aabb.join(&child_rl.aabb).surface_area());
        }
        if let Some((child_ll, child_lr)) = left_children_nodes {
            consider_rotation!(child_r,
                               child_ll,
                               child_ll.aabb.surface_area() +
                               child_r.aabb.join(&child_lr.aabb).surface_area());
            consider_rotation!(child_r,
                               child_lr,
                               child_lr.aabb.surface_area() +
                               child_r.aabb.join(&child_ll.aabb).surface_area());

            // Grandchild to grandchild rotations
            if let Some((child_rl, child_rr)) = right_children_nodes {
                consider_rotation!(child_ll,
                                   child_rl,
                                   child_rl.aabb.join(&child_lr.aabb).surface_area() +
                                   child_ll.aabb.join(&child_rr.aabb).surface_area());
                consider_rotation!(child_ll,
                                   child_rr,
                                   child_ll.aabb.join(&child_rl.aabb).surface_area() +
                                   child_lr.aabb.join(&child_rr.aabb).surface_area());
            }
        }

        let new_refit_node_index = if parent_index > 0 {
            Some(parent_index)
        } else {
            None
        };

        if let Some(rotation) = best_rotation {
            BVH::rotate(nodes, rotation.0, rotation.1);

            // TODO Update all changed node AABBs

            // Return parent node's index for upcoming refitting,
            // since this node just changed its AABB
            new_refit_node_index
        } else {
            // Update this node's AABBs (child_l_aabb, child_r_aabb)
            // according to the children nodes' AABBs.
            let mut node = &mut nodes[node_index];
            match node {
                &mut BVHNode::Node { ref mut child_l_aabb, ref mut child_r_aabb, .. } => {
                    *child_l_aabb = child_l.aabb;
                    *child_r_aabb = child_r.aabb;
                }
                _ => unreachable!(),
            }

            // Even with no rotation being useful for this node, a parent node's rotation
            // could be beneficial, so queue the parent sometimes.
            // TODO Return None most of the time, randomly
            // (see https://github.com/jeske/SimpleScene/blob/master/SimpleScene/Util/ssBVH/ssBVH_Node.cs#L307)
            new_refit_node_index
        }
    }

    /// Switch two nodes by rewiring the involved indices (not by moving them in the nodes slice).
    fn rotate(nodes: &mut Vec<BVHNode>, node_a_index: usize, node_b_index: usize) {
        // This function is not defined with a self parameter to make it easier to call
        // without running into borrow checker issues.
        macro_rules! should_not_happen {
            () => ( panic!("While rotating BVH nodes, something unexpected happened."); );
            ($s:expr) => ( panic!("While rotating BVH nodes, something unexpected happened: {}", $s); );
        }

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn get_parent_index(nodes: &Vec<BVHNode>, node_index: usize) -> usize {
            let node = &nodes[node_index];

            match *node {
                BVHNode::Node { parent, .. } |
                BVHNode::Leaf { parent, .. } => parent,
                _ => should_not_happen!(),
            }
        }

        // Get parent indices
        let node_a_parent_index = get_parent_index(nodes, node_a_index);
        let node_b_parent_index = get_parent_index(nodes, node_b_index);

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn get_is_left_child(nodes: &Vec<BVHNode>,
                             node_index: usize,
                             node_parent_index: usize)
                             -> bool {
            let node_parent = &nodes[node_parent_index];

            match *node_parent {
                BVHNode::Node { child_l, .. } => child_l == node_index,
                _ => should_not_happen!(),
            }
        }

        // Get info about the nodes being a left or right child
        let node_a_is_left_child = get_is_left_child(nodes, node_a_index, node_a_parent_index);
        let node_b_is_left_child = get_is_left_child(nodes, node_b_index, node_b_parent_index);

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn connect_nodes(nodes: &mut Vec<BVHNode>,
                         child_index: usize,
                         parent_index: usize,
                         left_child: bool) {
            // Set parent's child and get its depth
            let parent_depth = {
                let mut parent = &mut nodes[parent_index];
                match parent {
                    &mut BVHNode::Node { ref mut child_l, ref mut child_r, depth, .. } => {
                        if left_child {
                            *child_l = child_index;
                        } else {
                            *child_r = child_index;
                        }
                        depth
                    }
                    _ => should_not_happen!(),
                }
            };

            // Set child's parent and depth
            {
                let mut child = &mut nodes[child_index];
                match child {
                    &mut BVHNode::Node { ref mut parent, ref mut depth, .. } |
                    &mut BVHNode::Leaf { ref mut parent, ref mut depth, .. } => {
                        *parent = parent_index;
                        *depth = parent_depth + 1;
                    }
                    _ => should_not_happen!(),
                };
            }
        }

        // Perform the switch
        connect_nodes(nodes,
                      node_a_index,
                      node_b_parent_index,
                      node_b_is_left_child);
        connect_nodes(nodes,
                      node_b_index,
                      node_a_parent_index,
                      node_a_is_left_child);
    }
}

#[cfg(test)]
pub mod tests {
    use bvh::BVH;
    use std::collections::HashSet;
    use testbase::build_some_bh;

    #[test]
    /// Tests if the optimize function tries to change a fresh BVH even though it shouldn't
    fn test_optimizing_new_bvh() {
        let (mut shapes, mut bvh) = build_some_bh::<BVH>();

        let refit_shape_indices: HashSet<usize> = (0..shapes.len()).collect();
        bvh.optimize(&refit_shape_indices, &mut shapes);
    }

    // TODO Add tests for:
    // * correct parent
    // * correct depth
    // * correct BVH after optimizing
    // * correct parent and depth after optimizing
}
<|endoftext|>


<commit_before>pub use self::imp::read2;

#[cfg(unix)]
mod imp {
    use std::cmp;
    use std::io::prelude::*;
    use std::io;
    use std::mem;
    use std::os::unix::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use libc;

    pub fn read2(mut out_pipe: ChildStdout,
                 mut err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        unsafe {
            libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
        }

        let mut out_done = false;
        let mut err_done = false;
        let mut out = Vec::new();
        let mut err = Vec::new();

        let max = cmp::max(out_pipe.as_raw_fd(), err_pipe.as_raw_fd());
        loop {
            // wait for either pipe to become readable using `select`
            let r = unsafe {
                let mut read: libc::fd_set = mem::zeroed();
                if !out_done {
                    libc::FD_SET(out_pipe.as_raw_fd(), &mut read);
                }
                if !err_done {
                    libc::FD_SET(err_pipe.as_raw_fd(), &mut read);
                }
                libc::select(max + 1, &mut read, 0 as *mut _, 0 as *mut _,
                             0 as *mut _)
            };
            if r == -1 {
                let err = io::Error::last_os_error();
                if err.kind() == io::ErrorKind::Interrupted {
                    continue
                }
                return Err(err)
            }

            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
            // EAGAIN. If we hit EOF, then this will happen because the underlying
            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
            // this case we flip the other fd back into blocking mode and read
            // whatever's leftover on that file descriptor.
            let handle = |res: io::Result<_>| {
                match res {
                    Ok(_) => Ok(true),
                    Err(e) => {
                        if e.kind() == io::ErrorKind::WouldBlock {
                            Ok(false)
                        } else {
                            Err(e)
                        }
                    }
                }
            };
            if !out_done && handle(out_pipe.read_to_end(&mut out))? {
                out_done = true;
            }
            data(true, &mut out, out_done);
            if !err_done && handle(err_pipe.read_to_end(&mut err))? {
                err_done = true;
            }
            data(false, &mut err, err_done);

            if out_done && err_done {
                return Ok(())
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate miow;
    extern crate winapi;

    use std::io;
    use std::os::windows::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use std::slice;

    use self::miow::iocp::{CompletionPort, CompletionStatus};
    use self::miow::pipe::NamedPipe;
    use self::miow::Overlapped;
    use self::winapi::ERROR_BROKEN_PIPE;

    struct Pipe<'a> {
        dst: &'a mut Vec<u8>,
        overlapped: Overlapped,
        pipe: NamedPipe,
        done: bool,
    }

    pub fn read2(out_pipe: ChildStdout,
                 err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        let mut out = Vec::new();
        let mut err = Vec::new();

        let port = CompletionPort::new(1)?;
        port.add_handle(0, &out_pipe)?;
        port.add_handle(1, &err_pipe)?;

        unsafe {
            let mut out_pipe = Pipe::new(out_pipe, &mut out);
            let mut err_pipe = Pipe::new(err_pipe, &mut err);

            out_pipe.read()?;
            err_pipe.read()?;

            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];

            while !out_pipe.done || !err_pipe.done {
                for status in port.get_many(&mut status, None)? {
                    if status.token() == 0 {
                        out_pipe.complete(status);
                        data(true, out_pipe.dst, out_pipe.done);
                        out_pipe.read()?;
                    } else {
                        err_pipe.complete(status);
                        data(false, err_pipe.dst, err_pipe.done);
                        err_pipe.read()?;
                    }
                }
            }

            Ok(())
        }
    }

    impl<'a> Pipe<'a> {
        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
            Pipe {
                dst: dst,
                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
                overlapped: Overlapped::zero(),
                done: false,
            }
        }

        unsafe fn read(&mut self) -> io::Result<()> {
            let dst = slice_to_end(self.dst);
            match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
                        self.done = true;
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        unsafe fn complete(&mut self, status: &CompletionStatus) {
            let prev = self.dst.len();
            self.dst.set_len(prev + status.bytes_transferred() as usize);
            if status.bytes_transferred() == 0 {
                self.done = true;
            }
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}
<commit_msg>Use poll instead of select to handle large fds<commit_after>pub use self::imp::read2;

#[cfg(unix)]
mod imp {
    use std::io::prelude::*;
    use std::io;
    use std::mem;
    use std::os::unix::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use libc;

    pub fn read2(mut out_pipe: ChildStdout,
                 mut err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        unsafe {
            libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
            libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK);
        }

        let mut out_done = false;
        let mut err_done = false;
        let mut out = Vec::new();
        let mut err = Vec::new();

        let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
        fds[0].fd = out_pipe.as_raw_fd();
        fds[0].events = libc::POLLIN;
        fds[1].fd = err_pipe.as_raw_fd();
        fds[1].events = libc::POLLIN;
        loop {
            // wait for either pipe to become readable using `select`
            let r = unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) };
            if r == -1 {
                let err = io::Error::last_os_error();
                if err.kind() == io::ErrorKind::Interrupted {
                    continue
                }
                return Err(err)
            }

            // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
            // EAGAIN. If we hit EOF, then this will happen because the underlying
            // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
            // this case we flip the other fd back into blocking mode and read
            // whatever's leftover on that file descriptor.
            let handle = |res: io::Result<_>| {
                match res {
                    Ok(_) => Ok(true),
                    Err(e) => {
                        if e.kind() == io::ErrorKind::WouldBlock {
                            Ok(false)
                        } else {
                            Err(e)
                        }
                    }
                }
            };
            if !out_done && fds[0].revents != 0 && handle(out_pipe.read_to_end(&mut out))? {
                out_done = true;
            }
            data(true, &mut out, out_done);
            if !err_done && fds[1].revents != 0 && handle(err_pipe.read_to_end(&mut err))? {
                err_done = true;
            }
            data(false, &mut err, err_done);

            if out_done && err_done {
                return Ok(())
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate miow;
    extern crate winapi;

    use std::io;
    use std::os::windows::prelude::*;
    use std::process::{ChildStdout, ChildStderr};
    use std::slice;

    use self::miow::iocp::{CompletionPort, CompletionStatus};
    use self::miow::pipe::NamedPipe;
    use self::miow::Overlapped;
    use self::winapi::ERROR_BROKEN_PIPE;

    struct Pipe<'a> {
        dst: &'a mut Vec<u8>,
        overlapped: Overlapped,
        pipe: NamedPipe,
        done: bool,
    }

    pub fn read2(out_pipe: ChildStdout,
                 err_pipe: ChildStderr,
                 data: &mut FnMut(bool, &mut Vec<u8>, bool)) -> io::Result<()> {
        let mut out = Vec::new();
        let mut err = Vec::new();

        let port = CompletionPort::new(1)?;
        port.add_handle(0, &out_pipe)?;
        port.add_handle(1, &err_pipe)?;

        unsafe {
            let mut out_pipe = Pipe::new(out_pipe, &mut out);
            let mut err_pipe = Pipe::new(err_pipe, &mut err);

            out_pipe.read()?;
            err_pipe.read()?;

            let mut status = [CompletionStatus::zero(), CompletionStatus::zero()];

            while !out_pipe.done || !err_pipe.done {
                for status in port.get_many(&mut status, None)? {
                    if status.token() == 0 {
                        out_pipe.complete(status);
                        data(true, out_pipe.dst, out_pipe.done);
                        out_pipe.read()?;
                    } else {
                        err_pipe.complete(status);
                        data(false, err_pipe.dst, err_pipe.done);
                        err_pipe.read()?;
                    }
                }
            }

            Ok(())
        }
    }

    impl<'a> Pipe<'a> {
        unsafe fn new<P: IntoRawHandle>(p: P, dst: &'a mut Vec<u8>) -> Pipe<'a> {
            Pipe {
                dst: dst,
                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
                overlapped: Overlapped::zero(),
                done: false,
            }
        }

        unsafe fn read(&mut self) -> io::Result<()> {
            let dst = slice_to_end(self.dst);
            match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
                Ok(_) => Ok(()),
                Err(e) => {
                    if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
                        self.done = true;
                        Ok(())
                    } else {
                        Err(e)
                    }
                }
            }
        }

        unsafe fn complete(&mut self, status: &CompletionStatus) {
            let prev = self.dst.len();
            self.dst.set_len(prev + status.bytes_transferred() as usize);
            if status.bytes_transferred() == 0 {
                self.done = true;
            }
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}
<|endoftext|>