Reputation:
I have the following code in Rust, which does not compile, but shows the intent of what I'd like to do.
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 })
}
}
Essentially, I want to take the error description of an error returned by the byteorder library and use it to create the description of an error I'll pass back to the user of my library. This fails with packets.rs:166:58: 166:63 error:
errordoes not live long enough
, and I understand why.
The byteorder library solves this issue by wrapping an std::io::Result
in the byteorder::Error::Io
constructor. However, I don't want to take this route because I'd have to define my own error type that wraps either an std::io::Error
or a byteorder::Error
. It seems to me that my users shouldn't know or care that I use the byteorder library, and it shouldn't be part of my interface.
I'm a Rust newbie and don't yet know the idioms and best practices of the language and design. What are my options for dealing with this?
Upvotes: 4
Views: 251
Reputation: 128161
Your problem is in fact in that io::Error::new()
's second parameter is &'static str
, while byteorder::Error::description()
returns a &'a str
where 'a
is lifetime of the error object itself which is less than 'static
. Hence you can't use it for io::Error
's description.
The simplest fix would be moving byteorder::Error
description to detail
field of io::Error
:
Err(error) =>
Err(io::Error::new(
io::ErrorKind::Other,
"byteorder error",
Some(error.description().to_string())
)),
However, you should seriously consider making a custom wrapper error type which encapsulates all "downstream" errors. With properly written FromError
instances you should be able to write something like
try!(cursor.read_u16::<BigEndian>()
.map(|value| Ack { block_number: value }))
instead of your whole match. Custom error wrappers will also help you when your program grows and more "downstream" error sources appear - you could just add new enum variants and/or FromError
implementations to support these new errors.
Upvotes: 1
Reputation: 1562
I cannot test your code so I can't be sure. Isn't the ref keyword enough?
Err(byteorder::Error::Io(ref error)) => Err(error),
Upvotes: 0