Make Asset impls avoid panics when parsing fails

This commit is contained in:
Imbris
2020-03-28 21:09:19 -04:00
parent f34d4b379e
commit 831d7c77a6
7 changed files with 36 additions and 29 deletions

View File

@ -19,8 +19,8 @@ use std::{
/// The error returned by asset loading functions /// The error returned by asset loading functions
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Error { pub enum Error {
/// An internal error occurred. /// Parsing error occurred.
Internal(Arc<dyn std::error::Error>), ParseError(Arc<dyn std::fmt::Debug>),
/// An asset of a different type has already been loaded with this /// An asset of a different type has already been loaded with this
/// specifier. /// specifier.
InvalidType, InvalidType,
@ -28,10 +28,16 @@ pub enum Error {
NotFound(String), NotFound(String),
} }
impl Error {
pub fn parse_error<E: std::fmt::Debug + 'static>(err: E) -> Self {
Self::ParseError(Arc::new(err))
}
}
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
Error::Internal(err) => err.fmt(f), Error::ParseError(err) => write!(f, "{:?}", err),
Error::InvalidType => write!( Error::InvalidType => write!(
f, f,
"an asset of a different type has already been loaded with this specifier." "an asset of a different type has already been loaded with this specifier."
@ -226,7 +232,7 @@ impl Asset for DynamicImage {
fn parse(mut buf_reader: BufReader<File>) -> Result<Self, Error> { fn parse(mut buf_reader: BufReader<File>) -> Result<Self, Error> {
let mut buf = Vec::new(); let mut buf = Vec::new();
buf_reader.read_to_end(&mut buf)?; buf_reader.read_to_end(&mut buf)?;
Ok(image::load_from_memory(&buf).unwrap()) image::load_from_memory(&buf).map_err(Error::parse_error)
} }
} }
@ -236,7 +242,7 @@ impl Asset for DotVoxData {
fn parse(mut buf_reader: BufReader<File>) -> Result<Self, Error> { fn parse(mut buf_reader: BufReader<File>) -> Result<Self, Error> {
let mut buf = Vec::new(); let mut buf = Vec::new();
buf_reader.read_to_end(&mut buf)?; buf_reader.read_to_end(&mut buf)?;
Ok(dot_vox::load_bytes(&buf).unwrap()) dot_vox::load_bytes(&buf).map_err(Error::parse_error)
} }
} }
@ -245,7 +251,7 @@ impl Asset for Value {
const ENDINGS: &'static [&'static str] = &["json"]; const ENDINGS: &'static [&'static str] = &["json"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, Error> {
Ok(serde_json::from_reader(buf_reader).unwrap()) serde_json::from_reader(buf_reader).map_err(Error::parse_error)
} }
} }

View File

@ -16,7 +16,7 @@ use crate::{
}; };
use specs::{Component, FlaggedStorage}; use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage; use specs_idvs::IDVStorage;
use std::{fs::File, io::BufReader, sync::Arc}; use std::{fs::File, io::BufReader};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)] #[repr(u32)]
@ -84,7 +84,7 @@ impl<
const ENDINGS: &'static [&'static str] = &["json"]; const ENDINGS: &'static [&'static str] = &["json"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
serde_json::de::from_reader(buf_reader).map_err(|e| assets::Error::Internal(Arc::new(e))) serde_json::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }

View File

@ -75,7 +75,7 @@ impl Asset for Item {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).unwrap()) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }

View File

@ -78,7 +78,7 @@ impl Asset for ItemImagesSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing item images spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }

View File

@ -108,7 +108,8 @@ impl Asset for VoxygenLocalization {
/// Load the translations located in the input buffer and convert them /// Load the translations located in the input buffer and convert them
/// into a `VoxygenLocalization` object. /// into a `VoxygenLocalization` object.
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
let mut asked_localization: VoxygenLocalization = from_reader(buf_reader).unwrap(); let mut asked_localization: VoxygenLocalization =
from_reader(buf_reader).map_err(assets::Error::parse_error)?;
// Update the text if UTF-8 to ASCII conversion is enabled // Update the text if UTF-8 to ASCII conversion is enabled
if asked_localization.convert_utf8_to_ascii { if asked_localization.convert_utf8_to_ascii {

View File

@ -139,7 +139,7 @@ impl Asset for HumHeadSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid head spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -261,49 +261,49 @@ impl Asset for HumArmorShoulderSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor shoulder spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
impl Asset for HumArmorChestSpec { impl Asset for HumArmorChestSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor chest spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
impl Asset for HumArmorHandSpec { impl Asset for HumArmorHandSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor hand spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
impl Asset for HumArmorBeltSpec { impl Asset for HumArmorBeltSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor belt spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
impl Asset for HumArmorPantsSpec { impl Asset for HumArmorPantsSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor pants spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
impl Asset for HumArmorFootSpec { impl Asset for HumArmorFootSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid armor foot spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
impl Asset for HumMainWeaponSpec { impl Asset for HumMainWeaponSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing humanoid main weapon spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -667,7 +667,7 @@ impl Asset for QuadrupedSmallCentralSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing quad_small central spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -675,7 +675,7 @@ impl Asset for QuadrupedSmallLateralSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing quadruped small lateral spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -828,7 +828,7 @@ impl Asset for QuadrupedMediumCentralSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing quadruped medium central spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -836,7 +836,7 @@ impl Asset for QuadrupedMediumLateralSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing quadruped medium lateral spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -1074,7 +1074,7 @@ impl Asset for BirdMediumCenterSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing bird medium center spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -1082,7 +1082,7 @@ impl Asset for BirdMediumLateralSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing bird medium lateral spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -1232,7 +1232,7 @@ impl Asset for CritterCenterSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing critter center spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -1587,7 +1587,7 @@ impl Asset for BipedLargeCenterSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing biped large center spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }
@ -1595,7 +1595,7 @@ impl Asset for BipedLargeLateralSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing biped large lateral spec")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }

View File

@ -87,7 +87,7 @@ impl Asset for StructuresSpec {
const ENDINGS: &'static [&'static str] = &["ron"]; const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> { fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
Ok(ron::de::from_reader(buf_reader).expect("Error parsing structure specs")) ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
} }
} }