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 }
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)); 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}