Update snapshot error type and handle serde_json errors in JSON models

This commit is contained in:
Lucien Greathouse
2020-03-13 20:31:31 -07:00
parent b0fc9ee507
commit 6de74b41b3
2 changed files with 53 additions and 59 deletions

View File

@@ -1,5 +1,7 @@
use std::{error::Error, fmt, io, path::PathBuf}; use std::{error::Error, fmt, io, path::PathBuf};
use snafu::Snafu;
#[derive(Debug)] #[derive(Debug)]
pub struct SnapshotError { pub struct SnapshotError {
detail: SnapshotErrorDetail, detail: SnapshotErrorDetail,
@@ -8,49 +10,56 @@ pub struct SnapshotError {
impl SnapshotError { impl SnapshotError {
pub fn new(detail: SnapshotErrorDetail, path: Option<impl Into<PathBuf>>) -> Self { pub fn new(detail: SnapshotErrorDetail, path: Option<impl Into<PathBuf>>) -> Self {
SnapshotError { Self {
detail, detail,
path: path.map(Into::into), path: path.map(Into::into),
} }
} }
pub(crate) fn wrap(inner: impl Into<SnapshotErrorDetail>, path: impl Into<PathBuf>) -> Self { pub(crate) fn wrap(source: impl Into<SnapshotErrorDetail>, path: impl Into<PathBuf>) -> Self {
SnapshotError { Self {
detail: inner.into(), detail: source.into(),
path: Some(path.into()), path: Some(path.into()),
} }
} }
pub(crate) fn file_did_not_exist(path: impl Into<PathBuf>) -> SnapshotError { pub(crate) fn file_did_not_exist(path: impl Into<PathBuf>) -> Self {
SnapshotError { Self {
detail: SnapshotErrorDetail::FileDidNotExist, detail: SnapshotErrorDetail::FileDidNotExist,
path: Some(path.into()), path: Some(path.into()),
} }
} }
pub(crate) fn file_name_bad_unicode(path: impl Into<PathBuf>) -> SnapshotError { pub(crate) fn file_name_bad_unicode(path: impl Into<PathBuf>) -> Self {
SnapshotError { Self {
detail: SnapshotErrorDetail::FileNameBadUnicode, detail: SnapshotErrorDetail::FileNameBadUnicode,
path: Some(path.into()), path: Some(path.into()),
} }
} }
pub(crate) fn file_contents_bad_unicode( pub(crate) fn file_contents_bad_unicode(
inner: std::str::Utf8Error, source: std::str::Utf8Error,
path: impl Into<PathBuf>, path: impl Into<PathBuf>,
) -> SnapshotError { ) -> Self {
SnapshotError { Self {
detail: SnapshotErrorDetail::FileContentsBadUnicode { inner }, detail: SnapshotErrorDetail::FileContentsBadUnicode { source },
path: Some(path.into()), path: Some(path.into()),
} }
} }
pub(crate) fn malformed_project( pub(crate) fn malformed_project(source: serde_json::Error, path: impl Into<PathBuf>) -> Self {
inner: serde_json::Error, Self {
detail: SnapshotErrorDetail::MalformedProject { source },
path: Some(path.into()),
}
}
pub(crate) fn malformed_model_json(
source: serde_json::Error,
path: impl Into<PathBuf>, path: impl Into<PathBuf>,
) -> SnapshotError { ) -> Self {
SnapshotError { Self {
detail: SnapshotErrorDetail::MalformedProject { inner }, detail: SnapshotErrorDetail::MalformedModelJson { source },
path: Some(path.into()), path: Some(path.into()),
} }
} }
@@ -83,55 +92,38 @@ impl From<rlua::Error> for SnapshotError {
} }
} }
#[derive(Debug)] #[derive(Debug, Snafu)]
pub enum SnapshotErrorDetail { pub enum SnapshotErrorDetail {
IoError { inner: io::Error }, #[snafu(display("I/O error"))]
Lua { inner: rlua::Error }, IoError { source: io::Error },
#[snafu(display("Lua error"))]
Lua { source: rlua::Error },
#[snafu(display("file did not exist"))]
FileDidNotExist, FileDidNotExist,
#[snafu(display("file name had malformed Unicode"))]
FileNameBadUnicode, FileNameBadUnicode,
FileContentsBadUnicode { inner: std::str::Utf8Error },
MalformedProject { inner: serde_json::Error }, #[snafu(display("file had malformed Unicode contents"))]
FileContentsBadUnicode { source: std::str::Utf8Error },
#[snafu(display("malformed project file"))]
MalformedProject { source: serde_json::Error },
#[snafu(display("malformed .model.json file"))]
MalformedModelJson { source: serde_json::Error },
} }
impl From<io::Error> for SnapshotErrorDetail { impl From<io::Error> for SnapshotErrorDetail {
fn from(inner: io::Error) -> Self { fn from(source: io::Error) -> Self {
SnapshotErrorDetail::IoError { inner } SnapshotErrorDetail::IoError { source }
} }
} }
impl From<rlua::Error> for SnapshotErrorDetail { impl From<rlua::Error> for SnapshotErrorDetail {
fn from(inner: rlua::Error) -> Self { fn from(source: rlua::Error) -> Self {
SnapshotErrorDetail::Lua { inner } SnapshotErrorDetail::Lua { source }
}
}
impl SnapshotErrorDetail {
fn source(&self) -> Option<&(dyn Error + 'static)> {
use self::SnapshotErrorDetail::*;
match self {
IoError { inner } => Some(inner),
Lua { inner } => Some(inner),
FileContentsBadUnicode { inner } => Some(inner),
MalformedProject { inner } => Some(inner),
_ => None,
}
}
}
impl fmt::Display for SnapshotErrorDetail {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
use self::SnapshotErrorDetail::*;
match self {
IoError { inner } => write!(formatter, "I/O error: {}", inner),
Lua { inner } => write!(formatter, "{}", inner),
FileDidNotExist => write!(formatter, "file did not exist"),
FileNameBadUnicode => write!(formatter, "file name had malformed Unicode"),
FileContentsBadUnicode { inner } => {
write!(formatter, "file had malformed unicode: {}", inner)
}
MalformedProject { inner } => write!(formatter, "{}", inner),
}
} }
} }

View File

@@ -8,6 +8,7 @@ use serde::Deserialize;
use crate::snapshot::{InstanceContext, InstanceSnapshot}; use crate::snapshot::{InstanceContext, InstanceSnapshot};
use super::{ use super::{
error::SnapshotError,
middleware::{SnapshotInstanceResult, SnapshotMiddleware}, middleware::{SnapshotInstanceResult, SnapshotMiddleware},
util::match_file_name, util::match_file_name,
}; };
@@ -27,8 +28,9 @@ impl SnapshotMiddleware for SnapshotJsonModel {
None => return Ok(None), None => return Ok(None),
}; };
let instance: JsonModel = let contents = vfs.read(path)?;
serde_json::from_slice(&vfs.read(path)?).expect("TODO: Handle serde_json errors"); let instance: JsonModel = serde_json::from_slice(&contents)
.map_err(|source| SnapshotError::malformed_model_json(source, path))?;
if let Some(json_name) = &instance.name { if let Some(json_name) = &instance.name {
if json_name != instance_name { if json_name != instance_name {