use serde::{Deserialize, Serialize};
use std::any::Any;
use std::fmt;
use std::marker::PhantomData;
pub trait TypeDescriptor: fmt::Debug + Clone + Send + Sync + 'static {
fn name(&self) -> &str;
fn size_in_bytes(&self) -> usize;
fn is_numeric(&self) -> bool;
fn default_value(&self) -> Box<dyn Any>;
fn to_bytes(&self, value: &dyn Any) -> Vec<u8>;
fn parse_bytes(&self, bytes: &[u8]) -> Box<dyn Any>;
}
#[derive(Clone, Serialize, Deserialize)]
pub struct CustomDType<T: 'static> {
name: String,
size: usize,
numeric: bool,
#[serde(skip)]
phantom: PhantomData<T>,
}
impl<T: Clone + Default + Send + Sync + 'static> CustomDType<T> {
pub fn new<S: Into<String>>(name: S, size: usize, numeric: bool) -> Self {
Self {
name: name.into(),
size,
numeric,
phantom: PhantomData,
}
}
}
impl<T: fmt::Debug + Clone + Default + Send + Sync + 'static> TypeDescriptor for CustomDType<T> {
fn name(&self) -> &str {
&self.name
}
fn size_in_bytes(&self) -> usize {
self.size
}
fn is_numeric(&self) -> bool {
self.numeric
}
fn default_value(&self) -> Box<dyn Any> {
Box::new(T::default())
}
fn to_bytes(&self, value: &dyn Any) -> Vec<u8> {
if let Some(_val) = value.downcast_ref::<T>() {
vec![0; self.size] } else {
vec![0; self.size] }
}
fn parse_bytes(&self, _bytes: &[u8]) -> Box<dyn Any> {
Box::new(T::default())
}
}
impl<T: fmt::Debug + Clone + Default + Send + Sync + 'static> fmt::Debug for CustomDType<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CustomDType")
.field("name", &self.name)
.field("size", &self.size)
.field("numeric", &self.numeric)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Debug, Clone, Default)]
struct TestType {
#[allow(dead_code)]
value: i32,
}
#[test]
fn test_custom_dtype() {
let dtype = CustomDType::<TestType>::new("TestType", 4, true);
assert_eq!(dtype.name(), "TestType");
assert_eq!(dtype.size_in_bytes(), 4);
assert!(dtype.is_numeric());
let default_value = dtype.default_value();
let _: &TestType = default_value
.downcast_ref()
.expect("default_value should downcast to TestType");
}
}