use crate::{GraphEntry, Query};
use std::{
error::Error,
fmt::{Debug, Display, Formatter},
ops::DerefMut,
path::Path,
};
pub type GraphResult<T = ()> = Result<T, GraphError>;
#[derive(Debug)]
pub struct GraphError {
kind: Box<GraphErrorKind>,
}
#[derive(Debug)]
pub enum GraphErrorKind {
NotFound { query: Query },
NotSupported { query: Query },
OutOfRange {
entry: GraphEntry,
index: usize,
max: usize,
},
IO {
entry: String,
error: std::io::Error,
},
Custom {
message: String,
},
}
impl Error for GraphError {}
impl Display for GraphError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.kind, f)
}
}
impl Display for GraphErrorKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
GraphErrorKind::NotFound { query } => {
write!(f, "{query:?} not found")
}
GraphErrorKind::NotSupported { query } => {
write!(f, "{query:?} not found")
}
GraphErrorKind::OutOfRange { entry, index, max } => {
write!(f, "{entry:?} index {index} is out of range, max index is {max}")
}
GraphErrorKind::Custom { message } => f.write_str(message),
GraphErrorKind::IO { entry, error } if entry.is_empty() => {
write!(f, "IO error: {error}", error = error)
}
GraphErrorKind::IO { entry, error } => {
write!(f, "IO error at {entry:?}: {error}", entry = entry, error = error)
}
}
}
}
impl GraphError {
pub fn custom<S>(message: S) -> Self
where
S: ToString,
{
Self { kind: Box::new(GraphErrorKind::Custom { message: message.to_string() }) }
}
pub fn not_found<Q: Into<Query>>(query: Q) -> Self {
Self { kind: Box::new(GraphErrorKind::NotFound { query: query.into() }) }
}
pub fn not_support<Q: Into<Query>>(query: Q) -> Self {
Self { kind: Box::new(GraphErrorKind::NotSupported { query: query.into() }) }
}
pub fn with_io_path<P>(mut self, path: P) -> Self
where
P: AsRef<Path>,
{
match self.kind.deref_mut() {
GraphErrorKind::IO { entry, error: _ } => {
*entry = path.as_ref().to_string_lossy().to_string();
self
}
_ => self,
}
}
pub fn node_out_of_range(index: usize, max: usize) -> Self {
Self { kind: Box::new(GraphErrorKind::OutOfRange { entry: GraphEntry::Node, index, max }) }
}
pub fn edge_out_of_range(index: usize, max: usize) -> Self {
Self { kind: Box::new(GraphErrorKind::OutOfRange { entry: GraphEntry::Edge, index, max }) }
}
}