You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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,
        }
    }
}

问题原因与解决方法

  1. 类型可见性问题
    这是最常见的原因:如果ArchiverError和ErrorKind是私有定义(默认无pub修饰),调用方所在模块无法识别该类型,导致downcast_ref返回None。

修复:
将错误类型和枚举改为公开:

#[derive(Debug, Clone, Copy)]
pub enum ErrorKind {
    Other,
    InvalidData,
    // 其他错误变体
}

#[derive(Debug)]
pub struct ArchiverError {
    details: String,
    kind: ErrorKind
}
  1. 废弃方法的兼容性问题
    你实现的description方法已被Rust官方弃用,虽然不直接影响类型转换,但建议更新Error trait的实现以符合规范:
impl std::error::Error for ArchiverError {
    // 移除description方法,默认会使用Display的输出
    // 若需要关联底层错误,可实现source方法:
    // fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
    //     None
    // }
}
  1. 确保调用方正确导入类型
    调用方必须显式导入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 15:42:30