extern crate libc;
use libc::{free, c_char, c_void, size_t};
use std::borrow::Borrow;
use std::ffi::{CString, CStr};
use std::{fmt, mem, str};
use std::ops::{Deref, DerefMut, Drop};
use std::cmp::PartialEq;
use std::marker::PhantomData;
pub trait DisposeRef {
type RefTo;
unsafe fn dispose(ptr: *mut Self::RefTo) {
free(ptr as *mut c_void);
}
}
pub struct CSemiBox<'a, D:?Sized> where D:DisposeRef+'a {
ptr: *mut D::RefTo,
marker: PhantomData<&'a ()>
}
impl<'a, D:?Sized> CSemiBox<'a, D> where D:DisposeRef+'a {
#[inline(always)]
pub fn new(ptr: *mut D::RefTo) -> Self {
CSemiBox {
ptr: ptr,
marker: PhantomData
}
}
#[inline(always)]
pub unsafe fn as_ptr(&self) -> *mut D::RefTo {
self.ptr
}
#[inline(always)]
pub unsafe fn unwrap(self) -> *mut D::RefTo {
let ptr = self.ptr;
mem::forget(self);
ptr
}
}
impl<'a, D:?Sized> From<*mut D::RefTo> for CSemiBox<'a, D> where D:DisposeRef+'a {
#[inline(always)]
fn from(ptr: *mut D::RefTo) -> Self {
CSemiBox::new(ptr)
}
}
impl<'a, D:?Sized> Drop for CSemiBox<'a, D> where D:DisposeRef+'a {
#[inline(always)]
fn drop(&mut self) {
unsafe { <D as DisposeRef>::dispose(self.ptr) }
}
}
impl<'a, D> Deref for CSemiBox<'a, D> where D:DisposeRef+'a, *mut D::RefTo:Into<&'a D> {
type Target = D;
fn deref(&self) -> &D {
self.ptr.into()
}
}
impl<'a, D> Borrow<D> for CSemiBox<'a, D> where D:DisposeRef+'a, *mut D::RefTo:Into<&'a D> {
fn borrow(&self) -> &D {
self.ptr.into()
}
}
impl<'a, D> DerefMut for CSemiBox<'a, D> where D:DisposeRef+'a, *mut D::RefTo:Into<&'a D>, *mut D::RefTo:Into<&'a mut D> {
fn deref_mut(&mut self) -> &mut D {
self.ptr.into()
}
}
impl<'a, T> fmt::Display for CSemiBox<'a, T> where T:fmt::Display+DisposeRef+'a, *mut T::RefTo:Into<&'a T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self as &T, fmt)
}
}
impl<'a, T> fmt::Debug for CSemiBox<'a, T> where T:fmt::Debug+DisposeRef+'a, *mut T::RefTo:Into<&'a T> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self as &T, fmt)
}
}
impl<'a, T> PartialEq<T> for CSemiBox<'a, T> where T:'a+DisposeRef+PartialEq, *mut T::RefTo:Into<&'a T> {
fn eq(&self, other: &T) -> bool {
(self as &T).eq(other)
}
}
impl<'a> From<&'a CStr> for CSemiBox<'a, str> {
fn from(text: &'a CStr) -> CSemiBox<'a, str> {
CSemiBox::new(text.as_ptr() as *mut c_char)
}
}
impl DisposeRef for str {
type RefTo = c_char;
}
pub struct CBox<D:?Sized> where D:DisposeRef {
ptr: *mut D::RefTo
}
impl<D:?Sized> CBox<D> where D:DisposeRef {
#[inline(always)]
pub fn new(ptr: *mut D::RefTo) -> Self {
CBox {
ptr: ptr
}
}
#[inline(always)]
pub unsafe fn as_ptr(&self) -> *mut D::RefTo {
self.ptr
}
#[inline(always)]
pub unsafe fn unwrap(self) -> *mut D::RefTo {
let ptr = self.ptr;
mem::forget(self);
ptr
}
pub fn as_semi<'a>(&'a self) -> &CSemiBox<'a, D> {
unsafe {
mem::transmute(self)
}
}
pub fn as_semi_mut<'a>(&'a mut self) -> &mut CSemiBox<'a, D> {
unsafe {
mem::transmute(self)
}
}
}
impl<'a> From<&'a str> for CBox<str> {
fn from(text: &'a str) -> CBox<str> {
unsafe {
let cstr = CString::new(text).unwrap();
let ptr = libc::malloc(text.len() as size_t + 1) as *mut c_char;
libc::strcpy(ptr, cstr.as_ptr());
CBox::new(ptr)
}
}
}
impl<'a> Deref for CBox<str> {
type Target = str;
fn deref(&self) -> &str {
unsafe {
let text = CStr::from_ptr(self.ptr);
str::from_utf8_unchecked(text.to_bytes())
}
}
}
impl Clone for CBox<str> {
fn clone(&self) -> CBox<str> {
unsafe {
let ptr = libc::malloc(self.len() as size_t + 1) as *mut c_char;
libc::strcpy(ptr, self.ptr);
CBox::new(ptr)
}
}
}
impl fmt::Display for CBox<str> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(self.deref())
}
}
impl fmt::Debug for CBox<str> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(self.deref())
}
}
impl<T> Deref for CBox<T> where T:DisposeRef {
type Target = T;
fn deref(&self) -> &T {
unsafe { mem::transmute(self.ptr) }
}
}
impl<T> Borrow<T> for CBox<T> where T:DisposeRef {
fn borrow(&self) -> &T {
unsafe { mem::transmute(self.ptr) }
}
}
impl<T> DerefMut for CBox<T> where T:DisposeRef {
fn deref_mut(&mut self) -> &mut T {
unsafe { mem::transmute(self.ptr) }
}
}
impl<'a, T> PartialEq<T> for CBox<T> where T:'a+DisposeRef+PartialEq, *mut T::RefTo:Into<&'a T> {
fn eq(&self, other: &T) -> bool {
unsafe {
mem::transmute::<_, &T>(self.ptr) == other
}
}
}