cosmic_space/
hyper.rs

1use std::collections::HashSet;
2use std::ops::{Deref, DerefMut};
3
4use serde::{Deserialize, Serialize};
5
6use cosmic_macros_primitive::Autobox;
7
8use crate::command::common::StateSrc;
9use crate::config::mechtron::MechtronConfig;
10use crate::err::SpaceErr;
11use crate::kind::{Kind, KindParts, StarSub};
12use crate::loc::{StarKey, Surface, ToPoint, ToSurface};
13use crate::log::Log;
14use crate::parse::SkewerCase;
15use crate::particle::{Details, Status, Stub};
16use crate::selector::KindSelector;
17use crate::substance::Substance;
18use crate::wave::core::cmd::CmdMethod;
19use crate::wave::core::hyp::HypMethod;
20use crate::wave::core::{DirectedCore, ReflectedCore};
21use crate::wave::{
22    Ping, Pong, ReflectedKind, ReflectedProto, ToRecipients, UltraWave, Wave, WaveId, WaveKind,
23};
24use crate::{Agent, Document};
25use crate::point::Point;
26
27#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, strum_macros::Display)]
28pub enum AssignmentKind {
29    Create,
30    // eventually we will have Move as well as Create
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, strum_macros::Display)]
34pub enum ChildRegistry {
35    Shell,
36    Core,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub enum Location {
41    Central,
42    Nowhere,
43    Somewhere(Point),
44}
45
46impl ToString for Location {
47    fn to_string(&self) -> String {
48        match self {
49            Location::Nowhere => "Unassigned".to_string(),
50            Location::Somewhere(point) => point.to_string(),
51            Location::Central => Point::central().to_string(),
52        }
53    }
54}
55
56impl Location {
57    pub fn new(point: Point) -> Self {
58        Location::Somewhere(point)
59    }
60
61    pub fn ok_or(&self) -> Result<Point, SpaceErr> {
62        match self {
63            Location::Nowhere => Err("Particle is presently nowhere".into()),
64            Location::Somewhere(point) => Ok(point.clone()),
65
66            Location::Central => Ok(Point::central()),
67        }
68    }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct ParticleRecord {
73    pub details: Details,
74    pub location: ParticleLocation,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
78pub struct ParticleLocation {
79    pub star: Option<Point>,
80    pub host: Option<Point>,
81}
82
83impl ParticleLocation {
84    pub fn new(star: Option<Point>, host: Option<Point>) -> Self {
85        Self { star, host }
86    }
87}
88
89impl From<ParticleLocation> for ReflectedCore {
90    fn from(location: ParticleLocation) -> Self {
91        let location = Substance::Location(location);
92        ReflectedCore::ok_body(location)
93    }
94}
95
96impl Default for ParticleLocation {
97    fn default() -> Self {
98        ParticleLocation::new(None, None)
99    }
100}
101
102impl Default for ParticleRecord {
103    fn default() -> Self {
104        Self::root()
105    }
106}
107
108impl ParticleRecord {
109    pub fn new(details: Details, location: ParticleLocation) -> Self {
110        ParticleRecord { details, location }
111    }
112
113    pub fn root() -> Self {
114        Self {
115            details: Details {
116                stub: Stub {
117                    point: Point::root(),
118                    kind: Kind::Root,
119                    status: Status::Ready,
120                },
121                properties: Default::default(),
122            },
123            location: Default::default(),
124        }
125    }
126}
127
128impl Into<Stub> for ParticleRecord {
129    fn into(self) -> Stub {
130        self.details.stub
131    }
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
135pub struct Provision {
136    pub point: Point,
137    pub state: StateSrc,
138}
139
140impl Provision {
141    pub fn new(point: Point, state: StateSrc) -> Self {
142        Self { point, state }
143    }
144}
145
146impl TryFrom<Ping> for Provision {
147    type Error = SpaceErr;
148
149    fn try_from(request: Ping) -> Result<Self, Self::Error> {
150        if let Substance::Hyper(HyperSubstance::Provision(provision)) = request.core.body {
151            Ok(provision)
152        } else {
153            Err(SpaceErr::bad_request(
154                "expecting a Provision HyperSubstance",
155            ))
156        }
157    }
158}
159
160impl Into<Substance> for Provision {
161    fn into(self) -> Substance {
162        Substance::Hyper(HyperSubstance::Provision(self))
163    }
164}
165
166impl Into<DirectedCore> for Provision {
167    fn into(self) -> DirectedCore {
168        DirectedCore::new(HypMethod::Assign.into())
169            .with_body(Substance::Hyper(HyperSubstance::Provision(self)))
170    }
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
174pub struct Assign {
175    pub kind: AssignmentKind,
176    pub details: Details,
177    pub state: StateSrc,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
181pub struct HostCmd {
182    pub kind: AssignmentKind,
183    pub details: Details,
184    pub state: StateSrc,
185    pub config: MechtronConfig,
186}
187
188impl HostCmd {
189    pub fn kind(&self) -> &Kind {
190        &self.details.stub.kind
191    }
192
193    pub fn new(
194        kind: AssignmentKind,
195        details: Details,
196        state: StateSrc,
197        config: MechtronConfig,
198    ) -> Self {
199        Self {
200            kind,
201            details,
202            state,
203            config,
204        }
205    }
206}
207
208impl Assign {
209    pub fn kind(&self) -> &Kind {
210        &self.details.stub.kind
211    }
212
213    pub fn new(kind: AssignmentKind, details: Details, state: StateSrc) -> Self {
214        Self {
215            kind,
216            details,
217            state,
218        }
219    }
220
221    pub fn to_host_cmd(self, config: MechtronConfig) -> HostCmd {
222        HostCmd {
223            kind: self.kind,
224            details: self.details,
225            state: self.state,
226            config,
227        }
228    }
229}
230
231#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, strum_macros::Display, Autobox)]
232pub enum HyperSubstance {
233    Provision(Provision),
234    Assign(Assign),
235    Host(HostCmd),
236    Event(HyperEvent),
237    Log(Log),
238    Search(Search),
239    Discoveries(Discoveries),
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
243pub enum Search {
244    Star(StarKey),
245    StarKind(StarSub),
246    Kinds,
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
250pub struct Discovery {
251    pub star_kind: StarSub,
252    pub hops: u16,
253    pub star_key: StarKey,
254    pub kinds: HashSet<KindSelector>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
258pub struct Discoveries {
259    pub vec: Vec<Discovery>,
260}
261
262impl Discoveries {
263    pub fn new() -> Self {
264        Self { vec: vec![] }
265    }
266}
267
268impl Deref for Discoveries {
269    type Target = Vec<Discovery>;
270
271    fn deref(&self) -> &Self::Target {
272        &self.vec
273    }
274}
275
276impl DerefMut for Discoveries {
277    fn deref_mut(&mut self) -> &mut Self::Target {
278        &mut self.vec
279    }
280}
281
282impl TryFrom<Ping> for Assign {
283    type Error = SpaceErr;
284
285    fn try_from(request: Ping) -> Result<Self, Self::Error> {
286        if let Substance::Hyper(HyperSubstance::Assign(assign)) = request.core.body {
287            Ok(assign)
288        } else {
289            Err(SpaceErr::bad_request("expecting an Assign HyperSubstance"))
290        }
291    }
292}
293
294impl Into<Substance> for Assign {
295    fn into(self) -> Substance {
296        Substance::Hyper(HyperSubstance::Assign(self))
297    }
298}
299
300impl Into<DirectedCore> for Assign {
301    fn into(self) -> DirectedCore {
302        DirectedCore::new(HypMethod::Assign.into())
303            .with_body(Substance::Hyper(HyperSubstance::Assign(self)))
304    }
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, strum_macros::Display, Autobox)]
308pub enum HyperEvent {
309    Created(Created),
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
313pub struct Created {
314    pub point: Point,
315    pub kind: KindParts,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, strum_macros::Display, Hash)]
319pub enum InterchangeKind {
320    Singleton,
321    DefaultControl,
322    Control(ControlPattern),
323    Portal(ControlPattern),
324    Star(StarKey),
325}
326
327#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, strum_macros::Display, Hash)]
328pub enum ControlPattern {
329    Any,
330    Star(Point),
331}
332
333#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
334pub struct Knock {
335    pub kind: InterchangeKind,
336    pub auth: Box<Substance>,
337    pub remote: Option<Surface>,
338}
339
340impl Knock {
341    pub fn new(kind: InterchangeKind, remote: Surface, auth: Substance) -> Self {
342        Self {
343            kind,
344            remote: Some(remote),
345            auth: Box::new(auth),
346        }
347    }
348}
349
350impl Default for Knock {
351    fn default() -> Self {
352        Self {
353            kind: InterchangeKind::DefaultControl,
354            auth: Box::new(Substance::Empty),
355            remote: None,
356        }
357    }
358}
359
360impl Into<Wave<Ping>> for Knock {
361    fn into(self) -> Wave<Ping> {
362        let mut core = DirectedCore::new(HypMethod::Knock.into());
363        core.body = Substance::Knock(self);
364        let wave = Wave::new(
365            Ping::new(core, Point::local_endpoint().to_surface()),
366            Point::remote_endpoint().to_surface(),
367        );
368        wave
369    }
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
373pub struct Greet {
374    pub surface: Surface,
375    pub agent: Agent,
376    pub hop: Surface,
377    pub transport: Surface,
378}
379
380impl Greet {
381    pub fn new(agent: Agent, surface: Surface, hop: Surface, transport: Surface) -> Self {
382        Self {
383            agent,
384            surface,
385            hop,
386            transport,
387        }
388    }
389}
390
391impl Into<UltraWave> for Greet {
392    fn into(self) -> UltraWave {
393        let mut proto = ReflectedProto::new();
394        proto.kind(ReflectedKind::Pong);
395        proto.agent(Agent::HyperUser);
396        proto.from(self.transport.clone());
397        proto.to(self.surface.clone());
398        proto.intended(self.hop.clone());
399        proto.reflection_of(WaveId::new(WaveKind::Ping)); // this is just randomly created since this pong reflection will not be traditionally handled on the receiving end
400        proto.status(200u16);
401        proto.body(self.into());
402        proto.build().unwrap().to_ultra()
403    }
404}
405
406#[derive(Clone)]
407pub enum MountKind {
408    Control,
409    Portal,
410}
411
412impl MountKind {
413    pub fn kind(&self) -> Kind {
414        match self {
415            MountKind::Control => Kind::Control,
416            MountKind::Portal => Kind::Portal,
417        }
418    }
419}