use std::fmt;
#[derive(Debug)]
pub struct DataLoadingError {
kind: DataLoadingErrorKind,
}
#[derive(Debug)]
enum DataLoadingErrorKind {
Io(std::io::Error),
Parse { context: String, detail: String },
Unknown(String),
Table {
path: String,
row: usize,
detail: String,
},
Corrupt { path: String, detail: String },
FingerprintMismatch { path: String },
ScalarMismatch {
path: String,
expected: String,
found: String,
},
UnknownVersion { path: String, found: u16 },
MissingColumn { name: String },
}
impl DataLoadingError {
pub(crate) fn parse(context: impl Into<String>, detail: impl Into<String>) -> Self {
Self {
kind: DataLoadingErrorKind::Parse {
context: context.into(),
detail: detail.into(),
},
}
}
pub(crate) fn unknown(detail: impl Into<String>) -> Self {
Self {
kind: DataLoadingErrorKind::Unknown(detail.into()),
}
}
pub(crate) fn table(path: impl Into<String>, row: usize, detail: impl Into<String>) -> Self {
Self {
kind: DataLoadingErrorKind::Table {
path: path.into(),
row,
detail: detail.into(),
},
}
}
pub(crate) fn corrupt(path: impl Into<String>, detail: impl Into<String>) -> Self {
Self {
kind: DataLoadingErrorKind::Corrupt {
path: path.into(),
detail: detail.into(),
},
}
}
pub(crate) fn fingerprint_mismatch(path: impl Into<String>) -> Self {
Self {
kind: DataLoadingErrorKind::FingerprintMismatch { path: path.into() },
}
}
pub(crate) fn scalar_mismatch(
path: impl Into<String>,
expected: impl Into<String>,
found: impl Into<String>,
) -> Self {
Self {
kind: DataLoadingErrorKind::ScalarMismatch {
path: path.into(),
expected: expected.into(),
found: found.into(),
},
}
}
pub(crate) fn unknown_version(path: impl Into<String>, found: u16) -> Self {
Self {
kind: DataLoadingErrorKind::UnknownVersion {
path: path.into(),
found,
},
}
}
pub(crate) fn missing_column(name: impl Into<String>) -> Self {
Self {
kind: DataLoadingErrorKind::MissingColumn { name: name.into() },
}
}
}
impl fmt::Display for DataLoadingError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
DataLoadingErrorKind::Io(e) => write!(f, "data loading: I/O error: {e}"),
DataLoadingErrorKind::Parse { context, detail } => {
write!(f, "data loading: parse error in {context}: {detail}")
}
DataLoadingErrorKind::Unknown(d) => write!(f, "data loading: unknown identifier: {d}"),
DataLoadingErrorKind::Table { path, row, detail } => {
write!(
f,
"data loading: table error in {path} at row {row}: {detail}"
)
}
DataLoadingErrorKind::Corrupt { path, detail } => {
write!(f, "data loading: corrupt file {path}: {detail}")
}
DataLoadingErrorKind::FingerprintMismatch { path } => {
write!(
f,
"data loading: snapshot {path} belongs to a different world description \
(fingerprint mismatch)"
)
}
DataLoadingErrorKind::ScalarMismatch {
path,
expected,
found,
} => {
write!(
f,
"data loading: snapshot {path} was saved at scalar {found}, this program \
runs at {expected}"
)
}
DataLoadingErrorKind::UnknownVersion { path, found } => {
write!(
f,
"data loading: snapshot {path} has unknown format version {found}"
)
}
DataLoadingErrorKind::MissingColumn { name } => {
write!(f, "data loading: table has no column named '{name}'")
}
}
}
}
impl std::error::Error for DataLoadingError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match &self.kind {
DataLoadingErrorKind::Io(e) => Some(e),
_ => None,
}
}
}
impl From<std::io::Error> for DataLoadingError {
fn from(e: std::io::Error) -> Self {
Self {
kind: DataLoadingErrorKind::Io(e),
}
}
}