1#![allow(warnings)]
2
3pub mod err;
4pub mod guest;
5pub mod membrane;
6pub mod space;
7#[cfg(test)]
8pub mod test;
9
10#[macro_use]
11extern crate lazy_static;
12
13#[macro_use]
14extern crate cosmic_macros;
15
16#[macro_use]
17extern crate cosmic_macros_primitive;
18
19extern crate alloc;
20extern crate core;
21
22use alloc::boxed::Box;
23use alloc::string::String;
24use alloc::sync::Arc;
25use core::str::FromStr;
26use cosmic_macros::handler;
27use cosmic_macros::route;
28use cosmic_macros::DirectedHandler;
29use cosmic_space::err::SpaceErr;
30use cosmic_space::hyper::HyperSubstance;
31use cosmic_space::loc::{Layer, ToSurface, Uuid};
32use cosmic_space::log::{LogSource, NoAppender, PointLogger, RootLogger};
33use cosmic_space::parse::SkewerCase;
34use cosmic_space::particle::{Details, Stub};
35use cosmic_space::wasm::Timestamp;
36use cosmic_space::wave::exchange::SetStrategy;
37use cosmic_space::wave::{Agent, DirectedWave, ReflectedAggregate, ReflectedWave, UltraWave};
38use cosmic_space::{loc, VERSION};
39use std::collections::HashMap;
40use std::marker::PhantomData;
41use std::sync::mpsc::Sender;
42use std::sync::{mpsc, MutexGuard};
43
44use cosmic_space::wave::Bounce;
45
46use cosmic_space::artifact::synch::ArtifactApi;
47use cosmic_space::artifact::ArtRef;
48use cosmic_space::wave::exchange::synch::{
49 DirectedHandler, DirectedHandlerProxy, DirectedHandlerShell, ExchangeRouter, InCtx,
50 ProtoTransmitter, ProtoTransmitterBuilder,
51};
52use std::sync::RwLock;
53use cosmic_space::point::Point;
54
55use crate::err::{GuestErr, MechErr};
56use crate::guest::GuestCtx;
57use crate::membrane::{mechtron_frame_to_host, mechtron_timestamp, mechtron_uuid};
58
59#[no_mangle]
60extern "C" {
61 pub fn mechtron_guest(details: Details) -> Result<Arc<dyn Guest>, GuestErr>;
62}
63
64pub trait Guest: Send + Sync {
65 fn handler(&self, point: &Point) -> Result<DirectedHandlerShell, GuestErr>;
66 fn logger(&self) -> &PointLogger;
67}
68
69pub trait Platform: Clone + Send + Sync
70where
71 Self::Err: MechErr,
72{
73 type Err;
74 fn factories(&self) -> Result<MechtronFactories<Self>, Self::Err>
75 where
76 Self: Sized,
77 {
78 Ok(MechtronFactories::new())
79 }
80}
81
82pub struct MechtronFactories<P>
83where
84 P: Platform,
85{
86 factories: HashMap<String, RwLock<Box<dyn MechtronFactory<P>>>>,
87 phantom: PhantomData<P>,
88}
89
90impl<P> MechtronFactories<P>
91where
92 P: Platform,
93{
94 pub fn new() -> Self {
95 Self {
96 factories: HashMap::new(),
97 phantom: Default::default(),
98 }
99 }
100 pub fn add<F>(&mut self, factory: F)
101 where
102 F: MechtronFactory<P>,
103 {
104 SkewerCase::from_str(factory.name().as_str() ).expect("Mechtron Name must be valid kebab (skewer) case (all lower case alphanumeric and dashes with leading letter)");
105 self.factories
106 .insert(factory.name(), RwLock::new(Box::new(factory)));
107 }
108
109 pub fn get<S>(&self, name: S) -> Option<&RwLock<Box<dyn MechtronFactory<P>>>>
110 where
111 S: ToString,
112 {
113 self.factories.get(&name.to_string())
114 }
115}
116
117pub trait MechtronFactory<P>: Sync + Send + 'static
118where
119 P: Platform,
120{
121 fn name(&self) -> String;
122 fn new(&mut self, skel: MechtronSkel<P>) -> Result<(), P::Err>;
123 fn lifecycle(&self, skel: MechtronSkel<P>) -> Result<Box<dyn MechtronLifecycle<P>>, P::Err>;
124 fn handler(&self, skel: MechtronSkel<P>) -> Result<Box<dyn DirectedHandler>, P::Err>;
125}
126
127#[derive(Clone)]
133pub struct MechtronSkel<P>
134where
135 P: Platform,
136{
137 pub details: Details,
138 pub logger: PointLogger,
139 pub artifacts: ArtifactApi,
140 phantom: PhantomData<P>,
141}
142
143impl<P> MechtronSkel<P>
144where
145 P: Platform,
146{
147 pub fn new(
148 details: Details,
149 logger: PointLogger,
150 phantom: PhantomData<P>,
151 artifacts: ArtifactApi,
152 ) -> Self {
153 let logger = logger.point(details.stub.point.clone());
154 Self {
155 details,
156 logger,
157 phantom,
158 artifacts,
159 }
160 }
161 pub fn bundle(&self) -> Result<Point, P::Err> {
162 let config = self
163 .details
164 .properties
165 .get("config")
166 .ok_or::<P::Err>("expecting mechtron to have config property set".into())?;
167 let config = Point::from_str(config.value.as_str())?;
168 let bundle = config.to_bundle()?.push(":/")?;
169 Ok(bundle)
170 }
171
172 pub fn raw_from_bundle<S: ToString>(&self, path: S) -> Result<ArtRef<Vec<u8>>, P::Err> {
173 let point = self.bundle()?.push(path)?;
174 Ok(self.artifacts.raw(&point)?)
175 }
176}
177
178pub trait MechtronLifecycle<P>: DirectedHandler + Sync + Send
181where
182 P: Platform,
183{
184 fn create(&self, _skel: MechtronSkel<P>) -> Result<(), P::Err> {
185 Ok(())
186 }
187}
188
189pub trait Mechtron<P>: MechtronLifecycle<P> + Sync + Send + 'static
194where
195 P: Platform,
196{
197 type Skel;
203
204 type Cache;
208
209 type State;
213
214 fn restore(skel: Self::Skel, cache: Self::Cache, state: Self::State) -> Self;
217
218 fn cache(_skel: Self::Skel) -> Result<Option<Self::Cache>, P::Err> {
221 Ok(None)
222 }
223}