#![feature(core_intrinsics,unsize)] #![cfg_attr(no_std,feature(no_std,core_slice_ext))]
#![cfg_attr(no_std,no_std)]
#![crate_type="lib"]
#![crate_name="stack_dst"]
#[cfg(not(no_std))]
use std::{ops,mem,intrinsics,slice,marker};
#[cfg(no_std)]
use core::{ops,mem,intrinsics,slice,marker};
const DST_SIZE: usize = 8+1;
pub struct StackDST<T: ?Sized>
{
_align: [u64; 0],
_pd: marker::PhantomData<T>,
data: [usize; DST_SIZE],
}
unsafe fn ptr_as_slice<'p, T: ?Sized>(ptr: &'p mut &T) -> &'p mut [usize] {
assert!( mem::size_of::<&T>() % mem::size_of::<usize>() == 0 );
let words = mem::size_of::<&T>() / mem::size_of::<usize>();
slice::from_raw_parts_mut(ptr as *mut &T as *mut usize, words)
}
unsafe fn as_ptr<T: ?Sized>(s: &StackDST<T>) -> *mut T {
let mut ret: &T = mem::zeroed();
{
let ret_as_slice = ptr_as_slice(&mut ret);
ret_as_slice[0] = s.data[..].as_ptr() as usize;
let info_size = ret_as_slice.len() - 1;
let info_ofs = s.data.len() - info_size;
for i in (0 .. info_size) {
ret_as_slice[1+i] = s.data[info_ofs + i];
}
}
ret as *const _ as *mut _
}
impl<T: ?Sized> StackDST<T>
{
pub fn new<U: marker::Unsize<T>>(val: U) -> Result<StackDST<T>,U> {
let rv = unsafe {
let mut ptr: &T = &val;
let words = ptr_as_slice(&mut ptr);
assert!(words[0] == &val as *const _ as usize, "BUG: Pointer layout is not (data_ptr, info...)");
assert!(mem::align_of::<U>() <= mem::align_of::<Self>(), "TODO: Enforce alignment >{} (requires {})",
mem::align_of::<Self>(), mem::align_of::<U>());
StackDST::new_raw(&words[1..], words[0] as *mut (), mem::size_of::<U>())
};
match rv
{
Some(r) => {
mem::forget(val);
Ok(r)
},
None => {
Err(val)
},
}
}
unsafe fn new_raw(info: &[usize], data: *mut (), size: usize) -> Option<StackDST<T>>
{
if info.len()*mem::size_of::<usize>() + size > mem::size_of::<[usize; DST_SIZE]>() {
None
}
else {
let mut rv = StackDST {
_align: [],
_pd: marker::PhantomData,
data: mem::zeroed(),
};
{
let info_ofs = rv.data.len() - info.len();
let info_dst = &mut rv.data[info_ofs..];
for (d,v) in Iterator::zip( info_dst.iter_mut(), info.iter() ) {
*d = *v;
}
}
let src_ptr = data as *const u8;
let dataptr = rv.data[..].as_mut_ptr() as *mut u8;
for i in (0 .. size) {
*dataptr.offset(i as isize) = *src_ptr.offset(i as isize);
}
Some(rv)
}
}
}
impl<T: ?Sized> ops::Deref for StackDST<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
&*as_ptr(self)
}
}
}
impl<T: ?Sized> ops::DerefMut for StackDST<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
&mut *as_ptr(self)
}
}
}
impl<T: ?Sized> ops::Drop for StackDST<T> {
fn drop(&mut self) {
unsafe {
intrinsics::drop_in_place(&mut **self)
}
}
}