diff --git a/Cargo.toml b/Cargo.toml index 4ddaec0..dce4d9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,9 +11,10 @@ version = "0.7.1" [dependencies] bevy = {version = "0.12", default-features = false, features = ["bevy_asset"]} +pin-project = "1.1.3" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -isahc = "1" +surf = {version = "2.3", default-features = false, features = ["h1-client-rustls"]} [target.'cfg(target_arch = "wasm32")'.dependencies] web-sys = {version = "0.3.22", default-features = false} diff --git a/src/web_asset_source.rs b/src/web_asset_source.rs index ed7edf2..19c56b4 100644 --- a/src/web_asset_source.rs +++ b/src/web_asset_source.rs @@ -88,32 +88,55 @@ async fn get<'a>(path: PathBuf) -> Result>, AssetReaderError> { use std::pin::Pin; use std::task::{Context, Poll}; - use isahc::http::StatusCode; - use isahc::{get_async, AsyncBody, Error, Response, ResponseFuture}; + use bevy::asset::io::VecReader; + use surf::StatusCode; - struct ContinuousPoll<'a>(ResponseFuture<'a>); + #[pin_project::pin_project] + struct ContinuousPoll(#[pin] T); - impl<'a> Future for ContinuousPoll<'a> { - type Output = Result, Error>; + impl Future for ContinuousPoll { + type Output = T::Output; - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { // Always wake - blocks on single threaded executor. cx.waker().wake_by_ref(); - Pin::new(&mut self.0).poll(cx) + self.project().0.poll(cx) } } - let response = ContinuousPoll(get_async(path.to_str().unwrap())) - .await - .unwrap(); + let str_path = path.to_str().ok_or_else(|| { + AssetReaderError::Io(io::Error::new( + io::ErrorKind::Other, + format!("non-utf8 path: {}", path.display()), + )) + })?; + let mut response = ContinuousPoll(surf::get(str_path)).await.map_err(|err| { + AssetReaderError::Io(io::Error::new( + io::ErrorKind::Other, + format!( + "unexpected status code {} while loading {}: {}", + err.status(), + path.display(), + err.into_inner(), + ), + )) + })?; match response.status() { - StatusCode::OK => Ok(Box::new(response.into_body()) as _), - StatusCode::NOT_FOUND => Err(AssetReaderError::NotFound(path)), + StatusCode::Ok => Ok(Box::new(VecReader::new( + ContinuousPoll(response.body_bytes()) + .await + .map_err(|_| AssetReaderError::NotFound(path.to_path_buf()))?, + )) as _), + StatusCode::NotFound => Err(AssetReaderError::NotFound(path)), code => Err(AssetReaderError::Io(io::Error::new( io::ErrorKind::Other, - format!("unexpected status code {code}"), + format!( + "unexpected status code {} while loading {}", + code, + path.display() + ), ))), } }