#[cfg(feature = "serde-1")]
use serde::{Deserialize, Serialize};
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use petgraph::graph::{DefaultIx, IndexType, NodeIndex};
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde-1", derive(Serialize, Deserialize))]
pub enum BoundedGraphError<Ix: IndexType = DefaultIx> {
EdgeRejected {
source: NodeIndex<Ix>,
target: NodeIndex<Ix>,
source_rejected: bool,
target_rejected: bool,
},
NodeNotFound {
source: Option<NodeIndex<Ix>>,
target: Option<NodeIndex<Ix>>,
},
}
impl<Ix: IndexType> BoundedGraphError<Ix> {
pub fn source_rejected(source: NodeIndex<Ix>, target: NodeIndex<Ix>) -> Self {
Self::EdgeRejected {
source,
target,
source_rejected: true,
target_rejected: false,
}
}
pub fn target_rejected(source: NodeIndex<Ix>, target: NodeIndex<Ix>) -> Self {
Self::EdgeRejected {
source,
target,
source_rejected: false,
target_rejected: true,
}
}
pub fn both_rejected(source: NodeIndex<Ix>, target: NodeIndex<Ix>) -> Self {
Self::EdgeRejected {
source,
target,
source_rejected: true,
target_rejected: true,
}
}
pub fn not_found(source: Option<NodeIndex<Ix>>, target: Option<NodeIndex<Ix>>) -> Self {
Self::NodeNotFound { source, target }
}
}
impl<Ix: IndexType> Display for BoundedGraphError<Ix> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::EdgeRejected {
source,
target,
source_rejected,
target_rejected,
} => match (source_rejected, target_rejected) {
(true, true) => write!(
f,
"both nodes rejected the edge (source: {:?}, target: {:?})",
source.index(),
target.index()
),
(true, false) => write!(
f,
"source node {:?} rejected the outgoing edge",
source.index()
),
(false, true) => write!(
f,
"target node {:?} rejected the incoming edge",
target.index()
),
(false, false) => write!(f, "edge rejected (internal error: neither node flagged)"),
},
Self::NodeNotFound { source, target } => match (source, target) {
(Some(s), Some(t)) => {
write!(
f,
"nodes not found (source: {:?}, target: {:?})",
s.index(),
t.index()
)
}
(Some(s), None) => write!(f, "source node {:?} not found", s.index()),
(None, Some(t)) => write!(f, "target node {:?} not found", t.index()),
(None, None) => write!(f, "nodes not found"),
},
}
}
}
impl<Ix: IndexType> Error for BoundedGraphError<Ix> {}
#[derive(Debug, Clone, PartialEq)]
pub enum BoundedAcyclicGraphError<Ix: IndexType = DefaultIx> {
Bounded(BoundedGraphError<Ix>),
Acyclic(petgraph::acyclic::AcyclicEdgeError<NodeIndex<Ix>>),
}
impl<Ix: IndexType> Display for BoundedAcyclicGraphError<Ix> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::Bounded(err) => write!(f, "{}", err),
Self::Acyclic(petgraph::acyclic::AcyclicEdgeError::Cycle(_)) => {
write!(f, "adding edge would create a cycle")
}
Self::Acyclic(petgraph::acyclic::AcyclicEdgeError::SelfLoop) => {
write!(f, "adding edge would create a self-loop")
}
Self::Acyclic(petgraph::acyclic::AcyclicEdgeError::InvalidEdge) => {
write!(f, "could not add edge to underlying graph")
}
}
}
}
impl<Ix: IndexType> Error for BoundedAcyclicGraphError<Ix>
where
Ix: fmt::Debug,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Bounded(err) => Some(err),
Self::Acyclic(_) => None,
}
}
}
impl<Ix: IndexType> From<BoundedGraphError<Ix>> for BoundedAcyclicGraphError<Ix> {
fn from(err: BoundedGraphError<Ix>) -> Self {
Self::Bounded(err)
}
}
impl<Ix: IndexType> From<petgraph::acyclic::AcyclicEdgeError<NodeIndex<Ix>>>
for BoundedAcyclicGraphError<Ix>
{
fn from(err: petgraph::acyclic::AcyclicEdgeError<NodeIndex<Ix>>) -> Self {
Self::Acyclic(err)
}
}