use crate::codec::{Codec, CodecName};
use crate::neuron::{Neuron, NeuronError};
use std::any::{Any, TypeId};
use std::marker::PhantomData;
use std::sync::Arc;
pub trait NeuronErased: Send + Sync + 'static {
fn name(&self) -> String;
fn name_without_codec(&self) -> String;
fn schema(&self) -> String;
fn payload_type_id(&self) -> TypeId;
fn codec_type_id(&self) -> TypeId;
fn clone_to_box(&self) -> Box<dyn NeuronErased + Send + Sync + 'static>;
fn clone_to_arc(&self) -> Arc<dyn NeuronErased + Send + Sync + 'static>;
fn encode_any(&self, data: &dyn std::any::Any) -> Result<Vec<u8>, NeuronError>;
fn decode_any(&self, data: &[u8]) -> Result<Box<dyn std::any::Any + Send>, NeuronError>;
fn as_any(&self) -> &dyn Any;
}
pub struct NeuronErasedWrapper<T: 'static, C: 'static> {
neuron: Arc<dyn Neuron<T, C> + Send + Sync + 'static>,
_phantom: PhantomData<(T, C)>,
}
impl<T, C> NeuronErasedWrapper<T, C>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
pub fn new(neuron: Arc<dyn Neuron<T, C> + Send + Sync + 'static>) -> Self {
Self {
neuron,
_phantom: PhantomData,
}
}
pub fn from_typed_neuron(
neuron: Arc<dyn Neuron<T, C> + Send + Sync + 'static>,
) -> Arc<dyn NeuronErased + Send + Sync + 'static> {
Arc::new(Self::new(neuron))
}
pub fn get_typed_neuron(&self) -> Arc<dyn Neuron<T, C> + Send + Sync + 'static> {
self.neuron.clone()
}
}
impl<T, C> NeuronErased for NeuronErasedWrapper<T, C>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
fn name(&self) -> String {
self.neuron.name()
}
fn name_without_codec(&self) -> String {
self.neuron.name_without_codec()
}
fn schema(&self) -> String {
self.neuron.schema()
}
fn payload_type_id(&self) -> TypeId {
TypeId::of::<T>()
}
fn codec_type_id(&self) -> TypeId {
TypeId::of::<C>()
}
fn clone_to_box(&self) -> Box<dyn NeuronErased + Send + Sync + 'static> {
Box::new(NeuronErasedWrapper {
neuron: self.neuron.clone(),
_phantom: PhantomData,
})
}
fn clone_to_arc(&self) -> Arc<dyn NeuronErased + Send + Sync + 'static> {
Arc::new(NeuronErasedWrapper {
neuron: self.neuron.clone(),
_phantom: PhantomData,
})
}
fn encode_any(&self, data: &dyn std::any::Any) -> Result<Vec<u8>, NeuronError> {
if let Some(typed_data) = data.downcast_ref::<T>() {
self.neuron.encode(typed_data)
} else {
Err(NeuronError::Encode {
neuron_name: self.name(),
message: "Type mismatch in encode_any".to_string(),
})
}
}
fn decode_any(&self, data: &[u8]) -> Result<Box<dyn std::any::Any + Send>, NeuronError> {
let decoded = self.neuron.decode(data)?;
Ok(Box::new(decoded) as Box<dyn std::any::Any + Send>)
}
fn as_any(&self) -> &dyn Any {
self
}
}
impl<T, C> Clone for NeuronErasedWrapper<T, C>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
fn clone(&self) -> Self {
Self {
neuron: self.neuron.clone(),
_phantom: PhantomData,
}
}
}
pub fn erase_neuron<T, C>(
neuron: Arc<dyn Neuron<T, C> + Send + Sync + 'static>,
) -> Arc<dyn NeuronErased + Send + Sync + 'static>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
NeuronErasedWrapper::from_typed_neuron(neuron)
}