Decoders return the number of bytes that they read

Closes #35
This commit is contained in:
Ty Overby 2015-05-01 09:17:18 -07:00
parent d87e7dad2d
commit 5fa0c2bd8a
5 changed files with 31 additions and 20 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "bincode" name = "bincode"
version = "0.1.3" version = "0.2.0"
authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>"] authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>"]
repository = "https://github.com/TyOverby/bincode" repository = "https://github.com/TyOverby/bincode"

View File

@ -24,7 +24,7 @@ fn main() {
// 8 bytes for the length of the vector, 4 bytes per float. // 8 bytes for the length of the vector, 4 bytes per float.
assert_eq!(encoded.len(), 8 + 4 * 4); assert_eq!(encoded.len(), 8 + 4 * 4);
let decoded: World = bincode::decode(&encoded[..]).unwrap(); let (decoded, _): (World, _) = bincode::decode(&encoded[..]).unwrap();
assert!(world == decoded); assert!(world == decoded);
} }

View File

@ -18,7 +18,7 @@
//! let limit = bincode::SizeLimit::Bounded(20); //! let limit = bincode::SizeLimit::Bounded(20);
//! //!
//! let encoded: Vec<u8> = bincode::encode(&target, limit).unwrap(); //! let encoded: Vec<u8> = bincode::encode(&target, limit).unwrap();
//! let decoded: Option<String> = bincode::decode(&encoded[..]).unwrap(); //! let (decoded, len): (Option<String>, u64) = bincode::decode(&encoded[..]).unwrap();
//! assert_eq!(target, decoded); //! assert_eq!(target, decoded);
//! } //! }
//! ``` //! ```
@ -95,9 +95,12 @@ pub fn encode<T: Encodable>(t: &T, size_limit: SizeLimit) -> EncodingResult<Vec<
/// Decodes a slice of bytes into an object. /// Decodes a slice of bytes into an object.
/// ///
/// This method does not have a size-limit because if you already have the bytes /// If successful, this function returns the decoded object along with the number
/// in memory, then you don't gain anything by having a limiter. /// of bytes that were read.
pub fn decode<T: Decodable>(b: &[u8]) -> DecodingResult<T> { ///
/// 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<T: Decodable>(b: &[u8]) -> DecodingResult<(T, u64)> {
let mut b = b; let mut b = b;
decode_from(&mut b, SizeLimit::Infinite) decode_from(&mut b, SizeLimit::Infinite)
} }
@ -125,7 +128,8 @@ pub fn encode_into<T: Encodable, W: Write>(t: &T,
t.encode(&mut writer::EncoderWriter::new(w)) 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. /// If the provided `SizeLimit` is reached, the decode will bail immediately.
/// A SizeLimit can help prevent an attacker from flooding your server with /// A SizeLimit can help prevent an attacker from flooding your server with
@ -134,8 +138,11 @@ pub fn encode_into<T: Encodable, W: Write>(t: &T,
/// If this returns an `DecodingError`, assume that the buffer that you passed /// 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 is in an invalid state, as the error could be returned during any point
/// in the reading. /// in the reading.
pub fn decode_from<R: Read, T: Decodable>(r: &mut R, size_limit: SizeLimit) -> DecodingResult<T> { pub fn decode_from<R: Read, T: Decodable>(r: &mut R, size_limit: SizeLimit) -> DecodingResult<(T, u64)> {
Decodable::decode(&mut reader::DecoderReader::new(r, size_limit)) 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))
} }

View File

@ -114,6 +114,10 @@ impl<'a, R: Read> DecoderReader<'a, R> {
read: 0 read: 0
} }
} }
pub fn bytes_read(&self) -> u64 {
self.read
}
} }
impl <'a, A> DecoderReader<'a, A> { impl <'a, A> DecoderReader<'a, A> {

View File

@ -20,14 +20,14 @@ fn the_same<V>(element: V)
let rf = RefBox::new(v); let rf = RefBox::new(v);
let encoded = encode(&rf, Infinite).unwrap(); 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 decoded.take().deref() == v
} }
let size = encoded_size(&element); let size = encoded_size(&element);
let encoded = encode(&element, Infinite).unwrap(); let encoded = encode(&element, Infinite).unwrap();
let decoded = decode(&encoded[..]).unwrap(); let (decoded, _) = decode(&encoded[..]).unwrap();
assert!(element == decoded); assert!(element == decoded);
assert!(size == encoded.len() as u64); assert!(size == encoded.len() as u64);
assert!(ref_box_correct(&element)) assert!(ref_box_correct(&element))
@ -206,12 +206,12 @@ fn decoding_errors() {
fn too_big_decode() { fn too_big_decode() {
let encoded = vec![0,0,0,3]; let encoded = vec![0,0,0,3];
let mut encoded_ref = &encoded[..]; let mut encoded_ref = &encoded[..];
let decoded: Result<u32, _> = decode_from(&mut encoded_ref, Bounded(3)); let decoded: Result<(u32, _), _> = decode_from(&mut encoded_ref, Bounded(3));
assert!(decoded.is_err()); assert!(decoded.is_err());
let encoded = vec![0,0,0,3]; let encoded = vec![0,0,0,3];
let mut encoded_ref = &encoded[..]; let mut encoded_ref = &encoded[..];
let decoded: Result<u32, _> = decode_from(&mut encoded_ref, Bounded(4)); let decoded: Result<(u32, _), _> = decode_from(&mut encoded_ref, Bounded(4));
assert!(decoded.is_ok()); assert!(decoded.is_ok());
} }
@ -219,9 +219,9 @@ fn too_big_decode() {
fn too_big_char_decode() { fn too_big_char_decode() {
let encoded = vec![0x41]; let encoded = vec![0x41];
let mut encoded_ref = &encoded[..]; let mut encoded_ref = &encoded[..];
let decoded: Result<char, _> = decode_from(&mut encoded_ref, Bounded(1)); let decoded: Result<(char, _), _> = decode_from(&mut encoded_ref, Bounded(1));
assert!(decoded.is_ok()); assert!(decoded.is_ok());
assert_eq!(decoded.unwrap(), 'A'); assert_eq!(decoded.unwrap().0, 'A');
} }
#[test] #[test]
@ -268,9 +268,9 @@ fn test_refbox() {
// Test 1 // Test 1
{ {
let encoded = encode(&Message::M1(RefBox::new(&large_object)), Infinite).unwrap(); 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), Message::M1(b) => assert!(b.take().deref() == &large_object),
_ => assert!(false) _ => assert!(false)
} }
@ -279,9 +279,9 @@ fn test_refbox() {
// Test 2 // Test 2
{ {
let encoded = encode(&Message::M2(RefBox::new(&large_map)), Infinite).unwrap(); 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), Message::M2(b) => assert!(b.take().deref() == &large_map),
_ => assert!(false) _ => assert!(false)
} }