创建新错误时重复使用现有错误的描述

Reuse the description of an existing Error when creating a new Error

我在 Rust 中有以下代码,它无法编译,但显示了我想做的事情的意图。

    pub fn parse(cursor: &mut io::Cursor<&[u8]>) -> io::Result<Ack> {
        use self::byteorder::{BigEndian, ReadBytesExt};
        use self::core::error::Error;

        match cursor.read_u16::<BigEndian>() {
            Err(byteorder::Error::Io(error)) => Err(error),
            Err(error) =>
                Err(io::Error::new(io::ErrorKind::Other, error.description(),
                                   None)),
            Ok(value) => Ok(Ack { block_number: value })
        }
    }

本质上,我想获取字节顺序库返回的错误的错误描述,并使用它来创建错误描述,我将传回给我的库的用户。这失败了 packets.rs:166:58: 166:63 error: 错误 does not live long enough,我明白为什么。

byteorder 库通过在 byteorder::Error::Io 构造函数中包装 std::io::Result 解决了这个问题。但是,我不想走这条路,因为我必须定义自己的错误类型来包装 std::io::Errorbyteorder::Error。在我看来,我的用户不应该知道或关心我使用字节顺序库,它不应该成为我界面的一部分。

我是 Rust 新手,还不知道语言和设计的惯用语和最佳实践。我有什么选择来处理这个问题?

我无法测试您的代码,所以无法确定。 ref 关键字还不够吗?

Err(byteorder::Error::Io(ref error)) => Err(error),

你的问题实际上是 io::Error::new()'s second parameter is &'static str, while byteorder::Error::description() returns a &'a str 其中 'a 是错误对象本身的生命周期,它小于 'static .因此,您不能将其用于 io::Error 的描述。

最简单的修复方法是将 byteorder::Error 描述移动到 io::Errordetail 字段:

Err(error) =>
    Err(io::Error::new(
        io::ErrorKind::Other,
        "byteorder error",
        Some(error.description().to_string())
    )),

但是,您应该认真考虑制作一个自定义包装器错误类型来封装所有 "downstream" 错误。使用正确编写的 FromError 实例,您应该能够编写类似

的内容
try!(cursor.read_u16::<BigEndian>()
    .map(|value| Ack { block_number: value }))

而不是你的整场比赛。当您的程序增长并且出现更多 "downstream" 错误源时,自定义错误包装器也会帮助您 - 您可以添加新的枚举变体 and/or FromError 实现来支持这些新错误。