Skip to content

Commit

Permalink
Process Asset File Extensions With Multiple Dots
Browse files Browse the repository at this point in the history
Fixes #1276
  • Loading branch information
zicklag committed Jan 21, 2021
1 parent a880b54 commit 9942f0e
Showing 1 changed file with 124 additions and 6 deletions.
130 changes: 124 additions & 6 deletions crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use thiserror::Error;
pub enum AssetServerError {
#[error("asset folder path is not a directory")]
AssetFolderNotADirectory(String),
#[error("no AssetLoader found for the given extension")]
#[error("no AssetLoader found{}", format_missing_asset_ext(.0))]
MissingAssetLoader(Option<String>),
#[error("the given type does not match the type of the loaded asset")]
IncorrectHandleType,
Expand All @@ -28,6 +28,13 @@ pub enum AssetServerError {
PathLoaderError(#[from] AssetIoError),
}

fn format_missing_asset_ext(ext: &Option<String>) -> String {
return ext
.as_ref()
.map(|x| format!(" for the following extension(s): {}", x))
.unwrap_or_default();
}

#[derive(Default)]
pub(crate) struct AssetRefCounter {
pub(crate) channel: Arc<RefChangeChannel>,
Expand Down Expand Up @@ -132,11 +139,25 @@ impl AssetServer {
&self,
path: P,
) -> Result<Arc<Box<dyn AssetLoader>>, AssetServerError> {
path.as_ref()
.extension()
.and_then(|e| e.to_str())
.ok_or(AssetServerError::MissingAssetLoader(None))
.and_then(|extension| self.get_asset_loader(extension))
let s = path
.as_ref()
.file_name()
.ok_or(AssetServerError::MissingAssetLoader(None))?
.to_str()
.ok_or(AssetServerError::MissingAssetLoader(None))?;

let mut exts = Vec::new();
let mut ext = s;
while let Some(idx) = ext.find('.') {
ext = &ext[idx + 1..];
exts.push(ext);
if let Ok(loader) = self.get_asset_loader(ext) {
return Ok(loader);
}
}
let e = AssetServerError::MissingAssetLoader(Some(exts.join(", ")));
eprintln!("{}", e);
Err(e)
}

pub fn get_handle_path<H: Into<HandleId>>(&self, handle: H) -> Option<AssetPath<'_>> {
Expand Down Expand Up @@ -444,3 +465,100 @@ impl AssetServer {
pub fn free_unused_assets_system(asset_server: Res<AssetServer>) {
asset_server.free_unused_assets();
}

#[cfg(test)]
mod test {
use super::*;
use bevy_utils::BoxedFuture;

struct FakePngLoader;
impl AssetLoader for FakePngLoader {
fn load<'a>(
&'a self,
_: &'a [u8],
_: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<(), anyhow::Error>> {
Box::pin(async move { Ok(()) })
}

fn extensions(&self) -> &[&str] {
&["png"]
}
}

struct FakeMultipleDotLoader;
impl AssetLoader for FakeMultipleDotLoader {
fn load<'a>(
&'a self,
_: &'a [u8],
_: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<(), anyhow::Error>> {
Box::pin(async move { Ok(()) })
}

fn extensions(&self) -> &[&str] {
&["test.png"]
}
}

fn setup() -> AssetServer {
use crate::FileAssetIo;

let asset_server = AssetServer {
server: Arc::new(AssetServerInternal {
loaders: Default::default(),
extension_to_loader_index: Default::default(),
asset_sources: Default::default(),
asset_ref_counter: Default::default(),
handle_to_path: Default::default(),
asset_lifecycles: Default::default(),
task_pool: Default::default(),
asset_io: Box::new(FileAssetIo::new(&".")),
}),
};
asset_server.add_loader::<FakePngLoader>(FakePngLoader);
asset_server.add_loader::<FakeMultipleDotLoader>(FakeMultipleDotLoader);
asset_server
}

#[test]
fn extensions() {
let asset_server = setup();
let t = asset_server.get_path_asset_loader("test.png");
assert_eq!(t.unwrap().extensions()[0], "png");
}

#[test]
fn no_loader() {
let asset_server = setup();
let t = asset_server.get_path_asset_loader("test.pong");
assert!(t.is_err());
}

#[test]
fn multiple_extensions_no_loader() {
let asset_server = setup();

assert!(
match asset_server.get_path_asset_loader("test.v1.2.3.pong") {
Err(AssetServerError::MissingAssetLoader(Some(ext))) =>
ext == "v1.2.3.pong, 2.3.pong, 3.pong, pong",
_ => false,
}
)
}

#[test]
fn filename_with_dots() {
let asset_server = setup();
let t = asset_server.get_path_asset_loader("test-v1.2.3.png");
assert_eq!(t.unwrap().extensions()[0], "png");
}

#[test]
fn multiple_extensions() {
let asset_server = setup();
let t = asset_server.get_path_asset_loader("test.test.png");
assert_eq!(t.unwrap().extensions()[0], "test.png");
}
}

0 comments on commit 9942f0e

Please sign in to comment.