1use std::rc::Rc;
31
32use async_trait::async_trait;
33use gwr_components::store::Store;
34use gwr_engine::engine::Engine;
35use gwr_engine::executor::Spawner;
36use gwr_engine::port::PortStateResult;
37use gwr_engine::traits::SimObject;
38use gwr_engine::types::{SimError, SimResult};
39use gwr_model_builder::{EntityDisplay, Runnable};
40use gwr_track::entity::Entity;
41
42#[derive(EntityDisplay, Runnable)]
43pub struct Scrambler<T>
44where
45 T: SimObject,
46{
47 pub entity: Rc<Entity>,
48 scramble: bool,
49 buffer_a: Rc<Store<T>>,
50 buffer_b: Rc<Store<T>>,
51}
52
53impl<T> Scrambler<T>
54where
55 T: SimObject,
56{
57 pub fn new_and_register(
58 engine: &Engine,
59 parent: &Rc<Entity>,
60 name: &str,
61 spawner: Spawner,
62 scramble: bool,
63 ) -> Result<Rc<Self>, SimError> {
64 let entity = Rc::new(Entity::new(parent, name));
65 let buffer_a = Store::new_and_register(engine, &entity, "buffer_a", spawner.clone(), 1)?;
66 let buffer_b = Store::new_and_register(engine, &entity, "buffer_b", spawner, 1)?;
67
68 let rc_self = Rc::new(Self {
69 entity: entity.clone(),
70 scramble,
71 buffer_a,
72 buffer_b,
73 });
74 engine.register(rc_self.clone());
75 Ok(rc_self)
76 }
77
78 pub fn connect_port_tx_a(&self, port_state: PortStateResult<T>) -> SimResult {
79 if self.scramble {
80 self.buffer_b.connect_port_tx(port_state)
81 } else {
82 self.buffer_a.connect_port_tx(port_state)
83 }
84 }
85
86 pub fn connect_port_tx_b(&self, port_state: PortStateResult<T>) -> SimResult {
87 if self.scramble {
88 self.buffer_a.connect_port_tx(port_state)
89 } else {
90 self.buffer_b.connect_port_tx(port_state)
91 }
92 }
93
94 pub fn port_rx_a(&self) -> PortStateResult<T> {
95 self.buffer_a.port_rx()
96 }
97
98 pub fn port_rx_b(&self) -> PortStateResult<T> {
99 self.buffer_b.port_rx()
100 }
101}