use crate::{
LateFieldDescriptor, LateStructDescriptor, RawLateFieldDescriptor, RawLateStructDescriptor,
};
pub unsafe trait LateStruct: Sized + 'static + LateStructSealed {
type EraseTo: ?Sized + 'static;
fn raw_descriptor() -> &'static RawLateStructDescriptor;
fn descriptor() -> &'static LateStructDescriptor<Self> {
unsafe { Self::raw_descriptor().typed_unchecked() }
}
}
pub unsafe trait LateField<S: LateStruct>: Sized + 'static + LateFieldSealed<S> {
type Value: 'static + Default;
fn raw_descriptor() -> &'static RawLateFieldDescriptor;
fn descriptor() -> &'static LateFieldDescriptor<S> {
unsafe { Self::raw_descriptor().typed_unchecked() }
}
fn coerce(value: *mut Self::Value) -> *mut S::EraseTo;
}
mod sealed {
use super::LateStruct;
#[doc(hidden)]
pub trait LateStructSealed {}
#[doc(hidden)]
pub trait LateFieldSealed<S: LateStruct> {}
}
pub(crate) use sealed::{LateFieldSealed, LateStructSealed};
#[doc(hidden)]
pub mod late_macro_internals {
use std::{any::TypeId, fmt, marker::PhantomData};
pub use {
super::sealed::{LateFieldSealed, LateStructSealed},
crate::{
LateField, LateStruct, RawLateFieldDescriptor, RawLateStructDescriptor, late_field,
late_struct,
},
};
pub type DefaultEraseTo = dyn 'static + fmt::Debug;
pub const fn new_late_struct_descriptor<S: LateStruct>() -> RawLateStructDescriptor {
RawLateStructDescriptor::new::<S>()
}
pub const fn new_late_field_descriptor<S, F>() -> RawLateFieldDescriptor
where
S: LateStruct,
F: LateField<S>,
{
RawLateFieldDescriptor::new::<S, F>()
}
pub type OrDefault<Default, T = Default> =
<OrDefaultHelper<T, Default> as OrDefaultHelperTrait>::Out;
pub struct OrDefaultHelper<T, Ignore>(PhantomData<T>, PhantomData<Ignore>)
where
T: ?Sized,
Ignore: ?Sized;
pub trait OrDefaultHelperTrait {
type Out: ?Sized;
}
impl<T, Ignore> OrDefaultHelperTrait for OrDefaultHelper<T, Ignore>
where
T: ?Sized,
Ignore: ?Sized,
{
type Out = T;
}
#[derive(Debug, Copy, Clone)]
pub struct LateStructEntry {
pub struct_type: TypeId,
pub descriptor: &'static RawLateStructDescriptor,
}
impl LateStructEntry {
pub fn of<S: LateStruct>() -> Self {
Self {
struct_type: TypeId::of::<S>(),
descriptor: S::raw_descriptor(),
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct LateFieldEntry {
pub struct_type: TypeId,
pub descriptor: &'static RawLateFieldDescriptor,
}
impl LateFieldEntry {
pub fn of<S: LateStruct, F: LateField<S>>() -> Self {
Self {
struct_type: TypeId::of::<S>(),
descriptor: F::raw_descriptor(),
}
}
}
cfg_if::cfg_if! {
if #[cfg(target_family = "wasm")] {
pub use ::inventory;
pub struct LateStructEntryWrapper(pub fn() -> LateStructEntry);
pub struct LateFieldEntryWrapper(pub fn() -> LateFieldEntry);
inventory::collect!(LateStructEntryWrapper);
inventory::collect!(LateFieldEntryWrapper);
pub fn iter_late_structs() -> impl Iterator<Item = LateStructEntry> {
inventory::iter::<LateStructEntryWrapper>().map(|f| f.0())
}
pub fn iter_late_fields() -> impl Iterator<Item = LateFieldEntry> {
inventory::iter::<LateFieldEntryWrapper>().map(|f| f.0())
}
} else {
pub use ::linkme;
#[linkme::distributed_slice]
pub static LATE_STRUCTS: [fn() -> LateStructEntry];
#[linkme::distributed_slice]
pub static LATE_FIELDS: [fn() -> LateFieldEntry];
pub fn iter_late_structs() -> impl Iterator<Item = LateStructEntry> {
LATE_STRUCTS.iter().map(|&f| f())
}
pub fn iter_late_fields() -> impl Iterator<Item = LateFieldEntry> {
LATE_FIELDS.iter().map(|&f| f())
}
}
}
}
#[macro_export]
macro_rules! late_struct {
(
$($ty:ty $(=> $erase_to:ty)?),*
$(,)?
) => {$(
const _: () = {
static DESCRIPTOR: $crate::late_macro_internals::RawLateStructDescriptor =
$crate::late_macro_internals::new_late_struct_descriptor::<$ty>();
impl $crate::late_macro_internals::LateStructSealed for $ty {}
unsafe impl $crate::late_macro_internals::LateStruct for $ty {
type EraseTo = $crate::late_macro_internals::OrDefault<
$crate::late_macro_internals::DefaultEraseTo
$(, $erase_to)?
>;
fn raw_descriptor() -> &'static $crate::late_macro_internals::RawLateStructDescriptor {
&DESCRIPTOR
}
}
#[cfg(target_family = "wasm")]
$crate::late_macro_internals::inventory::submit! {
$crate::late_macro_internals::LateStructEntryWrapper(
$crate::late_macro_internals::LateStructEntry::of::<$ty>,
)
}
#[cfg(not(target_family = "wasm"))]
#[$crate::late_macro_internals::linkme::distributed_slice(
$crate::late_macro_internals::LATE_STRUCTS
)]
#[linkme(crate = $crate::late_macro_internals::linkme)]
static ENTRY: fn() -> $crate::late_macro_internals::LateStructEntry =
$crate::late_macro_internals::LateStructEntry::of::<$ty>;
};
)*};
}
#[macro_export]
macro_rules! late_field {
(
$($ty:ty [$ns:ty] $(=> $val:ty)?),*
$(,)?
) => {$(
const _: () = {
static DESCRIPTOR: $crate::late_macro_internals::RawLateFieldDescriptor =
$crate::late_macro_internals::new_late_field_descriptor::<$ns, $ty>();
impl $crate::late_macro_internals::LateFieldSealed<$ns> for $ty {}
unsafe impl $crate::late_macro_internals::LateField<$ns> for $ty {
type Value = $crate::late_macro_internals::OrDefault<$ty $(, $val)?>;
fn raw_descriptor() -> &'static $crate::late_macro_internals::RawLateFieldDescriptor {
&DESCRIPTOR
}
fn coerce(value: *mut Self::Value) -> *mut <$ns as $crate::late_macro_internals::LateStruct>::EraseTo {
value
}
}
#[cfg(target_family = "wasm")]
$crate::late_macro_internals::inventory::submit! {
$crate::late_macro_internals::LateFieldEntryWrapper(
$crate::late_macro_internals::LateFieldEntry::of::<$ns, $ty>,
)
}
#[cfg(not(target_family = "wasm"))]
#[$crate::late_macro_internals::linkme::distributed_slice(
$crate::late_macro_internals::LATE_FIELDS
)]
#[linkme(crate = $crate::late_macro_internals::linkme)]
static ENTRY: fn() -> $crate::late_macro_internals::LateFieldEntry =
$crate::late_macro_internals::LateFieldEntry::of::<$ns, $ty>;
};
)*};
}