Skip to content

Commit 3327ecc

Browse files
committed
auto merge of #17595 : danburkert/rust/tuple-index-deserialization, r=alexcrichton
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]
2 parents 39f90ae + 05f6bda commit 3327ecc

File tree

3 files changed

+57
-14
lines changed

3 files changed

+57
-14
lines changed

src/librbml/lib.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -558,9 +558,17 @@ pub mod reader {
558558
}
559559

560560
fn read_tuple<T>(&mut self,
561-
f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>) -> DecodeResult<T> {
561+
tuple_len: uint,
562+
f: |&mut Decoder<'doc>| -> DecodeResult<T>) -> DecodeResult<T> {
562563
debug!("read_tuple()");
563-
self.read_seq(f)
564+
self.read_seq(|d, len| {
565+
if len == tuple_len {
566+
f(d)
567+
} else {
568+
Err(Expected(format!("Expected tuple of length `{}`, \
569+
found tuple of length `{}`", tuple_len, len)))
570+
}
571+
})
564572
}
565573

566574
fn read_tuple_arg<T>(&mut self, idx: uint, f: |&mut Decoder<'doc>| -> DecodeResult<T>)
@@ -571,10 +579,11 @@ pub mod reader {
571579

572580
fn read_tuple_struct<T>(&mut self,
573581
name: &str,
574-
f: |&mut Decoder<'doc>, uint| -> DecodeResult<T>)
582+
len: uint,
583+
f: |&mut Decoder<'doc>| -> DecodeResult<T>)
575584
-> DecodeResult<T> {
576585
debug!("read_tuple_struct(name={})", name);
577-
self.read_tuple(f)
586+
self.read_tuple(len, f)
578587
}
579588

580589
fn read_tuple_struct_arg<T>(&mut self,

src/libserialize/json.rs

+33-4
Original file line numberDiff line numberDiff line change
@@ -2153,9 +2153,18 @@ impl ::Decoder<DecoderError> for Decoder {
21532153
Ok(value)
21542154
}
21552155

2156-
fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
2156+
fn read_tuple<T>(&mut self,
2157+
tuple_len: uint,
2158+
f: |&mut Decoder| -> DecodeResult<T>)
2159+
-> DecodeResult<T> {
21572160
debug!("read_tuple()");
2158-
self.read_seq(f)
2161+
self.read_seq(|d, len| {
2162+
if len == tuple_len {
2163+
f(d)
2164+
} else {
2165+
Err(ExpectedError(format!("Tuple{}", tuple_len), format!("Tuple{}", len)))
2166+
}
2167+
})
21592168
}
21602169

21612170
fn read_tuple_arg<T>(&mut self,
@@ -2167,10 +2176,11 @@ impl ::Decoder<DecoderError> for Decoder {
21672176

21682177
fn read_tuple_struct<T>(&mut self,
21692178
name: &str,
2170-
f: |&mut Decoder, uint| -> DecodeResult<T>)
2179+
len: uint,
2180+
f: |&mut Decoder| -> DecodeResult<T>)
21712181
-> DecodeResult<T> {
21722182
debug!("read_tuple_struct(name={})", name);
2173-
self.read_tuple(f)
2183+
self.read_tuple(len, f)
21742184
}
21752185

21762186
fn read_tuple_struct_arg<T>(&mut self,
@@ -2872,6 +2882,25 @@ mod tests {
28722882
assert_eq!(v, vec![vec![3], vec![1, 2]]);
28732883
}
28742884

2885+
#[test]
2886+
fn test_decode_tuple() {
2887+
let t: (uint, uint, uint) = super::decode("[1, 2, 3]").unwrap();
2888+
assert_eq!(t, (1u, 2, 3))
2889+
2890+
let t: (uint, string::String) = super::decode("[1, \"two\"]").unwrap();
2891+
assert_eq!(t, (1u, "two".to_string()));
2892+
}
2893+
2894+
#[test]
2895+
fn test_decode_tuple_malformed_types() {
2896+
assert!(super::decode::<(uint, string::String)>("[1, 2]").is_err());
2897+
}
2898+
2899+
#[test]
2900+
fn test_decode_tuple_malformed_length() {
2901+
assert!(super::decode::<(uint, uint)>("[1, 2, 3]").is_err());
2902+
}
2903+
28752904
#[test]
28762905
fn test_read_object() {
28772906
assert_eq!(from_str("{"), Err(SyntaxError(EOFWhileParsingObject, 1, 2)));

src/libserialize/serialize.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,13 @@ pub trait Decoder<E> {
142142
f: |&mut Self| -> Result<T, E>)
143143
-> Result<T, E>;
144144

145-
fn read_tuple<T>(&mut self, f: |&mut Self, uint| -> Result<T, E>) -> Result<T, E>;
145+
fn read_tuple<T>(&mut self, len: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
146146
fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Self| -> Result<T, E>) -> Result<T, E>;
147147

148148
fn read_tuple_struct<T>(&mut self,
149149
s_name: &str,
150-
f: |&mut Self, uint| -> Result<T, E>)
150+
len: uint,
151+
f: |&mut Self| -> Result<T, E>)
151152
-> Result<T, E>;
152153
fn read_tuple_struct_arg<T>(&mut self,
153154
a_idx: uint,
@@ -465,20 +466,24 @@ impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Option<T> {
465466

466467
macro_rules! peel(($name:ident, $($other:ident,)*) => (tuple!($($other,)*)))
467468

469+
/// Evaluates to the number of identifiers passed to it, for example: `count_idents!(a, b, c) == 3
470+
macro_rules! count_idents {
471+
() => { 0u };
472+
($_i:ident $(, $rest:ident)*) => { 1 + count_idents!($($rest),*) }
473+
}
474+
468475
macro_rules! tuple (
469476
() => ();
470477
( $($name:ident,)+ ) => (
471478
impl<E, D:Decoder<E>,$($name:Decodable<D, E>),*> Decodable<D,E> for ($($name,)*) {
472479
#[allow(non_snake_case)]
473480
fn decode(d: &mut D) -> Result<($($name,)*), E> {
474-
d.read_tuple(|d, amt| {
481+
let len: uint = count_idents!($($name),*);
482+
d.read_tuple(len, |d| {
475483
let mut i = 0;
476484
let ret = ($(try!(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name,E> {
477485
Decodable::decode(d)
478486
})),)*);
479-
assert!(amt == i,
480-
"expected tuple of length `{}`, found tuple \
481-
of length `{}`", i, amt);
482487
return Ok(ret);
483488
})
484489
}

0 commit comments

Comments
 (0)