Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Add file metadata to AssetIo #2123

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl AssetServer {
/// Enable watching of the filesystem for changes, if support is available, starting from after
/// the point of calling this function.
pub fn watch_for_changes(&self) -> Result<(), AssetServerError> {
self.server.asset_io.watch_for_changes()?;
self.asset_io().watch_for_changes()?;
Ok(())
}

Expand Down Expand Up @@ -308,7 +308,7 @@ impl AssetServer {
};

// load the asset bytes
let bytes = match self.server.asset_io.load_path(asset_path.path()).await {
let bytes = match self.asset_io().load_path(asset_path.path()).await {
Ok(bytes) => bytes,
Err(err) => {
set_asset_failed();
Expand All @@ -320,7 +320,7 @@ impl AssetServer {
let mut load_context = LoadContext::new(
asset_path.path(),
&self.server.asset_ref_counter.channel,
&*self.server.asset_io,
self.asset_io(),
version,
&self.server.task_pool,
);
Expand Down Expand Up @@ -368,8 +368,7 @@ impl AssetServer {
}
}

self.server
.asset_io
self.asset_io()
.watch_path_for_changes(asset_path.path())
.unwrap();
self.create_assets_in_load_context(&mut load_context);
Expand Down Expand Up @@ -410,15 +409,15 @@ impl AssetServer {
path: P,
) -> Result<Vec<HandleUntyped>, AssetServerError> {
let path = path.as_ref();
if !self.server.asset_io.is_directory(path) {
if !self.asset_io().is_dir(path) {
return Err(AssetServerError::AssetFolderNotADirectory(
path.to_str().unwrap().to_string(),
));
}

let mut handles = Vec::new();
for child_path in self.server.asset_io.read_directory(path.as_ref())? {
if self.server.asset_io.is_directory(&child_path) {
for child_path in self.asset_io().read_directory(path.as_ref())? {
if self.asset_io().is_dir(&child_path) {
handles.extend(self.load_folder(&child_path)?);
} else {
if self.get_path_asset_loader(&child_path).is_err() {
Expand Down
17 changes: 14 additions & 3 deletions crates/bevy_asset/src/io/android_asset_io.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::{AssetIo, AssetIoError};
use crate::{AssetIo, AssetIoError, Metadata};
use anyhow::Result;
use bevy_utils::BoxedFuture;
use std::{
convert::TryFrom,
ffi::CString,
path::{Path, PathBuf},
};
Expand Down Expand Up @@ -46,7 +47,17 @@ impl AssetIo for AndroidAssetIo {
Ok(())
}

fn is_directory(&self, path: &Path) -> bool {
self.root_path.join(path).is_dir()
fn get_metadata(&self, path: &Path) -> Result<Metadata, AssetIoError> {
let full_path = self.root_path.join(path);
full_path
.metadata()
.and_then(Metadata::try_from)
.map_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
AssetIoError::NotFound(full_path)
} else {
e.into()
}
})
}
}
17 changes: 14 additions & 3 deletions crates/bevy_asset/src/io/file_asset_io.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#[cfg(feature = "filesystem_watcher")]
use crate::{filesystem_watcher::FilesystemWatcher, AssetServer};
use crate::{AssetIo, AssetIoError};
use crate::{AssetIo, AssetIoError, Metadata};
use anyhow::Result;
#[cfg(feature = "filesystem_watcher")]
use bevy_ecs::system::Res;
Expand All @@ -15,6 +15,7 @@ use parking_lot::RwLock;
#[cfg(feature = "filesystem_watcher")]
use std::sync::Arc;
use std::{
convert::TryFrom,
env, fs,
io::Read,
path::{Path, PathBuf},
Expand Down Expand Up @@ -128,8 +129,18 @@ impl AssetIo for FileAssetIo {
Ok(())
}

fn is_directory(&self, path: &Path) -> bool {
self.root_path.join(path).is_dir()
fn get_metadata(&self, path: &Path) -> Result<Metadata, AssetIoError> {
let full_path = self.root_path.join(path);
full_path
.metadata()
.and_then(Metadata::try_from)
.map_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
AssetIoError::NotFound(full_path)
} else {
e.into()
}
})
}
}

Expand Down
77 changes: 77 additions & 0 deletions crates/bevy_asset/src/io/metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use std::convert::{TryFrom, TryInto};

/// A enum representing a type of file.
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum FileType {
geckoxx marked this conversation as resolved.
Show resolved Hide resolved
Directory,
File,
}

impl FileType {
#[inline]
pub const fn is_dir(&self) -> bool {
matches!(self, Self::Directory)
}

#[inline]
pub const fn is_file(&self) -> bool {
matches!(self, Self::File)
}
}

impl TryFrom<std::fs::FileType> for FileType {
type Error = std::io::Error;

fn try_from(file_type: std::fs::FileType) -> Result<Self, Self::Error> {
if file_type.is_dir() {
Ok(Self::Directory)
} else if file_type.is_file() {
Ok(Self::File)
} else {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"unknown file type",
))
}
}
}

/// Metadata information about a file.
///
/// This structure is returned from the [`AssetIo::get_metadata`](crate::AssetIo) method.
#[derive(Debug, Clone)]
pub struct Metadata {
file_type: FileType,
}

impl Metadata {
pub fn new(file_type: FileType) -> Self {
Self { file_type }
}
geckoxx marked this conversation as resolved.
Show resolved Hide resolved

#[inline]
pub const fn file_type(&self) -> FileType {
self.file_type
}

#[inline]
pub const fn is_dir(&self) -> bool {
geckoxx marked this conversation as resolved.
Show resolved Hide resolved
self.file_type.is_dir()
}

#[inline]
pub const fn is_file(&self) -> bool {
self.file_type.is_file()
}
}

impl TryFrom<std::fs::Metadata> for Metadata {
type Error = std::io::Error;

fn try_from(metadata: std::fs::Metadata) -> Result<Self, Self::Error> {
Ok(Self {
file_type: metadata.file_type().try_into()?,
})
}
}
20 changes: 19 additions & 1 deletion crates/bevy_asset/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ mod file_asset_io;
#[cfg(target_arch = "wasm32")]
mod wasm_asset_io;

mod metadata;

#[cfg(target_os = "android")]
pub use android_asset_io::*;
#[cfg(all(not(target_arch = "wasm32"), not(target_os = "android")))]
pub use file_asset_io::*;
#[cfg(target_arch = "wasm32")]
pub use wasm_asset_io::*;

pub use metadata::*;

use anyhow::Result;
use bevy_utils::BoxedFuture;
use downcast_rs::{impl_downcast, Downcast};
Expand Down Expand Up @@ -39,9 +43,23 @@ pub trait AssetIo: Downcast + Send + Sync + 'static {
&self,
path: &Path,
) -> Result<Box<dyn Iterator<Item = PathBuf>>, AssetIoError>;
fn is_directory(&self, path: &Path) -> bool;
fn get_metadata(&self, path: &Path) -> Result<Metadata, AssetIoError>;
fn watch_path_for_changes(&self, path: &Path) -> Result<(), AssetIoError>;
fn watch_for_changes(&self) -> Result<(), AssetIoError>;

fn is_dir(&self, path: &Path) -> bool {
self.get_metadata(path)
.as_ref()
.map(Metadata::is_dir)
.unwrap_or(false)
}

fn is_file(&self, path: &Path) -> bool {
self.get_metadata(path)
.as_ref()
.map(Metadata::is_file)
.unwrap_or(false)
}
}

impl_downcast!(AssetIo);
21 changes: 17 additions & 4 deletions crates/bevy_asset/src/io/wasm_asset_io.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use crate::{AssetIo, AssetIoError};
use crate::{AssetIo, AssetIoError, Metadata};
use anyhow::Result;
use bevy_utils::BoxedFuture;
use js_sys::Uint8Array;
use std::path::{Path, PathBuf};
use std::{
convert::TryFrom,
path::{Path, PathBuf},
};
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use web_sys::Response;
Expand Down Expand Up @@ -50,7 +53,17 @@ impl AssetIo for WasmAssetIo {
Ok(())
}

fn is_directory(&self, path: &Path) -> bool {
self.root_path.join(path).is_dir()
fn get_metadata(&self, path: &Path) -> Result<Metadata, AssetIoError> {
let full_path = self.root_path.join(path);
full_path
.metadata()
.and_then(Metadata::try_from)
.map_err(|e| {
if e.kind() == std::io::ErrorKind::NotFound {
AssetIoError::NotFound(full_path)
} else {
e.into()
}
})
}
}
4 changes: 4 additions & 0 deletions crates/bevy_asset/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ impl<'a> LoadContext<'a> {
pub fn task_pool(&self) -> &TaskPool {
self.task_pool
}

pub fn asset_io(&self) -> &dyn AssetIo {
self.asset_io
}
}

/// The result of loading an asset of type `T`
Expand Down
12 changes: 6 additions & 6 deletions examples/asset/custom_asset_io.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy::{
asset::{AssetIo, AssetIoError},
asset::{AssetIo, AssetIoError, Metadata},
prelude::*,
utils::BoxedFuture,
};
Expand All @@ -26,11 +26,6 @@ impl AssetIo for CustomAssetIo {
self.0.read_directory(path)
}

fn is_directory(&self, path: &Path) -> bool {
info!("is_directory({:?})", path);
self.0.is_directory(path)
}

fn watch_path_for_changes(&self, path: &Path) -> Result<(), AssetIoError> {
info!("watch_path_for_changes({:?})", path);
self.0.watch_path_for_changes(path)
Expand All @@ -40,6 +35,11 @@ impl AssetIo for CustomAssetIo {
info!("watch_for_changes()");
self.0.watch_for_changes()
}

fn get_metadata(&self, path: &Path) -> Result<Metadata, AssetIoError> {
info!("get_metadata({:?})", path);
self.0.get_metadata(path)
}
}

/// A plugin used to execute the override of the asset io
Expand Down