use super::{Data, DataType, Generic, SharingError, SharingResult};
use core::fmt::Display;
use melodium_common::descriptor::{
Collection, DescribedType as CommonDescribedType, Entry as CommonEntry,
Identifier as CommonIdentifier,
};
use melodium_engine::LogicError;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[cfg_attr(feature = "webassembly", derive(tsify::Tsify))]
#[cfg_attr(feature = "webassembly", tsify(into_wasm_abi, from_wasm_abi))]
pub enum DescribedType {
Void,
I8,
I16,
I32,
I64,
I128,
U8,
U16,
U32,
U64,
U128,
F32,
F64,
Bool,
Byte,
Char,
String,
Vec(Box<DescribedType>),
Option(Box<DescribedType>),
Data(Data),
Generic(Generic),
}
impl DescribedType {
pub fn to_described_type(
&self,
collection: &Collection,
scope: &CommonIdentifier,
) -> SharingResult<CommonDescribedType> {
match self {
DescribedType::Void => SharingResult::new_success(CommonDescribedType::Void),
DescribedType::I8 => SharingResult::new_success(CommonDescribedType::I8),
DescribedType::I16 => SharingResult::new_success(CommonDescribedType::I16),
DescribedType::I32 => SharingResult::new_success(CommonDescribedType::I32),
DescribedType::I64 => SharingResult::new_success(CommonDescribedType::I64),
DescribedType::I128 => SharingResult::new_success(CommonDescribedType::I128),
DescribedType::U8 => SharingResult::new_success(CommonDescribedType::U8),
DescribedType::U16 => SharingResult::new_success(CommonDescribedType::U16),
DescribedType::U32 => SharingResult::new_success(CommonDescribedType::U32),
DescribedType::U64 => SharingResult::new_success(CommonDescribedType::U64),
DescribedType::U128 => SharingResult::new_success(CommonDescribedType::U128),
DescribedType::F32 => SharingResult::new_success(CommonDescribedType::F32),
DescribedType::F64 => SharingResult::new_success(CommonDescribedType::F64),
DescribedType::Bool => SharingResult::new_success(CommonDescribedType::Bool),
DescribedType::Byte => SharingResult::new_success(CommonDescribedType::Byte),
DescribedType::Char => SharingResult::new_success(CommonDescribedType::Char),
DescribedType::String => SharingResult::new_success(CommonDescribedType::String),
DescribedType::Vec(dt) => {
SharingResult::new_success(CommonDescribedType::Vec(Box::new({
let result = dt.as_ref().to_described_type(collection, scope);
if let Some(subtype) = result.success() {
subtype.clone()
} else {
return result;
}
})))
}
DescribedType::Option(dt) => {
SharingResult::new_success(CommonDescribedType::Option(Box::new({
let result = dt.as_ref().to_described_type(collection, scope);
if let Some(subtype) = result.success() {
subtype.clone()
} else {
return result;
}
})))
}
DescribedType::Data(data) => {
let identifier: CommonIdentifier =
if let Ok(identifier) = (&data.identifier).try_into() {
identifier
} else {
return SharingResult::new_failure(SharingError::invalid_identifier(
5,
data.identifier.clone(),
));
};
if let Some(CommonEntry::Data(data)) = collection.get(&(&identifier).into()) {
SharingResult::new_success(CommonDescribedType::Data(Box::new(Arc::clone(
data,
))))
} else {
return SharingResult::new_failure(
LogicError::unexisting_data(231, scope.clone(), identifier.into(), None)
.into(),
);
}
}
DescribedType::Generic(generic) => {
SharingResult::new_success(CommonDescribedType::Generic(Box::new(generic.into())))
}
}
}
}
impl From<CommonDescribedType> for DescribedType {
fn from(value: CommonDescribedType) -> Self {
(&value).into()
}
}
impl From<&CommonDescribedType> for DescribedType {
fn from(value: &CommonDescribedType) -> Self {
match value {
CommonDescribedType::Void => DescribedType::Void,
CommonDescribedType::I8 => DescribedType::I8,
CommonDescribedType::I16 => DescribedType::I16,
CommonDescribedType::I32 => DescribedType::I32,
CommonDescribedType::I64 => DescribedType::I64,
CommonDescribedType::I128 => DescribedType::I128,
CommonDescribedType::U8 => DescribedType::U8,
CommonDescribedType::U16 => DescribedType::U16,
CommonDescribedType::U32 => DescribedType::U32,
CommonDescribedType::U64 => DescribedType::U64,
CommonDescribedType::U128 => DescribedType::U128,
CommonDescribedType::F32 => DescribedType::F32,
CommonDescribedType::F64 => DescribedType::F64,
CommonDescribedType::Bool => DescribedType::Bool,
CommonDescribedType::Byte => DescribedType::Byte,
CommonDescribedType::Char => DescribedType::Char,
CommonDescribedType::String => DescribedType::String,
CommonDescribedType::Vec(dt) => DescribedType::Vec(Box::new(dt.as_ref().into())),
CommonDescribedType::Option(dt) => DescribedType::Option(Box::new(dt.as_ref().into())),
CommonDescribedType::Data(data) => DescribedType::Data(data.as_ref().as_ref().into()),
CommonDescribedType::Generic(generic) => {
DescribedType::Generic(generic.as_ref().into())
}
}
}
}
impl From<DataType> for DescribedType {
fn from(value: DataType) -> Self {
match value {
DataType::Undetermined => DescribedType::Generic(Generic {
name: "undetermined".to_string(),
traits: Vec::new(),
}),
DataType::Void => DescribedType::Void,
DataType::I8 => DescribedType::I8,
DataType::I16 => DescribedType::I16,
DataType::I32 => DescribedType::I32,
DataType::I64 => DescribedType::I64,
DataType::I128 => DescribedType::I128,
DataType::U8 => DescribedType::U8,
DataType::U16 => DescribedType::U16,
DataType::U32 => DescribedType::U32,
DataType::U64 => DescribedType::U64,
DataType::U128 => DescribedType::U128,
DataType::F32 => DescribedType::F32,
DataType::F64 => DescribedType::F64,
DataType::Bool => DescribedType::Bool,
DataType::Byte => DescribedType::Byte,
DataType::Char => DescribedType::Char,
DataType::String => DescribedType::String,
DataType::Vec(inner) => DescribedType::Vec(Box::new(DescribedType::from(*inner))),
DataType::Option(inner) => DescribedType::Option(Box::new(DescribedType::from(*inner))),
DataType::Data(obj) => DescribedType::Data(obj),
}
}
}
impl From<&DataType> for DescribedType {
fn from(value: &DataType) -> Self {
match value {
DataType::Undetermined => DescribedType::Generic(Generic {
name: "undetermined".to_string(),
traits: Vec::new(),
}),
DataType::Void => DescribedType::Void,
DataType::I8 => DescribedType::I8,
DataType::I16 => DescribedType::I16,
DataType::I32 => DescribedType::I32,
DataType::I64 => DescribedType::I64,
DataType::I128 => DescribedType::I128,
DataType::U8 => DescribedType::U8,
DataType::U16 => DescribedType::U16,
DataType::U32 => DescribedType::U32,
DataType::U64 => DescribedType::U64,
DataType::U128 => DescribedType::U128,
DataType::F32 => DescribedType::F32,
DataType::F64 => DescribedType::F64,
DataType::Bool => DescribedType::Bool,
DataType::Byte => DescribedType::Byte,
DataType::Char => DescribedType::Char,
DataType::String => DescribedType::String,
DataType::Vec(inner) => {
DescribedType::Vec(Box::new(DescribedType::from(inner.as_ref())))
}
DataType::Option(inner) => {
DescribedType::Option(Box::new(DescribedType::from(inner.as_ref())))
}
DataType::Data(obj) => DescribedType::Data(obj.clone()),
}
}
}
impl TryInto<CommonDescribedType> for DescribedType {
type Error = ();
fn try_into(self) -> Result<CommonDescribedType, ()> {
TryInto::try_into(&self)
}
}
impl TryInto<CommonDescribedType> for &DescribedType {
type Error = ();
fn try_into(self) -> Result<CommonDescribedType, ()> {
match self {
DescribedType::Void => Ok(CommonDescribedType::Void),
DescribedType::I8 => Ok(CommonDescribedType::I8),
DescribedType::I16 => Ok(CommonDescribedType::I16),
DescribedType::I32 => Ok(CommonDescribedType::I32),
DescribedType::I64 => Ok(CommonDescribedType::I64),
DescribedType::I128 => Ok(CommonDescribedType::I128),
DescribedType::U8 => Ok(CommonDescribedType::U8),
DescribedType::U16 => Ok(CommonDescribedType::U16),
DescribedType::U32 => Ok(CommonDescribedType::U32),
DescribedType::U64 => Ok(CommonDescribedType::U64),
DescribedType::U128 => Ok(CommonDescribedType::U128),
DescribedType::F32 => Ok(CommonDescribedType::F32),
DescribedType::F64 => Ok(CommonDescribedType::F64),
DescribedType::Bool => Ok(CommonDescribedType::Bool),
DescribedType::Byte => Ok(CommonDescribedType::Byte),
DescribedType::Char => Ok(CommonDescribedType::Char),
DescribedType::String => Ok(CommonDescribedType::String),
DescribedType::Vec(dt) => {
Ok(CommonDescribedType::Vec(Box::new(dt.as_ref().try_into()?)))
}
DescribedType::Option(dt) => Ok(CommonDescribedType::Option(Box::new(
dt.as_ref().try_into()?,
))),
DescribedType::Data(_) => Err(()),
DescribedType::Generic(generic) => {
Ok(CommonDescribedType::Generic(Box::new(generic.into())))
}
}
}
}
impl Display for DescribedType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DescribedType::Void => write!(f, "void"),
DescribedType::I8 => write!(f, "i8"),
DescribedType::I16 => write!(f, "i16"),
DescribedType::I32 => write!(f, "i32"),
DescribedType::I64 => write!(f, "i64"),
DescribedType::I128 => write!(f, "i128"),
DescribedType::U8 => write!(f, "u8"),
DescribedType::U16 => write!(f, "u16"),
DescribedType::U32 => write!(f, "u32"),
DescribedType::U64 => write!(f, "u64"),
DescribedType::U128 => write!(f, "u128"),
DescribedType::F32 => write!(f, "f32"),
DescribedType::F64 => write!(f, "f64"),
DescribedType::Bool => write!(f, "bool"),
DescribedType::Byte => write!(f, "byte"),
DescribedType::Char => write!(f, "char"),
DescribedType::String => write!(f, "string"),
DescribedType::Vec(inner) => write!(f, "Vec<{inner}>"),
DescribedType::Option(inner) => write!(f, "Option<{inner}>"),
DescribedType::Data(obj) => write!(f, "{}", obj.identifier.name),
DescribedType::Generic(gen) => write!(f, "{}", gen.name),
}
}
}