Skip to main content

god_graph/
errors.rs

1//! 图操作错误类型定义
2//!
3//! 提供详细的错误类型,支持错误链和上下文信息
4
5use core::fmt;
6use core::fmt::{Display, Formatter};
7
8/// 图操作结果类型别名
9pub type GraphResult<T> = Result<T, GraphError>;
10
11/// 图操作错误类型
12#[derive(Debug, Clone, PartialEq)]
13pub enum GraphError {
14    /// 节点不存在:索引无效或超出范围
15    NodeNotFound {
16        /// 导致错误的节点索引
17        index: usize,
18    },
19
20    /// 节点已删除:generation 不匹配
21    NodeDeleted {
22        /// 导致错误的节点索引
23        index: usize,
24        /// 提供的 generation
25        provided: u32,
26        /// 当前的 generation
27        current: u32,
28    },
29
30    /// 边不存在:索引无效或超出范围
31    EdgeNotFound {
32        /// 导致错误的边索引
33        index: usize,
34    },
35
36    /// 边已删除:generation 不匹配
37    EdgeDeleted {
38        /// 导致错误的边索引
39        index: usize,
40        /// 提供的 generation
41        provided: u32,
42        /// 当前的 generation
43        current: u32,
44    },
45
46    /// 边已存在:简单图不允许重边
47    EdgeAlreadyExists {
48        /// 源节点索引
49        from: usize,
50        /// 目标节点索引
51        to: usize,
52    },
53
54    /// 不允许自环
55    SelfLoopNotAllowed {
56        /// 节点索引
57        node: usize,
58    },
59
60    /// 超过最大节点容量
61    GraphCapacityExceeded {
62        /// 当前数量
63        current: usize,
64        /// 最大容量
65        max: usize,
66    },
67
68    /// 内存分配失败
69    MemoryAllocationFailed {
70        /// 请求的大小(字节)
71        requested: usize,
72    },
73
74    /// 无效的图方向操作
75    InvalidDirection,
76
77    /// 图不是有向图
78    GraphNotDirected,
79
80    /// 图不是无向图
81    GraphNotUndirected,
82
83    /// 图中存在环(用于 DAG 操作)
84    GraphHasCycle,
85
86    /// 算法不收敛
87    AlgorithmNotConverged {
88        /// 执行的迭代次数
89        iterations: usize,
90        /// 最终误差
91        error: f64,
92    },
93
94    /// 负权环检测到(Bellman-Ford)
95    NegativeCycle,
96
97    /// 负权重边检测到(Dijkstra 不支持)
98    NegativeWeight {
99        /// 源节点索引
100        from: usize,
101        /// 目标节点索引
102        to: usize,
103        /// 权重值
104        weight: f64,
105    },
106
107    /// 索引越界
108    IndexOutOfBounds {
109        /// 提供的索引
110        index: usize,
111        /// 边界
112        bound: usize,
113    },
114
115    /// 未找到资源
116    NotFound(String),
117
118    /// 无效格式
119    InvalidFormat(String),
120
121    /// IO 错误
122    IoError(String),
123}
124
125impl Display for GraphError {
126    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
127        match self {
128            GraphError::NodeNotFound { index } => {
129                write!(f, "节点不存在:索引 {} 无效或超出范围", index)
130            }
131            GraphError::NodeDeleted {
132                index,
133                provided,
134                current,
135            } => {
136                write!(
137                    f,
138                    "节点已删除:索引 {} 的 generation 不匹配 (provided: {}, current: {})",
139                    index, provided, current
140                )
141            }
142            GraphError::EdgeNotFound { index } => {
143                write!(f, "边不存在:索引 {} 无效或超出范围", index)
144            }
145            GraphError::EdgeDeleted {
146                index,
147                provided,
148                current,
149            } => {
150                write!(
151                    f,
152                    "边已删除:索引 {} 的 generation 不匹配 (provided: {}, current: {})",
153                    index, provided, current
154                )
155            }
156            GraphError::EdgeAlreadyExists { from, to } => {
157                write!(f, "边已存在:从节点 {} 到节点 {} 的边已存在", from, to)
158            }
159            GraphError::SelfLoopNotAllowed { node } => {
160                write!(f, "不允许自环:节点 {} 不能作为自身的边端点", node)
161            }
162            GraphError::GraphCapacityExceeded { current, max } => {
163                write!(f, "超过最大容量:当前 {},最大 {}", current, max)
164            }
165            GraphError::MemoryAllocationFailed { requested } => {
166                write!(f, "内存分配失败:请求 {} 字节", requested)
167            }
168            GraphError::InvalidDirection => {
169                write!(f, "无效的图方向操作")
170            }
171            GraphError::GraphNotDirected => {
172                write!(f, "图不是有向图")
173            }
174            GraphError::GraphNotUndirected => {
175                write!(f, "图不是无向图")
176            }
177            GraphError::GraphHasCycle => {
178                write!(f, "图中存在环")
179            }
180            GraphError::AlgorithmNotConverged { iterations, error } => {
181                write!(
182                    f,
183                    "算法不收敛:执行 {} 次迭代后误差为 {}",
184                    iterations, error
185                )
186            }
187            GraphError::NegativeCycle => {
188                write!(f, "检测到负权环")
189            }
190            GraphError::NegativeWeight { from, to, weight } => {
191                write!(
192                    f,
193                    "检测到负权重边:节点 {} 到 {} 的权重为 {}(Dijkstra 不支持负权重,建议使用 Bellman-Ford 算法)",
194                    from, to, weight
195                )
196            }
197            GraphError::IndexOutOfBounds { index, bound } => {
198                write!(f, "索引越界:索引 {} 超出边界 {}", index, bound)
199            }
200            GraphError::NotFound(resource) => {
201                write!(f, "未找到资源:{}", resource)
202            }
203            GraphError::InvalidFormat(msg) => {
204                write!(f, "无效格式:{}", msg)
205            }
206            GraphError::IoError(err) => {
207                write!(f, "IO 错误:{}", err)
208            }
209        }
210    }
211}
212
213#[cfg(feature = "std")]
214impl std::error::Error for GraphError {}
215
216impl From<GraphError> for String {
217    fn from(err: GraphError) -> Self {
218        err.to_string()
219    }
220}
221
222#[cfg(test)]
223mod tests {
224    use super::*;
225
226    #[test]
227    fn test_error_display() {
228        let err = GraphError::NodeNotFound { index: 42 };
229        assert!(err.to_string().contains("42"));
230
231        let err = GraphError::EdgeAlreadyExists { from: 1, to: 2 };
232        assert!(err.to_string().contains("1"));
233        assert!(err.to_string().contains("2"));
234    }
235}