Tokio: std::io::Error → tokio::io::Error conversion

Created on 24 Sep 2020  Â·  3Comments  Â·  Source: tokio-rs/tokio

I've recently tried to implement streaming a multipart file to S3 using rust-s3 without having to keep the full file in memory or on disk.

let field: actix_multipart::Field = …;

let payload_stream = field.map_err(|e| {
    TokioIoError::new(multipart_error_to_tokio_io_error_kind(&e), anyhow!(e))
});
let mut payload_reader = tokio::io::stream_reader(payload_stream);

bucket
    .tokio_put_object_stream(&mut payload_reader, &upload_path)
    .await?;

For this to compile (it actually working is blocked on https://github.com/durch/rust-s3/issues/110) I needed some long-winded error conversion code:

fn multipart_error_to_tokio_io_error_kind(e: &MultipartError) -> TokioIoErrorKind {
    match e {
        MultipartError::Payload(p) => match p {
            PayloadError::Incomplete(_) => TokioIoErrorKind::UnexpectedEof,
            PayloadError::Io(io) => std_io_error_kind_to_tokio_io_error_kind(io.kind()),
            PayloadError::Http2Payload(h2) => match h2.get_io() {
                Some(io) => std_io_error_kind_to_tokio_io_error_kind(io.kind()),
                None => TokioIoErrorKind::Other,
            },
            _ => TokioIoErrorKind::Other,
        },
        _ => TokioIoErrorKind::Other,
    }
}

fn std_io_error_kind_to_tokio_io_error_kind(kind: StdIoErrorKind) -> TokioIoErrorKind {
    match kind {
        StdIoErrorKind::NotFound => TokioIoErrorKind::NotFound,
        StdIoErrorKind::PermissionDenied => TokioIoErrorKind::PermissionDenied,
        StdIoErrorKind::ConnectionRefused => TokioIoErrorKind::ConnectionRefused,
        StdIoErrorKind::ConnectionReset => TokioIoErrorKind::ConnectionReset,
        StdIoErrorKind::ConnectionAborted => TokioIoErrorKind::ConnectionAborted,
        StdIoErrorKind::NotConnected => TokioIoErrorKind::NotConnected,
        StdIoErrorKind::AddrInUse => TokioIoErrorKind::AddrInUse,
        StdIoErrorKind::AddrNotAvailable => TokioIoErrorKind::AddrNotAvailable,
        StdIoErrorKind::BrokenPipe => TokioIoErrorKind::BrokenPipe,
        StdIoErrorKind::AlreadyExists => TokioIoErrorKind::AlreadyExists,
        StdIoErrorKind::WouldBlock => TokioIoErrorKind::WouldBlock,
        StdIoErrorKind::InvalidInput => TokioIoErrorKind::InvalidInput,
        StdIoErrorKind::InvalidData => TokioIoErrorKind::InvalidData,
        StdIoErrorKind::TimedOut => TokioIoErrorKind::TimedOut,
        StdIoErrorKind::WriteZero => TokioIoErrorKind::WriteZero,
        StdIoErrorKind::Interrupted => TokioIoErrorKind::Interrupted,
        StdIoErrorKind::UnexpectedEof => TokioIoErrorKind::UnexpectedEof,
        _ => TokioIoErrorKind::Other,
    }
}

It seems to me like the second function, or sth. better, could just be part of tokio so I wouldn't have to write all of this myself.

Describe the solution you'd like

// in tokio::io
impl From<std::io::Error> for Error { ... }

Describe alternatives you've considered

I'm not actually sure I need all of this error conversion, but it seems like I'm setting myself up for hard to debug errors by just mapping everything to TokioIoErrorKind::Other. I've also looked into not using stream_reader, but haven't found an alternative that would work here. Any tips in that direction would be appreciated, separately from this feature request :slightly_smiling_face:

A-tokio C-question M-io

Most helpful comment

https://docs.rs/tokio/0.2.22/tokio/io/index.html#std-re-exports

std re-exports

Additionally, Error, ErrorKind, and Result are re-exported from std::io for ease of use.

All 3 comments

Tokio's io::Error is std's io::Error: https://docs.rs/tokio/0.2.22/src/tokio/io/mod.rs.html#239.

Oh. Well, seems like I wrote some quite stupid code. Is this documented anywhere?

https://docs.rs/tokio/0.2.22/tokio/io/index.html#std-re-exports

std re-exports

Additionally, Error, ErrorKind, and Result are re-exported from std::io for ease of use.

Was this page helpful?
0 / 5 - 0 ratings