rsocket_rust_transport_wasm 0.7.2

WASM Websocket RSocket transport implementation.
Documentation
use js_sys::{Promise, Uint8Array};
use rsocket_rust::prelude::*;
use rsocket_rust::Client;
use wasm_bindgen::prelude::{wasm_bindgen, JsValue};
use wasm_bindgen_futures::future_to_promise;

use super::client::WebsocketClientTransport;

#[derive(Serialize, Deserialize)]
pub struct JsPayload {
    data: Option<Vec<u8>>,
    metadata: Option<Vec<u8>>,
}

#[wasm_bindgen]
pub struct JsClient {
    inner: Client,
}

impl Into<JsValue> for &JsPayload {
    fn into(self) -> JsValue {
        JsValue::from_serde(self).unwrap()
    }
}

impl Into<Payload> for JsPayload {
    fn into(self) -> Payload {
        let mut bu = Payload::builder();
        if let Some(v) = self.data {
            bu = bu.set_data(v);
        }
        if let Some(v) = self.metadata {
            bu = bu.set_metadata(v);
        }
        bu.build()
    }
}

impl From<Payload> for JsPayload {
    fn from(input: Payload) -> JsPayload {
        let (d, m) = input.split();
        JsPayload {
            data: d.map(|v| v.to_vec()),
            metadata: m.map(|v| v.to_vec()),
        }
    }
}

#[wasm_bindgen]
pub fn new_payload(data: JsValue, metadata: JsValue) -> JsValue {
    let jp = JsPayload {
        data: to_vec(data),
        metadata: to_vec(metadata),
    };
    (&jp).into()
}

#[wasm_bindgen]
pub async fn connect(url: String) -> Result<JsClient, JsValue> {
    match RSocketFactory::connect()
        .transport(WebsocketClientTransport::from(url))
        .start()
        .await
    {
        Ok(inner) => Ok(JsClient { inner }),
        Err(e) => Err(JsValue::from_str(&format!("{}", e))),
    }
}

#[wasm_bindgen]
impl JsClient {
    pub fn request_response(&self, request: &JsValue) -> Promise {
        let inner = self.inner.clone();
        let request: JsPayload = request.into_serde().unwrap();
        future_to_promise(async move {
            match inner.request_response(request.into()).await {
                Ok(Some(v)) => {
                    let jp = JsPayload::from(v);
                    Ok((&jp).into())
                }
                Ok(None) => Ok(JsValue::UNDEFINED),
                Err(e) => Err(JsValue::from(&format!("{:?}", e))),
            }
        })
    }

    pub fn fire_and_forget(&self, request: &JsValue) -> Promise {
        let inner = self.inner.clone();
        let request: JsPayload = request.into_serde().unwrap();

        future_to_promise(async move {
            let _ = inner.fire_and_forget(request.into()).await;
            Ok(JsValue::NULL)
        })
    }
}

#[inline]
fn to_vec(input: JsValue) -> Option<Vec<u8>> {
    if input.is_null() || input.is_undefined() {
        None
    } else if input.is_string() {
        input.as_string().map(|s| s.into_bytes())
    } else {
        Some(Uint8Array::from(input).to_vec())
    }
}