use std::{
cmp::{Eq, Ord},
fmt::{self, Debug},
};
use crate::{
std_types::{RBoxError, RStr},
type_layout::StartLen,
type_level::{
impl_enum::{Implemented, Unimplemented},
trait_marker,
},
InterfaceType,
};
pub unsafe trait NonExhaustiveMarker<Storage>: GetEnumInfo {
type Marker;
}
pub unsafe trait GetEnumInfo: Sized {
type Discriminant: ValidDiscriminant;
type DefaultStorage;
type DefaultInterface;
const ENUM_INFO: &'static EnumInfo;
const 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<Enum>: InterfaceType {
type Proxy;
fn serialize_enum(this: &Enum) -> Result<Self::Proxy, RBoxError>;
}
#[doc(hidden)]
pub trait GetSerializeEnumProxy<E>: InterfaceType {
type ProxyType;
}
impl<I, E, PT> GetSerializeEnumProxy<E> for I
where
I: InterfaceType,
I: GetSerializeEnumProxyHelper<E, <I as InterfaceType>::Serialize, ProxyType = PT>,
{
type ProxyType = PT;
}
#[doc(hidden)]
pub trait GetSerializeEnumProxyHelper<E, IS>: InterfaceType {
type ProxyType;
}
impl<I, E> GetSerializeEnumProxyHelper<E, Implemented<trait_marker::Serialize>> for I
where
I: InterfaceType,
I: SerializeEnum<E>,
{
type ProxyType = <I as SerializeEnum<E>>::Proxy;
}
impl<I, E> GetSerializeEnumProxyHelper<E, Unimplemented<trait_marker::Serialize>> for I
where
I: InterfaceType,
{
type ProxyType = ();
}
pub trait DeserializeEnum<'borr, NE>: InterfaceType {
type Proxy;
fn deserialize_enum(s: Self::Proxy) -> Result<NE, RBoxError>;
}