use serde::{
Deserialize,
Serialize,
};
use crate::BlockHeader;
use crate::VecDataBlock;
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)]
#[serde(rename_all = "lowercase")]
pub enum DataType {
UINT8,
UINT16,
UINT32,
UINT64,
INT8,
INT16,
INT32,
INT64,
FLOAT32,
FLOAT64,
}
#[macro_export]
macro_rules! data_type_rstype_replace {
($rstype:ty, @($($stack:tt)*) ($($first:tt)*) $($rest:tt)*) => {
data_type_rstype_replace!($rstype, @(() $($stack)*) $($first)* __paren $($rest)*)
};
($rstype:ty, @($($stack:tt)*) [$($first:tt)*] $($rest:tt)*) => {
data_type_rstype_replace!($rstype, @(() $($stack)*) $($first)* __bracket $($rest)*)
};
($rstype:ty, @($($stack:tt)*) {$($first:tt)*} $($rest:tt)*) => {
data_type_rstype_replace!($rstype, @(() $($stack)*) $($first)* __brace $($rest)*)
};
($rstype:ty, @(($($close:tt)*) ($($top:tt)*) $($stack:tt)*) __paren $($rest:tt)*) => {
data_type_rstype_replace!($rstype, @(($($top)* ($($close)*)) $($stack)*) $($rest)*)
};
($rstype:ty, @(($($close:tt)*) ($($top:tt)*) $($stack:tt)*) __bracket $($rest:tt)*) => {
data_type_rstype_replace!($rstype, @(($($top)* [$($close)*]) $($stack)*) $($rest)*)
};
($rstype:ty, @(($($close:tt)*) ($($top:tt)*) $($stack:tt)*) __brace $($rest:tt)*) => {
data_type_rstype_replace!($rstype, @(($($top)* {$($close)*}) $($stack)*) $($rest)*)
};
($rstype:ty, @(($($top:tt)*) $($stack:tt)*) RsType $($rest:tt)*) => {
data_type_rstype_replace!($rstype, @(($($top)* $rstype) $($stack)*) $($rest)*)
};
($rstype:ty, @(($($top:tt)*) $($stack:tt)*) $first:tt $($rest:tt)*) => {
data_type_rstype_replace!($rstype, @(($($top)* $first) $($stack)*) $($rest)*)
};
($rstype:ty, @(($($top:tt)+))) => {
$($top)+
};
($rstype:ty, $($input:tt)+) => {
data_type_rstype_replace!($rstype, @(()) $($input)*)
};
}
#[macro_export]
macro_rules! data_type_match {
($match_expr:expr, $($expr:tt)*) => {
{
match $match_expr {
$crate::DataType::UINT8 => $crate::data_type_rstype_replace!(u8, $($expr)*),
$crate::DataType::UINT16 => $crate::data_type_rstype_replace!(u16, $($expr)*),
$crate::DataType::UINT32 => $crate::data_type_rstype_replace!(u32, $($expr)*),
$crate::DataType::UINT64 => $crate::data_type_rstype_replace!(u64, $($expr)*),
$crate::DataType::INT8 => $crate::data_type_rstype_replace!(i8, $($expr)*),
$crate::DataType::INT16 => $crate::data_type_rstype_replace!(i16, $($expr)*),
$crate::DataType::INT32 => $crate::data_type_rstype_replace!(i32, $($expr)*),
$crate::DataType::INT64 => $crate::data_type_rstype_replace!(i64, $($expr)*),
$crate::DataType::FLOAT32 => $crate::data_type_rstype_replace!(f32, $($expr)*),
$crate::DataType::FLOAT64 => $crate::data_type_rstype_replace!(f64, $($expr)*),
}
}
};
}
impl DataType {
pub fn size_of(self) -> usize {
data_type_match!(self,
{
std::mem::size_of::<RsType>()
}
)
}
}
impl std::fmt::Display for DataType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
pub trait ReflectedType: Send + Sync + Clone + Default + 'static {
const VARIANT: DataType;
fn create_data_block(
header: BlockHeader,
) -> VecDataBlock<Self> {
VecDataBlock::<Self>::new(
header.size,
header.grid_position,
vec![Self::default(); header.num_el],
)
}
}
macro_rules! reflected_type {
($d_name:ident, $d_type:ty) => {
impl ReflectedType for $d_type {
const VARIANT: DataType = DataType::$d_name;
}
}
}
reflected_type!(UINT8, u8);
reflected_type!(UINT16, u16);
reflected_type!(UINT32, u32);
reflected_type!(UINT64, u64);
reflected_type!(INT8, i8);
reflected_type!(INT16, i16);
reflected_type!(INT32, i32);
reflected_type!(INT64, i64);
reflected_type!(FLOAT32, f32);
reflected_type!(FLOAT64, f64);
#[cfg(test)]
mod tests {
use super::*;
fn test_data_type_reflection<T: ReflectedType>() {
assert_eq!(std::mem::size_of::<T>(), T::VARIANT.size_of());
}
#[test]
fn test_all_data_type_reflections() {
test_data_type_reflection::<u8>();
test_data_type_reflection::<u16>();
test_data_type_reflection::<u32>();
test_data_type_reflection::<u64>();
test_data_type_reflection::<i8>();
test_data_type_reflection::<i16>();
test_data_type_reflection::<i32>();
test_data_type_reflection::<i64>();
test_data_type_reflection::<f32>();
test_data_type_reflection::<f64>();
}
}