use super::{Result, WebSocketError};
use serde::de::DeserializeOwned;
use wasm_bindgen::{JsCast, JsValue};
use wasm_bindgen_futures::JsFuture;
use web_sys::MessageEvent;
#[allow(clippy::module_name_repetitions)]
#[derive(Debug)]
pub struct WebSocketMessage {
pub(crate) data: JsValue,
pub(crate) message_event: MessageEvent,
}
impl WebSocketMessage {
pub fn text(&self) -> Result<String> {
self.data
.as_string()
.ok_or_else(|| WebSocketError::TextError("data is not a valid utf-8 string"))
}
pub fn json<T: DeserializeOwned + 'static>(&self) -> Result<T> {
let text = self.text()?;
serde_json::from_str(&text).map_err(WebSocketError::SerdeError)
}
pub async fn bytes(&self) -> Result<Vec<u8>> {
if let Some(array_buffer) = self.data.dyn_ref::<js_sys::ArrayBuffer>() {
let bytes = js_sys::Uint8Array::new(array_buffer).to_vec();
return Ok(bytes);
}
if let Some(blob) = self.data.dyn_ref::<web_sys::Blob>() {
let bytes = JsFuture::from(blob.array_buffer())
.await
.map_err(WebSocketError::PromiseError)
.map(|array_buffer| js_sys::Uint8Array::new(&array_buffer))?
.to_vec();
return Ok(bytes);
}
Ok(self.text()?.into_bytes())
}
pub fn blob(self) -> Result<gloo_file::Blob> {
if self.contains_array_buffer() {
let array_buffer = self.data.unchecked_into::<js_sys::ArrayBuffer>();
return Ok(gloo_file::Blob::new(array_buffer));
}
if self.contains_blob() {
let blob = self.data.unchecked_into::<web_sys::Blob>();
return Ok(gloo_file::Blob::from(blob));
}
Ok(gloo_file::Blob::new(self.text()?.as_str()))
}
pub fn contains_array_buffer(&self) -> bool {
self.data.has_type::<js_sys::ArrayBuffer>()
}
pub fn contains_blob(&self) -> bool {
self.data.has_type::<web_sys::Blob>()
}
pub fn contains_text(&self) -> bool {
self.data.has_type::<js_sys::JsString>()
}
pub const fn raw_data(&self) -> &JsValue {
&self.data
}
pub const fn raw_message(&self) -> &web_sys::MessageEvent {
&self.message_event
}
}