Repository: alex/rust-asn1 (language: rust)

Issue:
_read_with_tag shouldn't copy the buffer

Move from Vec<u8> to &[u8]



Discussion / hints:

Fix patch:
diff --git a/src/deserializer.rs b/src/deserializer.rs
index 829167b..5f8f631 100644
--- a/src/deserializer.rs
+++ b/src/deserializer.rs
@@ -1,5 +1,5 @@
 use std::{convert};
-use std::io::{Cursor, Read};
+use std::io::{BufRead, Cursor};
 
 use byteorder::{self, ReadBytesExt};
 
@@ -26,7 +26,7 @@ impl convert::From<byteorder::Error> for DeserializationError {
 
 pub type DeserializationResult<T> = Result<T, DeserializationError>;
 
-fn _read_base128_int(reader: &mut Cursor<Vec<u8>>) -> DeserializationResult<u32> {
+fn _read_base128_int(reader: &mut Cursor<&[u8]>) -> DeserializationResult<u32> {
     let mut ret = 0u32;
     for _ in 0..4 {
         let b = try!(reader.read_u8());
@@ -39,12 +39,12 @@ fn _read_base128_int(reader: &mut Cursor<Vec<u8>>) -> DeserializationResult<u32>
     return Err(DeserializationError::InvalidValue);
 }
 
-pub struct Deserializer {
-    reader: Cursor<Vec<u8>>,
+pub struct Deserializer<'a> {
+    reader: Cursor<&'a [u8]>,
 }
 
-impl Deserializer {
-    pub fn new(data: Vec<u8>) -> Deserializer {
+impl<'a> Deserializer<'a> {
+    pub fn new(data: &[u8]) -> Deserializer {
         return Deserializer{
             reader: Cursor::new(data),
         }
@@ -82,22 +82,24 @@ impl Deserializer {
     }
 
     fn _read_with_tag<T, F>(&mut self, expected_tag: u8, body: F) -> DeserializationResult<T>
-            where F: Fn(Vec<u8>) -> DeserializationResult<T> {
+            where F: Fn(&[u8]) -> DeserializationResult<T> {
         let tag = try!(self.reader.read_u8());
         // TODO: only some of the bits in the first byte are for the tag
         if tag != expected_tag {
             return Err(DeserializationError::UnexpectedTag);
         }
         let length = try!(self._read_length());
-        // Check for short data before allocating the data Vec so we disallow obscenely large
-        // lengths
-        if length > (self.reader.get_ref().len() - self.reader.position() as usize) {
-            return Err(DeserializationError::ShortData);
-        }
-        let mut data = vec![0; length];
-        let n = self.reader.read(&mut data).unwrap();
-        assert_eq!(n, length);
-        return body(data);
+
+        let result = {
+            let buf = self.reader.fill_buf().unwrap();
+            if buf.len() < length {
+                return Err(DeserializationError::ShortData);
+            }
+            body(&buf[..length])
+        };
+
+        self.reader.consume(length);
+        return result;
     }
 
     pub fn finish(self) -> DeserializationResult<()> {
@@ -133,7 +135,7 @@ impl Deserializer {
 
     pub fn read_octet_string(&mut self) -> DeserializationResult<Vec<u8>> {
         return self._read_with_tag(4, |data| {
-            return Ok(data);
+            return Ok(data.to_owned());
         });
     }
 
@@ -170,7 +172,7 @@ impl Deserializer {
     }
 }
 
-pub fn from_vec<F, T>(data: Vec<u8>, f: F) -> DeserializationResult<T>
+pub fn from_vec<F, T>(data: &[u8], f: F) -> DeserializationResult<T>
         where F: Fn(&mut Deserializer) -> DeserializationResult<T> {
     let mut deserializer = Deserializer::new(data);
     let result = try!(f(&mut deserializer));
@@ -188,7 +190,7 @@ mod tests {
     use utils::{ObjectIdentifier};
     use super::{Deserializer, DeserializationError, DeserializationResult, from_vec};
 
-    fn assert_deserializes<T, F>(values: Vec<(DeserializationResult<T>, Vec<u8>)>, f: F)
+    fn assert_deserializes<T, F>(values: Vec<(DeserializationResult<T>, &[u8])>, f: F)
             where T: Eq + fmt::Debug, F: Fn(&mut Deserializer) -> DeserializationResult<T> {
         for (expected, value) in values {
             let result = from_vec(value, &f);
@@ -198,7 +200,7 @@ mod tests {
     #[test]
     fn test_read_extra_data() {
         assert_deserializes(vec![
-            (Err(DeserializationError::ExtraData), b"\x00".to_vec()),
+            (Err(DeserializationError::ExtraData), b"\x00"),
         ], |_| {
             return Ok(());
         });
@@ -207,12 +209,12 @@ mod tests {
     #[test]
     fn test_read_bool() {
         assert_deserializes(vec![
-            (Ok(true), b"\x01\x01\xff".to_vec()),
-            (Ok(false), b"\x01\x01\x00".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x01\x00".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x01\x01\x01".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x01\x02\x00\x00".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x01\x02\xff\x01".to_vec()),
+            (Ok(true), b"\x01\x01\xff"),
+            (Ok(false), b"\x01\x01\x00"),
+            (Err(DeserializationError::InvalidValue), b"\x01\x00"),
+            (Err(DeserializationError::InvalidValue), b"\x01\x01\x01"),
+            (Err(DeserializationError::InvalidValue), b"\x01\x02\x00\x00"),
+            (Err(DeserializationError::InvalidValue), b"\x01\x02\xff\x01"),
         ], |deserializer| {
             return deserializer.read_bool();
         });
@@ -221,25 +223,25 @@ mod tests {
     #[test]
     fn test_read_int_i64() {
         assert_deserializes(vec![
-            (Ok(0), b"\x02\x01\x00".to_vec()),
-            (Ok(127), b"\x02\x01\x7f".to_vec()),
-            (Ok(128), b"\x02\x02\x00\x80".to_vec()),
-            (Ok(256), b"\x02\x02\x01\x00".to_vec()),
-            (Ok(-128), b"\x02\x01\x80".to_vec()),
-            (Ok(-129), b"\x02\x02\xff\x7f".to_vec()),
-            (Ok(-256), b"\x02\x02\xff\x00".to_vec()),
-            (Ok(std::i64::MAX), b"\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff".to_vec()),
-            (Err(DeserializationError::UnexpectedTag), b"\x03".to_vec()),
-            (Err(DeserializationError::ShortData), b"\x02\x02\x00".to_vec()),
-            (Err(DeserializationError::ShortData), b"".to_vec()),
-            (Err(DeserializationError::ShortData), b"\x02".to_vec()),
+            (Ok(0), b"\x02\x01\x00"),
+            (Ok(127), b"\x02\x01\x7f"),
+            (Ok(128), b"\x02\x02\x00\x80"),
+            (Ok(256), b"\x02\x02\x01\x00"),
+            (Ok(-128), b"\x02\x01\x80"),
+            (Ok(-129), b"\x02\x02\xff\x7f"),
+            (Ok(-256), b"\x02\x02\xff\x00"),
+            (Ok(std::i64::MAX), b"\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff"),
+            (Err(DeserializationError::UnexpectedTag), b"\x03"),
+            (Err(DeserializationError::ShortData), b"\x02\x02\x00"),
+            (Err(DeserializationError::ShortData), b""),
+            (Err(DeserializationError::ShortData), b"\x02"),
             (
                 Err(DeserializationError::IntegerOverflow),
-                b"\x02\x09\x02\x00\x00\x00\x00\x00\x00\x00\x00".to_vec()
+                b"\x02\x09\x02\x00\x00\x00\x00\x00\x00\x00\x00"
             ),
-            (Err(DeserializationError::InvalidValue), b"\x02\x05\x00\x00\x00\x00\x01".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x02\x02\xff\x80".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x02\x00".to_vec()),
+            (Err(DeserializationError::InvalidValue), b"\x02\x05\x00\x00\x00\x00\x01"),
+            (Err(DeserializationError::InvalidValue), b"\x02\x02\xff\x80"),
+            (Err(DeserializationError::InvalidValue), b"\x02\x00"),
         ], |deserializer| {
             return deserializer.read_int();
         });
@@ -248,16 +250,16 @@ mod tests {
     #[test]
     fn test_read_int_i32() {
         assert_deserializes(vec![
-            (Ok(0i32), b"\x02\x01\x00".to_vec()),
-            (Ok(127i32), b"\x02\x01\x7f".to_vec()),
-            (Ok(128i32), b"\x02\x02\x00\x80".to_vec()),
-            (Ok(256i32), b"\x02\x02\x01\x00".to_vec()),
-            (Ok(-128i32), b"\x02\x01\x80".to_vec()),
-            (Ok(-129i32), b"\x02\x02\xff\x7f".to_vec()),
-            (Ok(-256i32), b"\x02\x02\xff\x00".to_vec()),
-            (Ok(std::i32::MAX), b"\x02\x04\x7f\xff\xff\xff".to_vec()),
-            (Err(DeserializationError::IntegerOverflow), b"\x02\x05\x02\x00\x00\x00\x00".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x02\x00".to_vec()),
+            (Ok(0i32), b"\x02\x01\x00"),
+            (Ok(127i32), b"\x02\x01\x7f"),
+            (Ok(128i32), b"\x02\x02\x00\x80"),
+            (Ok(256i32), b"\x02\x02\x01\x00"),
+            (Ok(-128i32), b"\x02\x01\x80"),
+            (Ok(-129i32), b"\x02\x02\xff\x7f"),
+            (Ok(-256i32), b"\x02\x02\xff\x00"),
+            (Ok(std::i32::MAX), b"\x02\x04\x7f\xff\xff\xff"),
+            (Err(DeserializationError::IntegerOverflow), b"\x02\x05\x02\x00\x00\x00\x00"),
+            (Err(DeserializationError::InvalidValue), b"\x02\x00"),
         ], |deserializer| {
             return deserializer.read_int();
         });
@@ -266,11 +268,11 @@ mod tests {
     #[test]
     fn test_read_int_i8() {
         assert_deserializes(vec![
-            (Ok(0i8), b"\x02\x01\x00".to_vec()),
-            (Ok(127i8), b"\x02\x01\x7f".to_vec()),
-            (Ok(-128i8), b"\x02\x01\x80".to_vec()),
-            (Err(DeserializationError::IntegerOverflow), b"\x02\x02\x02\x00".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x02\x00".to_vec()),
+            (Ok(0i8), b"\x02\x01\x00"),
+            (Ok(127i8), b"\x02\x01\x7f"),
+            (Ok(-128i8), b"\x02\x01\x80"),
+            (Err(DeserializationError::IntegerOverflow), b"\x02\x02\x02\x00"),
+            (Err(DeserializationError::InvalidValue), b"\x02\x00"),
         ], |deserializer| {
             return deserializer.read_int();
         });
@@ -279,22 +281,22 @@ mod tests {
     #[test]
     fn test_read_int_bigint() {
         assert_deserializes(vec![
-            (Ok(BigInt::from_i64(0).unwrap()), b"\x02\x01\x00".to_vec()),
-            (Ok(BigInt::from_i64(127).unwrap()), b"\x02\x01\x7f".to_vec()),
-            (Ok(BigInt::from_i64(128).unwrap()), b"\x02\x02\x00\x80".to_vec()),
-            (Ok(BigInt::from_i64(256).unwrap()), b"\x02\x02\x01\x00".to_vec()),
-            (Ok(BigInt::from_i64(-128).unwrap()), b"\x02\x01\x80".to_vec()),
-            (Ok(BigInt::from_i64(-129).unwrap()), b"\x02\x02\xff\x7f".to_vec()),
-            (Ok(BigInt::from_i64(-256).unwrap()), b"\x02\x02\xff\x00".to_vec()),
+            (Ok(BigInt::from_i64(0).unwrap()), b"\x02\x01\x00"),
+            (Ok(BigInt::from_i64(127).unwrap()), b"\x02\x01\x7f"),
+            (Ok(BigInt::from_i64(128).unwrap()), b"\x02\x02\x00\x80"),
+            (Ok(BigInt::from_i64(256).unwrap()), b"\x02\x02\x01\x00"),
+            (Ok(BigInt::from_i64(-128).unwrap()), b"\x02\x01\x80"),
+            (Ok(BigInt::from_i64(-129).unwrap()), b"\x02\x02\xff\x7f"),
+            (Ok(BigInt::from_i64(-256).unwrap()), b"\x02\x02\xff\x00"),
             (
                 Ok(BigInt::from_i64(std::i64::MAX).unwrap()),
-                b"\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff".to_vec()
+                b"\x02\x08\x7f\xff\xff\xff\xff\xff\xff\xff"
             ),
             (
                 Ok(BigInt::from_i64(std::i64::MAX).unwrap() + BigInt::one()),
-                b"\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00".to_vec()
+                b"\x02\x09\x00\x80\x00\x00\x00\x00\x00\x00\x00"
             ),
-            (Err(DeserializationError::InvalidValue), b"\x02\x00".to_vec()),
+            (Err(DeserializationError::InvalidValue), b"\x02\x00"),
         ], |deserializer| {
             return deserializer.read_int();
         });
@@ -303,21 +305,21 @@ mod tests {
     #[test]
     fn test_read_octet_string() {
         assert_deserializes(vec![
-            (Ok(b"".to_vec()), b"\x04\x00".to_vec()),
-            (Ok(b"\x01\x02\x03".to_vec()), b"\x04\x03\x01\x02\x03".to_vec()),
+            (Ok(b"".to_vec()), b"\x04\x00"),
+            (Ok(b"\x01\x02\x03".to_vec()), b"\x04\x03\x01\x02\x03"),
             (
                 Ok(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_vec()),
-                b"\x04\x81\x81aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_vec()
+                b"\x04\x81\x81aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
             ),
-            (Err(DeserializationError::InvalidValue), b"\x04\x80".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x04\x81\x00".to_vec()),
-            (Err(DeserializationError::InvalidValue), b"\x04\x81\x01\x09".to_vec()),
+            (Err(DeserializationError::InvalidValue), b"\x04\x80"),
+            (Err(DeserializationError::InvalidValue), b"\x04\x81\x00"),
+            (Err(DeserializationError::InvalidValue), b"\x04\x81\x01\x09"),
             (
                 Err(DeserializationError::IntegerOverflow),
-                b"\x04\x89\x01\x01\x01\x01\x01\x01\x01\x01\x01".to_vec()
+                b"\x04\x89\x01\x01\x01\x01\x01\x01\x01\x01\x01"
             ),
-            (Err(DeserializationError::ShortData), b"\x04\x03\x01\x02".to_vec()),
-            (Err(DeserializationError::ShortData), b"\x04\x86\xff\xff\xff\xff\xff\xff".to_vec()),
+            (Err(DeserializationError::ShortData), b"\x04\x03\x01\x02"),
+            (Err(DeserializationError::ShortData), b"\x04\x86\xff\xff\xff\xff\xff\xff"),
         ], |deserializer| {
             return deserializer.read_octet_string();
         });
@@ -326,30 +328,21 @@ mod tests {
     #[test]
     fn test_read_object_identifier() {
         assert_deserializes(vec![
-            (Ok(ObjectIdentifier::new(vec![2, 5]).unwrap()), b"\x06\x01\x55".to_vec()),
-            (Ok(ObjectIdentifier::new(vec![2, 5, 2]).unwrap()), b"\x06\x02\x55\x02".to_vec()),
+            (Ok(ObjectIdentifier::new(vec![2, 5]).unwrap()), b"\x06\x01\x55"),
+            (Ok(ObjectIdentifier::new(vec![2, 5, 2]).unwrap()), b"\x06\x02\x55\x02"),
             (
                 Ok(ObjectIdentifier::new(vec![1, 2, 840, 113549]).unwrap()),
-                b"\x06\x06\x2a\x86\x48\x86\xf7\x0d".to_vec()
-            ),
-            (
-                Ok(ObjectIdentifier::new(vec![1, 2, 3, 4]).unwrap()),
-                b"\x06\x03\x2a\x03\x04".to_vec(),
+                b"\x06\x06\x2a\x86\x48\x86\xf7\x0d"
             ),
+            (Ok(ObjectIdentifier::new(vec![1, 2, 3, 4]).unwrap()), b"\x06\x03\x2a\x03\x04"),
             (
                 Ok(ObjectIdentifier::new(vec![1, 2, 840, 133549, 1, 1, 5]).unwrap()),
-                b"\x06\x09\x2a\x86\x48\x88\x93\x2d\x01\x01\x05".to_vec(),
+                b"\x06\x09\x2a\x86\x48\x88\x93\x2d\x01\x01\x05",
             ),
-            (
-                Ok(ObjectIdentifier::new(vec![2, 100, 3]).unwrap()),
-                b"\x06\x03\x81\x34\x03".to_vec(),
-            ),
-            (Err(DeserializationError::InvalidValue), b"\x06\x00".to_vec()),
-            (
-                Err(DeserializationError::InvalidValue),
-                b"\x06\x07\x55\x02\xc0\x80\x80\x80\x80".to_vec()
-            ),
-            (Err(DeserializationError::ShortData), b"\x06\x02\x2a\x86".to_vec()),
+            (Ok(ObjectIdentifier::new(vec![2, 100, 3]).unwrap()), b"\x06\x03\x81\x34\x03"),
+            (Err(DeserializationError::InvalidValue), b"\x06\x00"),
+            (Err(DeserializationError::InvalidValue), b"\x06\x07\x55\x02\xc0\x80\x80\x80\x80"),
+            (Err(DeserializationError::ShortData), b"\x06\x02\x2a\x86"),
         ], |deserializer| {
             return deserializer.read_object_identifier();
         });
@@ -358,12 +351,9 @@ mod tests {
     #[test]
     fn test_read_sequence() {
         assert_deserializes(vec![
-            (Ok((1, 2)), b"\x30\x06\x02\x01\x01\x02\x01\x02".to_vec()),
-            (Err(DeserializationError::ShortData), b"\x30\x03\x02\x01\x01".to_vec()),
-            (
-                Err(DeserializationError::ExtraData),
-                b"\x30\x07\x02\x01\x01\x02\x01\x02\x00".to_vec()
-            ),
+            (Ok((1, 2)), b"\x30\x06\x02\x01\x01\x02\x01\x02"),
+            (Err(DeserializationError::ShortData), b"\x30\x03\x02\x01\x01"),
+            (Err(DeserializationError::ExtraData), b"\x30\x07\x02\x01\x01\x02\x01\x02\x00"),
         ], |deserializer| {
             return deserializer.read_sequence(|deserializer| {
                 return Ok((
diff --git a/src/utils.rs b/src/utils.rs
index a7866b5..7c8ba84 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -37,7 +37,7 @@ fn _int_length(v: i64) -> usize {
 
 pub trait Integer: Sized {
     fn encode(&self) -> Vec<u8>;
-    fn decode(Vec<u8>) -> DeserializationResult<Self>;
+    fn decode(&[u8]) -> DeserializationResult<Self>;
 }
 
 macro_rules! primitive_integer {
@@ -52,7 +52,7 @@ macro_rules! primitive_integer {
                 return result;
             }
 
-            fn decode(data: Vec<u8>) -> DeserializationResult<$Int> {
+            fn decode(data: &[u8]) -> DeserializationResult<$Int> {
                 if data.len() > mem::size_of::<$Int>() {
                     return Err(DeserializationError::IntegerOverflow);
                 } else if data.is_empty() {
@@ -104,7 +104,7 @@ impl Integer for BigInt {
         }
     }
 
-    fn decode(data: Vec<u8>) -> DeserializationResult<BigInt> {
+    fn decode(data: &[u8]) -> DeserializationResult<BigInt> {
         if data.is_empty() {
             return Err(DeserializationError::InvalidValue);
         }


Test patch: