diff --git a/.gitignore b/.gitignore index 96ef6c0b944e24fc22f51f18136cd62ffd5b0b8f..eb1d4ef928eca24390365db7861a19a97b3e37f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +.vscode \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 860fd47c6e5b1c4bcef2a22847e7ae13a024193a..7c2dd580509449adf89929ac7377ea7eab1528d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,3 +26,10 @@ features = [ [dev-dependencies] console_log = "0.2.0" console_error_panic_hook = "0.1.6" +wasm-bindgen-futures = "0.4.19" + +[dev-dependencies.web-sys] +version = "0.3.22" +features = [ + "Window", +] \ No newline at end of file diff --git a/examples/blocking.rs b/examples/blocking.rs new file mode 100644 index 0000000000000000000000000000000000000000..4a5d01a6d9ee8ae5446563752317fca73f475435 --- /dev/null +++ b/examples/blocking.rs @@ -0,0 +1,31 @@ +use console_error_panic_hook; +use log::{debug, error, info, trace, warn, Level}; +use std::cell::RefCell; +use std::panic; +use std::rc::Rc; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures; +use wasm_sockets::{self, ConnectionStatus}; + +fn main() -> Result<(), JsValue> { + panic::set_hook(Box::new(console_error_panic_hook::hook)); + console_log::init_with_level(Level::Trace).expect("Failed to enable logging"); + info!("Creating connection"); + + // Client is wrapped in an Rc<RefCell<>> so it can be used within setInterval + let client = Rc::new(RefCell::new(wasm_sockets::BlockingClient::new( + "wss://echo.websocket.org", + )?)); + + let f = Closure::wrap(Box::new(move || { + info!("{:#?}", client.borrow_mut().receive()); + }) as Box<dyn FnMut()>); + setInterval(&f, 100); // Create non-blocking loop + f.forget(); + + Ok(()) +} +#[wasm_bindgen] +extern "C" { + fn setInterval(closure: &Closure<dyn FnMut()>, time: u32) -> i32; +} diff --git a/examples/basic.rs b/examples/event.rs similarity index 100% rename from examples/basic.rs rename to examples/event.rs diff --git a/examples/index.html b/examples/index.html index 80ca979938ec19ff1fa06cd9274d9c3bfbc21648..263feb85dbdd652090f7c7ecadba82c8138a2f0f 100644 --- a/examples/index.html +++ b/examples/index.html @@ -22,7 +22,7 @@ </style> </head> <script type="module"> - import init from '../target/basic.js'; + import init from '../target/blocking.js'; init(); </script> </html> diff --git a/src/lib.rs b/src/lib.rs index 2168f58e716dcfe445b51266cacca7b3c158b80f..bba0d953580f4f97181903986006bd6e745eb2d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,26 +78,26 @@ pub fn start_websocket() -> Result<(), JsValue> { Ok(()) } -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq)] pub enum ConnectionStatus { Connecting, Connected, Error(ErrorEvent), } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Message { Text(String), Binary(Vec<u8>), } pub struct BlockingClient { pub url: String, - pub connection: Rc<RefCell<web_sys::WebSocket>>, + pub event_client: EventClient, pub status: Rc<RefCell<ConnectionStatus>>, - pub data: Rc<RefCell<Vec<String>>>, + pub data: Rc<RefCell<Vec<Message>>>, } // TODO: Replace unwraps and JsValue with custom error type impl BlockingClient { - pub fn connect_with_url(url: &str) -> Result<Self, JsValue> { + pub fn new(url: &str) -> Result<Self, JsValue> { // Create connection let mut client = EventClient::new(url)?; let data = Rc::new(RefCell::new(vec![])); @@ -115,13 +115,33 @@ impl BlockingClient { *status_ref.borrow_mut() = ConnectionStatus::Error(e); }))); + client.set_on_message(Some(Box::new(move |c: &EventClient, m: Message| { + data_ref.borrow_mut().push(m); + }))); + Ok(Self { url: url.to_string(), - connection: client.connection, + event_client: client, status, data, }) } + pub fn receive(&mut self) -> Vec<Message> { + let data = (*self.data.borrow()).clone(); + (*self.data.borrow_mut()).clear(); + data + } + pub fn status(&self) -> ConnectionStatus { + self.status.borrow().clone() + } + + pub fn send_string(&self, message: &str) -> Result<(), JsValue> { + self.event_client.send_string(message) + } + + pub fn send_binary(&self, message: Vec<u8>) -> Result<(), JsValue> { + self.event_client.send_binary(message) + } } pub struct EventClient { pub url: Rc<RefCell<String>>, @@ -257,12 +277,12 @@ impl EventClient { } pub fn send_string(&self, message: &str) -> Result<(), JsValue> { - self.connection.borrow_mut().send_with_str(message) + self.connection.borrow().send_with_str(message) } pub fn send_binary(&self, message: Vec<u8>) -> Result<(), JsValue> { self.connection - .borrow_mut() + .borrow() .send_with_u8_array(message.as_slice()) } }