Skip to main content

cosmic_space/wave/exchange/
synch.rs

1use crate::loc::ToPoint;
2use crate::wave::core::cmd::CmdMethod;
3use crate::wave::core::CoreBounce;
4use crate::wave::exchange::{
5    DirectedHandlerShellDef, InCtxDef, ProtoTransmitterBuilderDef, ProtoTransmitterDef,
6    RootInCtxDef, SetStrategy,
7};
8use crate::wave::{
9    Bounce, BounceBacks, DirectedKind, DirectedProto, DirectedWave, Echo, FromReflectedAggregate,
10    Handling, Ping, Pong, RecipientSelector, ReflectedAggregate, ReflectedProto, ReflectedWave,
11    Scope, UltraWave, Wave, WaveKind,
12};
13use crate::{Agent, ReflectedCore, SpaceErr, Substance, Surface, ToSubstance};
14use alloc::borrow::Cow;
15use std::sync::Arc;
16
17pub trait ExchangeRouter: Send + Sync {
18    fn route(&self, wave: UltraWave);
19    fn exchange(&self, direct: DirectedWave) -> Result<ReflectedAggregate, SpaceErr>;
20}
21
22#[derive(Clone)]
23pub struct SyncRouter {
24    pub router: Arc<dyn ExchangeRouter>,
25}
26
27impl SyncRouter {
28    pub fn new(router: Arc<dyn ExchangeRouter>) -> Self {
29        Self { router }
30    }
31}
32
33impl ExchangeRouter for SyncRouter {
34    fn route(&self, wave: UltraWave) {
35        self.router.route(wave)
36    }
37
38    fn exchange(&self, direct: DirectedWave) -> Result<ReflectedAggregate, SpaceErr> {
39        self.router.exchange(direct)
40    }
41}
42
43pub type ProtoTransmitter = ProtoTransmitterDef<SyncRouter, ()>;
44
45impl ProtoTransmitter {
46    pub fn new(router: Arc<dyn ExchangeRouter>) -> ProtoTransmitter {
47        let router = SyncRouter::new(router);
48        Self {
49            from: SetStrategy::None,
50            to: SetStrategy::None,
51            via: SetStrategy::None,
52            agent: SetStrategy::Fill(Agent::Anonymous),
53            scope: SetStrategy::Fill(Scope::None),
54            handling: SetStrategy::Fill(Handling::default()),
55            method: SetStrategy::None,
56            router,
57            exchanger: (),
58        }
59    }
60
61    pub fn direct<D, W>(&self, wave: D) -> Result<W, SpaceErr>
62    where
63        W: FromReflectedAggregate,
64        D: Into<DirectedProto>,
65    {
66        let mut wave: DirectedProto = wave.into();
67
68        self.prep_direct(&mut wave);
69
70        let directed = wave.build()?;
71
72        println!("DIRECTE!");
73        match directed.bounce_backs() {
74            BounceBacks::None => {
75                self.router.route(directed.to_ultra());
76                FromReflectedAggregate::from_reflected_aggregate(ReflectedAggregate::None)
77            }
78            _ => FromReflectedAggregate::from_reflected_aggregate(self.router.exchange(directed)?),
79        }
80    }
81
82    pub fn ping<D>(&self, ping: D) -> Result<Wave<Pong>, SpaceErr>
83    where
84        D: Into<DirectedProto>,
85    {
86        println!("PING!");
87        let mut ping: DirectedProto = ping.into();
88        ping.bounce_backs = Some(BounceBacks::Single);
89        if let Some(DirectedKind::Ping) = ping.kind {
90            self.direct(ping)
91        } else {
92            Err(SpaceErr::server_error("expected DirectedKind::Ping"))
93        }
94    }
95
96    pub fn ripple<D>(&self, ripple: D) -> Result<Vec<Wave<Echo>>, SpaceErr>
97    where
98        D: Into<DirectedProto>,
99    {
100        let mut ripple: DirectedProto = ripple.into();
101        if let Some(DirectedKind::Ripple) = ripple.kind {
102            self.direct(ripple)
103        } else {
104            Err(SpaceErr::server_error("expected DirectedKind::Ping"))
105        }
106    }
107
108    pub fn signal<D>(&self, signal: D) -> Result<(), SpaceErr>
109    where
110        D: Into<DirectedProto>,
111    {
112        let mut signal: DirectedProto = signal.into();
113        if let Some(DirectedKind::Signal) = signal.kind {
114            self.direct(signal)
115        } else {
116            Err(SpaceErr::server_error("expected DirectedKind::Ping"))
117        }
118    }
119
120    pub fn bounce_from(&self, to: &Surface, from: &Surface) -> bool {
121        let mut directed = DirectedProto::ping();
122        directed.from(from.clone());
123        directed.to(to.clone());
124        directed.method(CmdMethod::Bounce);
125        match self.ping(directed) {
126            Ok(pong) => pong.is_ok(),
127            Err(_) => false,
128        }
129    }
130
131    pub fn bounce(&self, to: &Surface) -> bool {
132        let mut directed = DirectedProto::ping();
133        directed.to(to.clone());
134        directed.method(CmdMethod::Bounce);
135        match self.ping(directed) {
136            Ok(pong) => pong.is_ok(),
137            Err(_) => false,
138        }
139    }
140
141    pub fn route(&self, wave: UltraWave) {
142        self.router.route(wave)
143    }
144
145    pub fn reflect<W>(&self, wave: W) -> Result<(), SpaceErr>
146    where
147        W: Into<ReflectedProto>,
148    {
149        let mut wave: ReflectedProto = wave.into();
150
151        self.prep_reflect(&mut wave);
152
153        let wave = wave.build()?;
154        let wave = wave.to_ultra();
155        self.router.route(wave);
156
157        Ok(())
158    }
159}
160
161pub type ProtoTransmitterBuilder = ProtoTransmitterBuilderDef<SyncRouter, ()>;
162
163impl ProtoTransmitterBuilder {
164    pub fn new(router: Arc<dyn ExchangeRouter>) -> ProtoTransmitterBuilder {
165        let router = SyncRouter::new(router);
166        Self {
167            from: SetStrategy::None,
168            to: SetStrategy::None,
169            via: SetStrategy::None,
170            agent: SetStrategy::Fill(Agent::Anonymous),
171            scope: SetStrategy::Fill(Scope::None),
172            handling: SetStrategy::Fill(Handling::default()),
173            method: SetStrategy::None,
174            router,
175            exchanger: (),
176        }
177    }
178}
179
180pub type RootInCtx = RootInCtxDef<ProtoTransmitter>;
181
182pub type InCtx<'a, I> = InCtxDef<'a, I, ProtoTransmitter>;
183
184impl<'a, I> InCtx<'a, I> {
185    pub fn push_from(self, from: Surface) -> InCtx<'a, I> {
186        let mut transmitter = self.transmitter.clone();
187        transmitter.to_mut().from = SetStrategy::Override(from);
188        InCtx {
189            root: self.root,
190            input: self.input,
191            logger: self.logger.clone(),
192            transmitter,
193        }
194    }
195}
196
197pub trait DirectedHandlerSelector {
198    fn select<'a>(&self, select: &'a RecipientSelector<'a>) -> Result<&dyn DirectedHandler, ()>;
199}
200
201pub trait DirectedHandler: Send + Sync {
202    fn handle(&self, ctx: RootInCtx) -> CoreBounce;
203
204    fn bounce(&self, ctx: RootInCtx) -> CoreBounce {
205        CoreBounce::Reflected(ReflectedCore::ok())
206    }
207}
208
209pub struct DirectedHandlerProxy {
210    proxy: Box<dyn DirectedHandler>,
211}
212
213impl DirectedHandlerProxy {
214    pub fn new<D>(handler: D) -> Self
215    where
216        D: DirectedHandler + 'static + Sized,
217    {
218        Self {
219            proxy: Box::new(handler),
220        }
221    }
222
223    pub fn boxed<D>(handler: Box<D>) -> Self
224    where
225        D: DirectedHandler + 'static + Sized,
226    {
227        Self { proxy: handler }
228    }
229}
230
231impl DirectedHandler for DirectedHandlerProxy {
232    fn handle(&self, ctx: RootInCtx) -> CoreBounce {
233        self.proxy.handle(ctx)
234    }
235}
236
237pub type DirectedHandlerShell =
238    DirectedHandlerShellDef<Box<dyn DirectedHandler>, ProtoTransmitterBuilder>;
239
240impl DirectedHandlerShell {
241    pub fn handle(&self, wave: DirectedWave) -> Bounce<ReflectedWave> {
242        let logger = self
243            .logger
244            .point(self.surface.clone().to_point())
245            .spanner(&wave);
246        let mut transmitter = self.builder.clone().build();
247        let reflection = wave.reflection();
248        let ctx = RootInCtx::new(wave, self.surface.clone(), logger, transmitter.clone());
249        match self.handler.handle(ctx) {
250            CoreBounce::Absorbed => Bounce::Absorbed,
251            CoreBounce::Reflected(reflected) => {
252                let wave = reflection.unwrap().make(reflected, self.surface.clone());
253                Bounce::Reflected(wave)
254            }
255        }
256    }
257}
258
259impl RootInCtx {
260    pub fn push<'a, I>(&self) -> Result<InCtx<I>, SpaceErr>
261    where
262        Substance: ToSubstance<I>,
263    {
264        let input = match self.wave.to_substance_ref() {
265            Ok(input) => input,
266            Err(err) => return Err(err.into()),
267        };
268        Ok(InCtx {
269            root: self,
270            input,
271            logger: self.logger.clone(),
272            transmitter: Cow::Borrowed(&self.transmitter),
273        })
274    }
275}