diff options
Diffstat (limited to 'compiler/rustc_serialize')
| -rw-r--r-- | compiler/rustc_serialize/src/collection_impls.rs | 42 | ||||
| -rw-r--r-- | compiler/rustc_serialize/src/lib.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_serialize/src/opaque.rs | 47 | ||||
| -rw-r--r-- | compiler/rustc_serialize/src/serialize.rs | 13 |
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)) } } |
