use super::*;
use crate::{
abi_stability::{
stable_abi_trait::{MakeGetAbiInfo,StableAbi_Bound},
},
std_types::RVec,
};
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, StableAbi)]
pub enum LifetimeIndex {
Static,
Param(u8),
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, StableAbi)]
pub struct TLPrefixType {
pub first_suffix_field:usize,
pub accessible_fields:FieldAccessibility,
pub conditional_prefix_fields:StaticSlice<IsConditional>,
pub fields: TLFieldsOrSlice,
}
impl Display for TLPrefixType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f,"first_suffix_field:{}",self.first_suffix_field)?;
write!(f,"accessible_fields:\n ")?;
f.debug_list()
.entries(self.accessible_fields.iter_field_count(self.fields.len()))
.finish()?;
writeln!(f,)?;
writeln!(f,"conditional_prefix_fields:\n {:?}",self.conditional_prefix_fields)?;
writeln!(f,"fields:\n{}",self.fields.to_string().left_padder(4))?;
Ok(())
}
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, StableAbi)]
pub enum ReprAttr{
OptionNonZero,
Primitive,
C(ROption<DiscriminantRepr>),
Transparent,
Int(DiscriminantRepr),
#[doc(hidden)]
Packed{
alignment:usize,
}
}
impl ReprAttr{
pub const fn c()->Self{
ReprAttr::C(RNone)
}
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, StableAbi)]
pub enum ModPath{
NoPath,
In(StaticStr),
Prelude,
}
impl ModPath{
pub const fn inside(path:&'static str)->Self{
ModPath::In(StaticStr::new(path))
}
}
impl Display for ModPath{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ModPath::NoPath=>Display::fmt("<no path>",f),
ModPath::In(mod_)=>Display::fmt(mod_,f),
ModPath::Prelude=>Display::fmt("<prelude>",f),
}
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, StableAbi)]
pub struct GenericParams {
pub lifetime: StaticSlice<StaticStr>,
pub type_: StaticSlice<&'static TypeLayout>,
pub const_: StaticSlice<StaticStr>,
}
impl GenericParams {
pub const fn new(
lifetime: &'static [StaticStr],
type_: &'static [&'static TypeLayout],
const_: &'static [StaticStr],
) -> Self {
Self {
lifetime: StaticSlice::new(lifetime),
type_: StaticSlice::new(type_),
const_: StaticSlice::new(const_),
}
}
pub fn is_empty(&self) -> bool {
self.lifetime.is_empty() && self.type_.is_empty() && self.const_.is_empty()
}
}
impl Display for GenericParams {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt("<", f)?;
let post_iter = |i: usize, len: usize, f: &mut Formatter<'_>| -> fmt::Result {
if i + 1 < len {
fmt::Display::fmt(", ", f)?;
}
Ok(())
};
for (i, param) in self.lifetime.iter().cloned().enumerate() {
fmt::Display::fmt(param.as_str(), &mut *f)?;
post_iter(i, self.lifetime.len(), &mut *f)?;
}
for (i, param) in self.type_.iter().cloned().enumerate() {
fmt::Debug::fmt(¶m.full_type(), &mut *f)?;
post_iter(i, self.type_.len(), &mut *f)?;
}
for (i, param) in self.const_.iter().cloned().enumerate() {
fmt::Display::fmt(param.as_str(), &mut *f)?;
post_iter(i, self.const_.len(), &mut *f)?;
}
fmt::Display::fmt(">", f)?;
Ok(())
}
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, StableAbi)]
pub enum TLData {
Primitive(TLPrimitive),
Opaque,
Struct {
fields: TLFieldsOrSlice
},
Union {
fields: TLFieldsOrSlice
},
Enum (&'static TLEnum),
PrefixType(TLPrefixType),
}
impl Display for TLData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TLData::Primitive(prim)=>{
writeln!(f,"Primitive:{:?}",prim)
},
TLData::Opaque=>{
writeln!(f,"Opaque data")
},
TLData::Struct{fields}=>{
writeln!(f,"Struct with Fields:\n{}",fields.to_string().left_padder(4))
},
TLData::Union{fields}=>{
writeln!(f,"Union with Fields:\n{}",fields.to_string().left_padder(4))
},
TLData::Enum (tlenum)=>{
writeln!(f,"Enum:")?;
Display::fmt(tlenum,f)
},
TLData::PrefixType(prefix)=>{
writeln!(f,"Prefix type:")?;
Display::fmt(prefix,f)
},
}
}
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, StableAbi)]
pub enum TLPrimitive{
U8,
I8,
U16,
I16,
U32,
I32,
U64,
I64,
Usize,
Isize,
Bool,
SharedRef,
MutRef,
ConstPtr,
MutPtr,
Array{
len:usize,
},
Custom(&'static CustomPrimitive)
}
#[repr(C)]
#[derive(Debug, Copy, Clone, StableAbi)]
pub struct CustomPrimitive{
pub typename:StaticStr,
pub start_gen:StaticStr,
pub ty_sep:StaticStr,
pub end_gen:StaticStr,
}
impl Eq for CustomPrimitive{}
impl PartialEq for CustomPrimitive{
fn eq(&self,other:&Self)->bool{
std::ptr::eq(self,other)
}
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, StableAbi)]
pub enum TLDataDiscriminant {
Primitive,
Opaque,
Struct,
Union,
Enum,
PrefixType,
}
impl TLData {
pub const EMPTY:Self=
TLData::Struct {
fields: TLFieldsOrSlice::from_slice(&[]),
};
pub const fn struct_(fields: &'static [TLField]) -> Self {
TLData::Struct {
fields: TLFieldsOrSlice::from_slice(fields),
}
}
pub const fn union_(fields: &'static [TLField]) -> Self {
TLData::Union {
fields: TLFieldsOrSlice::from_slice(fields),
}
}
pub const fn prefix_type(
first_suffix_field:usize,
accessible_fields:FieldAccessibility,
conditional_prefix_fields:&'static [IsConditional],
fields: &'static [TLField],
)->Self{
TLData::PrefixType(TLPrefixType{
first_suffix_field,
accessible_fields,
conditional_prefix_fields:StaticSlice::new(conditional_prefix_fields),
fields:TLFieldsOrSlice::from_slice(fields),
})
}
pub const fn struct_derive(fields: TLFields) -> Self {
TLData::Struct {
fields: TLFieldsOrSlice::TLFields(fields),
}
}
pub const fn union_derive(fields: TLFields) -> Self {
TLData::Union {
fields: TLFieldsOrSlice::TLFields(fields),
}
}
pub const fn prefix_type_derive(
first_suffix_field:usize,
accessible_fields:FieldAccessibility,
conditional_prefix_fields:&'static [IsConditional],
fields: TLFields,
)->Self{
TLData::PrefixType(TLPrefixType{
first_suffix_field,
accessible_fields,
conditional_prefix_fields:StaticSlice::new(conditional_prefix_fields),
fields:TLFieldsOrSlice::TLFields(fields),
})
}
pub fn as_discriminant(&self) -> TLDataDiscriminant {
match self {
TLData::Primitive { .. } => TLDataDiscriminant::Primitive,
TLData::Opaque { .. } => TLDataDiscriminant::Opaque,
TLData::Struct { .. } => TLDataDiscriminant::Struct,
TLData::Union { .. } => TLDataDiscriminant::Union,
TLData::Enum { .. } => TLDataDiscriminant::Enum,
TLData::PrefixType { .. } => TLDataDiscriminant::PrefixType,
}
}
}
#[repr(C)]
#[derive(Copy, Clone, PartialEq, StableAbi)]
pub struct FullType {
pub name: StaticStr,
pub primitive:ROption<TLPrimitive>,
pub generics: GenericParams,
}
impl FullType {
pub const fn new(
name: &'static str,
primitive: ROption<TLPrimitive>,
generics: GenericParams,
) -> Self {
Self {
name: StaticStr::new(name),
primitive,
generics,
}
}
}
impl Display for FullType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(self, f)
}
}
impl Debug for FullType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use self::TLPrimitive as TLP;
let (typename, start_gen, before_ty, ty_sep, end_gen) = match self.primitive {
RSome(TLP::SharedRef) => ("&", "", " ", " ", " "),
RSome(TLP::MutRef) => ("&", "", " mut ", " ", " "),
RSome(TLP::ConstPtr) => ("*const", " ", "", " ", " "),
RSome(TLP::MutPtr) => ("*mut", " ", "", " ", " "),
RSome(TLP::Array{..}) => ("", "[", "", ";", "]"),
RSome(TLP::Custom(c))=>{
(
c.typename.as_str(),
c.start_gen.as_str(),
"",
c.ty_sep.as_str(),
c.end_gen.as_str(),
)
}
RSome(TLP::U8)|RSome(TLP::I8)
|RSome(TLP::U16)|RSome(TLP::I16)
|RSome(TLP::U32)|RSome(TLP::I32)
|RSome(TLP::U64)|RSome(TLP::I64)
|RSome(TLP::Usize)|RSome(TLP::Isize)
|RSome(TLP::Bool)
|RNone => (self.name.as_str(), "<", "", ", ", ">"),
};
fmt::Display::fmt(typename, f)?;
let mut is_before_ty = true;
let generics = self.generics;
if !generics.is_empty() {
fmt::Display::fmt(start_gen, f)?;
let post_iter = |i: usize, len: usize, f: &mut Formatter<'_>| -> fmt::Result {
if i+1 < len {
fmt::Display::fmt(ty_sep, f)?;
}
Ok(())
};
let mut i=0;
let total_generics_len=
generics.lifetime.len()+generics.type_.len()+generics.const_.len();
for param in generics.lifetime.iter().cloned() {
fmt::Display::fmt(param.as_str(), &mut *f)?;
post_iter(i,total_generics_len, &mut *f)?;
i+=1;
}
for param in generics.type_.iter().cloned() {
if is_before_ty {
fmt::Display::fmt(before_ty, &mut *f)?;
is_before_ty = false;
}
fmt::Debug::fmt(¶m.full_type(), &mut *f)?;
post_iter(i,total_generics_len, &mut *f)?;
i+=1;
}
for param in generics.const_.iter().cloned() {
fmt::Display::fmt(param.as_str(), &mut *f)?;
post_iter(i,total_generics_len, &mut *f)?;
i+=1;
}
fmt::Display::fmt(end_gen, f)?;
}
Ok(())
}
}
#[repr(u8)]
#[derive(Copy,Clone,Debug,Eq,PartialEq,StableAbi)]
pub enum TLFieldOrFunction{
Field(TLField),
Function(TLFunction),
}
impl From<TLField> for TLFieldOrFunction{
fn from(x:TLField)->Self{
TLFieldOrFunction::Field(x)
}
}
impl From<TLFunction> for TLFieldOrFunction{
fn from(x:TLFunction)->Self{
TLFieldOrFunction::Function(x)
}
}
impl Display for TLFieldOrFunction{
fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
match self {
TLFieldOrFunction::Field(x)=>Display::fmt(x,f),
TLFieldOrFunction::Function(x)=>Display::fmt(x,f),
}
}
}
impl TLFieldOrFunction{
pub fn formatted_layout(&self)->String{
match self {
TLFieldOrFunction::Field(x)=>x.abi_info.get().layout.to_string(),
TLFieldOrFunction::Function(x)=>x.to_string(),
}
}
}
#[repr(C)]
#[derive(Copy,Clone,Debug,Eq,StableAbi)]
pub struct TLFunction{
pub name: RStr<'static>,
pub bound_lifetimes: RStr<'static>,
pub param_names: RStr<'static>,
pub param_abi_infos: RSlice<'static,GetAbiInfo>,
pub paramret_lifetime_indices: RSlice<'static,LifetimeIndex>,
pub return_abi_info:ROption<GetAbiInfo>,
}
impl PartialEq for TLFunction{
fn eq(&self,other:&Self)->bool{
self.name==other.name&&
self.bound_lifetimes==other.bound_lifetimes&&
self.param_names==other.param_names&&
self.get_params_ret_iter().eq(other.get_params_ret_iter())&&
self.paramret_lifetime_indices==other.paramret_lifetime_indices&&
self.return_abi_info.map(|x| x.get() )==other.return_abi_info.map(|x| x.get() )
}
}
impl TLFunction{
pub(crate) fn get_param_names(&self)->GetParamNames{
GetParamNames{
split:self.param_names.as_str().split(';'),
length:self.param_abi_infos.len(),
current:0,
}
}
pub(crate) fn get_params(&self)->impl ExactSizeIterator<Item=TLField>+Clone+Debug {
self.get_param_names()
.zip(self.param_abi_infos.as_slice().iter().cloned())
.map(|(param_name,abi_info)|{
TLField::new(param_name,&[],abi_info)
})
}
pub(crate) fn get_return(&self)->TLField{
const UNIT_GET_ABI_INFO:GetAbiInfo=<() as MakeGetAbiInfo<StableAbi_Bound>>::CONST;
TLField::new(
"__returns",
&[],
self.return_abi_info.unwrap_or(UNIT_GET_ABI_INFO)
)
}
pub(crate) fn get_params_ret_iter(&self)->
ChainOnce<impl ExactSizeIterator<Item=TLField>+Clone+Debug,TLField>
{
ChainOnce::new(self.get_params(),self.get_return())
}
#[allow(dead_code)]
pub(crate) fn get_params_ret_vec(&self)->RVec<TLField>{
self.get_params_ret_iter().collect()
}
}
impl Display for TLFunction{
fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
write!(f,"fn(")?;
let params=self.get_params();
let param_count=params.len();
for (param_i,param) in params.enumerate() {
Display::fmt(¶m.name,f)?;
Display::fmt(&": ",f)?;
Display::fmt(¶m.full_type(),f)?;
if param_i+1!=param_count {
Display::fmt(&", ",f)?;
}
}
write!(f,")")?;
let returns=self.get_return();
Display::fmt(&"->",f)?;
Display::fmt(&returns.full_type(),f)?;
if !self.paramret_lifetime_indices.is_empty() {
writeln!(f,"\nlifetime indices:{:?}",self.paramret_lifetime_indices)?;
}
Ok(())
}
}
#[derive(Debug,Clone)]
pub struct GetParamNames{
split:std::str::Split<'static,char>,
length:usize,
current:usize,
}
impl Iterator for GetParamNames{
type Item=&'static str;
fn next(&mut self) -> Option<Self::Item>{
if self.length==self.current{
return None;
}
let current=self.current;
self.current+=1;
match self.split.next().filter(|&x| !x.is_empty()||x=="_" ) {
Some(x)=>Some(x),
None=>Some(PARAM_INDEX[current]),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len=self.length-self.current;
(len,Some(len))
}
fn count(self) -> usize {
let len=self.length-self.current;
len
}
}
impl std::iter::ExactSizeIterator for GetParamNames{}
static PARAM_INDEX: [&'static str; 64] = [
"param_0", "param_1", "param_2", "param_3", "param_4", "param_5", "param_6", "param_7",
"param_8", "param_9", "param_10", "param_11", "param_12", "param_13", "param_14", "param_15",
"param_16", "param_17", "param_18", "param_19", "param_20", "param_21", "param_22", "param_23",
"param_24", "param_25", "param_26", "param_27", "param_28", "param_29", "param_30", "param_31",
"param_32", "param_33", "param_34", "param_35", "param_36", "param_37", "param_38", "param_39",
"param_40", "param_41", "param_42", "param_43", "param_44", "param_45", "param_46", "param_47",
"param_48", "param_49", "param_50", "param_51", "param_52", "param_53", "param_54", "param_55",
"param_56", "param_57", "param_58", "param_59", "param_60", "param_61", "param_62", "param_63",
];
#[derive(Debug,Clone)]
pub struct ChainOnce<I,T>{
iter:I,
once:Option<T>,
}
impl<I> ChainOnce<I,I::Item>
where
I:ExactSizeIterator
{
fn new(iter:I,once:I::Item)->Self{
Self{
iter,
once:Some(once),
}
}
fn length(&self)->usize{
self.iter.len()+(self.once.is_some() as usize)
}
}
impl<I> Iterator for ChainOnce<I,I::Item>
where
I:ExactSizeIterator
{
type Item=I::Item;
fn next(&mut self) -> Option<I::Item>{
if let ret@Some(_)=self.iter.next() {
return ret;
}
self.once.take()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len=self.length();
(len,Some(len))
}
fn count(self) -> usize {
self.length()
}
}
impl<I> std::iter::ExactSizeIterator for ChainOnce<I,I::Item>
where
I:ExactSizeIterator
{}