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(
|
#![feature(
|
||||||
ptr_metadata,
|
ptr_metadata,
|
||||||
ptr_as_ref_unchecked,
|
ptr_as_ref_unchecked,
|
||||||
|
sized_hierarchy,
|
||||||
generic_const_exprs,
|
generic_const_exprs,
|
||||||
inherent_associated_types
|
inherent_associated_types
|
||||||
)]
|
)]
|
||||||
|
|
||||||
use std::{marker::PhantomData, ops, ptr};
|
use std::{marker::PhantomData, mem::ManuallyDrop, ops, ptr};
|
||||||
|
|
||||||
#[repr(C, align(16))]
|
#[repr(C, align(16))]
|
||||||
struct Data([*mut u8; 6]);
|
struct Data([*mut std::ffi::c_void; 6]);
|
||||||
|
|
||||||
pub struct Dyn<'a, Trait: ?Sized + 'a> {
|
pub struct Dyn<'a, Trait: ?Sized + 'a> {
|
||||||
_phantom1: PhantomData<Trait>,
|
_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> {
|
impl<'a, Trait: ?Sized + 'a> Drop for Dyn<'a, Trait> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// SAFETY: `self` is valid for writing, and won't be accessed later.
|
// 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>()]:,
|
[(); std::mem::align_of::<Data>() - std::mem::align_of::<Iter>()]:,
|
||||||
{
|
{
|
||||||
fn from(value: Iter) -> Self {
|
fn from(value: Iter) -> Self {
|
||||||
let (_, meta) = (&value as &Self::Target as *const Self::Target).to_raw_parts();
|
let mut value = ManuallyDrop::new(value);
|
||||||
let mut ret = Self {
|
let ptr = &mut *value as &mut Self::Target as *mut Self::Target;
|
||||||
_phantom1: PhantomData,
|
unsafe { Self::from_ptr(ptr) }
|
||||||
_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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user