use std::{
cmp::{Eq,Ord},
fmt::{self,Debug},
};
use crate::{
std_types::{RStr,RBoxError},
type_layout::StartLen,
type_level::{
impl_enum::{Implemented,Unimplemented},
trait_marker,
},
InterfaceType,
};
pub unsafe trait GetNonExhaustive<Storage>:GetEnumInfo{
type NonExhaustive;
}
pub unsafe trait GetEnumInfo:Sized{
type Discriminant:ValidDiscriminant;
type DefaultStorage;
type DefaultInterface;
const ENUM_INFO:&'static EnumInfo;
fn discriminants()->&'static [Self::Discriminant];
fn is_valid_discriminant(discriminant:Self::Discriminant)->bool;
}
pub use self::_enum_info::EnumInfo;
mod _enum_info{
use super::*;
#[repr(C)]
#[derive(StableAbi)]
pub struct EnumInfo{
type_name:RStr<'static>,
strings:RStr<'static>,
variant_names_start_len:StartLen,
}
impl EnumInfo{
#[doc(hidden)]
pub const fn _for_derive(
type_name:RStr<'static>,
strings:RStr<'static>,
variant_names_start_len:StartLen,
)->Self{
Self{
type_name,
strings,
variant_names_start_len,
}
}
pub fn type_name(&self)->&'static str{
self.type_name.as_str()
}
pub fn variant_names(&self)->&'static str{
&self.strings.as_str()[self.variant_names_start_len.to_range()]
}
}
}
impl EnumInfo{
pub fn variant_names_iter(&self)->impl Iterator<Item=&'static str>+'static+Debug+Clone {
self.variant_names().split_terminator(';')
}
}
impl Debug for EnumInfo{
fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
f.debug_struct("EnumInfo")
.field("type_name",&self.type_name())
.field("variant_names",&IteratorAsList(self.variant_names_iter()))
.finish()
}
}
struct IteratorAsList<I>(I);
impl<I,T> Debug for IteratorAsList<I>
where
I:Iterator<Item=T>+Clone,
T:Debug,
{
fn fmt(&self,f:&mut fmt::Formatter<'_>)->fmt::Result{
f.debug_list()
.entries(self.0.clone())
.finish()
}
}
pub trait ValidDiscriminant:Sealed+Copy+Eq+Ord+Debug+Send+Sync+'static{}
mod sealed{
pub trait Sealed{}
}
use self::sealed::Sealed;
macro_rules! impl_valid_discriminant {
(
$($ty:ty),* $(,)*
) => (
$(
impl ValidDiscriminant for $ty{}
impl Sealed for $ty{}
)*
)
}
impl_valid_discriminant!{u8,i8,u16,i16,u32,i32,u64,i64,usize,isize}
pub trait SerializeEnum<NE>{
type Proxy;
fn serialize_enum(this:&NE) -> Result<Self::Proxy, RBoxError>;
}
#[doc(hidden)]
pub trait GetSerializeEnumProxy<NE>:InterfaceType{
type ProxyType;
}
impl<I,NE,PT> GetSerializeEnumProxy<NE> for I
where
I:InterfaceType,
I:GetSerializeEnumProxyHelper<
NE,
<I as InterfaceType>::Serialize,
ProxyType=PT
>,
{
type ProxyType=PT;
}
#[doc(hidden)]
pub trait GetSerializeEnumProxyHelper<NE,IS>:InterfaceType{
type ProxyType;
}
impl<I,NE>
GetSerializeEnumProxyHelper<NE,Implemented<trait_marker::Serialize>>
for I
where
I:InterfaceType,
I:SerializeEnum<NE>,
{
type ProxyType=<I as SerializeEnum<NE>>::Proxy;
}
impl<I,NE>
GetSerializeEnumProxyHelper<NE,Unimplemented<trait_marker::Serialize>>
for I
where
I:InterfaceType,
{
type ProxyType=();
}
pub trait DeserializeEnum<'borr,NE> {
type Proxy;
fn deserialize_enum(s: Self::Proxy) -> Result<NE, RBoxError>;
}
#[doc(hidden)]
pub trait GetDeserializeEnumProxy<'borr,NE>:InterfaceType{
type ProxyType;
}
impl<'borr,I,NE,PT> GetDeserializeEnumProxy<'borr,NE> for I
where
I:InterfaceType,
I:GetDeserializeEnumProxyHelper<
'borr,
NE,
<I as InterfaceType>::Deserialize,
ProxyType=PT
>,
{
type ProxyType=PT;
}
#[doc(hidden)]
pub trait GetDeserializeEnumProxyHelper<'borr,NE,IS>:InterfaceType{
type ProxyType;
}
impl<'borr,I,NE>
GetDeserializeEnumProxyHelper<'borr,NE,Implemented<trait_marker::Deserialize>>
for I
where
I:InterfaceType,
I:DeserializeEnum<'borr,NE>
{
type ProxyType=<I as DeserializeEnum<'borr,NE>>::Proxy;
}
impl<'borr,I,NE>
GetDeserializeEnumProxyHelper<'borr,NE,Unimplemented<trait_marker::Deserialize>>
for I
where
I:InterfaceType,
{
type ProxyType=();
}