use crate::{Object, Tuple, TypeInfo, VariantRtti, Vm, VmError};
use std::fmt;
use std::sync::Arc;
pub struct Variant {
pub(crate) rtti: Arc<VariantRtti>,
pub(crate) data: VariantData,
}
impl Variant {
pub fn unit(rtti: Arc<VariantRtti>) -> Self {
Self {
rtti,
data: VariantData::Unit,
}
}
pub fn tuple(rtti: Arc<VariantRtti>, tuple: Tuple) -> Self {
Self {
rtti,
data: VariantData::Tuple(tuple),
}
}
pub fn struct_(rtti: Arc<VariantRtti>, data: Object) -> Self {
Self {
rtti,
data: VariantData::Struct(data),
}
}
pub fn rtti(&self) -> &VariantRtti {
&self.rtti
}
pub fn data(&self) -> &VariantData {
&self.data
}
pub fn data_mut(&mut self) -> &mut VariantData {
&mut self.data
}
pub fn type_info(&self) -> TypeInfo {
TypeInfo::Variant(self.rtti.clone())
}
pub(crate) fn value_ptr_eq(vm: &mut Vm, a: &Self, b: &Self) -> Result<bool, VmError> {
debug_assert_eq!(
a.rtti.enum_hash, b.rtti.enum_hash,
"comparison only makes sense if enum hashes match"
);
if a.rtti.hash != b.rtti.hash {
return Ok(false);
}
Ok(match (&a.data, &b.data) {
(VariantData::Unit, VariantData::Unit) => true,
(VariantData::Tuple(a), VariantData::Tuple(b)) => return Tuple::value_ptr_eq(vm, a, b),
(VariantData::Struct(a), VariantData::Struct(b)) => {
return Object::value_ptr_eq(vm, a, b)
}
_ => false,
})
}
}
pub enum VariantData {
Unit,
Struct(Object),
Tuple(Tuple),
}
impl fmt::Debug for Variant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.rtti.item)?;
match &self.data {
VariantData::Unit => {}
VariantData::Struct(st) => {
write!(f, "{:?}", st)?;
}
VariantData::Tuple(tuple) => {
write!(f, "{:?}", tuple)?;
}
}
Ok(())
}
}