Add file metadata to AssetIo (#2123)
This is a replacement for #2106 This adds a `Metadata` struct which contains metadata information about a file, at the moment only the file type. It also adds a `get_metadata` to `AssetIo` trait and an `asset_io` accessor method to `AssetServer` and `LoadContext` I am not sure about the changes in `AndroidAssetIo ` and `WasmAssetIo`.
This commit is contained in:
		
							parent
							
								
									8283db69b4
								
							
						
					
					
						commit
						e29bd50de8
					
				@ -124,7 +124,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(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -301,7 +301,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();
 | 
			
		||||
@ -313,7 +313,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,
 | 
			
		||||
        );
 | 
			
		||||
@ -361,8 +361,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);
 | 
			
		||||
@ -403,15 +402,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() {
 | 
			
		||||
 | 
			
		||||
@ -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},
 | 
			
		||||
};
 | 
			
		||||
@ -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()
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
@ -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},
 | 
			
		||||
@ -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()
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										77
									
								
								crates/bevy_asset/src/io/metadata.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								crates/bevy_asset/src/io/metadata.rs
									
									
									
									
									
										Normal file
									
								
							@ -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 {
 | 
			
		||||
    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 }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub const fn file_type(&self) -> FileType {
 | 
			
		||||
        self.file_type
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub const fn is_dir(&self) -> bool {
 | 
			
		||||
        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()?,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -5,6 +5,8 @@ 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")))]
 | 
			
		||||
@ -12,6 +14,8 @@ 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};
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
@ -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()
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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`
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
use bevy::{
 | 
			
		||||
    asset::{AssetIo, AssetIoError},
 | 
			
		||||
    asset::{AssetIo, AssetIoError, Metadata},
 | 
			
		||||
    prelude::*,
 | 
			
		||||
    utils::BoxedFuture,
 | 
			
		||||
};
 | 
			
		||||
@ -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)
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user