Closed
Description
Decoding can fail in the same way as any IO operation or any read_xxx()
function in trait Reader
. So should the serialize::Decodable
trait, no? Otherwise, we again depend on using task::try
for decoding data structures.
My proposal is to change the signature of trait Decodable
to something like:
pub type DecodeResult<T> = Result<T, &str>;
pub trait Decodable<D: Decoder> {
fn decode(d: &mut D) -> DecodeResult<Self>;
}
Likewise, the trait serialize::Decoder
must be changed to return DecodeResult
s as well.
This of course comes with a slight performance penalty in the non-error case.
Metadata
Metadata
Assignees
Labels
No labels
Activity
mneumann commentedon Feb 15, 2014
I am volunteering to provide a patch (as I am also working on the rust-msgpack and rust-toml libraries, which needs to be changed as well), if we can agree upon a
DecodeResult
type (is&str
enough?).huonw commentedon Feb 15, 2014
It seems like Encodable should do something similar if we do do this.
mneumann commentedon Feb 15, 2014
Yes, so in case the underlying Encoder fails with an IoError, we can propagate it back. The big question is only, what will the type of EncodeResult/DecodeResult be?
mneumann commentedon Feb 15, 2014
For performance reasons, I don't like to bloat up the return values of each
read_xxx
method very much. Especially as errors are very rare, so I'd prefer something likewhich would only add one extra word (but of course incurrs an allocation in the error case).
mneumann commentedon Feb 15, 2014
As the underlying error can be manifold (it can be an IoError or a protocol error), it would be better to just signal an error condition, and being able to retrieve the exact error condition (e.g. the IoError) from the Decoder or Encoder struct. Also the error heavily depends on the underlying Encoder/Decoder. For example a Decoder which is based on a MemReader would not need an IoError.
wycats commentedon Mar 7, 2014
I agree with this. I was implementing a Decoder and the only real way to propagate errors at the moment is to store the error information in the Decoder and move on. However, this means you're forced to continue parsing a source that you already know is invalid (or explicitly handle this in
read_struct_field
).In my experience so far, IoError is actually not the predominant kind of error. Instead, a common problem is that the struct indicates that it wants a uint but the source gave you a string.
For example, if you had a struct like this:
struct Article { title: ~str, body: ~str }
and you were deserializing a JSON like:{ "title": 1 }
, you would have two errors (missing a mandatorybody
field and incorrect type provided fortitle
).These kinds of errors need to be handled by virtually all decoders, and should be supported out of the box rather than requiring an error field in the struct plus extra work in the handlers.
Also, the current approach requires each of the handlers to still return a dummy value (
0
foruint
, for example), even though there was no actual value in the source. This is a lot of overhead when building a Decoder that could be eliminated by allowing aResult
to be returned.arjantop commentedon Mar 11, 2014
Every encoder/decoder will deal with errors differently so my suggestion is to change traits to this:
erickt commentedon Mar 11, 2014
I feel @arjantop's solution is the right one. We'll need some way of communicating malformed values. The excess typarams is a bit of a shame though. I long for the day associated types (#5033) gets implemented.
arjantop commentedon Mar 12, 2014
The other solution would be using IoResult but i'm not convinced it's the right type for this. I think custom types with apropriate error information are the best way. For decoding only EndOfFile, InvalidInput and OtherIoError are useful and any error information must be included in message string.
9 remaining items