1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
use std::{collections::VecDeque, sync::{Arc, Mutex}};
use wasm_bindgen::prelude::*;
#[derive(Debug)]
pub enum Message {
Binary(Vec<u8>),
Text(String),
}
impl Message {
pub fn from_messageevent(e: web_sys::MessageEvent) -> Self {
if let Ok(abuf) = e.data().dyn_into::<js_sys::ArrayBuffer>() {
let array = js_sys::Uint8Array::new(&abuf).to_vec();
Message::Binary(array)
} else if let Ok(txt) = e.data().dyn_into::<js_sys::JsString>() {
Message::Text(txt.into())
} else {
panic!("received weird websocked message: {:?}", e);
}
}
}
pub struct Client {
pub ws: Option<web_sys::WebSocket>,
pub messages: Arc<Mutex<VecDeque<Message>>>,
}
impl Client {
pub fn new() -> Self {
Self {
ws: None,
messages: Arc::new(Mutex::new(VecDeque::new())),
}
}
pub fn connect(&mut self, url: &str) {
let ws = web_sys::WebSocket::new(url).expect("failed to open websocket");
let messages_ref = self.messages.clone();
let cb: Closure<dyn Fn(web_sys::MessageEvent)> = Closure::new(move |e: web_sys::MessageEvent| {
let msg = Message::from_messageevent(e);
log::info!("incoming: {:?}", msg);
messages_ref.lock().unwrap().push_back(msg);
});
ws.set_onmessage(Some(cb.as_ref().unchecked_ref()));
cb.forget();
self.ws = Some(ws);
}
pub fn poll(&mut self) -> Option<Message> {
self.messages.lock().unwrap().pop_front()
}
pub fn send(&self, msg: Message) {
if let Some(ws) = &self.ws {
match msg {
Message::Text(txt) => {
if let Err(e) = ws.send_with_str(&txt) {
log::warn!("failed to send string: {:?}", e);
}
},
Message::Binary(bytes) => {
if let Err(e) = ws.send_with_u8_array(&bytes) {
log::warn!("failed to send bytes: {:?}", e);
}
},
}
}
}
}
|