mf_core/
error_helpers.rs

1/// 错误处理辅助工具
2///
3/// 提供便捷的方法来替换 unwrap() 调用,提供更好的错误信息和上下文
4use crate::error::{ForgeError, ForgeResult};
5
6/// 扩展 Option 和 Result 类型以提供更好的错误处理
7pub trait UnwrapHelpers<T> {
8    /// 替代 unwrap(),提供上下文信息
9    fn unwrap_or_forge_error(
10        self,
11        context: &str,
12    ) -> ForgeResult<T>;
13
14    /// 在内部错误时提供默认值
15    fn unwrap_or_internal_error(
16        self,
17        context: &str,
18        location: &str,
19    ) -> ForgeResult<T>;
20}
21
22impl<T> UnwrapHelpers<T> for Option<T> {
23    fn unwrap_or_forge_error(
24        self,
25        context: &str,
26    ) -> ForgeResult<T> {
27        self.ok_or_else(|| ForgeError::Internal {
28            message: format!("意外的 None 值: {context}"),
29            location: None,
30        })
31    }
32
33    fn unwrap_or_internal_error(
34        self,
35        context: &str,
36        location: &str,
37    ) -> ForgeResult<T> {
38        self.ok_or_else(|| ForgeError::Internal {
39            message: format!("意外的 None 值: {context}"),
40            location: Some(location.to_string()),
41        })
42    }
43}
44
45impl<T, E> UnwrapHelpers<T> for Result<T, E>
46where
47    E: std::error::Error + Send + Sync + 'static,
48{
49    fn unwrap_or_forge_error(
50        self,
51        context: &str,
52    ) -> ForgeResult<T> {
53        self.map_err(|e| ForgeError::Internal {
54            message: format!("操作失败: {context}"),
55            location: Some(e.to_string()),
56        })
57    }
58
59    fn unwrap_or_internal_error(
60        self,
61        context: &str,
62        location: &str,
63    ) -> ForgeResult<T> {
64        self.map_err(|e| ForgeError::Internal {
65            message: format!("操作失败: {context}"),
66            location: Some(format!("{location}: {e}")),
67        })
68    }
69}
70
71/// 锁操作的辅助函数
72pub mod lock_helpers {
73    use super::*;
74    use std::sync::{RwLock, Mutex};
75
76    /// 安全地获取读锁,提供错误上下文
77    pub fn read_lock<'a, T>(
78        lock: &'a RwLock<T>,
79        context: &str,
80    ) -> ForgeResult<std::sync::RwLockReadGuard<'a, T>> {
81        lock.read().map_err(|_| ForgeError::Concurrency {
82            message: format!("无法获取读锁: {context}"),
83            source: None,
84        })
85    }
86
87    /// 安全地获取写锁,提供错误上下文
88    pub fn write_lock<'a, T>(
89        lock: &'a RwLock<T>,
90        context: &str,
91    ) -> ForgeResult<std::sync::RwLockWriteGuard<'a, T>> {
92        lock.write().map_err(|_| ForgeError::Concurrency {
93            message: format!("无法获取写锁: {context}"),
94            source: None,
95        })
96    }
97
98    /// 安全地获取互斥锁,提供错误上下文
99    pub fn mutex_lock<'a, T>(
100        lock: &'a Mutex<T>,
101        context: &str,
102    ) -> ForgeResult<std::sync::MutexGuard<'a, T>> {
103        lock.lock().map_err(|_| ForgeError::Concurrency {
104            message: format!("无法获取互斥锁: {context}"),
105            source: None,
106        })
107    }
108}
109
110/// 集合操作的辅助函数
111pub mod collection_helpers {
112    use super::*;
113    use std::collections::HashMap;
114
115    /// 安全地从 HashMap 获取值
116    pub fn get_required<'a, K, V>(
117        map: &'a HashMap<K, V>,
118        key: &K,
119        context: &str,
120    ) -> ForgeResult<&'a V>
121    where
122        K: std::hash::Hash + Eq + std::fmt::Debug,
123    {
124        map.get(key).ok_or_else(|| ForgeError::Internal {
125            message: format!("必需的键不存在: {key:?} ({context})"),
126            location: None,
127        })
128    }
129
130    /// 安全地从 Vec 获取值
131    pub fn get_at_index<'a, T>(
132        vec: &'a [T],
133        index: usize,
134        context: &str,
135    ) -> ForgeResult<&'a T> {
136        vec.get(index).ok_or_else(|| ForgeError::Internal {
137            message: format!(
138                "索引 {} 超出范围,长度: {} ({})",
139                index,
140                vec.len(),
141                context
142            ),
143            location: None,
144        })
145    }
146}
147
148/// Schema 相关的辅助函数
149pub mod schema_helpers {
150    use super::*;
151    use mf_model::schema::{Schema, SchemaSpec};
152    use std::sync::Arc;
153
154    /// 安全编译 schema
155    pub fn compile_schema(
156        spec: SchemaSpec,
157        context: &str,
158    ) -> ForgeResult<Arc<Schema>> {
159        Schema::compile(spec).map(Arc::new).map_err(|e| {
160            ForgeError::Validation {
161                message: format!("Schema 编译失败: {e} ({context})"),
162                field: None,
163            }
164        })
165    }
166}
167
168/// 状态管理的辅助函数
169pub mod state_helpers {
170    use super::*;
171
172    /// 安全地获取可变状态
173    pub fn get_mut_state<'a, T>(
174        option: &'a mut Option<T>,
175        context: &str,
176    ) -> ForgeResult<&'a mut T> {
177        option.as_mut().ok_or_else(|| ForgeError::State {
178            message: format!("状态未初始化: {context}"),
179            source: None,
180        })
181    }
182
183    /// 安全地获取不可变状态
184    pub fn get_state<'a, T>(
185        option: &'a Option<T>,
186        context: &str,
187    ) -> ForgeResult<&'a T> {
188        option.as_ref().ok_or_else(|| ForgeError::State {
189            message: format!("状态未初始化: {context}"),
190            source: None,
191        })
192    }
193}
194
195#[cfg(test)]
196mod tests {
197    use super::*;
198
199    #[test]
200    fn test_option_helpers() {
201        let some_val: Option<i32> = Some(42);
202        let none_val: Option<i32> = None;
203
204        assert!(some_val.unwrap_or_forge_error("测试值").is_ok());
205        assert!(none_val.unwrap_or_forge_error("空值测试").is_err());
206    }
207
208    #[test]
209    fn test_collection_helpers() {
210        use std::collections::HashMap;
211
212        let mut map = HashMap::new();
213        map.insert("key1", "value1");
214
215        assert!(
216            collection_helpers::get_required(&map, &"key1", "存在的键").is_ok()
217        );
218        assert!(
219            collection_helpers::get_required(&map, &"key2", "不存在的键")
220                .is_err()
221        );
222    }
223}