wasm_message_passing_3nweb/
wasm_mp1.rs

1// Copyright(c) 2021 3NSoft Inc.
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Lesser General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Lesser General Public License for more details.
12//
13// You should have received a copy of the GNU Lesser General Public License
14// along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16//! This module provide rust implementation for WASM module to talk with the
17//! outside according to version 1 of 3nweb's message passing api (should be
18//! called abi?).
19//! 
20//! Process of this message passing version is following.
21//! 
22//! - To send messages outside, WASM uses imported `_3nweb_mp1_send_out_msg`
23//! during which call embeddder must read message from identified memory area.
24//! 
25//! - To send messages inside, embedder uses exported from WASM
26//! `_3nweb_mp1_accept_msg`. During this call, WASM calls back embedder's
27//! imported `_3nweb_mp1_write_msg_into`, where embedder actually copies data
28//! into provided memory area.
29//! 
30
31mod internals {
32
33	use wasm_bindgen::prelude::*;
34
35	/// Sends given binary message to the outside. This is implementation.
36	/// 
37	pub fn send_msg_out(msg: &Vec<u8>) -> () {
38		unsafe {
39			_3nweb_mp1_send_out_msg(msg.as_ptr() as usize, msg.len());
40		}
41	}
42
43	#[allow(dead_code)]
44	static mut MSG_PROCESSOR: Option<&dyn Fn(Vec<u8>) -> ()> = None;
45
46	/// Sets a message `processor` function/closure that will be called with
47	/// binary messages from the outside. This is implementation.
48	/// 
49	/// Messages are given to `processor` as `Vec<u8>` completely separated from
50	/// workings of message exchange buffer(s).
51	/// 
52	pub fn set_msg_processor(processor: &'static dyn Fn(Vec<u8>) -> ()) -> () {
53		unsafe {
54			MSG_PROCESSOR = Some(processor);
55		}
56	}
57
58	/// This simple classic externing expects to find these functions in `env`
59	/// object/namespace imported to WASM by embedding.
60	/// 
61	extern {
62
63		/// Don't use this directly.
64		/// WASM embedding is expected to provide this function in accordance with
65		/// 3nweb's message passing api, version 1, indicated be `_3nweb_mp1_`
66		/// prefix in the name.
67		/// 
68		/// This function is called to tell embedding that a message for the
69		/// outside with length `len` can be copied from given pointer `ptr`.
70		/// 
71		/// Embedder provides this callback in `env` namespace of imports.
72		/// 
73		fn _3nweb_mp1_send_out_msg(ptr: usize, len: usize);
74
75		/// Don't use this directly.
76		/// WASM embedding is expected to provide this function in accordance with
77		/// 3nweb's message passing api, version 1, indicated be `_3nweb_mp1_`
78		/// prefix in the name.
79		/// 
80		/// This function is a callback invoked during passing message into WASM. 
81		/// Embedding calls exported `_3nweb_mp1_accept_msg`, which itself
82		/// prepairs memory for message, and calls this imported function so that
83		/// embedding writes its message into the buffer.
84		/// 
85		/// Embedder provides this callback in `env` namespace of imports.
86		/// 
87		fn _3nweb_mp1_write_msg_into(ptr: usize);
88
89	}
90
91	/// Don't use this directly.
92	/// This function is exported from WASM in accordance with 3nweb's message
93	/// passing api, version 1, indicated be `_3nweb_mp1_` prefix in the name.
94	/// 
95	/// This is called by WASM embedding with `len` size of the message.
96	/// Implementation prepares buffer for writing message bytes and calls back
97	/// imported `_3nweb_mp1_write_msg_into`. When callback returns, message is
98	/// given to processor.
99	/// 
100	#[wasm_bindgen]
101	pub fn _3nweb_mp1_accept_msg(len: usize) -> () {
102		let mut msg = Vec::with_capacity(len);
103		unsafe {
104			_3nweb_mp1_write_msg_into(msg.as_ptr() as usize);
105			msg.set_len(len);
106			if MSG_PROCESSOR.is_some() {
107				(MSG_PROCESSOR.as_ref().unwrap())(msg);
108			}
109		}
110	}
111
112}
113
114/// Sends given binary message to the outside.
115/// 
116#[inline]
117pub fn send_msg_out(msg: &Vec<u8>) -> () {
118	internals::send_msg_out(msg);
119}
120
121/// Sets a message `processor` function/closure that will be called with binary
122/// messages from the outside.
123/// 
124/// Messages are given to `processor` as `Vec<u8>` completely separated from
125/// workings of message exchange buffer(s).
126/// 
127#[inline]
128pub fn set_msg_processor(processor: &'static dyn Fn(Vec<u8>) -> ()) -> () {
129	internals::set_msg_processor(processor);
130}