ev 0.1.0

Cross-platform event loop primitives for unix systems.
use {Errno, Result, Signal};

use std::marker;
use std::mem;
use std::ptr;
use libc;


/// Resizable array backed by malloc.
pub struct Slab<T> {
    ptr: *mut libc::c_void,
    mark: marker::PhantomData<T>,
}

impl<T> Slab<T> {
    pub fn allocate(n: usize) -> Result<Self> {
        let ptr = unsafe { libc::malloc(mem::size_of::<T>() * n) };
        if ptr.is_null() {
            return Err(libc::ENOMEM);
        }

        Ok(Slab {
            ptr: ptr,
            mark: marker::PhantomData,
        })
    }

    pub fn resize(&mut self, n: usize) -> Result<()> {
        let ptr = unsafe { libc::realloc(self.ptr, mem::size_of::<T>() * n) };
        if ptr.is_null() {
            return Err(libc::ENOMEM);
        }

        self.ptr = ptr;
        Ok(())
    }

    pub fn as_ptr(&self) -> *const T {
        self.ptr as *const T
    }

    pub fn as_mut_ptr(&self) -> *mut T {
        self.ptr as *mut T
    }
}

impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        unsafe {
            libc::free(self.ptr);
        }
    }
}


/// Register a signal handler.
pub fn sigaction(signal: Signal, handler: libc::sighandler_t) -> Result<()> {
    unsafe {
        let mut act: libc::sigaction = mem::zeroed();
        act.sa_sigaction = handler;

        let r = libc::sigaction(signal, &act, ptr::null_mut());
        if r != 0 {
            Err(errno())
        } else {
            Ok(())
        }
    }
}


/// Read the current `errno` value.
pub fn errno() -> Errno {
    unsafe { *__errno() }
}

#[cfg(target_os = "macos")]
unsafe fn __errno() -> *mut libc::c_int { libc::__error() }