use plexor_core::codec::{Codec, CodecError, CodecName};
use plexor_core::erasure::neuron::{NeuronErased, NeuronErasedWrapper, erase_neuron};
use plexor_core::erasure::synapse::{
SynapseInternalErased, SynapseInternalErasedWrapper, erase_synapse_internal,
};
use plexor_core::namespace::NamespaceImpl;
use plexor_core::neuron::{Neuron, NeuronImpl};
use plexor_core::synapse::{SynapseInprocess, SynapseInternal};
use std::any::TypeId;
use std::sync::Arc;
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
struct TestStruct {
foo: i32,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
struct OtherStruct {
bar: String,
}
struct TestCodec;
impl CodecName for TestCodec {
fn name() -> &'static str {
"test"
}
}
impl Codec<TestStruct> for TestCodec {
fn encode(_data: &TestStruct) -> Result<Vec<u8>, CodecError> {
Ok(vec![])
}
fn decode(_data: &[u8]) -> Result<TestStruct, CodecError> {
Ok(TestStruct { foo: 42 })
}
}
impl Codec<OtherStruct> for TestCodec {
fn encode(_data: &OtherStruct) -> Result<Vec<u8>, CodecError> {
Ok(vec![])
}
fn decode(_data: &[u8]) -> Result<OtherStruct, CodecError> {
Ok(OtherStruct {
bar: "other".to_string(),
})
}
}
fn test_namespace() -> Arc<NamespaceImpl> {
Arc::new(NamespaceImpl {
delimiter: ".",
parts: vec!["test"],
})
}
#[test]
fn test_synapse_erasure_and_restoration() {
let ns = test_namespace();
let neuron = Arc::new(NeuronImpl::<TestStruct, TestCodec>::new(ns));
let synapse = SynapseInprocess::new(neuron.clone(), vec![], vec![]);
let erased = erase_synapse_internal(synapse);
{
let guard = erased.read();
let restored = guard
.as_any()
.downcast_ref::<SynapseInternalErasedWrapper<
TestStruct,
TestCodec,
SynapseInprocess<TestStruct, TestCodec>,
>>()
.expect("Safe downcast should work");
assert_eq!(restored.neuron_name(), neuron.name());
}
}
#[test]
fn test_multiple_neuron_types_in_universal_plexus_context() {
let ns1 = test_namespace();
let neuron1 = Arc::new(NeuronImpl::<TestStruct, TestCodec>::new(ns1));
let ns2 = test_namespace();
let neuron2 = Arc::new(NeuronImpl::<OtherStruct, TestCodec>::new(ns2));
let neurons: Vec<Arc<dyn NeuronErased + Send + Sync>> =
vec![erase_neuron(neuron1.clone()), erase_neuron(neuron2.clone())];
assert_eq!(neurons.len(), 2);
assert_ne!(neurons[0].payload_type_id(), neurons[1].payload_type_id());
assert_eq!(neurons[0].codec_type_id(), neurons[1].codec_type_id());
let restored1 = neurons[0]
.as_any()
.downcast_ref::<NeuronErasedWrapper<TestStruct, TestCodec>>()
.expect("Should restore first neuron");
assert_eq!(restored1.name(), neuron1.name());
let restored2 = neurons[1]
.as_any()
.downcast_ref::<NeuronErasedWrapper<OtherStruct, TestCodec>>()
.expect("Should restore second neuron");
assert_eq!(restored2.name(), neuron2.name());
}
#[test]
fn test_unsafe_transmute_justification() {
let ns = test_namespace();
let neuron = Arc::new(NeuronImpl::<TestStruct, TestCodec>::new(ns));
let synapse = SynapseInprocess::new(neuron.clone(), vec![], vec![]);
let erased_wrapper = SynapseInternalErasedWrapper::new(synapse);
let _ = erased_wrapper
.to_typed_synapse::<TestStruct, TestCodec, SynapseInprocess<TestStruct, TestCodec>>()
.expect("Should succeed");
}
#[test]
fn test_cross_type_interference_prevention() {
let ns = test_namespace();
let neuron1 = Arc::new(NeuronImpl::<TestStruct, TestCodec>::new(ns.clone()));
let synapse1 = SynapseInprocess::new(neuron1.clone(), vec![], vec![]);
let erased1 = SynapseInternalErasedWrapper::new(synapse1);
let result = erased1
.to_typed_synapse::<OtherStruct, TestCodec, SynapseInprocess<OtherStruct, TestCodec>>();
assert!(result.is_err(), "Should prevent cross-type restoration");
}
#[test]
fn test_complex_generic_restoration() {
fn restore_generic<T, C, S>(
erased: &SynapseInternalErasedWrapper<
TestStruct,
TestCodec,
SynapseInprocess<TestStruct, TestCodec>,
>,
) where
T: Send + Sync + 'static,
C: Codec<T> + CodecName + Send + Sync + 'static,
S: SynapseInternal<T, C> + Send + Sync + 'static,
{
if TypeId::of::<T>() == TypeId::of::<TestStruct>()
&& TypeId::of::<C>() == TypeId::of::<TestCodec>()
&& TypeId::of::<S>() == TypeId::of::<SynapseInprocess<TestStruct, TestCodec>>()
{
let _ = erased
.to_typed_synapse::<T, C, S>()
.expect("Restoration should work when TypeIds match");
}
}
let ns = test_namespace();
let neuron = Arc::new(NeuronImpl::<TestStruct, TestCodec>::new(ns));
let synapse = SynapseInprocess::new(neuron.clone(), vec![], vec![]);
let erased = SynapseInternalErasedWrapper::new(synapse);
restore_generic::<TestStruct, TestCodec, SynapseInprocess<TestStruct, TestCodec>>(&erased);
}