From e322ce190c89fdc3754dd80a5dd9d88fb9a6d2c7 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 29 Nov 2023 11:23:20 +0100 Subject: [PATCH 1/2] Use pin_project and make ContinuousPoll generic --- Cargo.toml | 1 + src/web_asset_source.rs | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4ddaec0..140512e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ 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" diff --git a/src/web_asset_source.rs b/src/web_asset_source.rs index ed7edf2..356453d 100644 --- a/src/web_asset_source.rs +++ b/src/web_asset_source.rs @@ -88,19 +88,20 @@ async fn get<'a>(path: PathBuf) -> Result>, AssetReaderError> { use std::pin::Pin; use std::task::{Context, Poll}; + use isahc::get_async; use isahc::http::StatusCode; - use isahc::{get_async, AsyncBody, Error, Response, ResponseFuture}; - 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) } } From dfe8f5b6e7bf1dbbde2c1a8a577f5a381c6a6e77 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 29 Nov 2023 11:24:33 +0100 Subject: [PATCH 2/2] Switch back to surf, which also works on android --- Cargo.toml | 2 +- src/web_asset_source.rs | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 140512e..dce4d9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ 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 356453d..19c56b4 100644 --- a/src/web_asset_source.rs +++ b/src/web_asset_source.rs @@ -88,8 +88,8 @@ async fn get<'a>(path: PathBuf) -> Result>, AssetReaderError> { use std::pin::Pin; use std::task::{Context, Poll}; - use isahc::get_async; - use isahc::http::StatusCode; + use bevy::asset::io::VecReader; + use surf::StatusCode; #[pin_project::pin_project] struct ContinuousPoll(#[pin] T); @@ -105,16 +105,38 @@ async fn get<'a>(path: PathBuf) -> Result>, AssetReaderError> { } } - 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() + ), ))), } }