1#![allow(warnings)]
2pub mod err;
3
4#[macro_use]
5extern crate lazy_static;
6
7use crate::err::{DefaultHostErr, HostErr};
8use cosmic_space::artifact::asynch::{ArtifactApi, ReadArtifactFetcher};
9use cosmic_space::artifact::ArtRef;
10use cosmic_space::config::mechtron::MechtronConfig;
11use cosmic_space::err::SpaceErr;
12use cosmic_space::loc::{Layer, ToSurface};
13use cosmic_space::particle::{Details, Property};
14use cosmic_space::substance::Bin;
15use cosmic_space::wave::DirectedWave;
16use cosmic_space::wave::{DirectedKind, UltraWave, WaveKind};
17
18use wasmer::Function;
19use wasmer_compiler_singlepass::Singlepass;
20
21use cosmic_space::hyper::{HostCmd, HyperSubstance};
22use cosmic_space::log::{LogSource, PointLogger, RootLogger, StdOutAppender};
23use cosmic_space::substance::Substance;
24use cosmic_space::wasm::Timestamp;
25use cosmic_space::wave::core::hyp::HypMethod;
26use cosmic_space::wave::{Agent, DirectedProto};
27use cosmic_space::{loc, VERSION};
28
29use cosmic_space::wave::core::cmd::CmdMethod;
30use cosmic_space::wave::core::Method;
31use cosmic_space::wave::exchange::asynch::ProtoTransmitter;
32use cosmic_space::wave::exchange::asynch::ProtoTransmitterBuilder;
33use cosmic_space::wave::exchange::SetStrategy;
34use std::collections::HashMap;
35use std::str::FromStr;
36use std::sync::{Arc, Mutex, RwLock};
37use std::{sync, thread};
38use threadpool::ThreadPool;
39use tokio::runtime::Handle;
40use tokio::sync::mpsc;
41use wasmer::{Array, imports, Instance, Module, Store, Value, WasmerEnv, WasmPtr};
42use cosmic_space::point::Point;
43
44#[derive(Clone)]
45pub struct HostsApi {
46 tx: tokio::sync::mpsc::Sender<HostsCall>,
47}
48
49impl HostsApi {
50 pub async fn get_via_wasm(&self, wasm: &Point) -> Result<WasmHostApi, SpaceErr> {
51 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
52 self.tx
53 .send(HostsCall::GetViaWasm {
54 wasm: wasm.clone(),
55 rtn,
56 })
57 .await?;
58 rtn_rx.await?
59 }
60
61 pub async fn get_via_point(&self, point: &Point) -> Result<WasmHostApi, SpaceErr> {
62 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
63 self.tx
64 .send(HostsCall::GetViaPoint {
65 point: point.clone(),
66 rtn,
67 })
68 .await?;
69 rtn_rx.await?
70 }
71
72 pub async fn create(&self, details: Details, wasm: Point) -> Result<WasmHostApi, SpaceErr> {
73 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
74 self.tx
75 .send(HostsCall::Create { details, wasm, rtn })
76 .await?;
77 rtn_rx.await?
78 }
79}
80
81pub enum HostsCall {
82 GetViaWasm {
83 wasm: Point,
84 rtn: tokio::sync::oneshot::Sender<Result<WasmHostApi, SpaceErr>>,
85 },
86 GetViaPoint {
87 point: Point,
88 rtn: tokio::sync::oneshot::Sender<Result<WasmHostApi, SpaceErr>>,
89 },
90 Create {
91 details: Details,
92 wasm: Point,
93 rtn: tokio::sync::oneshot::Sender<Result<WasmHostApi, SpaceErr>>,
94 },
95}
96
97pub struct HostsRunner {
98 store: Store,
99 artifacts: ArtifactApi,
100 wasm_to_host: HashMap<Point, WasmHostApi>,
101 point_to_host: HashMap<Point, WasmHostApi>,
102 mechtron_to_host: HashMap<Point, Point>,
103 transmitter: ProtoTransmitterBuilder,
104 logger: RootLogger,
105 rx: tokio::sync::mpsc::Receiver<HostsCall>,
106}
107
108impl HostsRunner {
109 pub fn new(
110 artifacts: ArtifactApi,
111 transmitter: ProtoTransmitterBuilder,
112 logger: RootLogger,
113 ) -> HostsApi {
114 let (tx, rx) = mpsc::channel(1024);
115 let runner = Self {
116 rx,
117 store: Store::default(),
118 artifacts,
119 wasm_to_host: Default::default(),
120 point_to_host: Default::default(),
121 mechtron_to_host: Default::default(),
122 transmitter,
123 logger,
124 };
125 tokio::spawn(async move {
126 runner.start().await;
127 });
128 HostsApi { tx }
129 }
130
131 async fn start(mut self) {
132 while let Some(call) = self.rx.recv().await {
133 match call {
134 HostsCall::Create { details, wasm, rtn } => {
135 rtn.send(
136 self.create_host(details, wasm, self.transmitter.clone())
137 .await,
138 )
139 .unwrap_or_default();
140 }
141 HostsCall::GetViaWasm { wasm, rtn } => {
142 rtn.send(self.wasm_to_host.get(&wasm).cloned().ok_or(
143 format!("could not get host via wasm: {}", wasm.to_string()).into(),
144 ));
145 }
146 HostsCall::GetViaPoint { point, rtn } => {
147 rtn.send(self.point_to_host.get(&point).cloned().ok_or(
148 format!("could not get host via point: {}", point.to_string()).into(),
149 ));
150 }
151 }
152 }
153 }
154
155 async fn create_host(
156 &mut self,
157 details: Details,
158 wasm: Point,
159 mut transmitter: ProtoTransmitterBuilder,
160 ) -> Result<WasmHostApi, SpaceErr> {
161 transmitter.via = SetStrategy::Override(details.stub.point.to_surface());
162 let transmitter = transmitter.build();
163
164 let logger = self.logger.point(details.stub.point.clone());
165 let bin = self.artifacts.wasm(&wasm).await?;
166 let host = WasmHostRunner::new(details.clone(), &mut self.store, bin, transmitter, logger)
167 .map_err(|e| e.to_space_err())?;
168 self.wasm_to_host.insert(wasm.clone(), host.clone());
169 self.point_to_host.insert(details.stub.point, host.clone());
170
171 host.init().await;
172
173 Ok(host)
174 }
175
176 pub fn get(&self, point: &Point) -> Result<WasmHostApi, SpaceErr> {
177 self.point_to_host
178 .get(point)
179 .cloned()
180 .ok_or(format!("cannot find host: {}", point.to_string()).into())
181 }
182}
183
184pub struct WasmHostSkel {
185 pool: Arc<ThreadPool>,
186}
187
188#[derive(Debug)]
189pub enum WasmHostCall {
190 Init(tokio::sync::oneshot::Sender<Result<(), DefaultHostErr>>),
191 Point(tokio::sync::oneshot::Sender<Point>),
192 HostCmd {
193 cmd: HostCmd,
194 rtn: tokio::sync::oneshot::Sender<Result<(), DefaultHostErr>>,
195 },
196 WriteString {
197 string: String,
198 rtn: tokio::sync::oneshot::Sender<Result<i32, DefaultHostErr>>,
199 },
200 WriteBuffer {
201 buffer: Vec<u8>,
202 rtn: tokio::sync::oneshot::Sender<Result<i32, DefaultHostErr>>,
203 },
204 SerializeWaveToGuest {
205 wave: UltraWave,
206 rtn: tokio::sync::oneshot::Sender<Result<i32, DefaultHostErr>>,
207 },
208 DeSerializeWaveToHost {
209 wave: i32,
210 rtn: tokio::sync::oneshot::Sender<Result<UltraWave, DefaultHostErr>>,
211 },
212 WaveToHost {
213 wave: UltraWave,
214 rtn: tokio::sync::oneshot::Sender<Result<Option<UltraWave>, DefaultHostErr>>,
215 },
216 GuestConsumeWave {
217 wave: i32,
218 rtn: tokio::sync::oneshot::Sender<Result<Option<UltraWave>, DefaultHostErr>>,
219 },
220 ConsumeString {
221 buffer_id: i32,
222 rtn: tokio::sync::oneshot::Sender<Result<String, DefaultHostErr>>,
223 },
224 ConsumeBuffer {
225 buffer_id: i32,
226 rtn: tokio::sync::oneshot::Sender<Result<Vec<u8>, DefaultHostErr>>,
227 },
228}
229
230#[derive(WasmerEnv, Clone)]
231pub struct WasmHostApi {
232 tx: mpsc::Sender<WasmHostCall>,
233}
234
235impl WasmHostApi {
236 pub fn new(tx: mpsc::Sender<WasmHostCall>) -> Self {
237 Self { tx }
238 }
239
240 pub async fn point(&self) -> Result<Point, DefaultHostErr> {
241 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
242 self.tx.send(WasmHostCall::Point(rtn)).await?;
243 Ok(rtn_rx.await?)
244 }
245
246 pub async fn init(&self) -> Result<(), DefaultHostErr> {
247 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
248 self.tx.send(WasmHostCall::Init(rtn)).await?;
249 let rtn = rtn_rx.await?;
250
251 rtn
252 }
253
254 pub async fn create_mechtron(&self, cmd: HostCmd) -> Result<(), DefaultHostErr> {
255 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
256 self.tx.send(WasmHostCall::HostCmd { cmd, rtn }).await?;
257 rtn_rx.await?
258 }
259
260 pub fn write_string<S: ToString>(&self, string: S) -> Result<i32, DefaultHostErr> {
261 tokio::task::block_in_place(move || {
262 Handle::current().block_on(async move {
263 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
264 self.tx
265 .send(WasmHostCall::WriteString {
266 string: string.to_string(),
267 rtn,
268 })
269 .await?;
270 rtn_rx.await?
271 })
272 })
273 }
274
275 pub fn consume_string(&self, buffer_id: i32) -> Result<String, DefaultHostErr> {
276 let api = self.clone();
277 tokio::task::block_in_place(move || {
278 Handle::current().block_on(async move {
279 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
280 api.tx
281 .send(WasmHostCall::ConsumeString { buffer_id, rtn })
282 .await
283 .unwrap();
284 rtn_rx.await?
285 })
286 })
287 }
288
289 pub fn write_buffer(&self, buffer: Vec<u8>) -> Result<i32, DefaultHostErr> {
290 let api = self.clone();
291 tokio::task::block_in_place(move || {
292 Handle::current().block_on(async move {
293 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
294 api.tx
295 .send(WasmHostCall::WriteBuffer { buffer, rtn })
296 .await?;
297 rtn_rx.await?
298 })
299 })
300 }
301
302 pub fn consume_buffer(&self, buffer_id: i32) -> Result<Vec<u8>, DefaultHostErr> {
303 let api = self.clone();
304 tokio::task::block_in_place(move || {
305 Handle::current().block_on(async move {
306 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
307 api.tx
308 .send(WasmHostCall::ConsumeBuffer { buffer_id, rtn })
309 .await?;
310 rtn_rx.await?
311 })
312 })
313 }
314
315 pub fn wave_to_host(&self, buffer_id: i32) -> Result<Option<UltraWave>, DefaultHostErr> {
316 let api = self.clone();
317 tokio::task::block_in_place(move || {
318 Handle::current().block_on(async move {
319 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
320 let wave = self.consume_buffer(buffer_id)?;
321 let wave: UltraWave = bincode::deserialize(wave.as_slice())?;
322
323 api.tx.send(WasmHostCall::WaveToHost { wave, rtn }).await?;
324 rtn_rx.await?
325 })
326 })
327 }
328
329 pub fn serialize_wave_to_guest(&self, wave: UltraWave) -> Result<i32, DefaultHostErr> {
330 let api = self.clone();
331 tokio::task::block_in_place(move || {
332 Handle::current().block_on(async move {
333 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
334 api.tx
335 .send(WasmHostCall::SerializeWaveToGuest { wave, rtn })
336 .await?;
337 rtn_rx.await?
338 })
339 })
340 }
341
342 pub fn guest_consume_wave(&self, wave: i32) -> Result<Option<UltraWave>, DefaultHostErr> {
343 let api = self.clone();
344 tokio::task::block_in_place(move || {
345 Handle::current().block_on(async move {
346 let (rtn, mut rtn_rx) = tokio::sync::oneshot::channel();
347 api.tx
348 .send(WasmHostCall::GuestConsumeWave { wave, rtn })
349 .await?;
350 rtn_rx.await?
351 })
352 })
353 }
354
355 pub fn transmit_to_guest(&self, wave: UltraWave) -> Result<Option<UltraWave>, DefaultHostErr> {
356 let wave_id = self.serialize_wave_to_guest(wave)?;
357 let rtn = self.guest_consume_wave(wave_id)?;
358 Ok(rtn)
359 }
360
361 pub fn host_mechtron(&self, cmd: HostCmd) {}
362}
363
364pub struct WasmHostRunner {
365 pub rx: mpsc::Receiver<WasmHostCall>,
366 pub host: WasmHost,
367}
368
369impl WasmHostRunner {
370 pub fn new(
371 details: Details,
372 store: &mut Store,
373 wasm: ArtRef<Bin>,
374 transmitter: ProtoTransmitter,
375 logger: PointLogger,
376 ) -> Result<WasmHostApi, DefaultHostErr> {
377 let module = Module::new(store, wasm.as_slice())?;
378
379 let (tx, rx) = mpsc::channel(1024);
380
381 let handle = Handle::current();
382
383 let api = WasmHostApi::new(tx);
384
385 let imports = imports! {
386
387 "env"=>{
388 "mechtron_timestamp"=>Function::new_native_with_env(module.store(),api.clone(),|env:&WasmHostApi| {
389 chrono::Utc::now().timestamp_millis()
390 }),
391
392 "mechtron_uuid"=>Function::new_native_with_env(module.store(),api.clone(),|env:&WasmHostApi | -> i32 {
393 env.write_string(uuid::Uuid::new_v4().to_string().as_str()).unwrap()
394 }),
395
396 "mechtron_host_panic"=>Function::new_native_with_env(module.store(),api.clone(),|env:&WasmHostApi,buffer_id:i32| {
397 let panic_message = env.consume_string(buffer_id).unwrap();
398 println!("WASM PANIC: {}",panic_message);
399 }),
400
401
402 "mechtron_frame_to_host"=>Function::new_native_with_env(module.store(),api.clone(),|env:&WasmHostApi,buffer_id:i32| -> i32 {
403 match env.wave_to_host(buffer_id).unwrap() {
404 Some( wave ) => {
405 let rtn = env.serialize_wave_to_guest(wave).unwrap();
406 rtn
407 }
408 None => 0
409 }
410 }),
411
412 } };
413 let instance = Some(Instance::new(&module, &imports)?);
414
415 let host = WasmHost {
416 details,
417 instance,
418 transmitter,
419 handle,
420 logger,
421 };
422
423 tokio::spawn(async move {
424 Self { host, rx }.start().await;
425 });
426
427 Ok(api)
428 }
429
430 pub async fn start(mut self) {
431 let handle = Handle::current();
432 while let Some(call) = self.rx.recv().await {
433 let host = self.host.clone();
434 handle.spawn_blocking(move || match call {
435 WasmHostCall::Init(rtn) => {
436 rtn.send(host.init());
437 }
438 WasmHostCall::Point(rtn) => {
439 rtn.send(host.details.stub.point.clone());
440 }
441 WasmHostCall::WriteString { string, rtn } => {
442 rtn.send(host.write_string(string));
443 }
444 WasmHostCall::WriteBuffer { buffer, rtn } => {
445 rtn.send(host.write_buffer(&buffer));
446 }
447 WasmHostCall::ConsumeString { buffer_id, rtn } => {
448 rtn.send(host.consume_string(buffer_id));
449 }
450 WasmHostCall::ConsumeBuffer { buffer_id, rtn } => {
451 rtn.send(host.consume_buffer(buffer_id));
452 }
453 WasmHostCall::DeSerializeWaveToHost { wave, rtn } => {
454 rtn.send(host.deserialize_wave_to_host(wave));
455 }
456 WasmHostCall::SerializeWaveToGuest { wave, rtn } => {
457 rtn.send(host.serialize_wave_to_guest(wave));
458 }
459 WasmHostCall::WaveToHost { wave, rtn } => {
460 rtn.send(host.wave_to_host(wave));
461 }
462 WasmHostCall::HostCmd { cmd, rtn } => {
463 rtn.send(host.create_mechtron(cmd));
464 }
465 WasmHostCall::GuestConsumeWave { wave, rtn } => {
466 let frame = host.mechtron_frame_to_guest(wave).unwrap();
467 if frame > 0 {
468 rtn.send(Ok(Some(host.deserialize_wave_to_host(frame).unwrap())));
469 } else {
470 rtn.send(Ok(None));
471 }
472 }
473 });
474 }
475 }
476}
477
478#[derive(Clone)]
479pub struct WasmHost {
480 details: Details,
481 instance: Option<Instance>,
482 pub transmitter: ProtoTransmitter,
483 handle: Handle,
484 logger: PointLogger,
485}
486
487impl WasmHost {
488 pub fn init(&self) -> Result<(), DefaultHostErr> {
489 let mut pass = true;
490 match self.instance.as_ref().unwrap().exports.get_memory("memory") {
491 Ok(_) => {
492 self.logger.info("verified: memory");
493 }
494 Err(_) => {
495 self.logger.info( "failed: memory. could not access wasm memory. (expecting the memory module named 'memory')");
496 pass = false
497 }
498 }
499
500 match self
501 .instance
502 .as_ref()
503 .unwrap()
504 .exports
505 .get_native_function::<i32, i32>("mechtron_guest_alloc_buffer")
506 {
507 Ok(_) => {
508 self.logger
509 .info("verified: mechtron_guest_alloc_buffer( i32 ) -> i32");
510 }
511 Err(_) => {
512 self.logger
513 .info("failed: mechtron_guest_alloc_buffer( i32 ) -> i32");
514 pass = false
515 }
516 }
517
518 match self
519 .instance
520 .as_ref()
521 .unwrap()
522 .exports
523 .get_native_function::<i32, WasmPtr<u8, Array>>("mechtron_guest_get_buffer_ptr")
524 {
525 Ok(_) => {
526 self.logger
527 .info("verified: mechtron_guest_get_buffer_ptr( i32 ) -> *const u8");
528 }
529 Err(_) => {
530 self.logger
531 .info("failed: mechtron_guest_get_buffer_ptr( i32 ) -> *const u8");
532 pass = false
533 }
534 }
535
536 match self
537 .instance
538 .as_ref()
539 .unwrap()
540 .exports
541 .get_native_function::<i32, i32>("mechtron_guest_get_buffer_len")
542 {
543 Ok(_) => {
544 self.logger
545 .info("verified: mechtron_guest_get_buffer_len( i32 ) -> i32");
546 }
547 Err(_) => {
548 self.logger
549 .info("failed: mechtron_guest_get_buffer_len( i32 ) -> i32");
550 pass = false
551 }
552 }
553 match self
554 .instance
555 .as_ref()
556 .unwrap()
557 .exports
558 .get_native_function::<i32, ()>("mechtron_guest_dealloc_buffer")
559 {
560 Ok(_) => {
561 self.logger
562 .info("verified: mechtron_guest_dealloc_buffer( i32 )");
563 }
564 Err(_) => {
565 self.logger
566 .info("failed: mechtron_guest_dealloc_buffer( i32 )");
567 pass = false
568 }
569 }
570
571 match self
572 .instance
573 .as_ref()
574 .unwrap()
575 .exports
576 .get_native_function::<(i32, i32), i32>("mechtron_guest_init")
577 {
578 Ok(func) => {
579 self.logger.info("verified: mechtron_guest_init()");
580 }
581 Err(_) => {
582 self.logger
583 .info("failed: mechtron_guest_init() [NOT REQUIRED]");
584 }
585 }
586
587 {
588 let test = "Test write string";
589 match self.write_string(test) {
590 Ok(_) => {
591 self.logger.info("passed: write_string()");
592 }
593 Err(e) => {
594 self.logger
595 .error(format!("failed: write_string() mem {:?}", e).as_str());
596 pass = false;
597 }
598 };
599 }
600
601 match pass {
602 true => {
603 let version = self.write_string(VERSION.to_string())?;
604 let details: Vec<u8> = bincode::serialize(&self.details)?;
605 let details = self.write_buffer(&details)?;
606 let ok = self
607 .instance
608 .as_ref()
609 .unwrap()
610 .exports
611 .get_native_function::<(i32, i32), i32>("mechtron_guest_init")
612 .unwrap()
613 .call(version, details)?;
614 if ok == 0 {
615 Ok(())
616 } else {
617 Err(format!("Mechtron init error {} ", ok).into())
618 }
619 }
620 false => Err("init failed".into()),
621 }
622 }
623
624 pub fn wave_to_host(&self, wave: UltraWave) -> Result<Option<UltraWave>, DefaultHostErr> {
625 let transmitter = self.transmitter.clone();
626 let (tx, mut rx): (
627 oneshot::Sender<Result<Option<UltraWave>, DefaultHostErr>>,
628 oneshot::Receiver<Result<Option<UltraWave>, DefaultHostErr>>,
629 ) = oneshot::channel();
630 let logger = self.logger.clone();
631 self.handle.spawn(async move {
632 if wave.is_directed() {
633 let wave = wave.to_directed().unwrap();
634
635 if let Method::Cmd(CmdMethod::Log) = wave.core().method {
636 if let Substance::Log(log) = wave.core().body.clone() {
637 if wave.to().is_single() {
638 let to = wave.to().clone().to_single().unwrap();
639 if to.point == Point::global_logger() {
640 logger.handle(log);
641 tx.send(Ok(None));
642 return;
643 }
644 }
645 }
646 }
647
648 match wave.directed_kind() {
649 DirectedKind::Ping => {
650 let wave: DirectedProto = wave.into();
651 let pong = transmitter.ping(wave).await.unwrap();
652 tx.send(Ok(Some(pong.to_ultra()))).unwrap_or_default();
653 }
654 DirectedKind::Ripple => {
655 unimplemented!()
656 }
657 DirectedKind::Signal => {
658 let wave: DirectedProto = wave.into();
659 transmitter.signal(wave).await.unwrap_or_default();
660 tx.send(Ok(None));
661 }
662 }
663 } else {
664 transmitter.route(wave).await;
665 tx.send(Ok(None));
666 }
667 });
668
669 rx.recv()?
670 }
671
672 pub fn deserialize_wave_to_host(&self, wave: i32) -> Result<UltraWave, DefaultHostErr> {
673 let buffer = self.read_buffer(wave).unwrap();
674 let wave: UltraWave = bincode::deserialize(buffer.as_slice())?;
675 Ok(wave)
676 }
677
678 pub fn serialize_wave_to_guest(&self, wave: UltraWave) -> Result<i32, DefaultHostErr> {
679 let wave: Vec<u8> = bincode::serialize(&wave)?;
680 Ok(self.write_buffer(&wave)?)
681 }
682
683 pub fn route(&self, wave: UltraWave) -> Result<i32, DefaultHostErr> {
684 let wave = self.serialize_wave_to_guest(wave)?;
685
686 let reflect = self
687 .instance
688 .as_ref()
689 .unwrap()
690 .exports
691 .get_native_function::<i32, i32>("mechtron_frame_to_guest")
692 .unwrap()
693 .call(wave)?;
694
695 Ok(reflect)
696 }
697
698 pub fn write_string<S: ToString>(&self, string: S) -> Result<i32, DefaultHostErr> {
699 let string = string.to_string();
700 let string = string.as_bytes();
701 let memory = self
702 .instance
703 .as_ref()
704 .unwrap()
705 .exports
706 .get_memory("memory")?;
707 let buffer_id = self.alloc_buffer(string.len() as _)?;
708 let buffer_ptr = self.get_buffer_ptr(buffer_id)?;
709 let values = buffer_ptr.deref(memory, 0, string.len() as u32).unwrap();
710 for i in 0..string.len() {
711 values[i].set(string[i]);
712 }
713
714 Ok(buffer_id)
715 }
716
717 pub fn write_buffer(&self, bytes: &Vec<u8>) -> Result<i32, DefaultHostErr> {
718 let memory = self
719 .instance
720 .as_ref()
721 .unwrap()
722 .exports
723 .get_memory("memory")?;
724 let buffer_id = self.alloc_buffer(bytes.len() as _)?;
725 let buffer_ptr = self.get_buffer_ptr(buffer_id)?;
726 let values = buffer_ptr.deref(memory, 0, bytes.len() as u32).unwrap();
727 for i in 0..bytes.len() {
728 values[i].set(bytes[i]);
729 }
730
731 Ok(buffer_id)
732 }
733
734 fn alloc_buffer(&self, len: i32) -> Result<i32, DefaultHostErr> {
735 let buffer_id = self
736 .instance
737 .as_ref()
738 .unwrap()
739 .exports
740 .get_native_function::<i32, i32>("mechtron_guest_alloc_buffer")
741 .unwrap()
742 .call(len.clone())?;
743 Ok(buffer_id)
744 }
745
746 fn get_buffer_ptr(&self, buffer_id: i32) -> Result<WasmPtr<u8, Array>, DefaultHostErr> {
747 Ok(self
748 .instance
749 .as_ref()
750 .unwrap()
751 .exports
752 .get_native_function::<i32, WasmPtr<u8, Array>>("mechtron_guest_get_buffer_ptr")
753 .unwrap()
754 .call(buffer_id)?)
755 }
756
757 pub fn read_buffer(&self, buffer_id: i32) -> Result<Vec<u8>, DefaultHostErr> {
758 let instance = self.instance.as_ref().unwrap();
759 let ptr = instance
760 .exports
761 .get_native_function::<i32, WasmPtr<u8, Array>>("mechtron_guest_get_buffer_ptr")
762 .unwrap()
763 .call(buffer_id)?;
764 let len = instance
765 .exports
766 .get_native_function::<i32, i32>("mechtron_guest_get_buffer_len")
767 .unwrap()
768 .call(buffer_id)?;
769 let memory = instance.exports.get_memory("memory")?;
770 let values = ptr.deref(memory, 0, len as u32).unwrap();
771 let mut rtn = vec![];
772 for i in 0..values.len() {
773 rtn.push(values[i].get())
774 }
775
776 Ok(rtn)
777 }
778
779 pub fn read_string(&self, buffer_id: i32) -> Result<String, DefaultHostErr> {
780 let raw = self.read_buffer(buffer_id)?;
781 let rtn = String::from_utf8(raw)?;
782
783 Ok(rtn)
784 }
785
786 pub fn consume_string(&self, buffer_id: i32) -> Result<String, DefaultHostErr> {
787 let raw = self.read_buffer(buffer_id)?;
788 let rtn = String::from_utf8(raw)?;
789 self.mechtron_guest_dealloc_buffer(buffer_id)?;
790 Ok(rtn)
791 }
792
793 pub fn consume_buffer(&self, buffer_id: i32) -> Result<Vec<u8>, DefaultHostErr> {
794 let raw = self.read_buffer(buffer_id)?;
795 self.mechtron_guest_dealloc_buffer(buffer_id)?;
796 Ok(raw)
797 }
798
799 fn mechtron_guest_dealloc_buffer(&self, buffer_id: i32) -> Result<(), DefaultHostErr> {
800 self.instance
801 .as_ref()
802 .unwrap()
803 .exports
804 .get_native_function::<i32, ()>("mechtron_guest_dealloc_buffer")?
805 .call(buffer_id.clone())?;
806 Ok(())
807 }
808
809 fn mechtron_frame_to_guest(&self, buffer_id: i32) -> Result<i32, DefaultHostErr> {
810 let rtn = self
811 .instance
812 .as_ref()
813 .unwrap()
814 .exports
815 .get_native_function::<i32, i32>("mechtron_frame_to_guest")?
816 .call(buffer_id.clone())?;
817 Ok(rtn)
818 }
819
820 fn create_mechtron(&self, host_cmd: HostCmd) -> Result<(), DefaultHostErr> {
821 let mut wave = DirectedProto::ping();
822 wave.to(self.details.stub.point.to_surface().with_layer(Layer::Core));
823 wave.from(self.details.stub.point.to_surface().with_layer(Layer::Host));
824 wave.method(HypMethod::Host);
825 wave.body(Substance::Hyper(HyperSubstance::Host(host_cmd)));
826 let wave = self.logger.result(wave.build())?;
827 let wave = wave.to_ultra();
828 self.logger.result(self.route(wave))?;
829 Ok(())
830 }
831}
832
833#[cfg(test)]
834pub mod test {
835 use crate::HostsRunner;
836 use cosmic_space::artifact::asynch::MapFetcher;
837 use cosmic_space::point::Point;
838 use cosmic_space::particle::Details;
839 use std::fs;
840 use std::str::FromStr;
841 use std::sync::Arc;
842
843 #[tokio::test]
844 pub async fn test() {}
845}