rsocket_rust_transport_wasm/
misc.rs1use js_sys::{Promise, Uint8Array};
2use rsocket_rust::prelude::*;
3use rsocket_rust::Client;
4use wasm_bindgen::prelude::{wasm_bindgen, JsValue};
5use wasm_bindgen_futures::future_to_promise;
6
7use super::client::WebsocketClientTransport;
8
9#[derive(Serialize, Deserialize)]
10pub struct JsPayload {
11 data: Option<Vec<u8>>,
12 metadata: Option<Vec<u8>>,
13}
14
15#[wasm_bindgen]
16pub struct JsClient {
17 inner: Client,
18}
19
20impl Into<JsValue> for &JsPayload {
21 fn into(self) -> JsValue {
22 JsValue::from_serde(self).unwrap()
23 }
24}
25
26impl Into<Payload> for JsPayload {
27 fn into(self) -> Payload {
28 let mut bu = Payload::builder();
29 if let Some(v) = self.data {
30 bu = bu.set_data(v);
31 }
32 if let Some(v) = self.metadata {
33 bu = bu.set_metadata(v);
34 }
35 bu.build()
36 }
37}
38
39impl From<Payload> for JsPayload {
40 fn from(input: Payload) -> JsPayload {
41 let (d, m) = input.split();
42 JsPayload {
43 data: d.map(|v| v.to_vec()),
44 metadata: m.map(|v| v.to_vec()),
45 }
46 }
47}
48
49#[wasm_bindgen]
50pub fn new_payload(data: JsValue, metadata: JsValue) -> JsValue {
51 let jp = JsPayload {
52 data: to_vec(data),
53 metadata: to_vec(metadata),
54 };
55 (&jp).into()
56}
57
58#[wasm_bindgen]
59pub async fn connect(url: String) -> Result<JsClient, JsValue> {
60 match RSocketFactory::connect()
61 .transport(WebsocketClientTransport::from(url))
62 .start()
63 .await
64 {
65 Ok(inner) => Ok(JsClient { inner }),
66 Err(e) => Err(JsValue::from_str(&format!("{}", e))),
67 }
68}
69
70#[wasm_bindgen]
71impl JsClient {
72 pub fn request_response(&self, request: &JsValue) -> Promise {
73 let inner = self.inner.clone();
74 let request: JsPayload = request.into_serde().unwrap();
75 future_to_promise(async move {
76 match inner.request_response(request.into()).await {
77 Ok(Some(v)) => {
78 let jp = JsPayload::from(v);
79 Ok((&jp).into())
80 }
81 Ok(None) => Ok(JsValue::UNDEFINED),
82 Err(e) => Err(JsValue::from(&format!("{:?}", e))),
83 }
84 })
85 }
86
87 pub fn fire_and_forget(&self, request: &JsValue) -> Promise {
88 let inner = self.inner.clone();
89 let request: JsPayload = request.into_serde().unwrap();
90
91 future_to_promise(async move {
92 let _ = inner.fire_and_forget(request.into()).await;
93 Ok(JsValue::NULL)
94 })
95 }
96}
97
98#[inline]
99fn to_vec(input: JsValue) -> Option<Vec<u8>> {
100 if input.is_null() || input.is_undefined() {
101 None
102 } else if input.is_string() {
103 input.as_string().map(|s| s.into_bytes())
104 } else {
105 Some(Uint8Array::from(input).to_vec())
106 }
107}