From c7ed0e106c3e86583f07df63d7e114056c491c77 Mon Sep 17 00:00:00 2001 From: Ty Overby Date: Thu, 8 Jan 2015 23:25:02 -0800 Subject: [PATCH] `decode` takes a slice rather than a vec. Also added comments for the main functions. --- examples/basic.rs | 4 +++- src/lib.rs | 29 ++++++++++++++++++++++------- src/test.rs | 20 ++++++++++++-------- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/examples/basic.rs b/examples/basic.rs index a08d3a2..1b5df8d 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -20,9 +20,11 @@ fn main() { }; let encoded: Vec = bincode::encode(&world, SizeLimit::Infinite).unwrap(); + // 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, SizeLimit::Infinite).unwrap(); + + let decoded: World = bincode::decode(encoded.as_slice()).unwrap(); assert!(world == decoded); } diff --git a/src/lib.rs b/src/lib.rs index 3903d3f..630968b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ extern crate "rustc-serialize" as rustc_serialize; -use std::io::{Buffer, MemWriter, MemReader}; +use std::io::{Buffer, MemWriter}; use rustc_serialize::{Encodable, Decodable}; pub use writer::{EncoderWriter, EncodingResult, EncodingError}; @@ -13,6 +13,7 @@ use writer::SizeChecker; mod writer; mod reader; +#[cfg(test)] mod test; #[derive(Clone, Copy)] pub enum SizeLimit { @@ -20,6 +21,10 @@ pub enum SizeLimit { UpperBound(u64) } +/// Encodes an encodable object into a `Vec` of bytes. +/// +/// If the encoding would take more bytes than allowed by `size_limit`, +/// an error is returned. pub fn encode(t: &T, size_limit: SizeLimit) -> EncodingResult> { let mut w = MemWriter::new(); match encode_into(t, &mut w, size_limit) { @@ -28,10 +33,16 @@ pub fn encode(t: &T, size_limit: SizeLimit) -> EncodingResult(b: Vec, size_limit: SizeLimit) -> DecodingResult { - decode_from(&mut MemReader::new(b), size_limit) +/// Decodes a slice of bytes into an object. +pub fn decode(b: &[u8]) -> DecodingResult { + let mut b = b; + decode_from(&mut b, SizeLimit::Infinite) } +/// Encodes an object directly into a `Writer`. +/// +/// If the encoding would take more bytes than allowed by `size_limit`, an error +/// is returned and *no bytes* will be written into the `Writer`. pub fn encode_into(t: &T, w: &mut W, size_limit: SizeLimit) -> EncodingResult<()> { try!(match size_limit { SizeLimit::Infinite => Ok(()), @@ -40,12 +51,16 @@ pub fn encode_into(t: &T, w: &mut W, size_limit: SizeLi t.encode(&mut size_checker) } }); + t.encode(&mut writer::EncoderWriter::new(w, size_limit)) } -pub fn decode_from(r: &mut R, size_limit: SizeLimit) -> DecodingResult { +/// Decoes an object directly from a Buffered Reader. +/// +/// If the provided `SizeLimit` is reached, the decode will bail immediately. +/// A SizeLimit can help prevent an attacker from flooding your server with +/// a neverending stream of values that runs your server out of memory. +pub fn decode_from(r: &mut R, size_limit: SizeLimit) -> +DecodingResult { Decodable::decode(&mut reader::DecoderReader::new(r, size_limit)) } - -#[cfg(test)] -mod test; diff --git a/src/test.rs b/src/test.rs index 96024f9..ef18a79 100644 --- a/src/test.rs +++ b/src/test.rs @@ -13,13 +13,14 @@ use rustc_serialize::{ use super::{ encode, decode, + decode_from, DecodingError, DecodingResult }; use super::SizeLimit::{Infinite, UpperBound}; fn the_same<'a, V>(element: V) where V: Encodable, V: Decodable, V: PartialEq, V: Show { - assert!(element == decode(encode(&element, Infinite).unwrap(), Infinite).unwrap()); + assert!(element == decode(encode(&element, Infinite).unwrap().as_slice()).unwrap()); } #[test] @@ -178,33 +179,36 @@ fn is_invalid_bytes(res: DecodingResult) { #[test] fn decoding_errors() { - is_invalid_bytes(decode::(vec![0xA], Infinite)); - is_invalid_bytes(decode::(vec![0, 0, 0, 0, 0, 0, 0, 1, 0xFF], Infinite)); + is_invalid_bytes(decode::(vec![0xA].as_slice())); + is_invalid_bytes(decode::(vec![0, 0, 0, 0, 0, 0, 0, 1, 0xFF].as_slice())); // Out-of-bounds variant #[derive(RustcEncodable, RustcDecodable)] enum Test { One, Two, }; - is_invalid_bytes(decode::(vec![0, 0, 0, 5], Infinite)); - is_invalid_bytes(decode::>(vec![5, 0], Infinite)); + is_invalid_bytes(decode::(vec![0, 0, 0, 5].as_slice())); + is_invalid_bytes(decode::>(vec![5, 0].as_slice())); } #[test] fn too_big_decode() { let encoded = vec![0,0,0,3]; - let decoded: Result = decode(encoded, UpperBound(3)); + let mut encoded_ref = encoded.as_slice(); + let decoded: Result = decode_from(&mut encoded_ref, UpperBound(3)); assert!(decoded.is_err()); let encoded = vec![0,0,0,3]; - let decoded: Result = decode(encoded, UpperBound(4)); + let mut encoded_ref = encoded.as_slice(); + let decoded: Result = decode_from(&mut encoded_ref, UpperBound(4)); assert!(decoded.is_ok()); } #[test] fn too_big_char_decode() { let encoded = vec![0x41]; - let decoded: Result = decode(encoded, UpperBound(1)); + let mut encoded_ref = encoded.as_slice(); + let decoded: Result = decode_from(&mut encoded_ref, UpperBound(1)); assert_eq!(decoded, Ok('A')); }