rsocket_rust_transport_wasm/
misc.rs

1use 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}