use crate::{
abi_stability::{GetStaticEquivalent, GetStaticEquivalent_, PrefixStableAbi, StableAbi},
pointer_trait::{GetPointerKind, PK_Reference},
prefix_type::{FieldAccessibility, PTStructLayout, PrefixRefTrait, WithMetadata_},
reexports::True,
reflection::ModReflMode,
sabi_types::StaticRef,
std_types::RSlice,
type_layout::{
CompTLField, GenericTLData, LifetimeRange, MonoTLData, MonoTypeLayout, ReprAttr, TypeLayout,
},
utils::Transmuter,
};
use std::{
fmt::{self, Debug},
ptr::NonNull,
};
#[repr(transparent)]
pub struct PrefixRef<P> {
ptr: NonNull<WithMetadata_<P, P>>,
}
impl<P> Clone for PrefixRef<P> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<P> Copy for PrefixRef<P> {}
unsafe impl<'a, P: 'a> Sync for PrefixRef<P> where &'a WithMetadata_<P, P>: Sync {}
unsafe impl<'a, P: 'a> Send for PrefixRef<P> where &'a WithMetadata_<P, P>: Send {}
impl<P> Debug for PrefixRef<P> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PrefixRef")
.field("type_layout", &self.type_layout())
.field("field_accessibility", &self.field_accessibility())
.field("value_type", &std::any::type_name::<P>())
.finish()
}
}
impl<P> PrefixRef<P> {
#[inline(always)]
pub const unsafe fn from_raw<T>(ptr: *const WithMetadata_<T, P>) -> Self {
Self {
ptr: unsafe {
NonNull::new_unchecked(
ptr as *const WithMetadata_<P, P> as *mut WithMetadata_<P, P>,
)
},
}
}
#[inline]
pub const fn from_staticref<T>(ptr: StaticRef<WithMetadata_<T, P>>) -> Self {
unsafe { Self::from_raw(ptr.as_ptr()) }
}
#[inline]
pub const fn from_ref<T>(ptr: &'static WithMetadata_<T, P>) -> Self {
unsafe { Self::from_raw(ptr) }
}
pub const fn field_accessibility(&self) -> FieldAccessibility {
let ptr: *const _ = self.ptr.as_ptr();
unsafe { (*ptr).field_accessibility }
}
pub const fn type_layout(&self) -> &'static PTStructLayout {
let ptr: *const _ = self.ptr.as_ptr();
unsafe { (*ptr).type_layout }
}
#[inline]
pub const fn prefix<'a>(self) -> &'a P {
let ptr: *const _ = self.ptr.as_ptr();
unsafe { &(*ptr).value.0 }
}
#[inline(always)]
pub const fn to_raw_ptr(self) -> *const WithMetadata_<P, P> {
unsafe { Transmuter { from: self }.to }
}
pub const unsafe fn cast<U>(self) -> PrefixRef<U> {
PrefixRef {
ptr: self.ptr.cast(),
}
}
}
unsafe impl<P> GetStaticEquivalent_ for PrefixRef<P>
where
P: GetStaticEquivalent_,
{
type StaticEquivalent = PrefixRef<GetStaticEquivalent<P>>;
}
unsafe impl<P> StableAbi for PrefixRef<P>
where
P: PrefixStableAbi,
{
type IsNonZeroType = True;
const LAYOUT: &'static TypeLayout = {
const MONO_TYPE_LAYOUT: &MonoTypeLayout = &MonoTypeLayout::new(
*mono_shared_vars,
rstr!("PrefixRef"),
make_item_info!(),
MonoTLData::struct_(rslice![]),
tl_genparams!('a;0;),
ReprAttr::Transparent,
ModReflMode::DelegateDeref { layout_index: 0 },
{
const S: &[CompTLField] =
&[CompTLField::std_field(field0, LifetimeRange::EMPTY, 0)];
RSlice::from_slice(S)
},
);
make_shared_vars! {
impl[P] PrefixRef<P>
where [P: PrefixStableAbi];
let (mono_shared_vars,shared_vars)={
strings={ field0:"0", },
prefix_type_layouts=[P],
};
}
&TypeLayout::from_std::<Self>(
shared_vars,
MONO_TYPE_LAYOUT,
Self::ABI_CONSTS,
GenericTLData::Struct,
)
};
}
unsafe impl<P> GetPointerKind for PrefixRef<P> {
type PtrTarget = WithMetadata_<P, P>;
type Kind = PK_Reference;
}
unsafe impl<P> PrefixRefTrait for PrefixRef<P> {
type PrefixFields = P;
}