1use std::io::Write;
2
3#[macro_export]
4macro_rules! elytra_wasm {
5 ( $e:expr ) => {
6
7 thread_local! {
8 static ELYTRA_WASM_OUT: std::cell::Cell<[u64; 8]> = std::cell::Cell::new([0; 8]);
9 }
10
11 #[allow(unused)]
12 #[unsafe(no_mangle)]
13 pub extern "C" fn send(a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: u64, h: u64) -> u8 {
14 let in_bytes = elytra_wasm::unpack64([a, b, c, d, e, f, g, h]);
15 let res = match elytra_conf::command::Command::from_bytes(&in_bytes) {
16 Ok(command) => $e(command),
17 Err(e) => elytra_conf::command::CommandResponse::error(e)
18 };
19 if let Ok(res_bytes) = res.as_bytes().try_into() {
20 ELYTRA_WASM_OUT.set(elytra_wasm::pack64(res_bytes));
21 return 8;
22 } else {
23 return 0;
24 }
25 }
26
27 #[allow(unused)]
28 #[unsafe(no_mangle)]
29 pub extern "C" fn recieve(index: usize) -> u64 {
30 ELYTRA_WASM_OUT.get().get(index).copied().unwrap_or_default()
31 }
32
33 };
34}
35
36
37pub fn sync_await<T, F: Future<Output = T>>(fut: F) -> T {
38 use std::task::Poll::*;
39 use std::pin::pin;
40 use std::task::{Context, Waker};
41
42 let mut pin = pin!(fut);
43 let mut ctx = Context::from_waker(Waker::noop());
44 loop {
45 match pin.as_mut().poll(&mut ctx) {
46 Ready(res) => {
47 return res;
48 },
49 Pending => {},
50 }
51 }
52}
53
54pub fn unpack64(value: [u64; 8]) -> [u8; 64] {
55 let mut buf = [0u8; 64];
56 let mut cursor = buf.as_mut_slice();
57 for v in value {
58 let _ = cursor.write(&v.to_be_bytes());
59 }
60 buf
61}
62
63pub fn pack64(value: [u8; 64]) -> [u64; 8] {
64 let mut buf = [0u64; 8];
65 for (i, bytes) in value.chunks(8).enumerate() {
66 let bytes = bytes.try_into()
67 .expect("input array should cleanly be divisible by 8");
68 buf[i] = u64::from_be_bytes(bytes);
69 }
70 buf
71}