Skip to main content

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}