about summary refs log tree commit diff
path: root/compiler/rustc_serialize
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_serialize')
-rw-r--r--compiler/rustc_serialize/src/collection_impls.rs42
-rw-r--r--compiler/rustc_serialize/src/lib.rs4
-rw-r--r--compiler/rustc_serialize/src/opaque.rs47
-rw-r--r--compiler/rustc_serialize/src/serialize.rs13
4 files changed, 62 insertions, 44 deletions
diff --git a/compiler/rustc_serialize/src/collection_impls.rs b/compiler/rustc_serialize/src/collection_impls.rs
index 3d274cb0150..ae6d27e037b 100644
--- a/compiler/rustc_serialize/src/collection_impls.rs
+++ b/compiler/rustc_serialize/src/collection_impls.rs
@@ -11,12 +11,8 @@ use smallvec::{Array, SmallVec};
 
 impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
+        let slice: &[A::Item] = self;
+        slice.encode(s)
     }
 }
 
@@ -292,46 +288,28 @@ where
 
 impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (index, e) in self.iter().enumerate() {
-                s.emit_seq_elt(index, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
+        let slice: &[T] = self;
+        slice.encode(s)
     }
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> {
     fn decode(d: &mut D) -> Result<Rc<[T]>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut vec = Vec::with_capacity(len);
-            for index in 0..len {
-                vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
-            }
-            Ok(vec.into())
-        })
+        let vec: Vec<T> = Decodable::decode(d)?;
+        Ok(vec.into())
     }
 }
 
 impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (index, e) in self.iter().enumerate() {
-                s.emit_seq_elt(index, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
+        let slice: &[T] = self;
+        slice.encode(s)
     }
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<[T]> {
     fn decode(d: &mut D) -> Result<Arc<[T]>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut vec = Vec::with_capacity(len);
-            for index in 0..len {
-                vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
-            }
-            Ok(vec.into())
-        })
+        let vec: Vec<T> = Decodable::decode(d)?;
+        Ok(vec.into())
     }
 }
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index fab29f29e87..f58ed14d997 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -13,7 +13,9 @@ Core encoding and decoding interfaces.
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(associated_type_bounds)]
-#![feature(min_const_generics)]
+#![cfg_attr(bootstrap, feature(min_const_generics))]
+#![feature(min_specialization)]
+#![feature(vec_spare_capacity)]
 #![cfg_attr(test, feature(test))]
 #![allow(rustc::internal)]
 
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 8b79c93e760..673742df7f0 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -1,6 +1,8 @@
 use crate::leb128::{self, read_signed_leb128, write_signed_leb128};
 use crate::serialize;
 use std::borrow::Cow;
+use std::mem::MaybeUninit;
+use std::ptr;
 
 // -----------------------------------------------------------------------------
 // Encoder
@@ -179,11 +181,19 @@ impl<'a> Decoder<'a> {
     }
 
     #[inline]
-    pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
+    pub fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> {
         let start = self.position;
         let end = start + s.len();
+        assert!(end <= self.data.len());
 
-        s.copy_from_slice(&self.data[start..end]);
+        // SAFETY: Both `src` and `dst` point to at least `s.len()` elements:
+        // `src` points to at least `s.len()` elements by above assert, and
+        // `dst` points to `s.len()` elements by derivation from `s`.
+        unsafe {
+            let src = self.data.as_ptr().add(start);
+            let dst = s.as_mut_ptr() as *mut u8;
+            ptr::copy_nonoverlapping(src, dst, s.len());
+        }
 
         self.position = end;
 
@@ -316,3 +326,36 @@ impl<'a> serialize::Decoder for Decoder<'a> {
         err.to_string()
     }
 }
+
+// Specializations for contiguous byte sequences follow. The default implementations for slices
+// encode and decode each element individually. This isn't necessary for `u8` slices when using
+// opaque encoders and decoders, because each `u8` is unchanged by encoding and decoding.
+// Therefore, we can use more efficient implementations that process the entire sequence at once.
+
+// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
+// since the default implementations call `encode` on their slices internally.
+impl serialize::Encodable<Encoder> for [u8] {
+    fn encode(&self, e: &mut Encoder) -> EncodeResult {
+        serialize::Encoder::emit_usize(e, self.len())?;
+        e.emit_raw_bytes(self);
+        Ok(())
+    }
+}
+
+// Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc.,
+// since the default implementations call `decode` to produce a `Vec<u8>` internally.
+impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> {
+    fn decode(d: &mut Decoder<'a>) -> Result<Self, String> {
+        let len = serialize::Decoder::read_usize(d)?;
+
+        let mut v = Vec::with_capacity(len);
+        let buf = &mut v.spare_capacity_mut()[..len];
+        d.read_raw_bytes(buf)?;
+
+        unsafe {
+            v.set_len(len);
+        }
+
+        Ok(v)
+    }
+}
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index aa305f3c7fc..47aad5b88c6 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -527,7 +527,7 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<T> {
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    default fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?
@@ -545,7 +545,7 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> {
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
-    fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
+    default fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut v = Vec::with_capacity(len);
             for i in 0..len {
@@ -591,13 +591,8 @@ where
     [T]: ToOwned<Owned = Vec<T>>,
 {
     fn decode(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut v = Vec::with_capacity(len);
-            for i in 0..len {
-                v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
-            }
-            Ok(Cow::Owned(v))
-        })
+        let v: Vec<T> = Decodable::decode(d)?;
+        Ok(Cow::Owned(v))
     }
 }