libserialize: tuple-arity should be provided to Decoder::read_tuple
Currently `Decoder` implementations are not provided the tuple arity as a parameter to `read_tuple`. This forces all encoder/decoder combos to serialize the arity along with the elements. Tuple-arity is always known statically at the decode site, because it is part of the type of the tuple, so it could instead be provided as an argument to `read_tuple`, as it is to `read_struct`. The upside to this is that serialized tuples could become smaller in encoder/decoder implementations which choose not to serialize type (arity) information. For example, @TyOverby's [binary-encode](https://github.com/TyOverby/binary-encode) format is currently forced to serialize the tuple-arity along with every tuple, despite the information being statically known at the decode site. A downside to this change is that the tuple-arity of serialized tuples can no longer be automatically checked during deserialization. However, for formats which do serialize the tuple-arity, either explicitly (rbml) or implicitly (json), this check can be added to the `read_tuple` method. The signature of `Deserialize::read_tuple` and `Deserialize::read_tuple_struct` are changed, and thus binary backwards-compatibility is broken. This change does *not* force serialization formats to change, and thus does not break decoding values serialized prior to this change. [breaking-change]
This commit is contained in:
parent
0547a407aa
commit
ca6b082c05
3 changed files with 52 additions and 14 deletions
|
@ -2153,9 +2153,14 @@ impl ::Decoder<DecoderError> for Decoder {
|
|||
Ok(value)
|
||||
}
|
||||
|
||||
fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
|
||||
fn read_tuple<T>(&mut self, tuple_len: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
|
||||
debug!("read_tuple()");
|
||||
self.read_seq(f)
|
||||
self.read_seq(|d, len| {
|
||||
assert!(len == tuple_len,
|
||||
"expected tuple of length `{}`, found tuple \
|
||||
of length `{}`", tuple_len, len);
|
||||
f(d)
|
||||
})
|
||||
}
|
||||
|
||||
fn read_tuple_arg<T>(&mut self,
|
||||
|
@ -2167,10 +2172,11 @@ impl ::Decoder<DecoderError> for Decoder {
|
|||
|
||||
fn read_tuple_struct<T>(&mut self,
|
||||
name: &str,
|
||||
f: |&mut Decoder, uint| -> DecodeResult<T>)
|
||||
len: uint,
|
||||
f: |&mut Decoder| -> DecodeResult<T>)
|
||||
-> DecodeResult<T> {
|
||||
debug!("read_tuple_struct(name={})", name);
|
||||
self.read_tuple(f)
|
||||
self.read_tuple(len, f)
|
||||
}
|
||||
|
||||
fn read_tuple_struct_arg<T>(&mut self,
|
||||
|
@ -2872,6 +2878,26 @@ mod tests {
|
|||
assert_eq!(v, vec![vec![3], vec![1, 2]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_tuple() {
|
||||
let t: (uint, uint, uint) = super::decode("[1, 2, 3]").unwrap();
|
||||
assert_eq!(t, (1u, 2, 3))
|
||||
|
||||
let t: (uint, string::String) = super::decode("[1, \"two\"]").unwrap();
|
||||
assert_eq!(t, (1u, "two".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_tuple_malformed_types() {
|
||||
assert!(super::decode::<(uint, string::String)>("[1, 2]").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_decode_tuple_malformed_length() {
|
||||
let _ = super::decode::<(uint, uint)>("[1, 2, 3]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_object() {
|
||||
assert_eq!(from_str("{"), Err(SyntaxError(EOFWhileParsingObject, 1, 2)));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue