use super::*;
#[repr(u8)]
#[derive(Copy, Clone, StableAbi)]
#[sabi(unsafe_sabi_opaque_fields)]
pub enum MonoTLData {
Primitive(TLPrimitive),
Opaque,
Struct {
fields: CompTLFields,
},
Union {
fields: CompTLFields,
},
Enum(MonoTLEnum),
PrefixType(MonoTLPrefixType),
}
impl MonoTLData {
pub const EMPTY: Self = MonoTLData::Struct {
fields: CompTLFields::EMPTY,
};
pub const fn struct_(fields: RSlice<'static, CompTLField>) -> Self {
MonoTLData::Struct {
fields: CompTLFields::from_fields(fields),
}
}
#[doc(hidden)]
pub const fn derive_struct(fields: CompTLFields) -> Self {
MonoTLData::Struct { fields }
}
pub const fn union_(fields: RSlice<'static, CompTLField>) -> Self {
MonoTLData::Union {
fields: CompTLFields::from_fields(fields),
}
}
#[doc(hidden)]
pub const fn derive_union(fields: CompTLFields) -> Self {
MonoTLData::Union { fields }
}
pub const fn prefix_type(
first_suffix_field: usize,
conditional_prefix_fields: FieldConditionality,
fields: RSlice<'static, CompTLField>,
) -> Self {
MonoTLData::PrefixType(MonoTLPrefixType {
first_suffix_field: first_suffix_field as u8,
conditional_prefix_fields,
fields: CompTLFields::from_fields(fields),
})
}
pub const fn struct_derive(fields: CompTLFields) -> Self {
MonoTLData::Struct { fields }
}
pub const fn union_derive(fields: CompTLFields) -> Self {
MonoTLData::Union { fields }
}
pub const fn prefix_type_derive(
first_suffix_field: usize,
conditional_prefix_fields: u64,
fields: CompTLFields,
) -> Self {
MonoTLData::PrefixType(MonoTLPrefixType {
first_suffix_field: first_suffix_field as u8,
conditional_prefix_fields: FieldConditionality::from_u64(conditional_prefix_fields),
fields,
})
}
pub const fn as_discriminant(&self) -> TLDataDiscriminant {
match self {
MonoTLData::Primitive { .. } => TLDataDiscriminant::Primitive,
MonoTLData::Opaque { .. } => TLDataDiscriminant::Opaque,
MonoTLData::Struct { .. } => TLDataDiscriminant::Struct,
MonoTLData::Union { .. } => TLDataDiscriminant::Union,
MonoTLData::Enum { .. } => TLDataDiscriminant::Enum,
MonoTLData::PrefixType { .. } => TLDataDiscriminant::PrefixType,
}
}
pub(super) const fn to_primitive(self) -> Option<TLPrimitive> {
match self {
MonoTLData::Primitive(x) => Some(x),
_ => None,
}
}
pub fn expand(
self,
generic: GenericTLData,
shared_vars: &'static SharedVars,
) -> Result<TLData, MismatchedTLDataVariant> {
Ok(match (self, generic) {
(MonoTLData::Primitive(prim), GenericTLData::Primitive) => TLData::Primitive(prim),
(MonoTLData::Opaque, GenericTLData::Opaque) => TLData::Opaque,
(MonoTLData::Struct { fields }, GenericTLData::Struct) => TLData::Struct {
fields: fields.expand(shared_vars),
},
(MonoTLData::Union { fields }, GenericTLData::Union) => TLData::Union {
fields: fields.expand(shared_vars),
},
(MonoTLData::Enum(nongeneric), GenericTLData::Enum(generic)) => {
TLData::Enum(nongeneric.expand(generic, shared_vars))
}
(MonoTLData::PrefixType(nongeneric), GenericTLData::PrefixType(generic)) => {
TLData::PrefixType(nongeneric.expand(generic, shared_vars))
}
_ => {
return Err(MismatchedTLDataVariant {
nongeneric: self.as_discriminant(),
generic: generic.as_discriminant(),
})
}
})
}
}
#[derive(Debug, Clone)]
pub struct MismatchedTLDataVariant {
nongeneric: TLDataDiscriminant,
generic: TLDataDiscriminant,
}
impl Display for MismatchedTLDataVariant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"Error combining TLData::{:?} and GenericTLData::{:?}",
self.nongeneric, self.generic,
)
}
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, StableAbi)]
#[sabi(unsafe_sabi_opaque_fields)]
pub enum TLDataDiscriminant {
Primitive,
Opaque,
Struct,
Union,
Enum,
PrefixType,
}
#[repr(C)]
#[derive(Copy, Clone, StableAbi)]
#[sabi(unsafe_sabi_opaque_fields)]
pub enum GenericTLData {
Primitive,
Opaque,
Struct,
Union,
Enum(GenericTLEnum),
PrefixType(GenericTLPrefixType),
}
impl GenericTLData {
pub const fn as_discriminant(&self) -> TLDataDiscriminant {
match self {
GenericTLData::Primitive { .. } => TLDataDiscriminant::Primitive,
GenericTLData::Opaque { .. } => TLDataDiscriminant::Opaque,
GenericTLData::Struct { .. } => TLDataDiscriminant::Struct,
GenericTLData::Union { .. } => TLDataDiscriminant::Union,
GenericTLData::Enum { .. } => TLDataDiscriminant::Enum,
GenericTLData::PrefixType { .. } => TLDataDiscriminant::PrefixType,
}
}
#[doc(hidden)]
pub const fn prefix_type_derive(accessible_fields: FieldAccessibility) -> Self {
GenericTLData::PrefixType(GenericTLPrefixType { accessible_fields })
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum TLData {
Primitive(TLPrimitive),
Opaque,
Struct {
fields: TLFields,
},
Union {
fields: TLFields,
},
Enum(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(enum_) => {
writeln!(f, "Enum:")?;
Display::fmt(enum_, f)?;
}
TLData::PrefixType(prefix) => {
writeln!(f, "Prefix type:")?;
Display::fmt(prefix, f)?;
}
}
Ok(())
}
}