1use alloc::string::String;
2use core::fmt;
3
4use crate::id::{EdgeId, NodeId, PortId};
5
6#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum GraphError {
9 EmptyPortId,
10 EmptyTypeTag,
11 NodeNotFound(NodeId),
12 EdgeNotFound(EdgeId),
13 PortNotFound {
14 node: NodeId,
15 port: PortId,
16 },
17 DuplicatePort(PortId),
18 PortDirectionMismatch,
19 TypeTagMismatch {
20 expected: String,
21 actual: String,
22 },
23 SelfLoop,
24 DuplicateEdge,
25 #[cfg(feature = "json")]
26 Json(neco_json::AccessError),
27}
28
29impl fmt::Display for GraphError {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 Self::EmptyPortId => f.write_str("port id must not be empty"),
33 Self::EmptyTypeTag => f.write_str("port type_tag must not be empty"),
34 Self::NodeNotFound(id) => write!(f, "node {id} not found"),
35 Self::EdgeNotFound(id) => write!(f, "edge {id} not found"),
36 Self::PortNotFound { node, port } => {
37 write!(f, "port {port} not found on node {node}")
38 }
39 Self::DuplicatePort(port) => write!(f, "duplicate port id {port}"),
40 Self::PortDirectionMismatch => {
41 f.write_str("edge endpoints must connect output to input")
42 }
43 Self::TypeTagMismatch { expected, actual } => {
44 write!(f, "port type mismatch: expected {expected}, got {actual}")
45 }
46 Self::SelfLoop => f.write_str("self-loop edges are not allowed"),
47 Self::DuplicateEdge => f.write_str("duplicate edge is not allowed"),
48 #[cfg(feature = "json")]
49 Self::Json(error) => write!(f, "json access error: {error}"),
50 }
51 }
52}
53
54impl core::error::Error for GraphError {
55 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
56 match self {
57 #[cfg(feature = "json")]
58 Self::Json(error) => Some(error),
59 _ => None,
60 }
61 }
62}
63
64#[cfg(feature = "json")]
65impl From<neco_json::AccessError> for GraphError {
66 fn from(value: neco_json::AccessError) -> Self {
67 Self::Json(value)
68 }
69}