libserialize: add error() to Decoder

A quick and dirty fix for #15036 until we get serious decoder reform.

Right now it is impossible for a Decodable to signal a decode error,
for example if it has only finitely many allowed values, is a string
which must be encoded a certain way, needs a valid checksum, etc. For
example in the libuuid implementation of Decodable an Option is
unwrapped, meaning that a decode of a malformed UUID will cause the
task to fail.

Since this adds a method to the `Decoder` trait, all users will need
to update their implementations to add it. The strategy used for the
current implementations for JSON and EBML is to add a new entry to
the error enum `ApplicationError(String)` which stores the string
provided to `.error()`.

[breaking-change]
This commit is contained in:
Andrew Poelstra 2014-07-30 19:35:32 -07:00
parent b495933a7f
commit 5bd8edc112
3 changed files with 19 additions and 6 deletions

View File

@ -105,7 +105,8 @@ pub enum EbmlEncoderTag {
pub enum Error { pub enum Error {
IntTooBig(uint), IntTooBig(uint),
Expected(String), Expected(String),
IoError(std::io::IoError) IoError(std::io::IoError),
ApplicationError(String)
} }
// -------------------------------------- // --------------------------------------
@ -119,11 +120,11 @@ pub mod reader {
use serialize; use serialize;
use super::{ EsVec, EsMap, EsEnum, EsVecLen, EsVecElt, EsMapLen, EsMapKey, use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsVecLen, EsVecElt,
EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64, EsI32, EsI16, EsI8, EsMapLen, EsMapKey, EsEnumVid, EsU64, EsU32, EsU16, EsU8, EsInt, EsI64,
EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, EsEnumBody, EsUint, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal,
EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc, Error, IntTooBig, EsEnumBody, EsUint, EsOpaque, EsLabel, EbmlEncoderTag, Doc, TaggedDoc,
Expected }; Error, IntTooBig, Expected };
pub type DecodeResult<T> = Result<T, Error>; pub type DecodeResult<T> = Result<T, Error>;
// rbml reading // rbml reading
@ -636,6 +637,10 @@ pub mod reader {
debug!("read_map_elt_val(idx={})", idx); debug!("read_map_elt_val(idx={})", idx);
self.push_doc(EsMapVal, f) self.push_doc(EsMapVal, f)
} }
fn error(&mut self, err: &str) -> Error {
ApplicationError(err.to_string())
}
} }
} }

View File

@ -257,6 +257,7 @@ pub enum DecoderError {
ExpectedError(String, String), ExpectedError(String, String),
MissingFieldError(String), MissingFieldError(String),
UnknownVariantError(String), UnknownVariantError(String),
ApplicationError(String)
} }
/// Returns a readable error string for a given error code. /// Returns a readable error string for a given error code.
@ -2071,6 +2072,10 @@ impl ::Decoder<DecoderError> for Decoder {
debug!("read_map_elt_val(idx={})", idx); debug!("read_map_elt_val(idx={})", idx);
f(self) f(self)
} }
fn error(&mut self, err: &str) -> DecoderError {
ApplicationError(err.to_string())
}
} }
/// A trait for converting values to JSON /// A trait for converting values to JSON

View File

@ -163,6 +163,9 @@ pub trait Decoder<E> {
fn read_map<T>(&mut self, f: |&mut Self, uint| -> Result<T, E>) -> Result<T, E>; fn read_map<T>(&mut self, f: |&mut Self, uint| -> Result<T, E>) -> Result<T, E>;
fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>; fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>; fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
// Failure
fn error(&mut self, err: &str) -> E;
} }
pub trait Encodable<S:Encoder<E>, E> { pub trait Encodable<S:Encoder<E>, E> {