diff options
Diffstat (limited to 'third_party/rust/indexmap/src/serde.rs')
-rw-r--r-- | third_party/rust/indexmap/src/serde.rs | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/third_party/rust/indexmap/src/serde.rs b/third_party/rust/indexmap/src/serde.rs index c6dd6d5ea0..25546d531b 100644 --- a/third_party/rust/indexmap/src/serde.rs +++ b/third_party/rust/indexmap/src/serde.rs @@ -1,3 +1,5 @@ +#![cfg_attr(docsrs, doc(cfg(feature = "serde")))] + use serde::de::value::{MapDeserializer, SeqDeserializer}; use serde::de::{ Deserialize, Deserializer, Error, IntoDeserializer, MapAccess, SeqAccess, Visitor, @@ -7,15 +9,30 @@ use serde::ser::{Serialize, Serializer}; use core::fmt::{self, Formatter}; use core::hash::{BuildHasher, Hash}; use core::marker::PhantomData; +use core::{cmp, mem}; + +use crate::{Bucket, IndexMap, IndexSet}; + +/// Limit our preallocated capacity from a deserializer `size_hint()`. +/// +/// We do account for the `Bucket` overhead from its saved `hash` field, but we don't count the +/// `RawTable` allocation or the fact that its raw capacity will be rounded up to a power of two. +/// The "max" is an arbitrary choice anyway, not something that needs precise adherence. +/// +/// This is based on the internal `serde::de::size_hint::cautious(hint)` function. +pub(crate) fn cautious_capacity<K, V>(hint: Option<usize>) -> usize { + const MAX_PREALLOC_BYTES: usize = 1024 * 1024; + + cmp::min( + hint.unwrap_or(0), + MAX_PREALLOC_BYTES / mem::size_of::<Bucket<K, V>>(), + ) +} -use crate::IndexMap; - -/// Requires crate feature `"serde"` or `"serde-1"` impl<K, V, S> Serialize for IndexMap<K, V, S> where - K: Serialize + Hash + Eq, + K: Serialize, V: Serialize, - S: BuildHasher, { fn serialize<T>(&self, serializer: T) -> Result<T::Ok, T::Error> where @@ -43,8 +60,8 @@ where where A: MapAccess<'de>, { - let mut values = - IndexMap::with_capacity_and_hasher(map.size_hint().unwrap_or(0), S::default()); + let capacity = cautious_capacity::<K, V>(map.size_hint()); + let mut values = IndexMap::with_capacity_and_hasher(capacity, S::default()); while let Some((key, value)) = map.next_entry()? { values.insert(key, value); @@ -54,7 +71,6 @@ where } } -/// Requires crate feature `"serde"` or `"serde-1"` impl<'de, K, V, S> Deserialize<'de> for IndexMap<K, V, S> where K: Deserialize<'de> + Eq + Hash, @@ -83,13 +99,9 @@ where } } -use crate::IndexSet; - -/// Requires crate feature `"serde"` or `"serde-1"` impl<T, S> Serialize for IndexSet<T, S> where - T: Serialize + Hash + Eq, - S: BuildHasher, + T: Serialize, { fn serialize<Se>(&self, serializer: Se) -> Result<Se::Ok, Se::Error> where @@ -116,8 +128,8 @@ where where A: SeqAccess<'de>, { - let mut values = - IndexSet::with_capacity_and_hasher(seq.size_hint().unwrap_or(0), S::default()); + let capacity = cautious_capacity::<T, ()>(seq.size_hint()); + let mut values = IndexSet::with_capacity_and_hasher(capacity, S::default()); while let Some(value) = seq.next_element()? { values.insert(value); @@ -127,7 +139,6 @@ where } } -/// Requires crate feature `"serde"` or `"serde-1"` impl<'de, T, S> Deserialize<'de> for IndexSet<T, S> where T: Deserialize<'de> + Eq + Hash, |