use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::ptr;
use {Message, ToMessage};
#[allow(missing_copy_implementations)]
pub enum Owned { }
#[allow(missing_copy_implementations)]
pub enum Shared { }
pub trait Ownership { }
impl Ownership for Owned { }
impl Ownership for Shared { }
#[unsafe_no_drop_flag]
pub struct Id<T: Message, O: Ownership = Owned> {
ptr: *mut T,
}
impl<T: Message, O: Ownership> Id<T, O> {
pub unsafe fn from_ptr(ptr: *mut T) -> Id<T, O> {
match Id::maybe_from_ptr(ptr) {
Some(id) => id,
None => panic!("Attempted to construct an Id from a null pointer"),
}
}
pub unsafe fn from_retained_ptr(ptr: *mut T) -> Id<T, O> {
match Id::maybe_from_retained_ptr(ptr) {
Some(id) => id,
None => panic!("Attempted to construct an Id from a null pointer"),
}
}
pub unsafe fn maybe_from_ptr(ptr: *mut T) -> Option<Id<T, O>> {
msg_send![ptr, retain];
Id::maybe_from_retained_ptr(ptr)
}
pub unsafe fn maybe_from_retained_ptr(ptr: *mut T) -> Option<Id<T, O>> {
if ptr.is_null() {
None
} else {
Some(Id { ptr: ptr })
}
}
}
impl<T: Message> Id<T, Owned> {
pub fn share(self) -> ShareId<T> {
let ptr = self.ptr;
unsafe {
mem::forget(self);
}
Id { ptr: ptr }
}
}
impl<T: Message, O: Ownership> ToMessage<T> for Id<T, O> {
fn as_ptr(&self) -> *mut T {
self.ptr
}
}
impl<T: Message> Clone for Id<T, Shared> {
fn clone(&self) -> ShareId<T> {
let ptr = self.ptr;
unsafe {
msg_send![ptr, retain];
}
Id { ptr: ptr }
}
}
#[unsafe_destructor]
impl<T: Message, O: Ownership> Drop for Id<T, O> {
fn drop(&mut self) {
if !self.ptr.is_null() {
let ptr = mem::replace(&mut self.ptr, ptr::null_mut());
unsafe {
msg_send![ptr, release];
}
}
}
}
impl<T: Message, O: Ownership> Deref for Id<T, O> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.ptr }
}
}
impl<T: Message> DerefMut for Id<T, Owned> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.ptr }
}
}
impl<T: Message + PartialEq, O: Ownership> PartialEq for Id<T, O> {
fn eq(&self, other: &Id<T, O>) -> bool {
self.deref() == other.deref()
}
fn ne(&self, other: &Id<T, O>) -> bool {
self.deref() != other.deref()
}
}
impl<T: Message + Eq, O: Ownership> Eq for Id<T, O> { }
impl<H: Hasher, T: Message + Hash<H>, O: Ownership> Hash<H> for Id<T, O> {
fn hash(&self, state: &mut H) {
self.deref().hash(state)
}
}
impl<T: Message + fmt::Show, O: Ownership> fmt::Show for Id<T, O> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.deref().fmt(f)
}
}
pub type ShareId<T> = Id<T, Shared>;
pub trait IdVector<T> {
fn as_refs_slice(&self) -> &[&T];
}
impl<T: Message, O: Ownership> IdVector<T> for [Id<T, O>] {
fn as_refs_slice(&self) -> &[&T] {
unsafe {
mem::transmute(self)
}
}
}
pub trait IntoIdVector<T> {
unsafe fn into_id_vec<O: Ownership>(self) -> Vec<Id<T, O>>;
}
impl<T: Message, R: ToMessage<T>> IntoIdVector<T> for Vec<R> {
unsafe fn into_id_vec<O: Ownership>(self) -> Vec<Id<T, O>> {
self.map_in_place(|obj| Id::from_ptr(obj.as_ptr()))
}
}