use std::error::Error;
use std::fmt;
use std::io;
use std::num::{ParseFloatError, ParseIntError};
pub type ObjResult<T> = Result<T, ObjError>;
#[derive(Debug)]
pub enum ObjError {
Io(io::Error),
ParseInt(ParseIntError),
ParseFloat(ParseFloatError),
Load(LoadError),
}
macro_rules! implmnt {
($name:ident, $error:path) => {
impl From<$error> for ObjError {
fn from(err: $error) -> Self {
ObjError::$name(err)
}
}
};
}
impl fmt::Display for ObjError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ObjError::Io(ref e) => e.fmt(f),
ObjError::ParseInt(ref e) => e.fmt(f),
ObjError::ParseFloat(ref e) => e.fmt(f),
ObjError::Load(ref e) => e.fmt(f),
}
}
}
impl Error for ObjError {
fn cause(&self) -> Option<&dyn Error> {
match *self {
ObjError::Io(ref err) => Some(err),
ObjError::ParseInt(ref err) => Some(err),
ObjError::ParseFloat(ref err) => Some(err),
ObjError::Load(ref err) => Some(err),
}
}
}
implmnt!(Io, io::Error);
implmnt!(ParseInt, ParseIntError);
implmnt!(ParseFloat, ParseFloatError);
implmnt!(Load, LoadError);
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct LoadError {
kind: LoadErrorKind,
message: String,
}
impl LoadError {
pub fn kind(&self) -> &LoadErrorKind {
&self.kind
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum LoadErrorKind {
UnexpectedStatement,
WrongNumberOfArguments,
WrongTypeOfArguments,
UntriangulatedModel,
InsufficientData,
IndexOutOfRange,
BackslashAtEOF,
TooBigGroupNumber,
}
impl LoadError {
#[deprecated(
since = "0.7.4",
note = "You shouldn’t need to create a LoadError instance on your own."
)]
pub fn new(kind: LoadErrorKind, message: &'static str) -> Self {
let message = message.to_string();
LoadError { kind, message }
}
pub(crate) fn new_internal(kind: LoadErrorKind, message: String) -> Self {
LoadError { kind, message }
}
}
impl Error for LoadError {}
impl fmt::Display for LoadError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
use LoadErrorKind::*;
let msg = match self.kind {
UnexpectedStatement => "Met unexpected statement",
WrongNumberOfArguments => "Received wrong number of arguments",
WrongTypeOfArguments => "Received unexpected type of arguments",
UntriangulatedModel => "Model should be triangulated first to be loaded properly",
InsufficientData => "Model cannot be transformed into requested form",
IndexOutOfRange => "Received index value out of range",
BackslashAtEOF => r"A line is expected after the backslash (\)",
TooBigGroupNumber => "Group number exceeded limitation.",
};
write!(fmt, "{}: {}", msg, self.message)
}
}
macro_rules! make_error {
($kind:ident, $message:expr) => {
return Err($crate::error::ObjError::Load(
$crate::error::LoadError::new_internal(
$crate::error::LoadErrorKind::$kind,
$message.to_string(),
),
))
};
}
pub(crate) use make_error;
pub(super) fn index_out_of_range<T, I>(index: usize) -> ObjResult<T> {
let name = std::any::type_name::<I>();
Err(ObjError::Load(LoadError {
kind: LoadErrorKind::IndexOutOfRange,
message: format!(
"Given index type '{name}' is not large enough to contain the index '{index}'"
),
}))
}