factor out common code out of per-trait implementation
This commit is contained in:
parent
ed66afe4b4
commit
3181644cee
41
src/lib.rs
41
src/lib.rs
|
|
@ -1,14 +1,15 @@
|
|||
#![feature(
|
||||
ptr_metadata,
|
||||
ptr_as_ref_unchecked,
|
||||
sized_hierarchy,
|
||||
generic_const_exprs,
|
||||
inherent_associated_types
|
||||
)]
|
||||
|
||||
use std::{marker::PhantomData, ops, ptr};
|
||||
use std::{marker::PhantomData, mem::ManuallyDrop, ops, ptr};
|
||||
|
||||
#[repr(C, align(16))]
|
||||
struct Data([*mut u8; 6]);
|
||||
struct Data([*mut std::ffi::c_void; 6]);
|
||||
|
||||
pub struct Dyn<'a, Trait: ?Sized + 'a> {
|
||||
_phantom1: PhantomData<Trait>,
|
||||
|
|
@ -33,6 +34,29 @@ impl<'a, Trait: ?Sized + 'a> Dyn<'a, Trait> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Trait: ?Sized + 'a> Dyn<'a, Trait>
|
||||
where
|
||||
Trait: ptr::Pointee<Metadata = ptr::DynMetadata<Trait>>,
|
||||
{
|
||||
/// SAFETY:
|
||||
/// The pointer must be valid for moving from.
|
||||
/// The value must fit into `Data` (by size and align).
|
||||
unsafe fn from_ptr(value: *mut Self::Target) -> Self {
|
||||
let (data, meta): (_, ptr::DynMetadata<_>) = value.to_raw_parts();
|
||||
debug_assert!(meta.size_of() <= std::mem::size_of::<Data>());
|
||||
debug_assert!(meta.align_of() <= std::mem::align_of::<Data>());
|
||||
let mut ret = Self {
|
||||
_phantom1: PhantomData,
|
||||
_phantom2: PhantomData,
|
||||
meta,
|
||||
data: Data([ptr::null_mut(); _]),
|
||||
};
|
||||
let pdata = ret.data.0.as_mut_ptr();
|
||||
unsafe { ptr::copy_nonoverlapping(data as *const u8, pdata as *mut u8, meta.size_of()) };
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Trait: ?Sized + 'a> Drop for Dyn<'a, Trait> {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: `self` is valid for writing, and won't be accessed later.
|
||||
|
|
@ -62,16 +86,9 @@ where
|
|||
[(); std::mem::align_of::<Data>() - std::mem::align_of::<Iter>()]:,
|
||||
{
|
||||
fn from(value: Iter) -> Self {
|
||||
let (_, meta) = (&value as &Self::Target as *const Self::Target).to_raw_parts();
|
||||
let mut ret = Self {
|
||||
_phantom1: PhantomData,
|
||||
_phantom2: PhantomData,
|
||||
meta,
|
||||
data: Data([std::ptr::null_mut(); _]),
|
||||
};
|
||||
let pdata = ret.data.0.as_mut_ptr();
|
||||
unsafe { (pdata as *mut Iter).write(value) };
|
||||
ret
|
||||
let mut value = ManuallyDrop::new(value);
|
||||
let ptr = &mut *value as &mut Self::Target as *mut Self::Target;
|
||||
unsafe { Self::from_ptr(ptr) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user