use std::marker::Unsize;
use std::mem::{align_of_val, size_of_val};
use std::ops::CoerceUnsized;
use std::ptr;
use std::ptr::{metadata, Pointee};
pub struct DynArg<T: ?Sized>(*const T);
impl<T: ?Sized> DynArg<T> {
pub unsafe fn from_raw(x: *const T) -> Self {
DynArg(x)
}
pub fn as_ptr(&self) -> *const T {
self.0
}
pub fn size(&self) -> usize {
size_of_val(unsafe { &*self.0 })
}
pub fn align(&self) -> usize {
align_of_val(unsafe { &*self.0 })
}
pub fn metadata(&self) -> <T as Pointee>::Metadata {
metadata(self.0)
}
pub unsafe fn write_into(self, dst: *mut T) {
ptr::copy_nonoverlapping(self.0 as *const u8, dst as *mut u8, self.size());
}
}
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<DynArg<U>> for DynArg<T> {}
pub macro dyn_arg($($input:tt)*) { {
let val = $($input)*;
let result = unsafe { DynArg::from_raw(&val) };
::std::mem::forget(val);
result
} }