cosmic_space/particle/
traversal.rs

1use std::ops::{Deref, DerefMut};
2
3use crate::loc::Layer;
4use crate::log::{SpanLogger, Trackable};
5use crate::wave::exchange::asynch::Exchanger;
6use crate::wave::{DirectedWave, Ping, Pong, ReflectedWave, SingularDirectedWave, UltraWave, Wave};
7use crate::{ParticleRecord, SpaceErr, Surface};
8use crate::point::Point;
9
10#[async_trait]
11pub trait TraversalLayer {
12    fn surface(&self) -> Surface;
13
14    async fn traverse_next(&self, traversal: Traversal<UltraWave>);
15    async fn inject(&self, wave: UltraWave);
16
17    fn exchanger(&self) -> &Exchanger;
18
19    async fn deliver_directed(&self, direct: Traversal<DirectedWave>) -> Result<(), SpaceErr> {
20        Err(SpaceErr::server_error(
21            "this layer does not handle directed messages",
22        ))
23    }
24
25    async fn deliver_reflected(&self, reflect: Traversal<ReflectedWave>) -> Result<(), SpaceErr> {
26        self.exchanger().reflected(reflect.payload).await
27    }
28
29    async fn visit(&self, traversal: Traversal<UltraWave>) -> Result<(), SpaceErr> {
30        if let Some(dest) = &traversal.dest {
31            if self.surface().layer == *dest {
32                if traversal.is_directed() {
33                    self.deliver_directed(traversal.unwrap_directed()).await?;
34                } else {
35                    self.deliver_reflected(traversal.unwrap_reflected()).await?;
36                }
37                return Ok(());
38            } else {
39            }
40        }
41
42        if traversal.is_directed() && traversal.dir == TraversalDirection::Fabric {
43            self.directed_fabric_bound(traversal.unwrap_directed())
44                .await?;
45        } else if traversal.is_reflected() && traversal.dir == TraversalDirection::Core {
46            self.reflected_core_bound(traversal.unwrap_reflected())
47                .await?;
48        } else if traversal.is_directed() && traversal.dir == TraversalDirection::Core {
49            self.directed_core_bound(traversal.unwrap_directed())
50                .await?;
51        } else if traversal.is_reflected() && traversal.dir == TraversalDirection::Fabric {
52            self.reflected_fabric_bound(traversal.unwrap_reflected())
53                .await?;
54        }
55
56        Ok(())
57    }
58
59    // override if you want to track outgoing requests
60    async fn directed_fabric_bound(
61        &self,
62        mut traversal: Traversal<DirectedWave>,
63    ) -> Result<(), SpaceErr> {
64        self.traverse_next(traversal.wrap()).await;
65        Ok(())
66    }
67
68    async fn directed_core_bound(
69        &self,
70        mut traversal: Traversal<DirectedWave>,
71    ) -> Result<(), SpaceErr> {
72        self.traverse_next(traversal.wrap()).await;
73        Ok(())
74    }
75
76    // override if you want to track incoming responses
77    async fn reflected_core_bound(
78        &self,
79        traversal: Traversal<ReflectedWave>,
80    ) -> Result<(), SpaceErr> {
81        self.traverse_next(traversal.to_ultra()).await;
82        Ok(())
83    }
84
85    async fn reflected_fabric_bound(
86        &self,
87        traversal: Traversal<ReflectedWave>,
88    ) -> Result<(), SpaceErr> {
89        self.traverse_next(traversal.to_ultra()).await;
90        Ok(())
91    }
92}
93
94#[derive(Clone)]
95pub struct TraversalPlan {
96    pub stack: Vec<Layer>,
97}
98
99impl TraversalPlan {
100    pub fn new(stack: Vec<Layer>) -> Self {
101        Self { stack }
102    }
103
104    pub fn towards_fabric(&self, layer: &Layer) -> Option<Layer> {
105        let mut layer = layer.clone();
106        let mut index: i32 = layer.ordinal() as i32;
107        loop {
108            index = index - 1;
109
110            if index < 0i32 {
111                return None;
112            } else if self
113                .stack
114                .contains(&Layer::from_ordinal(index as u8).unwrap())
115            {
116                return Some(Layer::from_ordinal(index as u8).unwrap());
117            }
118        }
119    }
120
121    pub fn towards_core(&self, layer: &Layer) -> Option<Layer> {
122        let mut layer = layer.clone();
123        let mut index = layer.ordinal();
124        loop {
125            index = index + 1;
126            let layer = match Layer::from_ordinal(index) {
127                Some(layer) => layer,
128                None => {
129                    return None;
130                }
131            };
132
133            if self.stack.contains(&layer) {
134                return Some(layer);
135            }
136        }
137    }
138
139    pub fn has_layer(&self, layer: &Layer) -> bool {
140        self.stack.contains(layer)
141    }
142}
143
144#[derive(Clone)]
145pub struct TraversalInjection {
146    pub surface: Surface,
147    pub wave: UltraWave,
148    pub from_gravity: bool,
149    pub dir: Option<TraversalDirection>,
150}
151
152impl TraversalInjection {
153    pub fn new(injector: Surface, wave: UltraWave) -> Self {
154        Self {
155            surface: injector,
156            wave,
157            from_gravity: false,
158            dir: None,
159        }
160    }
161}
162
163#[derive(Clone)]
164pub struct Traversal<W> {
165    pub point: Point,
166    pub payload: W,
167    pub record: ParticleRecord,
168    pub layer: Layer,
169    pub dest: Option<Layer>,
170    pub logger: SpanLogger,
171    pub dir: TraversalDirection,
172    pub to: Surface,
173}
174
175impl<W> Trackable for Traversal<W>
176where
177    W: Trackable,
178{
179    fn track_id(&self) -> String {
180        self.payload.track_id()
181    }
182
183    fn track_method(&self) -> String {
184        self.payload.track_method()
185    }
186
187    fn track_payload(&self) -> String {
188        self.payload.track_payload()
189    }
190
191    fn track_from(&self) -> String {
192        self.payload.track_from()
193    }
194
195    fn track_to(&self) -> String {
196        self.payload.track_to()
197    }
198
199    fn track(&self) -> bool {
200        self.payload.track()
201    }
202}
203
204#[derive(Clone, Eq, PartialEq, Hash, strum_macros::Display)]
205pub enum TraversalDirection {
206    Fabric,
207    Core,
208}
209
210impl TraversalDirection {
211    pub fn new(from: &Layer, to: &Layer) -> Result<Self, SpaceErr> {
212        if from == to {
213            return Err(
214                "cannot determine traversal direction if from and to are the same layer".into(),
215            );
216        } else if from.ordinal() < to.ordinal() {
217            Ok(TraversalDirection::Core)
218        } else {
219            Ok(TraversalDirection::Fabric)
220        }
221    }
222
223    pub fn is_fabric(&self) -> bool {
224        match self {
225            TraversalDirection::Fabric => true,
226            TraversalDirection::Core => false,
227        }
228    }
229    pub fn is_core(&self) -> bool {
230        match self {
231            TraversalDirection::Fabric => false,
232            TraversalDirection::Core => true,
233        }
234    }
235}
236
237impl TraversalDirection {
238    pub fn reverse(&self) -> TraversalDirection {
239        match self {
240            Self::Fabric => Self::Core,
241            Self::Core => Self::Fabric,
242        }
243    }
244}
245
246impl<W> Traversal<W> {
247    pub fn new(
248        payload: W,
249        record: ParticleRecord,
250        layer: Layer,
251        logger: SpanLogger,
252        dir: TraversalDirection,
253        dest: Option<Layer>,
254        to: Surface,
255        point: Point,
256    ) -> Self {
257        Self {
258            payload,
259            record,
260            layer,
261            logger,
262            dir,
263            dest,
264            to,
265            point,
266        }
267    }
268
269    pub fn extract(self) -> W {
270        self.payload
271    }
272
273    pub fn with<N>(self, payload: N) -> Traversal<N> {
274        Traversal {
275            payload,
276            record: self.record,
277            layer: self.layer,
278            logger: self.logger,
279            dir: self.dir,
280            dest: self.dest,
281            to: self.to,
282            point: self.point,
283        }
284    }
285
286    pub fn reverse(&mut self) {
287        self.dir = self.dir.reverse();
288    }
289}
290
291impl<W> Traversal<W> {
292    pub fn next(&mut self) -> Option<Layer> {
293        let next = match self.dir {
294            TraversalDirection::Fabric => self
295                .record
296                .details
297                .stub
298                .kind
299                .wave_traversal_plan()
300                .towards_fabric(&self.layer),
301            TraversalDirection::Core => self
302                .record
303                .details
304                .stub
305                .kind
306                .wave_traversal_plan()
307                .towards_core(&self.layer),
308        };
309        match &next {
310            None => {}
311            Some(layer) => {
312                self.layer = layer.clone();
313            }
314        }
315        next
316    }
317
318    pub fn is_inter_layer(&self) -> bool {
319        self.to.point == *self.logger.point()
320    }
321}
322
323impl Traversal<UltraWave> {
324    pub fn is_fabric_bound(&self) -> bool {
325        match self.dir {
326            TraversalDirection::Fabric => true,
327            TraversalDirection::Core => false,
328        }
329    }
330
331    pub fn is_core_bound(&self) -> bool {
332        match self.dir {
333            TraversalDirection::Fabric => false,
334            TraversalDirection::Core => true,
335        }
336    }
337
338    pub fn is_ping(&self) -> bool {
339        match &self.payload {
340            UltraWave::Ping(_) => true,
341            _ => false,
342        }
343    }
344
345    pub fn is_pong(&self) -> bool {
346        match &self.payload {
347            UltraWave::Pong(_) => true,
348            _ => false,
349        }
350    }
351
352    pub fn is_directed(&self) -> bool {
353        match self.payload {
354            UltraWave::Ping(_) => true,
355            UltraWave::Pong(_) => false,
356            UltraWave::Ripple(_) => true,
357            UltraWave::Echo(_) => false,
358            UltraWave::Signal(_) => true,
359        }
360    }
361
362    pub fn is_reflected(&self) -> bool {
363        !self.is_directed()
364    }
365
366    pub fn unwrap_directed(self) -> Traversal<DirectedWave> {
367        let clone = self.clone();
368        match self.payload {
369            UltraWave::Ping(ping) => clone.with(ping.to_directed().clone()),
370            UltraWave::Ripple(ripple) => clone.with(ripple.to_directed()),
371            UltraWave::Signal(signal) => clone.with(signal.to_directed()),
372            _ => {
373                panic!("cannot call this unless you are sure it's a DirectedWave")
374            }
375        }
376    }
377
378    pub fn unwrap_singular_directed(self) -> Traversal<SingularDirectedWave> {
379        let clone = self.clone();
380        match self.payload {
381            UltraWave::Ping(ping) => clone.with(ping.to_singular_directed()),
382            UltraWave::Ripple(ripple) => {
383                clone.with(ripple.to_singular_directed().expect("singular directed"))
384            }
385            UltraWave::Signal(signal) => clone.with(signal.to_singular_directed()),
386            _ => {
387                panic!("cannot call this unless you are sure it's a DirectedWave")
388            }
389        }
390    }
391
392    pub fn unwrap_reflected(self) -> Traversal<ReflectedWave> {
393        let clone = self.clone();
394        match self.payload {
395            UltraWave::Pong(pong) => clone.with(pong.to_reflected()),
396            UltraWave::Echo(echo) => clone.with(echo.to_reflected()),
397            _ => {
398                panic!("cannot call this unless you are sure it's a ReflectedWave")
399            }
400        }
401    }
402
403    pub fn unwrap_ping(self) -> Traversal<Wave<Ping>> {
404        if let UltraWave::Ping(ping) = self.payload.clone() {
405            self.with(ping)
406        } else {
407            panic!("cannot call this unless you are sure it's a Ping")
408        }
409    }
410
411    pub fn unwrap_pong(self) -> Traversal<Wave<Pong>> {
412        if let UltraWave::Pong(pong) = self.payload.clone() {
413            self.with(pong)
414        } else {
415            panic!("cannot call this unless you are sure it's a Pong")
416        }
417    }
418}
419
420impl Traversal<DirectedWave> {
421    pub fn wrap(self) -> Traversal<UltraWave> {
422        let ping = self.payload.clone();
423        self.with(ping.to_ultra())
424    }
425}
426
427impl Traversal<ReflectedWave> {
428    pub fn wrap(self) -> Traversal<UltraWave> {
429        let ping = self.payload.clone();
430        self.with(ping.to_ultra())
431    }
432}
433
434impl Traversal<SingularDirectedWave> {
435    pub fn wrap(self) -> Traversal<UltraWave> {
436        let ping = self.payload.clone();
437        self.with(ping.to_ultra())
438    }
439}
440
441impl Traversal<ReflectedWave> {
442    pub fn to_ultra(self) -> Traversal<UltraWave> {
443        let pong = self.payload.clone();
444        self.with(pong.to_ultra())
445    }
446}
447
448impl Traversal<Wave<Ping>> {
449    pub fn to_ultra(self) -> Traversal<UltraWave> {
450        let ping = self.payload.clone();
451        self.with(ping.to_ultra())
452    }
453
454    pub fn to_directed(self) -> Traversal<DirectedWave> {
455        let ping = self.payload.clone();
456        self.with(ping.to_directed())
457    }
458}
459
460impl Traversal<Wave<Pong>> {
461    pub fn to_ultra(self) -> Traversal<UltraWave> {
462        let pong = self.payload.clone();
463        self.with(pong.to_ultra())
464    }
465
466    pub fn to_reflected(self) -> Traversal<ReflectedWave> {
467        let pong = self.payload.clone();
468        self.with(pong.to_reflected())
469    }
470}
471
472impl<W> Deref for Traversal<W> {
473    type Target = W;
474
475    fn deref(&self) -> &Self::Target {
476        &self.payload
477    }
478}
479
480impl<W> DerefMut for Traversal<W> {
481    fn deref_mut(&mut self) -> &mut Self::Target {
482        &mut self.payload
483    }
484}