<commit_before>use std::io::{Read, Write};
use std::mem;
use std::net::Shutdown;
use std::os::unix::prelude::*;
use std::path::Path;

use libc;

use {io, Evented, Ready, Poll, PollOpt, Token};
use sys::unix::{cvt, Io};
use sys::unix::io::{set_nonblock, set_cloexec};

trait MyInto<T> {
    fn my_into(self) -> T;
}

impl MyInto<u32> for usize {
    fn my_into(self) -> u32 { self as u32 }
}

impl MyInto<usize> for usize {
    fn my_into(self) -> usize { self }
}

unsafe fn sockaddr_un(path: &Path)
                      -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
    let mut addr: libc::sockaddr_un = mem::zeroed();
    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;

    let bytes = path.as_os_str().as_bytes();

    if bytes.len() >= addr.sun_path.len() {
        return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                  "path must be shorter than SUN_LEN"))
    }
    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
        *dst = *src as libc::c_char;
    }
    // null byte for pathname addresses is already there because we zeroed the
    // struct

    let mut len = sun_path_offset() + bytes.len();
    match bytes.get(0) {
        Some(&0) | None => {}
        Some(_) => len += 1,
    }
    Ok((addr, len as libc::socklen_t))
}

fn sun_path_offset() -> usize {
    unsafe {
        // Work with an actual instance of the type since using a null pointer is UB
        let addr: libc::sockaddr_un = mem::uninitialized();
        let base = &addr as *const _ as usize;
        let path = &addr.sun_path as *const _ as usize;
        path - base
    }
}

#[derive(Debug)]
pub struct UnixSocket {
    io: Io,
}

impl UnixSocket {
    /// Returns a new, unbound, non-blocking Unix domain socket
    pub fn stream() -> io::Result<UnixSocket> {
        #[cfg(target_os = "linux")]
        use libc::{SOCK_CLOEXEC, SOCK_NONBLOCK};
        #[cfg(not(target_os = "linux"))]
        const SOCK_CLOEXEC: libc::c_int = 0;
        #[cfg(not(target_os = "linux"))]
        const SOCK_NONBLOCK: libc::c_int = 0;

        unsafe {
            if cfg!(target_os = "linux") {
                let flags = libc::SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK;
                match cvt(libc::socket(libc::AF_UNIX, flags, 0)) {
                    Ok(fd) => return Ok(UnixSocket::from_raw_fd(fd)),
                    Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
                    Err(e) => return Err(e),
                }
            }

            let fd = try!(cvt(libc::socket(libc::AF_UNIX, libc::SOCK_STREAM, 0)));
            let fd = UnixSocket::from_raw_fd(fd);
            try!(set_cloexec(fd.as_raw_fd()));
            try!(set_nonblock(fd.as_raw_fd()));
            Ok(fd)
        }
    }

    /// Connect the socket to the specified address
    pub fn connect<P: AsRef<Path> + ?Sized>(&self, addr: &P) -> io::Result<()> {
        unsafe {
            let (addr, len) = try!(sockaddr_un(addr.as_ref()));
            try!(cvt(libc::connect(self.as_raw_fd(),
                                   &addr as *const _ as *const _,
                                   len)));
            Ok(())
        }
    }

    /// Listen for incoming requests
    pub fn listen(&self, backlog: usize) -> io::Result<()> {
        unsafe {
            try!(cvt(libc::listen(self.as_raw_fd(), backlog as i32)));
            Ok(())
        }
    }

    pub fn accept(&self) -> io::Result<UnixSocket> {
        unsafe {
            let fd = try!(cvt(libc::accept(self.as_raw_fd(),
                                           0 as *mut _,
                                           0 as *mut _)));
            let fd = Io::from_raw_fd(fd);
            try!(set_cloexec(fd.as_raw_fd()));
            try!(set_nonblock(fd.as_raw_fd()));
            Ok(UnixSocket { io: fd })
        }
    }

    /// Bind the socket to the specified address
    pub fn bind<P: AsRef<Path> + ?Sized>(&self, addr: &P) -> io::Result<()> {
        unsafe {
            let (addr, len) = try!(sockaddr_un(addr.as_ref()));
            try!(cvt(libc::bind(self.as_raw_fd(),
                                &addr as *const _ as *const _,
                                len)));
            Ok(())
        }
    }

    pub fn try_clone(&self) -> io::Result<UnixSocket> {
        Ok(UnixSocket { io: try!(self.io.try_clone()) })
    }

    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        let how = match how {
            Shutdown::Read => libc::SHUT_RD,
            Shutdown::Write => libc::SHUT_WR,
            Shutdown::Both => libc::SHUT_RDWR,
        };
        unsafe {
            try!(cvt(libc::shutdown(self.as_raw_fd(), how)));
            Ok(())
        }
    }

    pub fn read_recv_fd(&mut self, buf: &mut [u8]) -> io::Result<(usize, Option<RawFd>)> {
        unsafe {
            let mut iov = libc::iovec {
                iov_base: buf.as_mut_ptr() as *mut _,
                iov_len: buf.len(),
            };
            struct Cmsg {
                hdr: libc::cmsghdr,
                data: [libc::c_int; 1],
            }
            let mut cmsg: Cmsg = mem::zeroed();
            let mut msg = libc::msghdr {
                msg_name: 0 as *mut _,
                msg_namelen: 0,
                msg_iov: &mut iov,
                msg_iovlen: 1,
                msg_control: &mut cmsg as *mut _ as *mut _,
                msg_controllen: mem::size_of_val(&cmsg).my_into(),
                msg_flags: 0,
            };
            let bytes = try!(cvt(libc::recvmsg(self.as_raw_fd(), &mut msg, 0)));

            const SCM_RIGHTS: libc::c_int = 1;

            let fd = if cmsg.hdr.cmsg_level == libc::SOL_SOCKET &&
                        cmsg.hdr.cmsg_type == SCM_RIGHTS {
                Some(cmsg.data[0])
            } else {
                None
            };
            Ok((bytes as usize, fd))
        }
    }

    pub fn write_send_fd(&mut self, buf: &[u8], fd: RawFd) -> io::Result<usize> {
        unsafe {
            let mut iov = libc::iovec {
                iov_base: buf.as_ptr() as *mut _,
                iov_len: buf.len(),
            };
            struct Cmsg {
                hdr: libc::cmsghdr,
                data: [libc::c_int; 1],
            }
            let mut cmsg: Cmsg = mem::zeroed();
            cmsg.hdr.cmsg_len = mem::size_of_val(&cmsg).my_into();
            cmsg.hdr.cmsg_level = libc::SOL_SOCKET;
            cmsg.hdr.cmsg_type = 1; // SCM_RIGHTS
            cmsg.data[0] = fd;
            let msg = libc::msghdr {
                msg_name: 0 as *mut _,
                msg_namelen: 0,
                msg_iov: &mut iov,
                msg_iovlen: 1,
                msg_control: &mut cmsg as *mut _ as *mut _,
                msg_controllen: mem::size_of_val(&cmsg).my_into(),
                msg_flags: 0,
            };
            let bytes = try!(cvt(libc::sendmsg(self.as_raw_fd(), &msg, 0)));
            Ok(bytes as usize)
        }
    }
}

impl Read for UnixSocket {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.io.read(buf)
    }
}

impl Write for UnixSocket {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.io.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }
}

impl Evented for UnixSocket {
    fn register(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        self.io.register(poll, token, interest, opts)
    }

    fn reregister(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        self.io.reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &Poll) -> io::Result<()> {
        self.io.deregister(poll)
    }
}

impl From<Io> for UnixSocket {
    fn from(io: Io) -> UnixSocket {
        UnixSocket { io: io }
    }
}

impl FromRawFd for UnixSocket {
    unsafe fn from_raw_fd(fd: RawFd) -> UnixSocket {
        UnixSocket { io: Io::from_raw_fd(fd) }
    }
}

impl IntoRawFd for UnixSocket {
    fn into_raw_fd(self) -> RawFd {
        self.io.into_raw_fd()
    }
}

impl AsRawFd for UnixSocket {
    fn as_raw_fd(&self) -> RawFd {
        self.io.as_raw_fd()
    }
}
<commit_msg>Fix compile on musl<commit_after>use std::io::{Read, Write};
use std::mem;
use std::net::Shutdown;
use std::os::unix::prelude::*;
use std::path::Path;

use libc;

use {io, Evented, Ready, Poll, PollOpt, Token};
use sys::unix::{cvt, Io};
use sys::unix::io::{set_nonblock, set_cloexec};

trait MyInto<T> {
    fn my_into(self) -> T;
}

impl MyInto<u32> for usize {
    fn my_into(self) -> u32 { self as u32 }
}

impl MyInto<usize> for usize {
    fn my_into(self) -> usize { self }
}

unsafe fn sockaddr_un(path: &Path)
                      -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
    let mut addr: libc::sockaddr_un = mem::zeroed();
    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;

    let bytes = path.as_os_str().as_bytes();

    if bytes.len() >= addr.sun_path.len() {
        return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                  "path must be shorter than SUN_LEN"))
    }
    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
        *dst = *src as libc::c_char;
    }
    // null byte for pathname addresses is already there because we zeroed the
    // struct

    let mut len = sun_path_offset() + bytes.len();
    match bytes.get(0) {
        Some(&0) | None => {}
        Some(_) => len += 1,
    }
    Ok((addr, len as libc::socklen_t))
}

fn sun_path_offset() -> usize {
    unsafe {
        // Work with an actual instance of the type since using a null pointer is UB
        let addr: libc::sockaddr_un = mem::uninitialized();
        let base = &addr as *const _ as usize;
        let path = &addr.sun_path as *const _ as usize;
        path - base
    }
}

#[derive(Debug)]
pub struct UnixSocket {
    io: Io,
}

impl UnixSocket {
    /// Returns a new, unbound, non-blocking Unix domain socket
    pub fn stream() -> io::Result<UnixSocket> {
        #[cfg(target_os = "linux")]
        use libc::{SOCK_CLOEXEC, SOCK_NONBLOCK};
        #[cfg(not(target_os = "linux"))]
        const SOCK_CLOEXEC: libc::c_int = 0;
        #[cfg(not(target_os = "linux"))]
        const SOCK_NONBLOCK: libc::c_int = 0;

        unsafe {
            if cfg!(target_os = "linux") {
                let flags = libc::SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK;
                match cvt(libc::socket(libc::AF_UNIX, flags, 0)) {
                    Ok(fd) => return Ok(UnixSocket::from_raw_fd(fd)),
                    Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
                    Err(e) => return Err(e),
                }
            }

            let fd = try!(cvt(libc::socket(libc::AF_UNIX, libc::SOCK_STREAM, 0)));
            let fd = UnixSocket::from_raw_fd(fd);
            try!(set_cloexec(fd.as_raw_fd()));
            try!(set_nonblock(fd.as_raw_fd()));
            Ok(fd)
        }
    }

    /// Connect the socket to the specified address
    pub fn connect<P: AsRef<Path> + ?Sized>(&self, addr: &P) -> io::Result<()> {
        unsafe {
            let (addr, len) = try!(sockaddr_un(addr.as_ref()));
            try!(cvt(libc::connect(self.as_raw_fd(),
                                   &addr as *const _ as *const _,
                                   len)));
            Ok(())
        }
    }

    /// Listen for incoming requests
    pub fn listen(&self, backlog: usize) -> io::Result<()> {
        unsafe {
            try!(cvt(libc::listen(self.as_raw_fd(), backlog as i32)));
            Ok(())
        }
    }

    pub fn accept(&self) -> io::Result<UnixSocket> {
        unsafe {
            let fd = try!(cvt(libc::accept(self.as_raw_fd(),
                                           0 as *mut _,
                                           0 as *mut _)));
            let fd = Io::from_raw_fd(fd);
            try!(set_cloexec(fd.as_raw_fd()));
            try!(set_nonblock(fd.as_raw_fd()));
            Ok(UnixSocket { io: fd })
        }
    }

    /// Bind the socket to the specified address
    pub fn bind<P: AsRef<Path> + ?Sized>(&self, addr: &P) -> io::Result<()> {
        unsafe {
            let (addr, len) = try!(sockaddr_un(addr.as_ref()));
            try!(cvt(libc::bind(self.as_raw_fd(),
                                &addr as *const _ as *const _,
                                len)));
            Ok(())
        }
    }

    pub fn try_clone(&self) -> io::Result<UnixSocket> {
        Ok(UnixSocket { io: try!(self.io.try_clone()) })
    }

    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        let how = match how {
            Shutdown::Read => libc::SHUT_RD,
            Shutdown::Write => libc::SHUT_WR,
            Shutdown::Both => libc::SHUT_RDWR,
        };
        unsafe {
            try!(cvt(libc::shutdown(self.as_raw_fd(), how)));
            Ok(())
        }
    }

    pub fn read_recv_fd(&mut self, buf: &mut [u8]) -> io::Result<(usize, Option<RawFd>)> {
        unsafe {
            let mut iov = libc::iovec {
                iov_base: buf.as_mut_ptr() as *mut _,
                iov_len: buf.len(),
            };
            struct Cmsg {
                hdr: libc::cmsghdr,
                data: [libc::c_int; 1],
            }
            let mut cmsg: Cmsg = mem::zeroed();
            let mut msg: libc::msghdr = mem::zeroed();
            msg.msg_iov = &mut iov;
            msg.msg_iovlen = 1;
            msg.msg_control = &mut cmsg as *mut _ as *mut _;
            msg.msg_controllen = mem::size_of_val(&cmsg).my_into();
            let bytes = try!(cvt(libc::recvmsg(self.as_raw_fd(), &mut msg, 0)));

            const SCM_RIGHTS: libc::c_int = 1;

            let fd = if cmsg.hdr.cmsg_level == libc::SOL_SOCKET &&
                        cmsg.hdr.cmsg_type == SCM_RIGHTS {
                Some(cmsg.data[0])
            } else {
                None
            };
            Ok((bytes as usize, fd))
        }
    }

    pub fn write_send_fd(&mut self, buf: &[u8], fd: RawFd) -> io::Result<usize> {
        unsafe {
            let mut iov = libc::iovec {
                iov_base: buf.as_ptr() as *mut _,
                iov_len: buf.len(),
            };
            struct Cmsg {
                hdr: libc::cmsghdr,
                data: [libc::c_int; 1],
            }
            let mut cmsg: Cmsg = mem::zeroed();
            cmsg.hdr.cmsg_len = mem::size_of_val(&cmsg).my_into();
            cmsg.hdr.cmsg_level = libc::SOL_SOCKET;
            cmsg.hdr.cmsg_type = 1; // SCM_RIGHTS
            cmsg.data[0] = fd;
            let mut msg: libc::msghdr = mem::zeroed();
            msg.msg_iov = &mut iov;
            msg.msg_iovlen = 1;
            msg.msg_control = &mut cmsg as *mut _ as *mut _;
            msg.msg_controllen = mem::size_of_val(&cmsg).my_into();
            let bytes = try!(cvt(libc::sendmsg(self.as_raw_fd(), &msg, 0)));
            Ok(bytes as usize)
        }
    }
}

impl Read for UnixSocket {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.io.read(buf)
    }
}

impl Write for UnixSocket {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.io.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.io.flush()
    }
}

impl Evented for UnixSocket {
    fn register(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        self.io.register(poll, token, interest, opts)
    }

    fn reregister(&self, poll: &Poll, token: Token, interest: Ready, opts: PollOpt) -> io::Result<()> {
        self.io.reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &Poll) -> io::Result<()> {
        self.io.deregister(poll)
    }
}

impl From<Io> for UnixSocket {
    fn from(io: Io) -> UnixSocket {
        UnixSocket { io: io }
    }
}

impl FromRawFd for UnixSocket {
    unsafe fn from_raw_fd(fd: RawFd) -> UnixSocket {
        UnixSocket { io: Io::from_raw_fd(fd) }
    }
}

impl IntoRawFd for UnixSocket {
    fn into_raw_fd(self) -> RawFd {
        self.io.into_raw_fd()
    }
}

impl AsRawFd for UnixSocket {
    fn as_raw_fd(&self) -> RawFd {
        self.io.as_raw_fd()
    }
}
<|endoftext|>


<commit_before><commit_msg>Add tests for g_print* functions<commit_after>extern crate glib;

use glib::*;

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

// Funny thing: we can't put those two tests in two different functions, otherwise they might
// conflict with the results of the other one (or it would be mandatory to run the tests on only
// one thread).
#[test]
fn check_print_handler() {
    //
    // g_print check part
    //
    let count = Arc::new(Mutex::new(0));
    set_print_handler(clone!(@weak count => move |_| {
        // we don't care about the message in here!
        *count.lock().expect("failed to lock 1") += 1;
    }));
    g_print!("test");
    assert_eq!(*count.lock().expect("failed to lock 2"), 1);
    g_printerr!("one");
    assert_eq!(*count.lock().expect("failed to lock 3"), 1);
    g_print!("another");
    assert_eq!(*count.lock().expect("failed to lock 4"), 2);
    unset_print_handler();
    g_print!("tadam");
    assert_eq!(*count.lock().expect("failed to lock 5"), 2);
    g_printerr!("toudoum");
    assert_eq!(*count.lock().expect("failed to lock 6"), 2);

    //
    // g_printerr check part
    //
    let count = Arc::new(Mutex::new(0));
    set_printerr_handler(clone!(@weak count => move |_| {
        // we don't care about the message in here!
        *count.lock().expect("failed to lock a") += 1;
    }));
    g_printerr!("test");
    assert_eq!(*count.lock().expect("failed to lock b"), 1);
    g_print!("one");
    assert_eq!(*count.lock().expect("failed to lock c"), 1);
    g_printerr!("another");
    assert_eq!(*count.lock().expect("failed to lock d"), 2);
    unset_printerr_handler();
    g_printerr!("tadam");
    assert_eq!(*count.lock().expect("failed to lock e"), 2);
    g_print!("toudoum");
    assert_eq!(*count.lock().expect("failed to lock f"), 2);
}
<|endoftext|>


<commit_before>use std::{fmt, mem, usize};
use std::ops::{Index, IndexMut};
use token::Token;

/// A preallocated chunk of memory for storing objects of the same type.
pub struct Slab<T> {
    // Chunk of memory
    entries: Vec<Entry<T>>,
    // Number of elements currently in the slab
    len: usize,
    // The token offset
    off: usize,
    // Offset of the next available slot in the slab. Set to the slab's
    // capacity when the slab is full.
    nxt: usize,
}

const MAX: usize = usize::MAX;

unsafe impl<T> Send for Slab<T> where T: Send {}

// TODO: Once NonZero lands, use it to optimize the layout
impl<T> Slab<T> {
    pub fn new(cap: usize) -> Slab<T> {
        Slab::new_starting_at(Token(0), cap)
    }

    pub fn new_starting_at(offset: Token, cap: usize) -> Slab<T> {
        assert!(cap <= MAX, "capacity too large");
        // TODO:
        // - Rename to with_capacity
        // - Use a power of 2 capacity
        // - Ensure that mem size is less than usize::MAX

        let entries = Vec::with_capacity(cap);

        Slab {
            entries: entries,
            len: 0,
            off: offset.as_usize(),
            nxt: 0,
        }
    }

    #[inline]
    pub fn count(&self) -> usize {
        self.len as usize
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        (self.entries.capacity() - self.len) as usize
    }

    #[inline]
    pub fn has_remaining(&self) -> bool {
        self.remaining() > 0
    }

    #[inline]
    pub fn contains(&self, idx: Token) -> bool {
        if idx.as_usize() < self.off {
            return false;
        }

        let idx = self.token_to_idx(idx);

        if idx < self.entries.len() {
            return self.entries[idx].in_use();
        }

        false
    }

    pub fn get(&self, idx: Token) -> Option<&T> {
        assert!(self.contains(idx), "slab does not contain token `{:?}`", idx);

        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            if idx < self.entries.len() {
                return self.entries[idx].val.as_ref();
            }
        }

        None
    }

    pub fn get_mut(&mut self, idx: Token) -> Option<&mut T> {
        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            if idx < self.entries.len() {
                return self.entries[idx].val.as_mut();
            }
        }

        None
    }

    pub fn insert(&mut self, val: T) -> Result<Token, T> {
        let idx = self.nxt;

        if idx == self.entries.len() {
            // Using an uninitialized entry
            if idx == self.entries.capacity() {
                // No more capacity
                debug!("slab out of capacity; cap={}", self.entries.capacity());
                return Err(val);
            }

            self.entries.push(Entry {
                nxt: MAX,
                val: Some(val),
            });

            self.len += 1;
            self.nxt = self.len;
        }
        else {
            self.len += 1;
            self.nxt = self.entries[idx].put(val);
        }

        Ok(self.idx_to_token(idx))
    }

    /// Releases the given slot
    pub fn remove(&mut self, idx: Token) -> Option<T> {
        // Cast to usize
        let idx = self.token_to_idx(idx);

        if idx > self.entries.len() {
            return None;
        }

        match self.entries[idx].remove(self.nxt) {
            Some(v) => {
                self.nxt = idx;
                self.len -= 1;
                Some(v)
            }
            None => None
        }
    }

    pub fn iter(&self) -> SlabIter<T> {
        SlabIter {
            slab: self,
            cur_idx: 0,
            yielded: 0
        }
    }

    pub fn iter_mut(&mut self) -> SlabMutIter<T> {
        SlabMutIter { iter: self.iter() }
    }

    #[inline]
    fn validate_idx(&self, idx: usize) -> usize {
        if idx < self.entries.len() {
            return idx;
        }

        panic!("invalid index {} -- greater than capacity {}", idx, self.entries.capacity());
    }

    fn token_to_idx(&self, token: Token) -> usize {
        token.as_usize() - self.off
    }

    fn idx_to_token(&self, idx: usize) -> Token {
        Token(idx as usize + self.off)
    }
}

impl<T> Index<Token> for Slab<T> {
    type Output = T;

    fn index<'a>(&'a self, idx: Token) -> &'a T {
        let idx = self.token_to_idx(idx);
        let idx = self.validate_idx(idx);

        self.entries[idx].val.as_ref()
            .expect("invalid index")
    }
}

impl<T> IndexMut<Token> for Slab<T> {
    fn index_mut<'a>(&'a mut self, idx: Token) -> &'a mut T {
        let idx = self.token_to_idx(idx);
        let idx = self.validate_idx(idx);

        self.entries[idx].val.as_mut()
            .expect("invalid index")
    }
}

impl<T> fmt::Debug for Slab<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Slab {{ len: {}, cap: {} }}", self.len, self.entries.capacity())
    }
}

// Holds the values in the slab.
struct Entry<T> {
    nxt: usize,
    val: Option<T>,
}

impl<T> Entry<T> {
    #[inline]
    fn put(&mut self, val: T) -> usize{
        let ret = self.nxt;
        self.val = Some(val);
        ret
    }

    fn remove(&mut self, nxt: usize) -> Option<T> {
        if self.in_use() {
            self.nxt = nxt;
            self.val.take()
        } else {
            None
        }
    }

    #[inline]
    fn in_use(&self) -> bool {
        self.val.is_some()
    }
}

pub struct SlabIter<'a, T: 'a> {
    slab: &'a Slab<T>,
    cur_idx: usize,
    yielded: usize
}

impl<'a, T> Iterator for SlabIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        while self.yielded < self.slab.len {
            match self.slab.entries[self.cur_idx].val {
                Some(ref v) => {
                    self.cur_idx += 1;
                    self.yielded += 1;
                    return Some(v);
                }
                None => {
                    self.cur_idx += 1;
                }
            }
        }

        None
    }
}

pub struct SlabMutIter<'a, T: 'a> {
    iter: SlabIter<'a, T>,
}

impl<'a, 'b, T> Iterator for SlabMutIter<'a, T> {
    type Item = &'b mut T;

    fn next(&mut self) -> Option<&'b mut T> {
        unsafe { mem::transmute(self.iter.next()) }
    }
}

#[cfg(test)]
mod tests {
    use super::Slab;
    use {Token};

    #[test]
    fn test_insertion() {
        let mut slab = Slab::new(1);
        let token = slab.insert(10).ok().expect("Failed to insert");
        assert_eq!(slab[token], 10);
    }

    #[test]
    fn test_repeated_insertion() {
        let mut slab = Slab::new(10);

        for i in (0..10) {
            let token = slab.insert(i + 10).ok().expect("Failed to insert");
            assert_eq!(slab[token], i + 10);
        }

        slab.insert(20).err().expect("Inserted when full");
    }

    #[test]
    fn test_repeated_insertion_and_removal() {
        let mut slab = Slab::new(10);
        let mut tokens = vec![];

        for i in (0..10) {
            let token = slab.insert(i + 10).ok().expect("Failed to insert");
            tokens.push(token);
            assert_eq!(slab[token], i + 10);
        }

        for &i in tokens.iter() {
            slab.remove(i);
        }

        slab.insert(20).ok().expect("Failed to insert in newly empty slab");
    }

    #[test]
    fn test_insertion_when_full() {
        let mut slab = Slab::new(1);
        slab.insert(10).ok().expect("Failed to insert");
        slab.insert(10).err().expect("Inserted into a full slab");
    }

    #[test]
    fn test_removal_is_successful() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert(10).ok().expect("Failed to insert");
        slab.remove(t1);
        let t2 = slab.insert(20).ok().expect("Failed to insert");
        assert_eq!(slab[t2], 20);
    }

    #[test]
    fn test_mut_retrieval() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert("foo".to_string()).ok().expect("Failed to insert");

        slab[t1].push_str("bar");

        assert_eq!(&slab[t1][..], "foobar");
    }

    #[test]
    #[should_panic]
    fn test_reusing_slots_1() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123).unwrap();
        let t1 = slab.insert(456).unwrap();

        assert!(slab.count() == 2);
        assert!(slab.remaining() == 14);

        slab.remove(t0);

        assert!(slab.count() == 1, "actual={}", slab.count());
        assert!(slab.remaining() == 15);

        slab.remove(t1);

        assert!(slab.count() == 0);
        assert!(slab.remaining() == 16);

        let _ = slab[t1];
    }

    #[test]
    fn test_reusing_slots_2() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123).unwrap();

        assert!(slab[t0] == 123);
        assert!(slab.remove(t0) == Some(123));

        let t0 = slab.insert(456).unwrap();

        assert!(slab[t0] == 456);

        let t1 = slab.insert(789).unwrap();

        assert!(slab[t0] == 456);
        assert!(slab[t1] == 789);

        assert!(slab.remove(t0).unwrap() == 456);
        assert!(slab.remove(t1).unwrap() == 789);

        assert!(slab.count() == 0);
    }

    #[test]
    #[should_panic]
    fn test_accessing_out_of_bounds() {
        let slab = Slab::<usize>::new(16);
        slab[Token(0)];
    }

    #[test]
    fn test_contains() {
        let mut slab = Slab::new_starting_at(Token(5),16);
        assert!(!slab.contains(Token(0)));

        let tok = slab.insert(111).unwrap();
        assert!(slab.contains(tok));
    }

    #[test]
    fn test_iter() {
        let mut slab: Slab<u32> = Slab::new_starting_at(Token(0), 4);
        for i in (0..4) {
            slab.insert(i).unwrap();
        }

        let vals: Vec<u32> = slab.iter().map(|r| *r).collect();
        assert_eq!(vals, vec![0, 1, 2, 3]);

        slab.remove(Token(1));

        let vals: Vec<u32> = slab.iter().map(|r| *r).collect();
        assert_eq!(vals, vec![0, 2, 3]);
    }

    #[test]
    fn test_iter_mut() {
        let mut slab: Slab<u32> = Slab::new_starting_at(Token(0), 4);
        for i in (0..4) {
            slab.insert(i).unwrap();
        }
        for e in slab.iter_mut() {
            *e = *e + 1;
        }

        let vals: Vec<u32> = slab.iter().map(|r| *r).collect();
        assert_eq!(vals, vec![1, 2, 3, 4]);

        slab.remove(Token(2));
        for e in slab.iter_mut() {
            *e = *e + 1;
        }

        let vals: Vec<u32> = slab.iter().map(|r| *r).collect();
        assert_eq!(vals, vec![2, 3, 5]);
    }
}
<commit_msg>Implement IntoInterator instances for Slab<commit_after>use std::{fmt, mem, usize};
use std::iter::IntoIterator;
use std::ops::{Index, IndexMut};
use token::Token;

/// A preallocated chunk of memory for storing objects of the same type.
pub struct Slab<T> {
    // Chunk of memory
    entries: Vec<Entry<T>>,
    // Number of elements currently in the slab
    len: usize,
    // The token offset
    off: usize,
    // Offset of the next available slot in the slab. Set to the slab's
    // capacity when the slab is full.
    nxt: usize,
}

const MAX: usize = usize::MAX;

unsafe impl<T> Send for Slab<T> where T: Send {}

// TODO: Once NonZero lands, use it to optimize the layout
impl<T> Slab<T> {
    pub fn new(cap: usize) -> Slab<T> {
        Slab::new_starting_at(Token(0), cap)
    }

    pub fn new_starting_at(offset: Token, cap: usize) -> Slab<T> {
        assert!(cap <= MAX, "capacity too large");
        // TODO:
        // - Rename to with_capacity
        // - Use a power of 2 capacity
        // - Ensure that mem size is less than usize::MAX

        let entries = Vec::with_capacity(cap);

        Slab {
            entries: entries,
            len: 0,
            off: offset.as_usize(),
            nxt: 0,
        }
    }

    #[inline]
    pub fn count(&self) -> usize {
        self.len as usize
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        (self.entries.capacity() - self.len) as usize
    }

    #[inline]
    pub fn has_remaining(&self) -> bool {
        self.remaining() > 0
    }

    #[inline]
    pub fn contains(&self, idx: Token) -> bool {
        if idx.as_usize() < self.off {
            return false;
        }

        let idx = self.token_to_idx(idx);

        if idx < self.entries.len() {
            return self.entries[idx].in_use();
        }

        false
    }

    pub fn get(&self, idx: Token) -> Option<&T> {
        assert!(self.contains(idx), "slab does not contain token `{:?}`", idx);

        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            if idx < self.entries.len() {
                return self.entries[idx].val.as_ref();
            }
        }

        None
    }

    pub fn get_mut(&mut self, idx: Token) -> Option<&mut T> {
        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            if idx < self.entries.len() {
                return self.entries[idx].val.as_mut();
            }
        }

        None
    }

    pub fn insert(&mut self, val: T) -> Result<Token, T> {
        let idx = self.nxt;

        if idx == self.entries.len() {
            // Using an uninitialized entry
            if idx == self.entries.capacity() {
                // No more capacity
                debug!("slab out of capacity; cap={}", self.entries.capacity());
                return Err(val);
            }

            self.entries.push(Entry {
                nxt: MAX,
                val: Some(val),
            });

            self.len += 1;
            self.nxt = self.len;
        }
        else {
            self.len += 1;
            self.nxt = self.entries[idx].put(val);
        }

        Ok(self.idx_to_token(idx))
    }

    /// Releases the given slot
    pub fn remove(&mut self, idx: Token) -> Option<T> {
        // Cast to usize
        let idx = self.token_to_idx(idx);

        if idx > self.entries.len() {
            return None;
        }

        match self.entries[idx].remove(self.nxt) {
            Some(v) => {
                self.nxt = idx;
                self.len -= 1;
                Some(v)
            }
            None => None
        }
    }

    pub fn iter(&self) -> SlabIter<T> {
        SlabIter {
            slab: self,
            cur_idx: 0,
            yielded: 0
        }
    }

    pub fn iter_mut(&mut self) -> SlabMutIter<T> {
        SlabMutIter { iter: self.iter() }
    }

    #[inline]
    fn validate_idx(&self, idx: usize) -> usize {
        if idx < self.entries.len() {
            return idx;
        }

        panic!("invalid index {} -- greater than capacity {}", idx, self.entries.capacity());
    }

    fn token_to_idx(&self, token: Token) -> usize {
        token.as_usize() - self.off
    }

    fn idx_to_token(&self, idx: usize) -> Token {
        Token(idx as usize + self.off)
    }
}

impl<T> Index<Token> for Slab<T> {
    type Output = T;

    fn index<'a>(&'a self, idx: Token) -> &'a T {
        let idx = self.token_to_idx(idx);
        let idx = self.validate_idx(idx);

        self.entries[idx].val.as_ref()
            .expect("invalid index")
    }
}

impl<T> IndexMut<Token> for Slab<T> {
    fn index_mut<'a>(&'a mut self, idx: Token) -> &'a mut T {
        let idx = self.token_to_idx(idx);
        let idx = self.validate_idx(idx);

        self.entries[idx].val.as_mut()
            .expect("invalid index")
    }
}

impl<T> fmt::Debug for Slab<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Slab {{ len: {}, cap: {} }}", self.len, self.entries.capacity())
    }
}

// Holds the values in the slab.
struct Entry<T> {
    nxt: usize,
    val: Option<T>,
}

impl<T> Entry<T> {
    #[inline]
    fn put(&mut self, val: T) -> usize{
        let ret = self.nxt;
        self.val = Some(val);
        ret
    }

    fn remove(&mut self, nxt: usize) -> Option<T> {
        if self.in_use() {
            self.nxt = nxt;
            self.val.take()
        } else {
            None
        }
    }

    #[inline]
    fn in_use(&self) -> bool {
        self.val.is_some()
    }
}

pub struct SlabIter<'a, T: 'a> {
    slab: &'a Slab<T>,
    cur_idx: usize,
    yielded: usize
}

impl<'a, T> Iterator for SlabIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        while self.yielded < self.slab.len {
            match self.slab.entries[self.cur_idx].val {
                Some(ref v) => {
                    self.cur_idx += 1;
                    self.yielded += 1;
                    return Some(v);
                }
                None => {
                    self.cur_idx += 1;
                }
            }
        }

        None
    }
}

pub struct SlabMutIter<'a, T: 'a> {
    iter: SlabIter<'a, T>,
}

impl<'a, 'b, T> Iterator for SlabMutIter<'a, T> {
    type Item = &'b mut T;

    fn next(&mut self) -> Option<&'b mut T> {
        unsafe { mem::transmute(self.iter.next()) }
    }
}

impl<'a, T> IntoIterator for &'a Slab<T> {
    type Item = &'a T;
    type IntoIter = SlabIter<'a, T>;

    fn into_iter(self) -> SlabIter<'a, T> {
        self.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut Slab<T> {
    type Item = &'a mut T;
    type IntoIter = SlabMutIter<'a, T>;

    fn into_iter(self) -> SlabMutIter<'a, T> {
        self.iter_mut()
    }
}

#[cfg(test)]
mod tests {
    use super::Slab;
    use {Token};

    #[test]
    fn test_insertion() {
        let mut slab = Slab::new(1);
        let token = slab.insert(10).ok().expect("Failed to insert");
        assert_eq!(slab[token], 10);
    }

    #[test]
    fn test_repeated_insertion() {
        let mut slab = Slab::new(10);

        for i in (0..10) {
            let token = slab.insert(i + 10).ok().expect("Failed to insert");
            assert_eq!(slab[token], i + 10);
        }

        slab.insert(20).err().expect("Inserted when full");
    }

    #[test]
    fn test_repeated_insertion_and_removal() {
        let mut slab = Slab::new(10);
        let mut tokens = vec![];

        for i in (0..10) {
            let token = slab.insert(i + 10).ok().expect("Failed to insert");
            tokens.push(token);
            assert_eq!(slab[token], i + 10);
        }

        for &i in tokens.iter() {
            slab.remove(i);
        }

        slab.insert(20).ok().expect("Failed to insert in newly empty slab");
    }

    #[test]
    fn test_insertion_when_full() {
        let mut slab = Slab::new(1);
        slab.insert(10).ok().expect("Failed to insert");
        slab.insert(10).err().expect("Inserted into a full slab");
    }

    #[test]
    fn test_removal_is_successful() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert(10).ok().expect("Failed to insert");
        slab.remove(t1);
        let t2 = slab.insert(20).ok().expect("Failed to insert");
        assert_eq!(slab[t2], 20);
    }

    #[test]
    fn test_mut_retrieval() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert("foo".to_string()).ok().expect("Failed to insert");

        slab[t1].push_str("bar");

        assert_eq!(&slab[t1][..], "foobar");
    }

    #[test]
    #[should_panic]
    fn test_reusing_slots_1() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123).unwrap();
        let t1 = slab.insert(456).unwrap();

        assert!(slab.count() == 2);
        assert!(slab.remaining() == 14);

        slab.remove(t0);

        assert!(slab.count() == 1, "actual={}", slab.count());
        assert!(slab.remaining() == 15);

        slab.remove(t1);

        assert!(slab.count() == 0);
        assert!(slab.remaining() == 16);

        let _ = slab[t1];
    }

    #[test]
    fn test_reusing_slots_2() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123).unwrap();

        assert!(slab[t0] == 123);
        assert!(slab.remove(t0) == Some(123));

        let t0 = slab.insert(456).unwrap();

        assert!(slab[t0] == 456);

        let t1 = slab.insert(789).unwrap();

        assert!(slab[t0] == 456);
        assert!(slab[t1] == 789);

        assert!(slab.remove(t0).unwrap() == 456);
        assert!(slab.remove(t1).unwrap() == 789);

        assert!(slab.count() == 0);
    }

    #[test]
    #[should_panic]
    fn test_accessing_out_of_bounds() {
        let slab = Slab::<usize>::new(16);
        slab[Token(0)];
    }

    #[test]
    fn test_contains() {
        let mut slab = Slab::new_starting_at(Token(5),16);
        assert!(!slab.contains(Token(0)));

        let tok = slab.insert(111).unwrap();
        assert!(slab.contains(tok));
    }

    #[test]
    fn test_iter() {
        let mut slab: Slab<u32> = Slab::new_starting_at(Token(0), 4);
        for i in (0..4) {
            slab.insert(i).unwrap();
        }

        let vals: Vec<u32> = slab.iter().map(|r| *r).collect();
        assert_eq!(vals, vec![0, 1, 2, 3]);

        slab.remove(Token(1));

        let vals: Vec<u32> = slab.iter().map(|r| *r).collect();
        assert_eq!(vals, vec![0, 2, 3]);
    }

    #[test]
    fn test_iter_mut() {
        let mut slab: Slab<u32> = Slab::new_starting_at(Token(0), 4);
        for i in (0..4) {
            slab.insert(i).unwrap();
        }
        for e in slab.iter_mut() {
            *e = *e + 1;
        }

        let vals: Vec<u32> = slab.iter().map(|r| *r).collect();
        assert_eq!(vals, vec![1, 2, 3, 4]);

        slab.remove(Token(2));
        for e in slab.iter_mut() {
            *e = *e + 1;
        }

        let vals: Vec<u32> = slab.iter().map(|r| *r).collect();
        assert_eq!(vals, vec![2, 3, 5]);
    }
}
<|endoftext|>


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

//! Temporal quantification.

#![stable(feature = "time", since = "1.3.0")]

use error::Error;
use fmt;
use ops::{Add, Sub};
use sys::time;

#[stable(feature = "time", since = "1.3.0")]
pub use self::duration::Duration;

mod duration;

/// A measurement of a monotonically increasing clock which is suitable for
/// measuring the amount of time that an operation takes.
///
/// Instants are guaranteed always be greater than any previously measured
/// instant when created, and are often useful for tasks such as measuring
/// benchmarks or timing how long an operation takes.
///
/// Note, however, that instants are not guaranteed to be **steady**.  In other
/// words each tick of the underlying clock may not be the same length (e.g.
/// some seconds may be longer than others). An instant may jump forwards or
/// experience time dilation (slow down or speed up), but it will never go
/// backwards.
///
/// Instants are opaque types that can only be compared to one another. There is
/// no method to get "the number of seconds" from an instant but instead it only
/// allow learning the duration between two instants (or comparing two
/// instants).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct Instant(time::Instant);

/// A measurement of the system clock appropriate for timestamps such as those
/// on files on the filesystem.
///
/// Distinct from the `Instant` type, this time measurement **is not
/// monotonic**. This means that you can save a file to the file system, then
/// save another file to the file system, **and the second file has a
/// `SystemTime` measurement earlier than the second**. In other words, an
/// operation that happens after another operation in real time may have an
/// earlier `SystemTime`!
///
/// Consequently, comparing two `SystemTime` instances to learn about the
/// duration between them returns a `Result` instead of an infallible `Duration`
/// to indicate that this sort of time drift may happen and needs to be handled.
///
/// Although a `SystemTime` cannot be directly inspected, the `UNIX_EPOCH`
/// constant is provided in this module as an anchor in time to learn
/// information about a `SystemTime`. By calculating the duration from this
/// fixed point in time a `SystemTime` can be converted to a human-readable time
/// or perhaps some other string representation.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTime(time::SystemTime);

/// An error returned from the `duration_from_earlier` method on `SystemTime`,
/// used to learn about why how far in the opposite direction a timestamp lies.
#[derive(Clone, Debug)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTimeError(Duration);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Instant {
    /// Returns an instant corresponding to "now".
    pub fn now() -> Instant {
        Instant(time::Instant::now())
    }

    /// Returns the amount of time elapsed from another instant to this one.
    ///
    /// # Panics
    ///
    /// This function will panic if `earlier` is later than `self`, which should
    /// only be possible if `earlier` was created after `self`. Because
    /// `Instant` is monotonic, the only time that this should happen should be
    /// a bug.
    pub fn duration_from_earlier(&self, earlier: Instant) -> Duration {
        self.0.sub_instant(&earlier.0)
    }

    /// Returns the amount of time elapsed since this instant was created.
    ///
    /// # Panics
    ///
    /// This function may panic if the current time is earlier than this instant
    /// which can happen if an `Instant` is produced synthetically.
    pub fn elapsed(&self) -> Duration {
        Instant::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for Instant {
    type Output = Instant;

    fn add(self, other: Duration) -> Instant {
        Instant(self.0.add_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for Instant {
    type Output = Instant;

    fn sub(self, other: Duration) -> Instant {
        Instant(self.0.sub_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for Instant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTime {
    /// Returns the system time corresponding to "now".
    pub fn now() -> SystemTime {
        SystemTime(time::SystemTime::now())
    }

    /// Returns the amount of time elapsed from an earlier point in time.
    ///
    /// This function may fail because measurements taken earlier are not
    /// guaranteed to always be before later measurements (due to anomalies such
    /// as the system clock being adjusted either forwards or backwards).
    ///
    /// If successful, `Ok(duration)` is returned where the duration represents
    /// the amount of time elapsed from the specified measurement to this one.
    ///
    /// Returns an `Err` if `earlier` is later than `self`, and the error
    /// contains how far from `self` the time is.
    pub fn duration_from_earlier(&self, earlier: SystemTime)
                                 -> Result<Duration, SystemTimeError> {
        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
    }

    /// Returns the amount of time elapsed since this system time was created.
    ///
    /// This function may fail as the underlying system clock is susceptible to
    /// drift and updates (e.g. the system clock could go backwards), so this
    /// function may not always succeed. If successful, `Ok(duration)` is
    /// returned where the duration represents the amount of time elapsed from
    /// this time measurement to the current time.
    ///
    /// Returns an `Err` if `self` is later than the current system time, and
    /// the error contains how far from the current system time `self` is.
    pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
        SystemTime::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for SystemTime {
    type Output = SystemTime;

    fn add(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.add_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for SystemTime {
    type Output = SystemTime;

    fn sub(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.sub_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for SystemTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// An anchor in time which can be used to create new `SystemTime` instances or
/// learn about where in time a `SystemTime` lies.
///
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
/// respect to the system clock. Using `duration_from_earlier` on an existing
/// `SystemTime` instance can tell how far away from this point in time a
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
/// `SystemTime` instance to represent another fixed point in time.
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTimeError {
    /// Returns the positive duration which represents how far forward the
    /// second system time was from the first.
    ///
    /// A `SystemTimeError` is returned from the `duration_from_earlier`
    /// operation whenever the second duration, `earlier`, actually represents a
    /// point later in time than the `self` of the method call. This function
    /// will extract and return the amount of time later `earlier` actually is.
    pub fn duration(&self) -> Duration {
        self.0
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Error for SystemTimeError {
    fn description(&self) -> &str { "other time was not earlier than self" }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Display for SystemTimeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "second time provided was later than self")
    }
}

#[cfg(test)]
mod tests {
    use super::{Instant, SystemTime, Duration, UNIX_EPOCH};

    macro_rules! assert_almost_eq {
        ($a:expr, $b:expr) => ({
            let (a, b) = ($a, $b);
            if a != b {
                let (a, b) = if a > b {(a, b)} else {(b, a)};
                assert!(a - Duration::new(0, 1) <= b);
            }
        })
    }

    #[test]
    fn instant_monotonic() {
        let a = Instant::now();
        let b = Instant::now();
        assert!(b >= a);
    }

    #[test]
    fn instant_elapsed() {
        let a = Instant::now();
        a.elapsed();
    }

    #[test]
    fn instant_math() {
        let a = Instant::now();
        let b = Instant::now();
        let dur = b.duration_from_earlier(a);
        assert_almost_eq!(b - dur, a);
        assert_almost_eq!(a + dur, b);

        let second = Duration::new(1, 0);
        assert_almost_eq!(a - second + second, a);
    }

    #[test]
    #[should_panic]
    fn instant_duration_panic() {
        let a = Instant::now();
        (a - Duration::new(1, 0)).duration_from_earlier(a);
    }

    #[test]
    fn system_time_math() {
        let a = SystemTime::now();
        let b = SystemTime::now();
        match b.duration_from_earlier(a) {
            Ok(dur) if dur == Duration::new(0, 0) => {
                assert_almost_eq!(a, b);
            }
            Ok(dur) => {
                assert!(b > a);
                assert_almost_eq!(b - dur, a);
                assert_almost_eq!(a + dur, b);
            }
            Err(dur) => {
                let dur = dur.duration();
                assert!(a > b);
                assert_almost_eq!(b + dur, a);
                assert_almost_eq!(b - dur, a);
            }
        }

        let second = Duration::new(1, 0);
        assert_almost_eq!(a.duration_from_earlier(a - second).unwrap(), second);
        assert_almost_eq!(a.duration_from_earlier(a + second).unwrap_err()
                           .duration(), second);

        assert_almost_eq!(a - second + second, a);

        let eighty_years = second * 60 * 60 * 24 * 365 * 80;
        assert_almost_eq!(a - eighty_years + eighty_years, a);
        assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
    }

    #[test]
    fn system_time_elapsed() {
        let a = SystemTime::now();
        drop(a.elapsed());
    }

    #[test]
    fn since_epoch() {
        let ts = SystemTime::now();
        let a = ts.duration_from_earlier(UNIX_EPOCH).unwrap();
        let b = ts.duration_from_earlier(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
        assert!(b > a);
        assert_eq!(b - a, Duration::new(1, 0));

        // let's assume that we're all running computers later than 2000
        let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
        assert!(a > thirty_years);

        // let's assume that we're all running computers earlier than 2090.
        // Should give us ~70 years to fix this!
        let hundred_twenty_years = thirty_years * 4;
        assert!(a < hundred_twenty_years);
    }
}
<commit_msg>Auto merge of #30061 - tshepang:doc-time, r=brson<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Temporal quantification.

#![stable(feature = "time", since = "1.3.0")]

use error::Error;
use fmt;
use ops::{Add, Sub};
use sys::time;

#[stable(feature = "time", since = "1.3.0")]
pub use self::duration::Duration;

mod duration;

/// A measurement of a monotonically increasing clock.
///
/// Instants are always guaranteed to be greater than any previously measured
/// instant when created, and are often useful for tasks such as measuring
/// benchmarks or timing how long an operation takes.
///
/// Note, however, that instants are not guaranteed to be **steady**.  In other
/// words, each tick of the underlying clock may not be the same length (e.g.
/// some seconds may be longer than others). An instant may jump forwards or
/// experience time dilation (slow down or speed up), but it will never go
/// backwards.
///
/// Instants are opaque types that can only be compared to one another. There is
/// no method to get "the number of seconds" from an instant. Instead, it only
/// allows measuring the duration between two instants (or comparing two
/// instants).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct Instant(time::Instant);

/// A measurement of the system clock appropriate for timestamps such as those
/// on files on the filesystem.
///
/// Distinct from the `Instant` type, this time measurement **is not
/// monotonic**. This means that you can save a file to the file system, then
/// save another file to the file system, **and the second file has a
/// `SystemTime` measurement earlier than the second**. In other words, an
/// operation that happens after another operation in real time may have an
/// earlier `SystemTime`!
///
/// Consequently, comparing two `SystemTime` instances to learn about the
/// duration between them returns a `Result` instead of an infallible `Duration`
/// to indicate that this sort of time drift may happen and needs to be handled.
///
/// Although a `SystemTime` cannot be directly inspected, the `UNIX_EPOCH`
/// constant is provided in this module as an anchor in time to learn
/// information about a `SystemTime`. By calculating the duration from this
/// fixed point in time, a `SystemTime` can be converted to a human-readable time,
/// or perhaps some other string representation.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTime(time::SystemTime);

/// An error returned from the `duration_from_earlier` method on `SystemTime`,
/// used to learn about why how far in the opposite direction a timestamp lies.
#[derive(Clone, Debug)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTimeError(Duration);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Instant {
    /// Returns an instant corresponding to "now".
    pub fn now() -> Instant {
        Instant(time::Instant::now())
    }

    /// Returns the amount of time elapsed from another instant to this one.
    ///
    /// # Panics
    ///
    /// This function will panic if `earlier` is later than `self`, which should
    /// only be possible if `earlier` was created after `self`. Because
    /// `Instant` is monotonic, the only time that this should happen should be
    /// a bug.
    pub fn duration_from_earlier(&self, earlier: Instant) -> Duration {
        self.0.sub_instant(&earlier.0)
    }

    /// Returns the amount of time elapsed since this instant was created.
    ///
    /// # Panics
    ///
    /// This function may panic if the current time is earlier than this
    /// instant, which is something that can happen if an `Instant` is
    /// produced synthetically.
    pub fn elapsed(&self) -> Duration {
        Instant::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for Instant {
    type Output = Instant;

    fn add(self, other: Duration) -> Instant {
        Instant(self.0.add_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for Instant {
    type Output = Instant;

    fn sub(self, other: Duration) -> Instant {
        Instant(self.0.sub_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for Instant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTime {
    /// Returns the system time corresponding to "now".
    pub fn now() -> SystemTime {
        SystemTime(time::SystemTime::now())
    }

    /// Returns the amount of time elapsed from an earlier point in time.
    ///
    /// This function may fail because measurements taken earlier are not
    /// guaranteed to always be before later measurements (due to anomalies such
    /// as the system clock being adjusted either forwards or backwards).
    ///
    /// If successful, `Ok(Duration)` is returned where the duration represents
    /// the amount of time elapsed from the specified measurement to this one.
    ///
    /// Returns an `Err` if `earlier` is later than `self`, and the error
    /// contains how far from `self` the time is.
    pub fn duration_from_earlier(&self, earlier: SystemTime)
                                 -> Result<Duration, SystemTimeError> {
        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
    }

    /// Returns the amount of time elapsed since this system time was created.
    ///
    /// This function may fail as the underlying system clock is susceptible to
    /// drift and updates (e.g. the system clock could go backwards), so this
    /// function may not always succeed. If successful, `Ok(duration)` is
    /// returned where the duration represents the amount of time elapsed from
    /// this time measurement to the current time.
    ///
    /// Returns an `Err` if `self` is later than the current system time, and
    /// the error contains how far from the current system time `self` is.
    pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
        SystemTime::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for SystemTime {
    type Output = SystemTime;

    fn add(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.add_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for SystemTime {
    type Output = SystemTime;

    fn sub(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.sub_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for SystemTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// An anchor in time which can be used to create new `SystemTime` instances or
/// learn about where in time a `SystemTime` lies.
///
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
/// respect to the system clock. Using `duration_from_earlier` on an existing
/// `SystemTime` instance can tell how far away from this point in time a
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
/// `SystemTime` instance to represent another fixed point in time.
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTimeError {
    /// Returns the positive duration which represents how far forward the
    /// second system time was from the first.
    ///
    /// A `SystemTimeError` is returned from the `duration_from_earlier`
    /// operation whenever the second system time represents a point later
    /// in time than the `self` of the method call.
    pub fn duration(&self) -> Duration {
        self.0
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Error for SystemTimeError {
    fn description(&self) -> &str { "other time was not earlier than self" }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Display for SystemTimeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "second time provided was later than self")
    }
}

#[cfg(test)]
mod tests {
    use super::{Instant, SystemTime, Duration, UNIX_EPOCH};

    macro_rules! assert_almost_eq {
        ($a:expr, $b:expr) => ({
            let (a, b) = ($a, $b);
            if a != b {
                let (a, b) = if a > b {(a, b)} else {(b, a)};
                assert!(a - Duration::new(0, 1) <= b);
            }
        })
    }

    #[test]
    fn instant_monotonic() {
        let a = Instant::now();
        let b = Instant::now();
        assert!(b >= a);
    }

    #[test]
    fn instant_elapsed() {
        let a = Instant::now();
        a.elapsed();
    }

    #[test]
    fn instant_math() {
        let a = Instant::now();
        let b = Instant::now();
        let dur = b.duration_from_earlier(a);
        assert_almost_eq!(b - dur, a);
        assert_almost_eq!(a + dur, b);

        let second = Duration::new(1, 0);
        assert_almost_eq!(a - second + second, a);
    }

    #[test]
    #[should_panic]
    fn instant_duration_panic() {
        let a = Instant::now();
        (a - Duration::new(1, 0)).duration_from_earlier(a);
    }

    #[test]
    fn system_time_math() {
        let a = SystemTime::now();
        let b = SystemTime::now();
        match b.duration_from_earlier(a) {
            Ok(dur) if dur == Duration::new(0, 0) => {
                assert_almost_eq!(a, b);
            }
            Ok(dur) => {
                assert!(b > a);
                assert_almost_eq!(b - dur, a);
                assert_almost_eq!(a + dur, b);
            }
            Err(dur) => {
                let dur = dur.duration();
                assert!(a > b);
                assert_almost_eq!(b + dur, a);
                assert_almost_eq!(b - dur, a);
            }
        }

        let second = Duration::new(1, 0);
        assert_almost_eq!(a.duration_from_earlier(a - second).unwrap(), second);
        assert_almost_eq!(a.duration_from_earlier(a + second).unwrap_err()
                           .duration(), second);

        assert_almost_eq!(a - second + second, a);

        let eighty_years = second * 60 * 60 * 24 * 365 * 80;
        assert_almost_eq!(a - eighty_years + eighty_years, a);
        assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
    }

    #[test]
    fn system_time_elapsed() {
        let a = SystemTime::now();
        drop(a.elapsed());
    }

    #[test]
    fn since_epoch() {
        let ts = SystemTime::now();
        let a = ts.duration_from_earlier(UNIX_EPOCH).unwrap();
        let b = ts.duration_from_earlier(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
        assert!(b > a);
        assert_eq!(b - a, Duration::new(1, 0));

        // let's assume that we're all running computers later than 2000
        let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
        assert!(a > thirty_years);

        // let's assume that we're all running computers earlier than 2090.
        // Should give us ~70 years to fix this!
        let hundred_twenty_years = thirty_years * 4;
        assert!(a < hundred_twenty_years);
    }
}
<|endoftext|>


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

//! C-string manipulation and management
//!
//! This modules provides the basic methods for creating and manipulating
//! null-terminated strings for use with FFI calls (back to C). Most C APIs require
//! that the string being passed to them is null-terminated, and by default rust's
//! string types are *not* null terminated.
//!
//! The other problem with translating Rust strings to C strings is that Rust
//! strings can validly contain a null-byte in the middle of the string (0 is a
//! valid Unicode codepoint). This means that not all Rust strings can actually be
//! translated to C strings.
//!
//! # Creation of a C string
//!
//! A C string is managed through the `CString` type defined in this module. It
//! "owns" the internal buffer of characters and will automatically deallocate the
//! buffer when the string is dropped. The `ToCStr` trait is implemented for `&str`
//! and `&[u8]`, but the conversions can fail due to some of the limitations
//! explained above.
//!
//! This also means that currently whenever a C string is created, an allocation
//! must be performed to place the data elsewhere (the lifetime of the C string is
//! not tied to the lifetime of the original string/data buffer). If C strings are
//! heavily used in applications, then caching may be advisable to prevent
//! unnecessary amounts of allocations.
//!
//! Be carefull to remember that the memory is managed by C allocator API and not
//! by Rust allocator API.
//! That means that the CString pointers should be freed with C allocator API
//! if you intend to do that on your own, as the behaviour if you free them with
//! Rust's allocator API is not well defined
//!
//! An example of creating and using a C string would be:
//!
//! ```rust
//! extern crate libc;
//!
//! use std::c_str::ToCStr;
//!
//! extern {
//!     fn puts(s: *const libc::c_char);
//! }
//!
//! fn main() {
//!     let my_string = "Hello, world!";
//!
//!     // Allocate the C string with an explicit local that owns the string. The
//!     // `c_buffer` pointer will be deallocated when `my_c_string` goes out of scope.
//!     let my_c_string = my_string.to_c_str();
//!     unsafe {
//!         puts(my_c_string.as_ptr());
//!     }
//!
//!     // Don't save/return the pointer to the C string, the `c_buffer` will be
//!     // deallocated when this block returns!
//!     my_string.with_c_str(|c_buffer| {
//!         unsafe { puts(c_buffer); }
//!     });
//! }
//! ```

use core::prelude::*;
use libc;

use cmp::Ordering;
use fmt;
use hash;
use mem;
use ptr;
use slice::{self, IntSliceExt};
use str;
use string::String;
use core::kinds::marker;

/// The representation of a C String.
///
/// This structure wraps a `*libc::c_char`, and will automatically free the
/// memory it is pointing to when it goes out of scope.
#[allow(missing_copy_implementations)]
pub struct CString {
    buf: *const libc::c_char,
    owns_buffer_: bool,
}

unsafe impl Send for CString { }
unsafe impl Sync for CString { }

impl Clone for CString {
    /// Clone this CString into a new, uniquely owned CString. For safety
    /// reasons, this is always a deep clone with the memory allocated
    /// with C's allocator API, rather than the usual shallow clone.
    fn clone(&self) -> CString {
        let len = self.len() + 1;
        let buf = unsafe { libc::malloc(len as libc::size_t) } as *mut libc::c_char;
        if buf.is_null() { ::alloc::oom() }
        unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); }
        CString { buf: buf as *const libc::c_char, owns_buffer_: true }
    }
}

impl PartialEq for CString {
    fn eq(&self, other: &CString) -> bool {
        // Check if the two strings share the same buffer
        if self.buf as uint == other.buf as uint {
            true
        } else {
            unsafe {
                libc::strcmp(self.buf, other.buf) == 0
            }
        }
    }
}

impl PartialOrd for CString {
    #[inline]
    fn partial_cmp(&self, other: &CString) -> Option<Ordering> {
        self.as_bytes().partial_cmp(other.as_bytes())
    }
}

impl Eq for CString {}

impl<S: hash::Writer> hash::Hash<S> for CString {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_bytes().hash(state)
    }
}

impl CString {
    /// Create a C String from a pointer, with memory managed by C's allocator
    /// API, so avoid calling it with a pointer to memory managed by Rust's
    /// allocator API, as the behaviour would not be well defined.
    ///
    ///# Panics
    ///
    /// Panics if `buf` is null
    pub unsafe fn new(buf: *const libc::c_char, owns_buffer: bool) -> CString {
        assert!(!buf.is_null());
        CString { buf: buf, owns_buffer_: owns_buffer }
    }

    /// Return a pointer to the NUL-terminated string data.
    ///
    /// `.as_ptr` returns an internal pointer into the `CString`, and
    /// may be invalidated when the `CString` falls out of scope (the
    /// destructor will run, freeing the allocation if there is
    /// one).
    ///
    /// ```rust
    /// use std::c_str::ToCStr;
    ///
    /// let foo = "some string";
    ///
    /// // right
    /// let x = foo.to_c_str();
    /// let p = x.as_ptr();
    ///
    /// // wrong (the CString will be freed, invalidating `p`)
    /// let p = foo.to_c_str().as_ptr();
    /// ```
    ///
    /// # Example
    ///
    /// ```rust
    /// extern crate libc;
    ///
    /// use std::c_str::ToCStr;
    ///
    /// fn main() {
    ///     let c_str = "foo bar".to_c_str();
    ///     unsafe {
    ///         libc::puts(c_str.as_ptr());
    ///     }
    /// }
    /// ```
    pub fn as_ptr(&self) -> *const libc::c_char {
        self.buf
    }

    /// Return a mutable pointer to the NUL-terminated string data.
    ///
    /// `.as_mut_ptr` returns an internal pointer into the `CString`, and
    /// may be invalidated when the `CString` falls out of scope (the
    /// destructor will run, freeing the allocation if there is
    /// one).
    ///
    /// ```rust
    /// use std::c_str::ToCStr;
    ///
    /// let foo = "some string";
    ///
    /// // right
    /// let mut x = foo.to_c_str();
    /// let p = x.as_mut_ptr();
    ///
    /// // wrong (the CString will be freed, invalidating `p`)
    /// let p = foo.to_c_str().as_mut_ptr();
    /// ```
    pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
        self.buf as *mut _
    }

    /// Returns whether or not the `CString` owns the buffer.
    pub fn owns_buffer(&self) -> bool {
        self.owns_buffer_
    }

    /// Converts the CString into a `&[u8]` without copying.
    /// Includes the terminating NUL byte.
    #[inline]
    pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
        unsafe {
            slice::from_raw_buf(&self.buf, self.len() + 1).as_unsigned()
        }
    }

    /// Converts the CString into a `&[u8]` without copying.
    /// Does not include the terminating NUL byte.
    #[inline]
    pub fn as_bytes_no_nul<'a>(&'a self) -> &'a [u8] {
        unsafe {
            slice::from_raw_buf(&self.buf, self.len()).as_unsigned()
        }
    }

    /// Converts the CString into a `&str` without copying.
    /// Returns None if the CString is not UTF-8.
    #[inline]
    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
        let buf = self.as_bytes_no_nul();
        str::from_utf8(buf).ok()
    }

    /// Return a CString iterator.
    pub fn iter<'a>(&'a self) -> CChars<'a> {
        CChars {
            ptr: self.buf,
            marker: marker::ContravariantLifetime,
        }
    }

    /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
    ///
    /// Any ownership of the buffer by the `CString` wrapper is
    /// forgotten, meaning that the backing allocation of this
    /// `CString` is not automatically freed if it owns the
    /// allocation. In this case, a user of `.unwrap()` should ensure
    /// the allocation is freed, to avoid leaking memory. You should
    /// use libc's memory allocator in this case.
    ///
    /// Prefer `.as_ptr()` when just retrieving a pointer to the
    /// string data, as that does not relinquish ownership.
    pub unsafe fn into_inner(mut self) -> *const libc::c_char {
        self.owns_buffer_ = false;
        self.buf
    }

    /// Return the number of bytes in the CString (not including the NUL
    /// terminator).
    #[inline]
    pub fn len(&self) -> uint {
        unsafe { libc::strlen(self.buf) as uint }
    }

    /// Returns if there are no bytes in this string
    #[inline]
    pub fn is_empty(&self) -> bool { self.len() == 0 }
}

impl Drop for CString {
    fn drop(&mut self) {
        if self.owns_buffer_ {
            unsafe {
                libc::free(self.buf as *mut libc::c_void)
            }
        }
    }
}

impl fmt::Show for CString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        String::from_utf8_lossy(self.as_bytes_no_nul()).fmt(f)
    }
}

/// A generic trait for converting a value to a CString.
pub trait ToCStr for Sized? {
    /// Copy the receiver into a CString.
    ///
    /// # Panics
    ///
    /// Panics the task if the receiver has an interior null.
    fn to_c_str(&self) -> CString;

    /// Unsafe variant of `to_c_str()` that doesn't check for nulls.
    unsafe fn to_c_str_unchecked(&self) -> CString;

    /// Work with a temporary CString constructed from the receiver.
    /// The provided `*libc::c_char` will be freed immediately upon return.
    ///
    /// # Example
    ///
    /// ```rust
    /// extern crate libc;
    ///
    /// use std::c_str::ToCStr;
    ///
    /// fn main() {
    ///     let s = "PATH".with_c_str(|path| unsafe {
    ///         libc::getenv(path)
    ///     });
    /// }
    /// ```
    ///
    /// # Panics
    ///
    /// Panics the task if the receiver has an interior null.
    #[inline]
    fn with_c_str<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        let c_str = self.to_c_str();
        f(c_str.as_ptr())
    }

    /// Unsafe variant of `with_c_str()` that doesn't check for nulls.
    #[inline]
    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        let c_str = self.to_c_str_unchecked();
        f(c_str.as_ptr())
    }
}

impl ToCStr for str {
    #[inline]
    fn to_c_str(&self) -> CString {
        self.as_bytes().to_c_str()
    }

    #[inline]
    unsafe fn to_c_str_unchecked(&self) -> CString {
        self.as_bytes().to_c_str_unchecked()
    }

    #[inline]
    fn with_c_str<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        self.as_bytes().with_c_str(f)
    }

    #[inline]
    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        self.as_bytes().with_c_str_unchecked(f)
    }
}

impl ToCStr for String {
    #[inline]
    fn to_c_str(&self) -> CString {
        self.as_bytes().to_c_str()
    }

    #[inline]
    unsafe fn to_c_str_unchecked(&self) -> CString {
        self.as_bytes().to_c_str_unchecked()
    }

    #[inline]
    fn with_c_str<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        self.as_bytes().with_c_str(f)
    }

    #[inline]
    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        self.as_bytes().with_c_str_unchecked(f)
    }
}

// The length of the stack allocated buffer for `vec.with_c_str()`
const BUF_LEN: uint = 128;

impl ToCStr for [u8] {
    fn to_c_str(&self) -> CString {
        let mut cs = unsafe { self.to_c_str_unchecked() };
        check_for_null(self, cs.as_mut_ptr());
        cs
    }

    unsafe fn to_c_str_unchecked(&self) -> CString {
        let self_len = self.len();
        let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
        if buf.is_null() { ::alloc::oom() }

        ptr::copy_memory(buf, self.as_ptr(), self_len);
        *buf.offset(self_len as int) = 0;

        CString::new(buf as *const libc::c_char, true)
    }

    fn with_c_str<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        unsafe { with_c_str(self, true, f) }
    }

    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        with_c_str(self, false, f)
    }
}

impl<'a, Sized? T: ToCStr> ToCStr for &'a T {
    #[inline]
    fn to_c_str(&self) -> CString {
        (**self).to_c_str()
    }

    #[inline]
    unsafe fn to_c_str_unchecked(&self) -> CString {
        (**self).to_c_str_unchecked()
    }

    #[inline]
    fn with_c_str<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        (**self).with_c_str(f)
    }

    #[inline]
    unsafe fn with_c_str_unchecked<T, F>(&self, f: F) -> T where
        F: FnOnce(*const libc::c_char) -> T,
    {
        (**self).with_c_str_unchecked(f)
    }
}

// Unsafe function that handles possibly copying the &[u8] into a stack array.
unsafe fn with_c_str<T, F>(v: &[u8], checked: bool, f: F) -> T where
    F: FnOnce(*const libc::c_char) -> T,
{
    let c_str = if v.len() < BUF_LEN {
        let mut buf: [u8; BUF_LEN] = mem::uninitialized();
        slice::bytes::copy_memory(&mut buf, v);
        buf[v.len()] = 0;

        let buf = buf.as_mut_ptr();
        if checked {
            check_for_null(v, buf as *mut libc::c_char);
        }

        return f(buf as *const libc::c_char)
    } else if checked {
        v.to_c_str()
    } else {
        v.to_c_str_unchecked()
    };

    f(c_str.as_ptr())
}

#[inline]
fn check_for_null(v: &[u8], buf: *mut libc::c_char) {
    for i in range(0, v.len()) {
        unsafe {
            let p = buf.offset(i as int);
            assert!(*p != 0);
        }
    }
}

/// External iterator for a CString's bytes.
///
/// Use with the `std::iter` module.
#[allow(raw_pointer_deriving)]
#[derive(Clone)]
pub struct CChars<'a> {
    ptr: *const libc::c_char,
    marker: marker::ContravariantLifetime<'a>,
}

impl<'a> Iterator for CChars<'a> {
    type Item = libc::c_char;

    fn next(&mut self) -> Option<libc::c_char> {
        let ch = unsafe { *self.ptr };
        if ch == 0 {
            None
        } else {
            self.ptr = unsafe { self.ptr.offset(1) };
            Some(ch)
        }
    }
}

/// Parses a C "multistring", eg windows env values or
/// the req->ptr result in a uv_fs_readdir() call.
///
/// Optionally, a `count` can be passed in, limiting the
/// parsing to only being done `count`-times.
///
/// The specified closure is invoked with each string that
/// is found, and the number of strings found is returned.
pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
                                    count: Option<uint>,
                                    mut f: F)
                                    -> uint where
    F: FnMut(&CString),
{

    let mut curr_ptr: uint = buf as uint;
    let mut ctr = 0;
    let (limited_count, limit) = match count {
        Some(limit) => (true, limit),
        None => (false, 0)
    };
    while ((limited_count && ctr < limit) || !limited_count)
          && *(curr_ptr as *const libc::c_char) != 0 as libc::c_char {
        let cstr = CString::new(curr_ptr as *const libc::c_char, false);
        f(&cstr);
        curr_ptr += cstr.len() + 1;
        ctr += 1;
    }
    return ctr;
}

#[cfg(test)]
mod tests {
    use prelude::v1::*;
    use super::*;
    use ptr;
    use thread::Thread;
    use libc;

    #[test]
    fn test_str_multistring_parsing() {
        unsafe {
            let input = b"zero\0one\0\0";
            let ptr = input.as_ptr();
            let expected = ["zero", "one"];
            let mut it = expected.iter();
            let result = from_c_multistring(ptr as *const libc::c_char, None, |c| {
                let cbytes = c.as_bytes_no_nul();
                assert_eq!(cbytes, it.next().unwrap().as_bytes());
            });
            assert_eq!(result, 2);
            assert!(it.next().is_none());
        }
    }

    #[test]
    fn test_str_to_c_str() {
        let c_str = "".to_c_str();
        unsafe {
            assert_eq!(*c_str.as_ptr().offset(0), 0);
        }

        let c_str = "hello".to_c_str();
        let buf = c_str.as_ptr();
        unsafe {
            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
            assert_eq!(*buf.offset(2), 'l' as libc::c_char);
            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
            assert_eq!(*buf.offset(4), 'o' as libc::c_char);
            assert_eq!(*buf.offset(5), 0);
        }
    }

    #[test]
    fn test_vec_to_c_str() {
        let b: &[u8] = &[];
        let c_str = b.to_c_str();
        unsafe {
            assert_eq!(*c_str.as_ptr().offset(0), 0);
        }

        let c_str = b"hello".to_c_str();
        let buf = c_str.as_ptr();
        unsafe {
            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
            assert_eq!(*buf.offset(2), 'l' as libc::c_char);
            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
            assert_eq!(*buf.offset(4), 'o' as libc::c_char);
            assert_eq!(*buf.offset(5), 0);
        }

        let c_str = b"foo\xFF".to_c_str();
        let buf = c_str.as_ptr();
        unsafe {
            assert_eq!(*buf.offset(0), 'f' as libc::c_char);
            assert_eq!(*buf.offset(1), 'o' as libc::c_char);
            assert_eq!(*buf.offset(2), 'o' as libc::c_char);
            assert_eq!(*buf.offset(3), 0xffu8 as libc::c_char);
            assert_eq!(*buf.offset(4), 0);
        }
    }

    #[test]
    fn test_unwrap() {
        let c_str = "hello".to_c_str();
        unsafe { libc::free(c_str.into_inner() as *mut libc::c_void) }
    }

    #[test]
    fn test_as_ptr() {
        let c_str = "hello".to_c_str();
        let len = unsafe { libc::strlen(c_str.as_ptr()) };
        assert_eq!(len, 5);
    }

    #[test]
    fn test_iterator() {
        let c_str = "".to_c_str();
        let mut iter = c_str.iter();
        assert_eq!(iter.next(), None);

        let c_str = "hello".to_c_str();
        let mut iter = c_str.iter();
        assert_eq!(iter.next(), Some('h' as libc::c_char));
        assert_eq!(iter.next(), Some('e' as libc::c_char));
        assert_eq!(iter.next(), Some('l' as libc::c_char));
        assert_eq!(iter.next(), Some('l' as libc::c_char));
        assert_eq!(iter.next(), Some('o' as libc::c_char));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_to_c_str_fail() {
        assert!(Thread::spawn(move|| { "he\x00llo".to_c_str() }).join().is_err());
    }

    #[test]
    fn test_to_c_str_unchecked() {
        unsafe {
            let c_string = "he\x00llo".to_c_str_unchecked();
            let buf = c_string.as_ptr();
            assert_eq!(*buf.offset(0), 'h' as libc::c_char);
            assert_eq!(*buf.offset(1), 'e' as libc::c_char);
            assert_eq!(*buf.offset(2), 0);
            assert_eq!(*buf.offset(3), 'l' as libc::c_char);
            assert_eq!(*buf.offset(4), 'l' as libc::c_char);
            assert_eq!(*buf.offset(5), 'o' as libc::c_char);
            assert_eq!(*buf.offset(6), 0);
        }
    }

    #[test]
    fn test_as_bytes() {
        let c_str = "hello".to_c_str();
        assert_eq!(c_str.as_bytes(), b"hello\0");
        let c_str = "".to_c_str();
        assert_eq!(c_str.as_bytes(), b"\0");
        let c_str = b"foo\xFF".to_c_str();
        assert_eq!(c_str.as_bytes(), b"foo\xFF\0");
    }

    #[test]
    fn test_as_bytes_no_nul() {
        let c_str = "hello".to_c_str();
        assert_eq!(c_str.as_bytes_no_nul(), b"hello");
        let c_str = "".to_c_str();
        let exp: &[u8] = &[];
        assert_eq!(c_str.as_bytes_no_nul(), exp);
        let c_str = b"foo\xFF".to_c_str();
        assert_eq!(c_str.as_bytes_no_nul(), b"foo\xFF");
    }

    #[test]
    fn test_as_str() {
        let c_str = "hello".to_c_str();
        assert_eq!(c_str.as_str(), Some("hello"));
        let c_str = "".to_c_str();
        assert_eq!(c_str.as_str(), Some(""));
        let c_str = b"foo\xFF".to_c_str();
        assert_eq!(c_str.as_str(), None);
    }

    #[test]
    #[should_fail]
    fn test_new_fail() {
        let _c_str = unsafe { CString::new(ptr::null(), false) };
    }

    #[test]
    fn test_clone() {
        let a = "hello".to_c_str();
        let b = a.clone();
        assert!(a == b);
    }

    #[test]
    fn test_clone_noleak() {
        fn foo<F>(f: F) where F: FnOnce(&CString) {
            let s = "test".to_string();
            let c = s.to_c_str();
            // give the closure a non-owned CString
            let mut c_ = unsafe { CString::new(c.as_ptr(), false) };
            f(&c_);
            // muck with the buffer for later printing
            unsafe { *c_.as_mut_ptr() = 'X' as libc::c_char }
        }

        let mut c_: Option<CString> = None;
        foo(|c| {
            c_ = Some(c.clone());
            c.clone();
            // force a copy, reading the memory
            c.as_bytes().to_vec();
        });
        let c_ = c_.unwrap();
        // force a copy, reading the memory
        c_.as_bytes().to_vec();
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use prelude::v1::*;
    use self::test::Bencher;
    use libc;
    use c_str::ToCStr;

    #[inline]
    fn check(s: &str, c_str: *const libc::c_char) {
        let s_buf = s.as_ptr();
        for i in range(0, s.len()) {
            unsafe {
                assert_eq!(
                    *s_buf.offset(i as int) as libc::c_char,
                    *c_str.offset(i as int));
            }
        }
    }

    static S_SHORT: &'static str = "Mary";
    static S_MEDIUM: &'static str = "Mary had a little lamb";
    static S_LONG: &'static str = "\
        Mary had a little lamb, Little lamb
        Mary had a little lamb, Little lamb
        Mary had a little lamb, Little lamb
        Mary had a little lamb, Little lamb
        Mary had a little lamb, Little lamb
        Mary had a little lamb, Little lamb";

    fn bench_to_string(b: &mut Bencher, s: &str) {
        b.iter(|| {
            let c_str = s.to_c_str();
            check(s, c_str.as_ptr());
        })
    }

    #[bench]
    fn bench_to_c_str_short(b: &mut Bencher) {
        bench_to_string(b, S_SHORT)
    }

    #[bench]
    fn bench_to_c_str_medium(b: &mut Bencher) {
        bench_to_string(b, S_MEDIUM)
    }

    #[bench]
    fn bench_to_c_str_long(b: &mut Bencher) {
        bench_to_string(b, S_LONG)
    }

    fn bench_to_c_str_unchecked(b: &mut Bencher, s: &str) {
        b.iter(|| {
            let c_str = unsafe { s.to_c_str_unchecked() };
            check(s, c_str.as_ptr())
        })
    }

    #[bench]
    fn bench_to_c_str_unchecked_short(b: &mut Bencher) {
        bench_to_c_str_unchecked(b, S_SHORT)
    }

    #[bench]
    fn bench_to_c_str_unchecked_medium(b: &mut Bencher) {
        bench_to_c_str_unchecked(b, S_MEDIUM)
    }

    #[bench]
    fn bench_to_c_str_unchecked_long(b: &mut Bencher) {
        bench_to_c_str_unchecked(b, S_LONG)
    }

    fn bench_with_c_str(b: &mut Bencher, s: &str) {
        b.iter(|| {
            s.with_c_str(|c_str_buf| check(s, c_str_buf))
        })
    }

    #[bench]
    fn bench_with_c_str_short(b: &mut Bencher) {
        bench_with_c_str(b, S_SHORT)
    }

    #[bench]
    fn bench_with_c_str_medium(b: &mut Bencher) {
        bench_with_c_str(b, S_MEDIUM)
    }

    #[bench]
    fn bench_with_c_str_long(b: &mut Bencher) {
        bench_with_c_str(b, S_LONG)
    }

    fn bench_with_c_str_unchecked(b: &mut Bencher, s: &str) {
        b.iter(|| {
            unsafe {
                s.with_c_str_unchecked(|c_str_buf| check(s, c_str_buf))
            }
        })
    }

    #[bench]
    fn bench_with_c_str_unchecked_short(b: &mut Bencher) {
        bench_with_c_str_unchecked(b, S_SHORT)
    }

    #[bench]
    fn bench_with_c_str_unchecked_medium(b: &mut Bencher) {
        bench_with_c_str_unchecked(b, S_MEDIUM)
    }

    #[bench]
    fn bench_with_c_str_unchecked_long(b: &mut Bencher) {
        bench_with_c_str_unchecked(b, S_LONG)
    }
}
<|endoftext|>


<commit_before><commit_msg>Add some tests for attributes<commit_after>#![feature(phase)]
#![feature(unboxed_closures)]

#[phase(plugin)]
extern crate glium_macros;

extern crate glutin;
extern crate glium;

use glium::Surface;

mod support;

#[test]
fn attribute_types_matching() {
    let display = support::build_display();

    #[vertex_format]
    #[deriving(Copy)]
    struct Vertex {
        field1: [f32, ..2],
        field2: [i32, ..3],
    }

    let vertex_buffer = glium::VertexBuffer::new(&display, vec![
            Vertex { field1: [0.0, 0.0], field2: [0, 0, 0] }
        ]);
    let index_buffer = glium::IndexBuffer::new(&display,
                            glium::index_buffer::PointsList(vec![0u16]));

    let program = glium::Program::new(&display,
        // vertex shader
        "
            #version 110

            attribute vec2 field1;
            attribute ivec3 field2;

            void main() {
                float z = 0.0;
                gl_Position = vec4(field1, z, 1.0);
            }
        ",
        "
            #version 110
            void main() {
                gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
            }
        ",

        // geometry shader
        None)
        .unwrap();

    // drawing a frame
    let mut target = display.draw();
    target.draw(&vertex_buffer, &index_buffer, &program, &glium::uniforms::EmptyUniforms,
                &std::default::Default::default());
    target.finish();

    display.assert_no_error();
}

#[test]
#[should_fail(expected = "The program attributes do not match the vertex format")]
fn attribute_types_mismatch() {
    let display = support::build_display();

    #[vertex_format]
    #[deriving(Copy)]
    struct Vertex {
        field1: [f32, ..4],
    }

    let vertex_buffer = glium::VertexBuffer::new(&display, Vec::<Vertex>::new());
    let index_buffer = glium::IndexBuffer::new(&display,
                            glium::index_buffer::PointsList(Vec::<u16>::new()));

    let program = glium::Program::new(&display,
        // vertex shader
        "
            #version 110

            attribute vec2 field1;

            void main() {
                gl_Position = vec4(field1, 0.0, 1.0);
            }
        ",
        "
            #version 110
            void main() {
                gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
            }
        ",

        // geometry shader
        None)
        .unwrap();

    // drawing a frame
    let mut target = display.draw();
    target.draw(&vertex_buffer, &index_buffer, &program, &glium::uniforms::EmptyUniforms,
                &std::default::Default::default());
    target.finish();

    display.assert_no_error();
}
<|endoftext|>


<commit_before><commit_msg>Add debug output<commit_after><|endoftext|>


<commit_before><commit_msg>Force a rebuild when spirv-reflect.cpp changes, rerun-if-changed in build.rs (partial fix for issue #44)<commit_after><|endoftext|>