use std::intrinsics::{ get_tydesc, TypeId };
#[allow(missing_copy_implementations)]
pub struct Ptr(TypeId, *const u8, &'static str);
impl Ptr {
#[inline(always)]
pub unsafe fn with<T: 'static, U>(ptr: *const u8, f: |&Ptr| -> U) -> U {
let name = (*get_tydesc::<T>()).name;
f(&Ptr(TypeId::of::<&T>(), ptr, name))
}
#[inline(always)]
pub fn with_str<U>(text: &str, f: |&Ptr| -> U) -> U {
unsafe { Ptr::with::<&str, U>(&text as *const &str as *const u8, f) }
}
#[inline(always)]
pub fn with_slice<T: 'static, U>(arr: &[T], f: |&Ptr| -> U) -> U {
unsafe { Ptr::with::<&[T], U>(&arr as *const &[T] as *const u8, f) }
}
#[inline(always)]
pub fn with_ref<T: 'static, U>(val: &T, f: |&Ptr| -> U) -> U {
unsafe { Ptr::with::<T, U>(val as *const T as *const u8, f) }
}
#[inline(always)]
pub fn cast<'a, T: 'static>(&'a self) -> Result<&'a T, String> {
let id = TypeId::of::<&T>();
let &Ptr(ptr_id, blob, name) = self;
if ptr_id == id {
Ok(unsafe { &*(blob as *const T) })
} else {
let expected_name = unsafe {
(*get_tydesc::<T>()).name
};
Err(format!("Expected `{}`, found `{}`", expected_name, name))
}
}
#[inline(always)]
pub fn expect_str(&self) -> &str {
*self.cast::<&str>().unwrap()
}
#[inline(always)]
pub fn expect_slice<T: 'static>(&self) -> &[T] {
*self.cast::<&[T]>().unwrap()
}
#[inline(always)]
pub fn expect<T: 'static>(&self) -> &T {
self.cast::<T>().unwrap()
}
}