summaryrefslogtreecommitdiffstats
path: root/third_party/rust/indexmap/src/serde.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/indexmap/src/serde.rs')
-rw-r--r--third_party/rust/indexmap/src/serde.rs43
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,