Use specialisation to optimise collect_seq and collect_map

This commit is contained in:
Anthony Ramine 2017-02-04 12:22:58 +01:00
parent 763ab9c2a1
commit 17c175a1a6
3 changed files with 52 additions and 3 deletions

View File

@ -61,7 +61,7 @@
#![doc(html_root_url="https://docs.serde.rs")]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "unstable", feature(nonzero, inclusive_range, zero_one))]
#![cfg_attr(feature = "unstable", feature(inclusive_range, nonzero, specialization, zero_one))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "collections", feature(collections))]
#![cfg_attr(feature = "cargo-clippy", allow(linkedlist, type_complexity, doc_markdown))]

View File

@ -199,6 +199,7 @@ array_impls!(32);
///////////////////////////////////////////////////////////////////////////////
#[cfg(not(feature = "unstable"))]
macro_rules! serialize_seq {
() => {
#[inline]
@ -214,6 +215,18 @@ macro_rules! serialize_seq {
}
}
#[cfg(feature = "unstable")]
macro_rules! serialize_seq {
() => {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
serializer.collect_seq(self)
}
}
}
impl<T> Serialize for [T]
where T: Serialize,
{
@ -508,6 +521,7 @@ tuple_impls! {
///////////////////////////////////////////////////////////////////////////////
#[cfg(not(feature = "unstable"))]
macro_rules! serialize_map {
() => {
#[inline]
@ -524,6 +538,18 @@ macro_rules! serialize_map {
}
}
#[cfg(feature = "unstable")]
macro_rules! serialize_map {
() => {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer,
{
serializer.collect_map(self)
}
}
}
#[cfg(any(feature = "std", feature = "collections"))]
impl<K, V> Serialize for BTreeMap<K, V>
where K: Serialize + Ord,

View File

@ -616,7 +616,7 @@ pub trait Serializer: Sized {
<I as IntoIterator>::Item: Serialize,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_seq(iterator_len_hint(&iter)));
let mut serializer = try!(self.serialize_seq(iter.len_hint()));
for item in iter {
try!(serializer.serialize_element(&item));
}
@ -634,7 +634,7 @@ pub trait Serializer: Sized {
I: IntoIterator<Item = (K, V)>,
{
let iter = iter.into_iter();
let mut serializer = try!(self.serialize_map(iterator_len_hint(&iter)));
let mut serializer = try!(self.serialize_map(iter.len_hint()));
for (key, value) in iter {
try!(serializer.serialize_entry(&key, &value));
}
@ -836,6 +836,29 @@ pub trait SerializeStructVariant {
fn end(self) -> Result<Self::Ok, Self::Error>;
}
trait LenHint: Iterator {
fn len_hint(&self) -> Option<usize>;
}
impl<I: Iterator> LenHint for I {
#[cfg(not(feature = "unstable"))]
fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
#[cfg(feature = "unstable")]
default fn len_hint(&self) -> Option<usize> {
iterator_len_hint(self)
}
}
#[cfg(feature = "unstable")]
impl<I: ExactSizeIterator> LenHint for I {
fn len_hint(&self) -> Option<usize> {
Some(self.len())
}
}
fn iterator_len_hint<I: Iterator>(iter: &I) -> Option<usize> {
match iter.size_hint() {
(lo, Some(hi)) if lo == hi => Some(lo),