wasi_worker/lib.rs
1//! This crate provides rust library to easily compose WASM/WASI browser service worker.
2//!
3//! # General overview
4//!
5//! ServiceWorker is a singleton which holds input and output file handles and
6//! owns worker via Handler trait. Worker is supposedly reactive, usually operating
7//! on incoming events (on_message) and posting messages to main browser application
8//! via ServiceWorker::post_message().
9//!
10//! # Example usage:
11//! ```
12//! use wasi_worker::*;
13//!
14//! struct MyWorker {}
15//! impl Handler for MyWorker {
16//! fn on_message(&self, msg: &[u8]) -> std::io::Result<()> {
17//! // Process incoming message
18//! println!("My Worker got message: {:?}", msg);
19//! Ok(())
20//! }
21//! }
22//!
23//! fn main() {
24//! // In WASI setup with JS glue all output will be posted to memfs::/output.bin
25//! // In native OS to be able to run test from shell output goes to ./output.bin
26//! let opt = ServiceOptions::default().with_cleanup();
27//! let output_file = match &opt.output { FileOptions::File(path) => path.clone() };
28//! ServiceWorker::initialize(opt)
29//! .expect("ServiceWorker::initialize");
30//!
31//! // Attach Agent to ServiceWorker as message handler singleton
32//! ServiceWorker::set_message_handler(Box::new(MyWorker {}));
33//!
34//! // Send binary message to main browser application
35//! ServiceWorker::post_message(b"message")
36//! .expect("ServiceWorker.post_message");
37//! }
38//! ```
39mod service;
40
41pub use service::{Handler, ServiceWorker};
42
43/// Instructs on file descriptor configuration for ServiceWorker
44pub enum FileOptions {
45 File(String),
46}
47
48/// Options for ServiceWorker
49pub struct ServiceOptions {
50 // TODO: input: FileOptions,
51 pub cleanup: bool,
52 pub output: FileOptions,
53}
54
55impl ServiceOptions {
56 pub fn with_cleanup(mut self) -> Self {
57 self.cleanup = true;
58 self
59 }
60}
61
62impl Default for ServiceOptions {
63 fn default() -> Self {
64 Self {
65 output: if cfg!(target_os = "wasi") {
66 FileOptions::File("/output.bin".to_string())
67 } else {
68 FileOptions::File("./output.bin".to_string())
69 },
70 cleanup: false,
71 }
72 }
73}
74
75// This function will be called from worker.js on new message
76// To operate it requires JS glue - see wasi-worker-cli
77// Note: It will be substituted by poll_oneoff,
78// though currently poll_oneoff does not transfer control
79#[no_mangle]
80pub extern "C" fn message_ready() -> usize {
81 ServiceWorker::on_message().expect("ServiceWorker.on_message")
82}
83
84
85#[cfg(test)]
86mod tests {
87 use super::{FileOptions, ServiceOptions, ServiceWorker};
88
89 #[test]
90 fn cleanup() {
91 {
92 let opt = ServiceOptions {
93 output: FileOptions::File("./testdata/output.bin".to_string()),
94 cleanup: true,
95 };
96 ServiceWorker::initialize(opt).expect("ServiceWorker::initialize");
97 std::fs::File::open("./testdata/output.bin")
98 .expect("/testdata/output.bin should been created");
99 ServiceWorker::kill();
100 }
101 std::fs::File::open("./testdata/output.bin")
102 .expect_err("/testdata/output.bin should been cleaned up");
103 }
104}