add load_expect, change error reporting

Former-commit-id: 6064384b14e055701f11c3a1f4931aa6eb27adda
This commit is contained in:
Imbris 2019-04-28 20:23:14 -04:00
parent 775b5e731e
commit 8232ffbd33
2 changed files with 48 additions and 29 deletions

View File

@ -11,19 +11,21 @@ use std::{
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Error { pub enum Error {
/// An asset has already been loaded with this specifier but anot type
InvalidType, InvalidType,
NotFound, /// Asset does not exist
NotFound(String),
} }
impl From<Arc<dyn Any + 'static + Sync + Send>> for Error { impl From<Arc<dyn Any + 'static + Sync + Send>> for Error {
fn from(_err: Arc<dyn Any + 'static + Sync + Send>) -> Self { fn from(_: Arc<dyn Any + 'static + Sync + Send>) -> Self {
Error::InvalidType Error::InvalidType
} }
} }
impl From<std::io::Error> for Error { impl From<std::io::Error> for Error {
fn from(_err: std::io::Error) -> Self { fn from(err: std::io::Error) -> Self {
Error::NotFound Error::NotFound(format!("{:?}", err))
} }
} }
@ -33,13 +35,14 @@ lazy_static! {
} }
/// Function used to load assets /// Function used to load assets
/// loaded assets are cached in a global singleton hashmap
/// Example usage: /// Example usage:
/// ``` /// ```
/// use image::DynamicImage; /// use image::DynamicImage;
/// use common::assets;
/// ///
/// let my_image = common::asset::load::<DynamicImage>("core.ui.backgrounds.city").unwrap(); /// let my_image = assets::load::<DynamicImage>("core.ui.backgrounds.city").unwrap();
/// ``` /// ```
// TODO: consider assets that we only need in one place or that don't need to be kept in memory?
pub fn load<A: Asset + 'static>(specifier: &str) -> Result<Arc<A>, Error> { pub fn load<A: Asset + 'static>(specifier: &str) -> Result<Arc<A>, Error> {
Ok(ASSETS Ok(ASSETS
.write().unwrap() .write().unwrap()
@ -49,6 +52,21 @@ pub fn load<A: Asset + 'static>(specifier: &str) -> Result<Arc<A>, Error> {
.downcast()?) .downcast()?)
} }
/// Function used to load assets that will panic if the asset is not found
/// Use this to load essential assets
/// loaded assets are cached in a global singleton hashmap
/// Example usage:
/// ```
/// use image::DynamicImage;
/// use common::assets;
///
/// let my_image = assets::load_expect::<DynamicImage>("core.ui.backgrounds.city");
/// ```
pub fn load_expect<A: Asset + 'static>(specifier: &str) -> Arc<A> {
load(specifier)
.expect(&format!("Failed loading essential asset: {}", specifier))
}
/// Asset Trait /// Asset Trait
pub trait Asset: Send + Sync + Sized { pub trait Asset: Send + Sync + Sized {
fn load(specifier: &str) -> Result<Self, Error>; fn load(specifier: &str) -> Result<Self, Error>;
@ -75,41 +93,42 @@ impl Asset for DotVoxData {
} }
// TODO: System to load file from specifiers (eg "core.ui.backgrounds.city") // TODO: System to load file from specifiers (eg "core.ui.backgrounds.city")
fn try_load_from_path(name: &str) -> Option<File> { fn try_open_with_path(name: &str) -> Option<File> {
let basepaths = [ // if it's stupid and it works..,
[env!("CARGO_MANIFEST_DIR"), "/../assets"].concat(), [
// if it's stupid and it works..,
"assets".to_string(), "assets".to_string(),
"../../assets".to_string(),
"../assets".to_string(), /* optimizations */ "../assets".to_string(), /* optimizations */
"../../assets".to_string(),
[env!("CARGO_MANIFEST_DIR"), "/../assets"].concat(),
[env!("CARGO_MANIFEST_DIR"), "/assets"].concat(), [env!("CARGO_MANIFEST_DIR"), "/assets"].concat(),
[env!("CARGO_MANIFEST_DIR"), "/../../assets"].concat(), [env!("CARGO_MANIFEST_DIR"), "/../../assets"].concat(),
"../../../assets".to_string(), "../../../assets".to_string(),
[env!("CARGO_MANIFEST_DIR"), "/../../../assets"].concat(), [env!("CARGO_MANIFEST_DIR"), "/../../../assets"].concat(),
]; ]
for bp in &basepaths { .into_iter()
let filename = [bp, name].concat(); .map(|bp| [bp, name].concat())
match File::open(&filename) { .find_map(|ref filename| match File::open(filename) {
Ok(f) => { Ok(file) => {
debug!("Loading {} successful", filename); debug!("Loading {} successful", filename);
return Some(f); Some(file)
}, }
Err(e) => { Err(err) => {
debug!("Loading {} failed: {}", filename, e); error!("Loading {} failed: {}", filename, err);
} None
}; }
}; })
None
} }
pub fn load_from_path(name: &str) -> Result<Vec<u8>, Error> { pub fn load_from_path(name: &str) -> Result<Vec<u8>, Error> {
match try_load_from_path(name) { match try_open_with_path(name) {
Some(mut f) => { Some(mut f) => {
let mut content: Vec<u8> = vec!(); let mut content = Vec::<u8>::new();
f.read_to_end(&mut content)?; f.read_to_end(&mut content)?;
Ok(content) Ok(content)
}, },
None => Err(Error::NotFound), None => {
Err(Error::NotFound(name.to_owned()))
}
} }
} }

View File

@ -101,7 +101,7 @@ impl FigureCache {
fn load_mesh(filename: &str, position: Vec3<f32>) -> Mesh<FigurePipeline> { fn load_mesh(filename: &str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
let fullpath: String = ["/voxygen/voxel/", filename].concat(); let fullpath: String = ["/voxygen/voxel/", filename].concat();
Segment::from( Segment::from(
assets::load::<dot_vox::DotVoxData>(fullpath.as_str()).unwrap().as_ref() assets::load_expect::<DotVoxData>(fullpath.as_str()).as_ref()
) )
.generate_mesh(position) .generate_mesh(position)
} }