如何在Rust中对自定义ArchiverError类型进行类型检查?
Rust自定义错误类型的类型判断与属性访问问题
我定义了一个带kind属性的自定义错误类型ArchiverError,并用Box<dyn Error>的形式返回它。但调用方无法判断返回的错误是否为ArchiverError类型,也没法访问它的kind属性。
自定义错误类型定义
#[derive(Debug)] struct ArchiverError { details: String, kind: ErrorKind } impl ArchiverError { fn new(foo: ErrorKind, msg: &str) -> ArchiverError { ArchiverError{details: msg.to_string(), kind: foo} } fn kind(&self) -> ErrorKind { self.kind } } impl fmt::Display for ArchiverError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f,"{}",self.details) } } impl Error for ArchiverError { fn description(&self) -> &str { &self.details } } type Result2<T> = std::result::Result<T, Box<dyn std::error::Error>>;
错误返回代码
pub fn extract_packet(buffer: &Vec<u8>, offset: &mut usize) -> Result2<RdtpPacketV1> { //let frame_delimeter = buffer_to_u32(&buffer[*offset]); let mut bytes: &[u8] = vec_to_bytes(buffer, *offset, 4); if bytes.len() == 0 { return Err(Box::new(ArchiverError::new(ErrorKind::Other,"Error: Unable to extract packet. Buffer Underrun (Frame Delimiter)"))); } // 其他逻辑... }
调用方匹配错误的代码
match extract_packet(&byte_array, &mut offset) { Ok(packet) => { let packetStartTime = Timestamp::new(packet.get_timestamp().unwrap()).to_utc_datetime(); let packetEndTime = Timestamp::new(packet.get_end_timestamp().unwrap()).to_utc_datetime(); if (packetEndTime >= start && packetStartTime < end) { packets.push(packet); } } Err(error) => { match error.downcast_ref::<ArchiverError>() { Some(ae) => { match ae.kind() { ErrorKind::Other => { break; }, ErrorKind::InvalidData => { // 继续执行 }, other_error => { break; } } }, None => break, } } }
问题原因与解决方法
- 类型可见性问题
这是最常见的原因:如果ArchiverError和ErrorKind是私有定义(默认无pub修饰),调用方所在模块无法识别该类型,导致downcast_ref返回None。
修复:
将错误类型和枚举改为公开:
#[derive(Debug, Clone, Copy)] pub enum ErrorKind { Other, InvalidData, // 其他错误变体 } #[derive(Debug)] pub struct ArchiverError { details: String, kind: ErrorKind }
- 废弃方法的兼容性问题
你实现的description方法已被Rust官方弃用,虽然不直接影响类型转换,但建议更新Errortrait的实现以符合规范:
impl std::error::Error for ArchiverError { // 移除description方法,默认会使用Display的输出 // 若需要关联底层错误,可实现source方法: // fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { // None // } }
- 确保调用方正确导入类型
调用方必须显式导入ArchiverError和ErrorKind才能识别类型:
use your_crate::ArchiverError; use your_crate::ErrorKind;
可选优化:使用downcast获取所有权
如果需要获取错误的所有权而非引用,可以改用downcast方法:
Err(error) => { match error.downcast::<ArchiverError>() { Ok(boxed_ae) => { match boxed_ae.kind() { ErrorKind::Other => break, ErrorKind::InvalidData => {}, _ => break, } }, Err(_) => break, } }
内容的提问来源于stack exchange,提问作者svenyonson
相关产品推荐
相关产品推荐

