use super::ClientRes;
use crate::{
error::{FromServerFnError, IntoAppError, ServerFnErrorErr},
redirect::REDIRECT_HEADER,
};
use bytes::Bytes;
use futures::{Stream, StreamExt};
pub use gloo_net::http::Response;
use js_sys::Uint8Array;
use send_wrapper::SendWrapper;
use std::future::Future;
use wasm_bindgen::JsCast;
use wasm_streams::ReadableStream;
pub struct BrowserResponse(pub(crate) SendWrapper<Response>);
impl<E: FromServerFnError> ClientRes<E> for BrowserResponse {
fn try_into_string(self) -> impl Future<Output = Result<String, E>> + Send {
SendWrapper::new(async move {
self.0.text().await.map_err(|e| {
ServerFnErrorErr::Deserialization(e.to_string())
.into_app_error()
})
})
}
fn try_into_bytes(self) -> impl Future<Output = Result<Bytes, E>> + Send {
SendWrapper::new(async move {
self.0.binary().await.map(Bytes::from).map_err(|e| {
ServerFnErrorErr::Deserialization(e.to_string())
.into_app_error()
})
})
}
fn try_into_stream(
self,
) -> Result<impl Stream<Item = Result<Bytes, E>> + Send + 'static, E> {
let stream = ReadableStream::from_raw(self.0.body().unwrap())
.into_stream()
.map(|data| match data {
Err(e) => {
web_sys::console::error_1(&e);
Err(ServerFnErrorErr::Request(format!("{e:?}"))
.into_app_error())
}
Ok(data) => {
let data = data.unchecked_into::<Uint8Array>();
let mut buf = Vec::new();
let length = data.length();
buf.resize(length as usize, 0);
data.copy_to(&mut buf);
Ok(Bytes::from(buf))
}
});
Ok(SendWrapper::new(stream))
}
fn status(&self) -> u16 {
self.0.status()
}
fn status_text(&self) -> String {
self.0.status_text()
}
fn location(&self) -> String {
self.0
.headers()
.get("Location")
.unwrap_or_else(|| self.0.url())
}
fn has_redirect(&self) -> bool {
self.0.headers().get(REDIRECT_HEADER).is_some()
}
}