Skip to main content

extern_trait/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3
4pub use extern_trait_impl::*;
5
6/// Opaque representation used to store implementation types in proxy structs.
7///
8/// This type is two pointers in size, which means implementation types must be
9/// at most `2 * size_of::<usize>()` bytes (16 bytes on 64-bit, 8 bytes on 32-bit).
10/// On 32-bit targets it is 8-byte aligned so common 64-bit primitives can
11/// still be stored inline without making the proxy larger.
12///
13/// The size and alignment constraints are checked at compile time.
14#[doc(hidden)]
15#[derive(Clone, Copy)]
16#[repr(C)]
17#[cfg_attr(target_pointer_width = "32", repr(align(8)))]
18pub struct Repr(
19    *mut (),
20    *mut (),
21    // make this type `!Send + !Sync + !Unpin + !UnwindSafe + !RefUnwindSafe + !Freeze`
22    core::marker::PhantomData<(
23        &'static mut (),
24        core::cell::UnsafeCell<()>,
25        core::marker::PhantomPinned,
26    )>,
27);
28
29const _: () = assert!(size_of::<Repr>() == size_of::<usize>() * 2);
30
31impl Repr {
32    #[doc(hidden)]
33    #[inline]
34    pub unsafe fn from_value<T: Sized>(value: T) -> Self {
35        const { assert!(size_of::<T>() <= size_of::<Repr>()) };
36        const { assert!(align_of::<T>() <= align_of::<Repr>()) };
37        let mut repr = core::mem::MaybeUninit::<Repr>::zeroed();
38        // SAFETY: We just asserted that T fits in Repr and does not require stricter alignment.
39        unsafe {
40            core::ptr::write(repr.as_mut_ptr().cast::<T>(), value);
41            repr.assume_init()
42        }
43    }
44
45    #[doc(hidden)]
46    #[inline]
47    pub unsafe fn into_value<T: Sized>(self) -> T {
48        const { assert!(size_of::<T>() <= size_of::<Repr>()) };
49        const { assert!(align_of::<T>() <= align_of::<Repr>()) };
50        // SAFETY: We require that T fits in Repr and does not require stricter alignment,
51        // and the caller ensures the Repr was created from a valid T.
52        unsafe { core::ptr::read((&self as *const Repr).cast::<T>()) }
53    }
54}
55
56#[doc(hidden)]
57pub mod __private {
58    #[doc(hidden)]
59    pub use typeid::ConstTypeId;
60}