use crate::feedback::{FeedbackSink, FeedbackSinkProducer, FeedbackSource, FeedbackSourceConsumer}; use crate::node::{ CommonConsumerIndex, CommonProducerIndex, ConsumerIndex, Node, NodeClass, NodeIndex, NodeWrapper, ProducerIndex, }; pub enum InternalNode { FeedbackSource(FeedbackSource), FeedbackSink(FeedbackSink), } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum InternalNodeClass { FeedbackSource, FeedbackSink, } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum InternalConsumer { FeedbackSource(FeedbackSourceConsumer), } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum InternalProducer { FeedbackSink(FeedbackSinkProducer), } impl NodeClass for InternalNode { type Class = InternalNodeClass; fn class(&self) -> Self::Class { match self { Self::FeedbackSource(_) => Self::Class::FeedbackSource, Self::FeedbackSink(_) => Self::Class::FeedbackSink, } } } impl NodeWrapper for InternalNode where T: Default + Copy, { type Payload = T; type Consumer = InternalConsumer; type Producer = InternalProducer; fn read(&self, producer: IntoP) -> T where IntoP: Into, { match self { Self::FeedbackSink(feedback_sink) => match producer.into() { Self::Producer::FeedbackSink(producer) => feedback_sink.read(producer), }, Self::FeedbackSource(_) => unreachable!("Feedback source does not offer any producers"), } } fn write(&mut self, consumer: IntoC, input: T) where IntoC: Into, { match self { Self::FeedbackSource(feedback_source) => match consumer.into() { Self::Consumer::FeedbackSource(consumer) => feedback_source.write(consumer, input), }, Self::FeedbackSink(_) => unreachable!("Feedback sink does not offer any consumers"), } } } #[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)] pub struct InternalNodeIndex { class: InternalNodeClass, index: usize, } pub type InternalConsumerIndex = CommonConsumerIndex; pub type InternalProducerIndex = CommonProducerIndex; impl NodeIndex for InternalNodeIndex { type Class = InternalNodeClass; type Consumer = InternalConsumer; type ConsumerIndex = InternalConsumerIndex; type Producer = InternalProducer; type ProducerIndex = InternalProducerIndex; fn new(class: Self::Class, index: usize) -> Self { Self { class, index } } fn consumer(&self, consumer: IntoC) -> InternalConsumerIndex where IntoC: Into, { let consumer = consumer.into(); match self.class { Self::Class::FeedbackSource => match consumer { Self::Consumer::FeedbackSource(_) => InternalConsumerIndex::new(*self, consumer), }, Self::Class::FeedbackSink => panic!("Feedback sink does not offer any consumers"), } } fn producer(&self, producer: IntoP) -> InternalProducerIndex where IntoP: Into, { let producer = producer.into(); match self.class { Self::Class::FeedbackSink => match producer { Self::Producer::FeedbackSink(_) => InternalProducerIndex::new(*self, producer), }, Self::Class::FeedbackSource => panic!("Feedback source does not offer any producers"), } } } #[cfg(test)] mod tests { use super::*; use crate::feedback; #[test] fn access_nested_node_i32() { let (source, sink) = feedback::new_feedback_pair(); let mut source: InternalNode<_> = InternalNode::FeedbackSource(source); let mut sink: InternalNode<_> = InternalNode::FeedbackSink(sink); source.write(InternalConsumer::FeedbackSource(FeedbackSourceConsumer), 10); source.tick(); sink.tick(); assert_eq!( sink.read(InternalProducer::FeedbackSink(FeedbackSinkProducer)), 10 ); } #[test] fn access_nested_node_array_i32() { let (source, sink) = feedback::new_feedback_pair(); let mut source: InternalNode<_> = InternalNode::FeedbackSource(source); let mut sink: InternalNode<_> = InternalNode::FeedbackSink(sink); source.write( InternalConsumer::FeedbackSource(FeedbackSourceConsumer), [10, 20], ); source.tick(); sink.tick(); assert_eq!( sink.read(InternalProducer::FeedbackSink(FeedbackSinkProducer)), [10, 20] ); } #[test] fn initialize_node_index() { let source = InternalNodeIndex::new(InternalNodeClass::FeedbackSource, 1); let sink = InternalNodeIndex::new(InternalNodeClass::FeedbackSink, 0); let _source_consumer = source.consumer(InternalConsumer::FeedbackSource(FeedbackSourceConsumer)); let _sink_producer = sink.producer(InternalProducer::FeedbackSink(FeedbackSinkProducer)); } }