summaryrefslogtreecommitdiffstats
path: root/third_party/rust/hashlink/src/serde.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/hashlink/src/serde.rs')
-rw-r--r--third_party/rust/hashlink/src/serde.rs161
1 files changed, 161 insertions, 0 deletions
diff --git a/third_party/rust/hashlink/src/serde.rs b/third_party/rust/hashlink/src/serde.rs
new file mode 100644
index 0000000000..f44ebb3a65
--- /dev/null
+++ b/third_party/rust/hashlink/src/serde.rs
@@ -0,0 +1,161 @@
+use std::{
+ fmt::{self, Formatter},
+ hash::{BuildHasher, Hash},
+ marker::PhantomData,
+};
+
+use serde::{
+ de::{MapAccess, SeqAccess, Visitor},
+ ser::{SerializeMap, SerializeSeq},
+ Deserialize, Deserializer, Serialize, Serializer,
+};
+
+use crate::{LinkedHashMap, LinkedHashSet};
+
+// LinkedHashMap impls
+
+impl<K, V, S> Serialize for LinkedHashMap<K, V, S>
+where
+ K: Serialize + Eq + Hash,
+ V: Serialize,
+ S: BuildHasher,
+{
+ #[inline]
+ fn serialize<T: Serializer>(&self, serializer: T) -> Result<T::Ok, T::Error> {
+ let mut map_serializer = serializer.serialize_map(Some(self.len()))?;
+ for (k, v) in self {
+ map_serializer.serialize_key(k)?;
+ map_serializer.serialize_value(v)?;
+ }
+ map_serializer.end()
+ }
+}
+
+impl<'de, K, V, S> Deserialize<'de> for LinkedHashMap<K, V, S>
+where
+ K: Deserialize<'de> + Eq + Hash,
+ V: Deserialize<'de>,
+ S: BuildHasher + Default,
+{
+ fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+ #[derive(Debug)]
+ pub struct LinkedHashMapVisitor<K, V, S> {
+ marker: PhantomData<LinkedHashMap<K, V, S>>,
+ }
+
+ impl<K, V, S> LinkedHashMapVisitor<K, V, S> {
+ fn new() -> Self {
+ LinkedHashMapVisitor {
+ marker: PhantomData,
+ }
+ }
+ }
+
+ impl<K, V, S> Default for LinkedHashMapVisitor<K, V, S> {
+ fn default() -> Self {
+ Self::new()
+ }
+ }
+
+ impl<'de, K, V, S> Visitor<'de> for LinkedHashMapVisitor<K, V, S>
+ where
+ K: Deserialize<'de> + Eq + Hash,
+ V: Deserialize<'de>,
+ S: BuildHasher + Default,
+ {
+ type Value = LinkedHashMap<K, V, S>;
+
+ fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
+ write!(formatter, "a map")
+ }
+
+ #[inline]
+ fn visit_map<M: MapAccess<'de>>(self, mut map: M) -> Result<Self::Value, M::Error> {
+ let mut values = LinkedHashMap::with_capacity_and_hasher(
+ map.size_hint().unwrap_or(0),
+ S::default(),
+ );
+
+ while let Some((k, v)) = map.next_entry()? {
+ values.insert(k, v);
+ }
+
+ Ok(values)
+ }
+ }
+
+ deserializer.deserialize_map(LinkedHashMapVisitor::default())
+ }
+}
+
+// LinkedHashSet impls
+
+impl<T, S> Serialize for LinkedHashSet<T, S>
+where
+ T: Serialize + Eq + Hash,
+ S: BuildHasher,
+{
+ #[inline]
+ fn serialize<U: Serializer>(&self, serializer: U) -> Result<U::Ok, U::Error> {
+ let mut seq_serializer = serializer.serialize_seq(Some(self.len()))?;
+ for v in self {
+ seq_serializer.serialize_element(v)?;
+ }
+ seq_serializer.end()
+ }
+}
+
+impl<'de, T, S> Deserialize<'de> for LinkedHashSet<T, S>
+where
+ T: Deserialize<'de> + Eq + Hash,
+ S: BuildHasher + Default,
+{
+ fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+ #[derive(Debug)]
+ pub struct LinkedHashSetVisitor<T, S> {
+ marker: PhantomData<LinkedHashSet<T, S>>,
+ }
+
+ impl<T, S> LinkedHashSetVisitor<T, S> {
+ fn new() -> Self {
+ LinkedHashSetVisitor {
+ marker: PhantomData,
+ }
+ }
+ }
+
+ impl<T, S> Default for LinkedHashSetVisitor<T, S> {
+ fn default() -> Self {
+ Self::new()
+ }
+ }
+
+ impl<'de, T, S> Visitor<'de> for LinkedHashSetVisitor<T, S>
+ where
+ T: Deserialize<'de> + Eq + Hash,
+ S: BuildHasher + Default,
+ {
+ type Value = LinkedHashSet<T, S>;
+
+ fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
+ write!(formatter, "a sequence")
+ }
+
+ #[inline]
+ fn visit_seq<SA: SeqAccess<'de>>(self, mut seq: SA) -> Result<Self::Value, SA::Error> {
+ let mut values = LinkedHashSet::with_capacity_and_hasher(
+ seq.size_hint().unwrap_or(0),
+ S::default(),
+ );
+
+ while let Some(v) = seq.next_element()? {
+ values.insert(v);
+ }
+
+ Ok(values)
+ }
+ }
+
+ deserializer.deserialize_seq(LinkedHashSetVisitor::default())
+ }
+}