use std::error::Error;
use std::fmt::{Display, Formatter};
#[derive(Debug)]
pub struct LoadError {
inner: LoadErrorImpl,
node: Option<String>,
}
impl LoadError {
pub(crate) fn new(kind: LoadErrorImpl) -> Self {
Self {
inner: kind,
node: None,
}
}
pub(crate) fn for_node(node: Option<&str>, kind: LoadErrorImpl) -> Self {
Self {
inner: kind,
node: node.map(|n| n.to_string()),
}
}
pub fn node(&self) -> Option<&str> {
self.node.as_deref()
}
pub fn kind(&self) -> LoadErrorKind {
self.inner.kind()
}
}
impl Display for LoadError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if let Some(node) = self.node.as_deref() {
write!(f, "in node \"{}\": {}", node, self.inner)
} else {
self.inner.fmt(f)
}
}
}
impl Error for LoadError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.inner.source()
}
}
impl From<LoadErrorImpl> for LoadError {
fn from(val: LoadErrorImpl) -> Self {
Self::new(val)
}
}
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub enum LoadErrorKind {
IoError,
ParseError,
OperatorInvalid,
GraphError,
OptimizeError,
UnknownFileType,
ExternalDataError,
FormatNotEnabled,
}
#[derive(Debug)]
pub(crate) enum LoadErrorImpl {
ReadFailed(std::io::Error),
#[cfg(feature = "rten_format")]
InvalidHeader(Box<dyn Error + Send + Sync>),
ParseFailed(Box<dyn Error + Send + Sync>),
OperatorInvalid(Box<dyn Error + Send + Sync>),
GraphError(Box<dyn Error + Send + Sync>),
OptimizeError(Box<dyn Error + Send + Sync>),
UnknownFileType,
ExternalDataError(Box<dyn Error + Send + Sync>),
#[allow(unused)]
FormatNotEnabled,
}
impl LoadErrorImpl {
fn kind(&self) -> LoadErrorKind {
type Kind = LoadErrorKind;
match self {
Self::ReadFailed(_) => Kind::IoError,
#[cfg(feature = "rten_format")]
Self::InvalidHeader(_) => Kind::ParseError,
Self::ParseFailed(_) => Kind::ParseError,
Self::OperatorInvalid(_) => Kind::OperatorInvalid,
Self::GraphError(_) => Kind::GraphError,
Self::OptimizeError(_) => Kind::OptimizeError,
Self::UnknownFileType => Kind::UnknownFileType,
Self::ExternalDataError(_) => Kind::ExternalDataError,
Self::FormatNotEnabled => Kind::FormatNotEnabled,
}
}
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::ReadFailed(err) => Some(err),
#[cfg(feature = "rten_format")]
Self::InvalidHeader(err) => Some(err.as_ref()),
Self::ParseFailed(err) => Some(err.as_ref()),
Self::OperatorInvalid(err) => Some(err.as_ref()),
Self::GraphError(err) => Some(err.as_ref()),
Self::OptimizeError(err) => Some(err.as_ref()),
Self::UnknownFileType => None,
Self::ExternalDataError(err) => Some(err.as_ref()),
Self::FormatNotEnabled => None,
}
}
}
impl Display for LoadErrorImpl {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::ReadFailed(e) => write!(f, "read error: {e}"),
#[cfg(feature = "rten_format")]
Self::InvalidHeader(e) => write!(f, "invalid header: {e}"),
Self::ParseFailed(e) => write!(f, "parse error: {e}"),
Self::OperatorInvalid(e) => write!(f, "operator error: {e}"),
Self::GraphError(e) => write!(f, "graph error: {e}"),
Self::OptimizeError(e) => write!(f, "graph optimization error: {e}"),
Self::UnknownFileType => write!(f, "unknown model file type"),
Self::ExternalDataError(e) => write!(f, "external data error: {e}"),
Self::FormatNotEnabled => {
write!(f, "rten was built without support for this model format")
}
}
}
}
macro_rules! load_error {
($kind:ident, $node_name:expr, $format_str:literal, $($arg:tt)*) => {{
let err = format!($format_str, $($arg)*);
LoadError::for_node($node_name, LoadErrorImpl::$kind(err.into()))
}};
($kind:ident, $node_name:expr, $err:expr) => {{
LoadError::for_node($node_name, LoadErrorImpl::$kind($err.into()))
}}
}
pub(crate) use load_error;