Process Asset File Extensions With Multiple Dots (#1277)
Process Asset File Extensions With Multiple Dots Fixes #1276
This commit is contained in:
parent
5edf2d2395
commit
b6485ccf29
@ -19,8 +19,8 @@ use thiserror::Error;
|
|||||||
pub enum AssetServerError {
|
pub enum AssetServerError {
|
||||||
#[error("asset folder path is not a directory: {0}")]
|
#[error("asset folder path is not a directory: {0}")]
|
||||||
AssetFolderNotADirectory(String),
|
AssetFolderNotADirectory(String),
|
||||||
#[error("no `AssetLoader` found for the given extension: {0:?}")]
|
#[error("no `AssetLoader` found{}", format_missing_asset_ext(.extensions))]
|
||||||
MissingAssetLoader(Option<String>),
|
MissingAssetLoader { extensions: Vec<String> },
|
||||||
#[error("the given type does not match the type of the loaded asset")]
|
#[error("the given type does not match the type of the loaded asset")]
|
||||||
IncorrectHandleType,
|
IncorrectHandleType,
|
||||||
#[error("encountered an error while loading an asset: {0}")]
|
#[error("encountered an error while loading an asset: {0}")]
|
||||||
@ -29,6 +29,18 @@ pub enum AssetServerError {
|
|||||||
AssetIoError(#[from] AssetIoError),
|
AssetIoError(#[from] AssetIoError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn format_missing_asset_ext(exts: &[String]) -> String {
|
||||||
|
if exts.is_empty() {
|
||||||
|
format!(
|
||||||
|
" for the following extension{}: {}",
|
||||||
|
if exts.len() > 1 { "s" } else { "" },
|
||||||
|
exts.join(", ")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct AssetRefCounter {
|
pub(crate) struct AssetRefCounter {
|
||||||
pub(crate) channel: Arc<RefChangeChannel>,
|
pub(crate) channel: Arc<RefChangeChannel>,
|
||||||
@ -126,18 +138,38 @@ impl AssetServer {
|
|||||||
.read()
|
.read()
|
||||||
.get(extension)
|
.get(extension)
|
||||||
.map(|index| self.server.loaders.read()[*index].clone())
|
.map(|index| self.server.loaders.read()[*index].clone())
|
||||||
.ok_or_else(|| AssetServerError::MissingAssetLoader(Some(extension.to_string())))
|
.ok_or_else(|| AssetServerError::MissingAssetLoader {
|
||||||
|
extensions: vec![extension.to_string()],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_path_asset_loader<P: AsRef<Path>>(
|
fn get_path_asset_loader<P: AsRef<Path>>(
|
||||||
&self,
|
&self,
|
||||||
path: P,
|
path: P,
|
||||||
) -> Result<Arc<Box<dyn AssetLoader>>, AssetServerError> {
|
) -> Result<Arc<Box<dyn AssetLoader>>, AssetServerError> {
|
||||||
path.as_ref()
|
let s = path
|
||||||
.extension()
|
.as_ref()
|
||||||
.and_then(|e| e.to_str())
|
.file_name()
|
||||||
.ok_or(AssetServerError::MissingAssetLoader(None))
|
.ok_or(AssetServerError::MissingAssetLoader {
|
||||||
.and_then(|extension| self.get_asset_loader(extension))
|
extensions: Vec::new(),
|
||||||
|
})?
|
||||||
|
.to_str()
|
||||||
|
.ok_or(AssetServerError::MissingAssetLoader {
|
||||||
|
extensions: Vec::new(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(AssetServerError::MissingAssetLoader {
|
||||||
|
extensions: exts.into_iter().map(String::from).collect(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_handle_path<H: Into<HandleId>>(&self, handle: H) -> Option<AssetPath<'_>> {
|
pub fn get_handle_path<H: Into<HandleId>>(&self, handle: H) -> Option<AssetPath<'_>> {
|
||||||
@ -457,3 +489,100 @@ impl AssetServer {
|
|||||||
pub fn free_unused_assets_system(asset_server: Res<AssetServer>) {
|
pub fn free_unused_assets_system(asset_server: Res<AssetServer>) {
|
||||||
asset_server.free_unused_assets();
|
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 { extensions }) =>
|
||||||
|
extensions == vec!["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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user