use std::{
cmp::{PartialEq,Eq},
cell::RefCell,
collections::HashSet,
fmt::{self, Debug, Display, Formatter},
mem::{self,ManuallyDrop},
};
use core_extensions::{matches,StringExt};
use crate::{
abi_stability::{
extra_checks::{StoredExtraChecks,ExtraChecksStaticRef},
stable_abi_trait::{TypeLayoutCtor,AbiConsts},
},
const_utils::log2_usize,
sabi_types::VersionStrings,
sabi_types::{CmpIgnored,Constructor,NulStr},
std_types::{RStr,RSlice,UTypeId},
prefix_type::{FieldAccessibility,FieldConditionality},
reflection::ModReflMode,
};
mod construction;
pub mod data_structures;
mod iterators;
mod shared_vars;
mod small_types;
mod printing;
pub mod tagging;
mod tl_data;
mod tl_enums;
mod tl_field;
mod tl_fields;
mod tl_functions;
mod tl_lifetimes;
mod tl_multi_tl;
mod tl_other;
mod tl_prefix;
mod tl_reflection;
pub(crate) use self::{
iterators::ChainOnce,
};
pub use self::{
construction::{
_private_TypeLayoutDerive,
_private_MonoTypeLayoutDerive,
ItemInfo,
},
shared_vars::{
SharedVars,
MonoSharedVars,
},
small_types::{
StartLen,
StartLenRepr,
StartLenConverter,
OptionU16,
OptionU8,
},
tl_data::{
GenericTLData,
MismatchedTLDataVariant,
MonoTLData,
TLData,
TLDataDiscriminant,
},
tl_enums::{
DiscriminantRepr,
GenericTLEnum,
IncompatibleWithNonExhaustive,
IsExhaustive,
MonoTLEnum,
TLDiscriminant,
TLDiscriminants,
TLEnum,
TLNonExhaustive,
MakeTLNonExhaustive,
},
tl_field::{
CompTLField,
CompTLFieldRepr,
TLField,
},
tl_fields::{
CompTLFields,
TLFields,
TLFieldsIterator,
},
tl_functions::{
TLFunctionIter,
TLFunctions,
TLFunctionSlice,
CompTLFunction,
TLFunction,
},
tl_lifetimes::{
LifetimeArrayOrSlice,
LifetimeIndex,
LifetimeIndexArray,
LifetimeIndexPair,
LifetimeIndexPairRepr,
LifetimeRange,
},
tl_multi_tl::{
TypeLayoutIndex,
TypeLayoutRange,
MultipleTypeLayouts,
MTLIterator,
},
tl_other::{
CompGenericParams,
FmtFullType,
GenericParams,
ModPath,
ReprAttr,
TLFieldOrFunction,
TLPrimitive,
},
tl_prefix::{
GenericTLPrefixType,
MonoTLPrefixType,
TLPrefixType,
},
tl_reflection::{
CompFieldAccessor,
FieldAccessor,
},
tagging::Tag,
};
#[repr(C)]
#[derive(Copy, Clone,StableAbi)]
#[sabi(unsafe_sabi_opaque_fields)]
pub struct TypeLayout {
shared_vars: &'static SharedVars,
mono:&'static MonoTypeLayout,
is_nonzero: bool,
alignment_power_of_two: u8,
size: usize,
tag:Option<&'static Tag>,
data:GenericTLData,
extra_checks:CmpIgnored<Option<&'static ManuallyDrop<StoredExtraChecks>>>,
type_id:Constructor<UTypeId>,
}
unsafe impl Send for TypeLayout{}
unsafe impl Sync for TypeLayout{}
unsafe impl Send for MonoTypeLayout{}
unsafe impl Sync for MonoTypeLayout{}
impl TypeLayout {
pub(crate) const fn from_std<T>(
shared_vars: &'static SharedVars,
mono:&'static MonoTypeLayout,
abi_consts:AbiConsts,
data: GenericTLData,
) -> Self {
Self {
shared_vars,
mono,
is_nonzero:abi_consts.is_nonzero,
type_id:abi_consts.type_id,
alignment_power_of_two: log2_usize(mem::align_of::<T>()),
size: mem::size_of::<T>(),
data,
extra_checks:CmpIgnored::new(None),
tag:None,
}
}
#[doc(hidden)]
pub const fn from_derive<T>(p: _private_TypeLayoutDerive) -> Self {
Self {
shared_vars: p.shared_vars,
mono: p.mono,
is_nonzero: p.abi_consts.is_nonzero,
type_id: p.abi_consts.type_id,
alignment_power_of_two: log2_usize(mem::align_of::<T>()),
size: mem::size_of::<T>(),
data: p.data,
extra_checks:CmpIgnored::new(p.extra_checks),
tag:p.tag,
}
}
pub const fn shared_vars(&self)->&'static SharedVars{
self.shared_vars
}
#[doc(hidden)]
pub fn full_type(&self) -> FmtFullType {
FmtFullType{
name: self.mono.name(),
generics: self.generics(),
primitive: self.mono.data.to_primitive(),
utypeid: self.get_utypeid(),
}
}
pub fn package_and_version(&self)->(RStr<'static>,VersionStrings){
let (package,version)=self.item_info().package_and_version();
(
RStr::from_str(package),
VersionStrings::new(version)
)
}
pub fn package(&self)->RStr<'static>{
let (package,_)=self.item_info().package_and_version();
RStr::from_str(package)
}
pub fn package_version(&self)->VersionStrings{
let (_,version)=self.item_info().package_and_version();
VersionStrings::new(version)
}
pub fn line(&self)->u32{
self.item_info().line
}
pub fn mod_path(&self)->ModPath{
self.item_info().mod_path
}
#[inline]
pub fn extra_checks(&self)->Option<ExtraChecksStaticRef>{
self.extra_checks.value.map(|x| x.sabi_reborrow() )
}
pub fn get_fields(&self)->Option<TLFields>{
let fields=self.mono.get_fields()?;
Some(fields.expand(self.shared_vars))
}
pub fn is_prefix_kind(&self)->bool{
matches!(GenericTLData::PrefixType{..}=self.data)
}
#[inline]
pub fn name(&self)->&'static str{
self.mono.name()
}
#[inline]
pub fn is_nonzero(&self)->bool{
self.is_nonzero
}
#[doc(hidden)]
#[cfg(feature = "testing")]
pub const fn _set_is_nonzero(mut self,is_nonzero:bool)->Self{
self.is_nonzero=is_nonzero;
self
}
#[doc(hidden)]
#[cfg(feature = "testing")]
pub const fn _set_extra_checks(
mut self,
extra_checks:CmpIgnored<Option<&'static ManuallyDrop<StoredExtraChecks>>>
)->Self{
self.extra_checks=extra_checks;
self
}
#[doc(hidden)]
#[cfg(feature = "testing")]
pub const fn _set_type_id(
mut self,
type_id:Constructor<UTypeId>,
)->Self{
self.type_id=type_id;
self
}
#[inline]
pub fn get_utypeid(&self)->UTypeId{
self.type_id.get()
}
#[inline]
pub fn item_info(&self)->&ItemInfo{
&self.mono.item_info()
}
#[inline]
pub fn alignment(&self)->usize{
1_usize << (self.alignment_power_of_two as u32)
}
#[inline]
pub fn size(&self)->usize{
self.size
}
pub fn tag(&self)->&'static Tag{
self.tag.unwrap_or(Tag::NULL)
}
pub fn repr_attr(&self)->ReprAttr{
self.mono.repr_attr()
}
pub const fn mod_refl_mode(&self)->ModReflMode{
self.mono.mod_refl_mode()
}
pub fn data(&self)-> TLData {
self.mono.data
.expand(self.data,self.shared_vars)
.unwrap_or_else(|e|{
panic!("\nError inside of '{}' type \n{}",self.full_type(),e);
})
}
pub fn data_discriminant(&self)-> TLDataDiscriminant {
self.mono.data.as_discriminant()
}
#[inline]
pub fn phantom_fields(&self)->TLFields{
unsafe{
let slice=std::slice::from_raw_parts(
self.mono.phantom_fields,
self.mono.phantom_fields_len as usize,
);
TLFields::from_fields(slice,self.shared_vars)
}
}
pub fn generics(&self)->GenericParams{
self.mono.generics.expand(self.shared_vars)
}
pub fn mono_type_layout(&self)->&MonoTypeLayout{
&self.mono
}
}
impl PartialEq for TypeLayout{
fn eq(&self,other:&TypeLayout)->bool{
self.get_utypeid()==other.get_utypeid()
}
}
impl Eq for TypeLayout{}
#[repr(C)]
#[derive(Copy, Clone,StableAbi)]
#[sabi(unsafe_sabi_opaque_fields)]
pub struct MonoTypeLayout{
shared_vars:MonoSharedVars,
name: *const u8,
item_info:CmpIgnored<ItemInfo>,
data: MonoTLData,
generics: CompGenericParams,
phantom_fields: *const CompTLField,
phantom_fields_len: u8,
repr_attr:ReprAttr,
mod_refl_mode:ModReflMode,
name_len: u16,
}
#[allow(clippy::too_many_arguments)]
impl MonoTypeLayout{
pub(crate) const fn new(
shared_vars:MonoSharedVars,
name: RStr<'static>,
item_info:ItemInfo,
data: MonoTLData,
generics: CompGenericParams,
repr_attr:ReprAttr,
mod_refl_mode:ModReflMode,
phantom_fields:RSlice<'static,CompTLField>,
)->Self{
Self{
shared_vars,
name :name.as_ptr(),
name_len:name.len() as u16,
item_info:CmpIgnored::new(item_info),
data,
generics,
repr_attr,
mod_refl_mode,
phantom_fields: phantom_fields.as_ptr(),
phantom_fields_len: phantom_fields.len() as u8,
}
}
#[doc(hidden)]
pub const fn from_derive(p:_private_MonoTypeLayoutDerive)->Self{
Self{
name : p.name.as_ptr(),
name_len: p.name.len() as u16,
phantom_fields : p.phantom_fields.as_ptr()
as *const CompTLFieldRepr
as *const CompTLField,
phantom_fields_len: p.phantom_fields.len() as u8,
item_info: CmpIgnored::new(p.item_info),
data: p.data,
generics: p.generics,
repr_attr: p.repr_attr,
mod_refl_mode: p.mod_refl_mode,
shared_vars: p.shared_vars,
}
}
pub fn name(&self)->&'static str{
unsafe{
let slic=std::slice::from_raw_parts( self.name, self.name_len as usize );
std::str::from_utf8_unchecked(slic)
}
}
pub const fn repr_attr(&self)->ReprAttr{
self.repr_attr
}
pub const fn mod_refl_mode(&self)->ModReflMode{
self.mod_refl_mode
}
pub const fn item_info(&self)->&ItemInfo{
&self.item_info.value
}
pub const fn shared_vars(&self)->&MonoSharedVars{
&self.shared_vars
}
pub const fn shared_vars_static(&'static self)->&'static MonoSharedVars{
&self.shared_vars
}
pub fn get_fields(&self)->Option<CompTLFields>{
match self.data {
MonoTLData::Primitive{..}=>None,
MonoTLData::Opaque=>None,
MonoTLData::Struct{fields}=>Some(fields),
MonoTLData::Union{fields}=>Some(fields),
MonoTLData::Enum (tlenum)=>Some(tlenum.fields),
MonoTLData::PrefixType(prefix)=>Some(prefix.fields),
}
}
pub fn field_names(&self)->impl ExactSizeIterator<Item=&'static str>+Clone+'static{
self.get_fields()
.unwrap_or(CompTLFields::EMPTY)
.field_names( &self.shared_vars )
}
pub fn get_field_name(&self,nth:usize)->Option<&'static str>{
self.get_fields()
.unwrap_or(CompTLFields::EMPTY)
.get_field_name( nth, &self.shared_vars )
}
}
impl Debug for MonoTypeLayout{
fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
f.debug_struct("MonoTypeLayout")
.field("name",&self.name())
.field("item_info",self.item_info())
.field("repr_attr",&self.repr_attr())
.field("mod_refl_mode",&self.mod_refl_mode())
.finish()
}
}