use crate::codec::{Codec, CodecName};
use crate::erasure::error::{ErasureError, ErasureResult};
use crate::erasure::neuron::{NeuronErased, NeuronErasedWrapper};
use crate::logging::{LogTrace, TraceContext};
use crate::payload::{Payload, PayloadRaw};
use std::any::{Any, TypeId};
use std::marker::PhantomData;
use std::sync::Arc;
use uuid::Uuid;
pub trait PayloadErased: LogTrace + Send + Sync + 'static {
fn as_any(&self) -> &dyn Any;
fn get_trace_context(&self) -> TraceContext;
fn get_correlation_id(&self) -> Uuid {
self.get_trace_context().correlation_id
}
fn get_neuron_name(&self) -> String;
fn get_span_id(&self) -> u64 {
self.get_trace_context().span_id
}
fn get_parent_id(&self) -> Option<u64> {
self.get_trace_context().parent_id
}
fn payload_type_id(&self) -> TypeId;
fn codec_type_id(&self) -> TypeId;
fn clone_to_box(&self) -> Box<dyn PayloadErased + Send + Sync + 'static>;
fn clone_to_arc(&self) -> Arc<dyn PayloadErased + Send + Sync + 'static>;
fn get_erased_neuron(&self) -> Arc<dyn NeuronErased + Send + Sync + 'static>;
fn get_value(&self) -> &dyn std::any::Any;
}
pub trait PayloadRawErased: LogTrace + Send + Sync + 'static {
fn as_any(&self) -> &dyn Any;
fn get_bytes(&self) -> Arc<Vec<u8>>;
fn get_trace_context(&self) -> TraceContext;
fn get_correlation_id(&self) -> Uuid {
self.get_trace_context().correlation_id
}
fn get_neuron_name(&self) -> String;
fn get_span_id(&self) -> u64 {
self.get_trace_context().span_id
}
fn get_parent_id(&self) -> Option<u64> {
self.get_trace_context().parent_id
}
fn get_erased_neuron(&self) -> Arc<dyn NeuronErased + Send + Sync + 'static>;
fn payload_type_id(&self) -> TypeId;
fn codec_type_id(&self) -> TypeId;
fn clone_to_box(&self) -> Box<dyn PayloadRawErased + Send + Sync + 'static>;
fn clone_to_arc(&self) -> Arc<dyn PayloadRawErased + Send + Sync + 'static>;
}
#[derive(Debug)]
pub struct SimplePayloadRawErased {
pub bytes: Arc<Vec<u8>>,
pub neuron_name: String,
pub trace: TraceContext,
pub payload_type_id: TypeId,
pub codec_type_id: TypeId,
}
impl SimplePayloadRawErased {
pub fn new(
bytes: Arc<Vec<u8>>,
neuron_name: String,
trace: TraceContext,
payload_type_id: TypeId,
codec_type_id: TypeId,
) -> Self {
Self {
bytes,
neuron_name,
trace,
payload_type_id,
codec_type_id,
}
}
}
impl PayloadRawErased for SimplePayloadRawErased {
fn as_any(&self) -> &dyn Any {
self
}
fn get_bytes(&self) -> Arc<Vec<u8>> {
self.bytes.clone()
}
fn get_trace_context(&self) -> TraceContext {
self.trace
}
fn get_neuron_name(&self) -> String {
self.neuron_name.clone()
}
fn get_erased_neuron(&self) -> Arc<dyn NeuronErased + Send + Sync + 'static> {
panic!("SimplePayloadRawErased does not store the neuron. This is a design limitation. In the factory-based architecture, the neuron is typically retrieved from the synapse or provided by the transport.");
}
fn payload_type_id(&self) -> TypeId {
self.payload_type_id
}
fn codec_type_id(&self) -> TypeId {
self.codec_type_id
}
fn clone_to_box(&self) -> Box<dyn PayloadRawErased + Send + Sync + 'static> {
Box::new(Self {
bytes: self.bytes.clone(),
neuron_name: self.neuron_name.clone(),
trace: self.trace,
payload_type_id: self.payload_type_id,
codec_type_id: self.codec_type_id,
})
}
fn clone_to_arc(&self) -> Arc<dyn PayloadRawErased + Send + Sync + 'static> {
Arc::new(Self {
bytes: self.bytes.clone(),
neuron_name: self.neuron_name.clone(),
trace: self.trace,
payload_type_id: self.payload_type_id,
codec_type_id: self.codec_type_id,
})
}
}
#[derive(Debug)]
pub struct PayloadErasedWrapper<T: 'static, C: 'static> {
payload: Arc<Payload<T, C>>,
_phantom: PhantomData<(T, C)>,
}
impl<T, C> PayloadErasedWrapper<T, C>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
pub fn new(payload: Arc<Payload<T, C>>) -> Self {
Self {
payload,
_phantom: PhantomData,
}
}
pub fn from_typed_payload(
payload: Arc<Payload<T, C>>,
) -> Arc<dyn PayloadErased + Send + Sync + 'static> {
Arc::new(Self::new(payload))
}
pub fn get_typed_payload(&self) -> Arc<Payload<T, C>> {
self.payload.clone()
}
pub fn get_erased_neuron(&self) -> Arc<dyn NeuronErased + Send + Sync + 'static> {
NeuronErasedWrapper::from_typed_neuron(self.payload.neuron.clone())
}
pub fn to_typed_payload<U, D>(&self) -> ErasureResult<Arc<Payload<U, D>>>
where
U: Send + Sync + 'static,
D: Send + Sync + 'static,
{
if let Some(wrapper) = (self as &dyn Any).downcast_ref::<PayloadErasedWrapper<U, D>>() {
Ok(wrapper.payload.clone())
} else {
Err(ErasureError::PayloadTypeMismatch {
expected_payload_type: TypeId::of::<U>(),
expected_codec_type: TypeId::of::<D>(),
actual_payload_type: TypeId::of::<T>(),
actual_codec_type: TypeId::of::<C>(),
})
}
}
}
impl<T, C> PayloadErased for PayloadErasedWrapper<T, C>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
fn as_any(&self) -> &dyn Any {
self
}
fn get_trace_context(&self) -> TraceContext {
self.payload.trace
}
fn get_neuron_name(&self) -> String {
self.payload.neuron.name()
}
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 PayloadErased + Send + Sync + 'static> {
Box::new(PayloadErasedWrapper {
payload: self.payload.clone(),
_phantom: PhantomData,
})
}
fn clone_to_arc(&self) -> Arc<dyn PayloadErased + Send + Sync + 'static> {
Arc::new(PayloadErasedWrapper {
payload: self.payload.clone(),
_phantom: PhantomData,
})
}
fn get_erased_neuron(&self) -> Arc<dyn NeuronErased + Send + Sync + 'static> {
NeuronErasedWrapper::from_typed_neuron(self.payload.neuron.clone())
}
fn get_value(&self) -> &dyn std::any::Any {
&*self.payload.value as &dyn std::any::Any
}
}
#[derive(Debug)]
pub struct PayloadRawErasedWrapper<T: 'static, C: 'static> {
payload: Arc<PayloadRaw<T, C>>,
_phantom: PhantomData<(T, C)>,
}
impl<T, C> PayloadRawErasedWrapper<T, C>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
pub fn new(payload: Arc<PayloadRaw<T, C>>) -> Self {
Self {
payload,
_phantom: PhantomData,
}
}
pub fn from_payload_raw(
payload: Arc<PayloadRaw<T, C>>,
) -> Arc<dyn PayloadRawErased + Send + Sync + 'static> {
Arc::new(Self::new(payload))
}
pub fn get_payload_raw(&self) -> Arc<PayloadRaw<T, C>> {
self.payload.clone()
}
pub fn to_typed_payload(&self) -> Arc<PayloadRaw<T, C>> {
self.payload.clone()
}
}
impl<T, C> PayloadRawErased for PayloadRawErasedWrapper<T, C>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
fn as_any(&self) -> &dyn Any {
self
}
fn get_bytes(&self) -> Arc<Vec<u8>> {
self.payload.value.clone()
}
fn get_trace_context(&self) -> TraceContext {
self.payload.trace
}
fn get_neuron_name(&self) -> String {
self.payload.neuron.name()
}
fn get_erased_neuron(&self) -> Arc<dyn NeuronErased + Send + Sync + 'static> {
NeuronErasedWrapper::from_typed_neuron(self.payload.neuron.clone())
}
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 PayloadRawErased + Send + Sync + 'static> {
Box::new(PayloadRawErasedWrapper {
payload: self.payload.clone(),
_phantom: PhantomData,
})
}
fn clone_to_arc(&self) -> Arc<dyn PayloadRawErased + Send + Sync + 'static> {
Arc::new(PayloadRawErasedWrapper {
payload: self.payload.clone(),
_phantom: PhantomData,
})
}
}
pub fn erase_payload<T, C>(
payload: Arc<Payload<T, C>>,
) -> Arc<dyn PayloadErased + Send + Sync + 'static>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
PayloadErasedWrapper::from_typed_payload(payload)
}
pub fn erase_payload_raw<T, C>(
payload: Arc<PayloadRaw<T, C>>,
) -> Arc<dyn PayloadRawErased + Send + Sync + 'static>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
PayloadRawErasedWrapper::from_payload_raw(payload)
}
pub fn unerase_payload<T, C>(wrapper: &PayloadErasedWrapper<T, C>) -> Arc<Payload<T, C>>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
wrapper.get_typed_payload()
}
pub fn unerase_payload_raw<T, C>(wrapper: &PayloadRawErasedWrapper<T, C>) -> Arc<PayloadRaw<T, C>>
where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
{
wrapper.get_payload_raw()
}