From 17c175a1a6bde98e947b1b02872a138c6afdb1fc Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 4 Feb 2017 12:22:58 +0100 Subject: [PATCH] Use specialisation to optimise collect_seq and collect_map --- serde/src/lib.rs | 2 +- serde/src/ser/impls.rs | 26 ++++++++++++++++++++++++++ serde/src/ser/mod.rs | 27 +++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 58cc9b8f..467a2266 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -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))] diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 93c00dc4..f2fbb37d 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -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(&self, serializer: S) -> Result + where S: Serializer, + { + serializer.collect_seq(self) + } + } +} + impl 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(&self, serializer: S) -> Result + where S: Serializer, + { + serializer.collect_map(self) + } + } +} + #[cfg(any(feature = "std", feature = "collections"))] impl Serialize for BTreeMap where K: Serialize + Ord, diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index c7635c34..331928a3 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -616,7 +616,7 @@ pub trait Serializer: Sized { ::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, { 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; } +trait LenHint: Iterator { + fn len_hint(&self) -> Option; +} + +impl LenHint for I { + #[cfg(not(feature = "unstable"))] + fn len_hint(&self) -> Option { + iterator_len_hint(self) + } + + #[cfg(feature = "unstable")] + default fn len_hint(&self) -> Option { + iterator_len_hint(self) + } +} + +#[cfg(feature = "unstable")] +impl LenHint for I { + fn len_hint(&self) -> Option { + Some(self.len()) + } +} + fn iterator_len_hint(iter: &I) -> Option { match iter.size_hint() { (lo, Some(hi)) if lo == hi => Some(lo),