From 5fa0c2bd8afca94061e1bb6d3d3e956da0dd331c Mon Sep 17 00:00:00 2001 From: Ty Overby Date: Fri, 1 May 2015 09:17:18 -0700 Subject: [PATCH] Decoders return the number of bytes that they read Closes #35 --- Cargo.toml | 2 +- examples/basic.rs | 2 +- src/lib.rs | 23 +++++++++++++++-------- src/reader.rs | 4 ++++ src/test.rs | 20 ++++++++++---------- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e7f9e99..6ff47d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bincode" -version = "0.1.3" +version = "0.2.0" authors = ["Ty Overby ", "Francesco Mazzoli "] repository = "https://github.com/TyOverby/bincode" diff --git a/examples/basic.rs b/examples/basic.rs index 66972cb..f7f7eec 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -24,7 +24,7 @@ fn main() { // 8 bytes for the length of the vector, 4 bytes per float. assert_eq!(encoded.len(), 8 + 4 * 4); - let decoded: World = bincode::decode(&encoded[..]).unwrap(); + let (decoded, _): (World, _) = bincode::decode(&encoded[..]).unwrap(); assert!(world == decoded); } diff --git a/src/lib.rs b/src/lib.rs index c17057b..ba4bbbe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,8 +17,8 @@ //! // The maximum size of the encoded message. //! let limit = bincode::SizeLimit::Bounded(20); //! -//! let encoded: Vec = bincode::encode(&target, limit).unwrap(); -//! let decoded: Option = bincode::decode(&encoded[..]).unwrap(); +//! let encoded: Vec = bincode::encode(&target, limit).unwrap(); +//! let (decoded, len): (Option, u64) = bincode::decode(&encoded[..]).unwrap(); //! assert_eq!(target, decoded); //! } //! ``` @@ -95,9 +95,12 @@ pub fn encode(t: &T, size_limit: SizeLimit) -> EncodingResult(b: &[u8]) -> DecodingResult { +/// If successful, this function returns the decoded object along with the number +/// of bytes that were read. +/// +/// This method does not have a size-limit because with all the bytes contiguous +/// in memory, then nothing is gained by having a limiter. +pub fn decode(b: &[u8]) -> DecodingResult<(T, u64)> { let mut b = b; decode_from(&mut b, SizeLimit::Infinite) } @@ -125,7 +128,8 @@ pub fn encode_into(t: &T, t.encode(&mut writer::EncoderWriter::new(w)) } -/// Decoes an object directly from a `Buffer`ed Reader. +/// Decodes an object directly from a `Read`er. If successful, returns the +/// decoded object and the number of bytes read out of the `Read`er. /// /// If the provided `SizeLimit` is reached, the decode will bail immediately. /// A SizeLimit can help prevent an attacker from flooding your server with @@ -134,8 +138,11 @@ pub fn encode_into(t: &T, /// If this returns an `DecodingError`, assume that the buffer that you passed /// in is in an invalid state, as the error could be returned during any point /// in the reading. -pub fn decode_from(r: &mut R, size_limit: SizeLimit) -> DecodingResult { - Decodable::decode(&mut reader::DecoderReader::new(r, size_limit)) +pub fn decode_from(r: &mut R, size_limit: SizeLimit) -> DecodingResult<(T, u64)> { + let mut decoder_reader = reader::DecoderReader::new(r, size_limit); + let value = try!(Decodable::decode(&mut decoder_reader)); + let bytes_read = decoder_reader.bytes_read(); + Ok((value, bytes_read)) } diff --git a/src/reader.rs b/src/reader.rs index fbc95aa..52d4e9c 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -114,6 +114,10 @@ impl<'a, R: Read> DecoderReader<'a, R> { read: 0 } } + + pub fn bytes_read(&self) -> u64 { + self.read + } } impl <'a, A> DecoderReader<'a, A> { diff --git a/src/test.rs b/src/test.rs index daa4dd2..e05ac8c 100644 --- a/src/test.rs +++ b/src/test.rs @@ -20,14 +20,14 @@ fn the_same(element: V) let rf = RefBox::new(v); let encoded = encode(&rf, Infinite).unwrap(); - let decoded: RefBox<'static, V> = decode(&encoded[..]).unwrap(); + let (decoded, _): (RefBox<'static, V>, _) = decode(&encoded[..]).unwrap(); decoded.take().deref() == v } let size = encoded_size(&element); let encoded = encode(&element, Infinite).unwrap(); - let decoded = decode(&encoded[..]).unwrap(); + let (decoded, _) = decode(&encoded[..]).unwrap(); assert!(element == decoded); assert!(size == encoded.len() as u64); assert!(ref_box_correct(&element)) @@ -206,12 +206,12 @@ fn decoding_errors() { fn too_big_decode() { let encoded = vec![0,0,0,3]; let mut encoded_ref = &encoded[..]; - let decoded: Result = decode_from(&mut encoded_ref, Bounded(3)); + let decoded: Result<(u32, _), _> = decode_from(&mut encoded_ref, Bounded(3)); assert!(decoded.is_err()); let encoded = vec![0,0,0,3]; let mut encoded_ref = &encoded[..]; - let decoded: Result = decode_from(&mut encoded_ref, Bounded(4)); + let decoded: Result<(u32, _), _> = decode_from(&mut encoded_ref, Bounded(4)); assert!(decoded.is_ok()); } @@ -219,9 +219,9 @@ fn too_big_decode() { fn too_big_char_decode() { let encoded = vec![0x41]; let mut encoded_ref = &encoded[..]; - let decoded: Result = decode_from(&mut encoded_ref, Bounded(1)); + let decoded: Result<(char, _), _> = decode_from(&mut encoded_ref, Bounded(1)); assert!(decoded.is_ok()); - assert_eq!(decoded.unwrap(), 'A'); + assert_eq!(decoded.unwrap().0, 'A'); } #[test] @@ -268,9 +268,9 @@ fn test_refbox() { // Test 1 { let encoded = encode(&Message::M1(RefBox::new(&large_object)), Infinite).unwrap(); - let decoded: Message<'static> = decode(&encoded[..]).unwrap(); + let decoded: (Message<'static>, _) = decode(&encoded[..]).unwrap(); - match decoded { + match decoded.0 { Message::M1(b) => assert!(b.take().deref() == &large_object), _ => assert!(false) } @@ -279,9 +279,9 @@ fn test_refbox() { // Test 2 { let encoded = encode(&Message::M2(RefBox::new(&large_map)), Infinite).unwrap(); - let decoded: Message<'static> = decode(&encoded[..]).unwrap(); + let decoded: (Message<'static>, _) = decode(&encoded[..]).unwrap(); - match decoded { + match decoded.0 { Message::M2(b) => assert!(b.take().deref() == &large_map), _ => assert!(false) }