在实现std :: io :: Write时处理非std :: io :: Error(s)?

时间:2018-01-21 15:09:13

标签: error-handling rust

我正在尝试通过HTTP实现std::io::Write,而我不确定如何处理std::io::ErrorKind中没有对应项的错误。

这是一个简短的复制品:

extern crate reqwest;

use std::io::Write;
use std::io::Result;

struct HttpClient {
    // Some configurations (compression, certificates, timeouts)
}

impl Write for HttpClient {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        let client = ::reqwest::Client::builder().build()?;
        let res = client.post("http://httpbin.org/post").body(buf).send()?;
        Ok(buf.len())
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

编译器响应2个错误:

error[E0277]: the trait bound `std::io::Error: std::convert::From<reqwest::Error>` is not satisfied
  --> src/main.rs:12:22
   |
12 |         let client = ::reqwest::Client::builder().build()?;
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<reqwest::Error>` is not implemented for `std::io::Error`
   |
   = help: the following implementations were found:
             <std::io::Error as std::convert::From<std::io::ErrorKind>>
             <std::io::Error as std::convert::From<std::ffi::NulError>>
             <std::io::Error as std::convert::From<std::io::IntoInnerError<W>>>
             <std::io::Error as std::convert::From<serde_json::error::Error>>
             <std::io::Error as std::convert::From<openssl::error::ErrorStack>>
   = note: required by `std::convert::From::from`

error[E0277]: the trait bound `std::io::Error: std::convert::From<reqwest::Error>` is not satisfied
  --> src/main.rs:13:19
   |
13 |         let res = client.post("http://httpbin.org/post").body(buf).send()?;
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<reqwest::Error>` is not implemented for `std::io::Error`
   |
   = help: the following implementations were found:
             <std::io::Error as std::convert::From<std::io::ErrorKind>>
             <std::io::Error as std::convert::From<std::ffi::NulError>>
             <std::io::Error as std::convert::From<std::io::IntoInnerError<W>>>
             <std::io::Error as std::convert::From<serde_json::error::Error>>
             <std::io::Error as std::convert::From<openssl::error::ErrorStack>>
   = note: required by `std::convert::From::from`

我可以做几件事,但我对其中任何一件都不满意:

  1. 使用map_errreqwest::Error映射到std::io::Error - 这并不总是微不足道的。例如,我如何映射TooManyRedirects?我可以使用std::io::ErrorKind::Other,但感觉不对。

  2. 定义我自己的错误类型MyError,并为std::convert::Fromreqwest::Error以及MyErrorMyError实施std::io::Error - 此从以前提出同样的担忧 - 并非所有错误都可以轻易兑换。

  3. 这里还有其他更好的选择吗?

1 个答案:

答案 0 :(得分:1)

使用io::Error是您可以执行的唯一事情,因为这是特征所需的合同。其他一切都归结为细节和人体工程学。

io::Error::new接受io::ErrorKind和可以转换为error::Error的内容。

我可能会编写一个函数,通过调用io::Error将您的域错误转换为io::Error::new,然后在map_err处使用此新函数。我首先将所有内容都塞进ErrorKind::Other,直到找到一个特定的Reqwest错误应该是其他原因的原因。

您的消费者是否真的关心某些特别是重定向过多的内容?通过构造,答案必须为“否”,因为它们可能在FileTcpSocket上运行,两者都没有这样的概念。

我不相信在这种情况下我会创建一个包装错误类型;我看不出它会如何提供任何价值。它需要额外的类型注释,你可以通过函数“免费”获得。

  

这并非总是微不足道。

这是正确的 - 将两个截然不同的部分胶合在一起有时并不完全符合我们想要的方式。这是使编程既令人兴奋又可怕的部分原因。