summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs154
1 files changed, 148 insertions, 6 deletions
diff --git a/src/lib.rs b/src/lib.rs
index c15c45b..d254b6f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -194,12 +194,23 @@ impl<'settings, 'de> Deserializer<'de> for Transmute<'settings> {
             | Collection::TupleStruct { .. }
             => visitor.visit_seq(self),
             Collection::Map(_) => {
-                todo!()
+                visitor.visit_map(MapAccess {
+                    transmute: self,
+                    // FIXME?
+                    value: Err(TransmuteError(())),
+                })
             }
             | Collection::StructVariant { .. }
             | Collection::Struct { .. }
             => {
-                todo!()
+                match self.settings.structs_are_seqs {
+                    false => visitor.visit_map(MapAccess {
+                        transmute: self,
+                        // FIXME?
+                        value: Err(TransmuteError(())),
+                    }),
+                    true => visitor.visit_seq(self),
+                }
             }
         }
     }
@@ -216,8 +227,7 @@ impl<'settings, 'de> Deserializer<'de> for Transmute<'settings> {
             | Collection::TupleVariant { .. }
             | Collection::StructVariant { .. }
             => visitor.visit_enum(self),
-            // FIXME?
-            _ => Err(TransmuteError(())),
+            _ => self.deserialize_any(visitor),
         }
     }
 
@@ -240,6 +250,103 @@ impl<'settings, 'de> Deserializer<'de> for Transmute<'settings> {
     }
 }
 
+struct MapAccess<'settings> {
+    transmute: Transmute<'settings>,
+    value: Result<Collection, TransmuteError>,
+}
+
+impl<'settings, 'de> serde::de::MapAccess<'de> for MapAccess<'settings> {
+    type Error = TransmuteError;
+    fn next_key_seed<T>(
+        &mut self,
+        seed: T,
+    ) -> Result<Option<T::Value>, Self::Error>
+    where
+        T: DeserializeSeed<'de>,
+    {
+        if self.value.is_ok() {
+            // FIXME?
+            return Err(TransmuteError(()));
+        }
+        match &mut self.transmute.collection {
+            Collection::Map(values) => {
+                values.next().map(|(k, v)| {
+                    self.value = Ok(v);
+                    seed.deserialize(Transmute {
+                        settings: self.transmute.settings,
+                        collection: k,
+                    })
+                }).transpose()
+            },
+            | Collection::StructVariant { values, .. }
+            | Collection::Struct { values, .. }
+            => {
+                values.next().map(|(k, v)| {
+                    self.value = Ok(v);
+                    seed.deserialize(serde::de::value::StrDeserializer::new(k))
+                }).transpose()
+            },
+            _ => unreachable!(),
+        }
+    }
+    fn next_value_seed<T>(
+        &mut self,
+        seed: T,
+    ) -> Result<T::Value, Self::Error>
+    where
+        T: DeserializeSeed<'de>,
+    {
+        // FIXME?
+        let v = std::mem::replace(&mut self.value, Err(TransmuteError(())));
+        v.and_then(|it| {
+            seed.deserialize(Transmute {
+                settings: self.transmute.settings,
+                collection: it,
+            })
+        })
+    }
+    fn next_entry_seed<K, V>(
+        &mut self,
+        key_seed: K,
+        value_seed: V,
+    ) -> Result<Option<(K::Value, V::Value)>, Self::Error>
+    where
+        K: DeserializeSeed<'de>,
+        V: DeserializeSeed<'de>,
+    {
+        if self.value.is_ok() {
+            // FIXME?
+            return Err(TransmuteError(()));
+        }
+        match &mut self.transmute.collection {
+            Collection::Map(values) => {
+                values.next().map(|(k, v)| {
+                    key_seed.deserialize(Transmute {
+                        settings: self.transmute.settings,
+                        collection: k,
+                    }).and_then(|k| value_seed.deserialize(Transmute {
+                        settings: self.transmute.settings,
+                        collection: v,
+                    }).map(|v| (k, v)))
+                }).transpose()
+            },
+            | Collection::StructVariant { values, .. }
+            | Collection::Struct { values, .. }
+            => {
+                values.next().map(|(k, v)| {
+                    key_seed.deserialize(
+                        serde::de::value::StrDeserializer::new(k)
+                    ).and_then(|k| value_seed.deserialize(Transmute {
+                        settings: self.transmute.settings,
+                        collection: v,
+                    }).map(|v| (k, v)))
+                }).transpose()
+            },
+            _ => unreachable!(),
+        }
+    }
+}
+
 impl<'settings, 'de> serde::de::SeqAccess<'de> for Transmute<'settings> {
     type Error = TransmuteError;
     fn next_element_seed<T>(
@@ -255,6 +362,9 @@ impl<'settings, 'de> serde::de::SeqAccess<'de> for Transmute<'settings> {
             | Collection::TupleVariant { values, .. }
             | Collection::TupleStruct { values, .. }
             => values.next(),
+            | Collection::StructVariant { values, .. }
+            | Collection::Struct { values, .. }
+            => values.next().map(|(_, v)| v),
             _ => unreachable!(),
         }.map(|value| seed.deserialize(Self {
             settings: self.settings,
@@ -268,6 +378,9 @@ impl<'settings, 'de> serde::de::SeqAccess<'de> for Transmute<'settings> {
             | Collection::TupleVariant { values, .. }
             | Collection::TupleStruct { values, .. }
             => values.size_hint().1,
+            | Collection::StructVariant { values, .. }
+            | Collection::Struct { values, .. }
+            => values.size_hint().1,
             _ => unreachable!(),
         }
     }
@@ -371,7 +484,9 @@ impl<'settings, 'de> serde::de::VariantAccess<'de> for Transmute<'settings> {
         Vis: Visitor<'de>,
     {
         match self.collection {
-            Collection::TupleVariant { .. } => todo!(),
+            Collection::TupleVariant { .. } => {
+                visitor.visit_seq(self)
+            },
             _ => {
                 let unexp = match self.collection {
                     Collection::UnitVariant { .. } => {
@@ -401,7 +516,16 @@ impl<'settings, 'de> serde::de::VariantAccess<'de> for Transmute<'settings> {
         Vis: Visitor<'de>,
     {
         match self.collection {
-            Collection::StructVariant { .. } => todo!(),
+            Collection::StructVariant { .. } => {
+                match self.settings.structs_are_seqs {
+                    false => visitor.visit_map(MapAccess {
+                        transmute: self,
+                        // FIXME?
+                        value: Err(TransmuteError(())),
+                    }),
+                    true => visitor.visit_seq(self),
+                }
+            },
             _ => {
                 let unexp = match self.collection {
                     Collection::UnitVariant { .. } => {
@@ -782,6 +906,24 @@ impl<'settings> serde::ser::SerializeMap for CollectMap<'settings> {
             value.serialize(self.ser).map(|it| self.values.push((key, it)))
         })
     }
+    fn serialize_entry<K, V>(
+        &mut self,
+        key: &K,
+        value: &V,
+    ) -> Result<(), Self::Error>
+    where
+        K: Serialize + ?Sized,
+        V: Serialize + ?Sized,
+    {
+        if self.key.is_ok() {
+            // FIXME?
+            Err(TransmuteError(()))
+        } else {
+            key.serialize(self.ser).and_then(|key| {
+                value.serialize(self.ser).map(|it| self.values.push((key, it)))
+            })
+        }
+    }
     fn end(self) -> Result<Self::Ok, Self::Error> {
         if self.key.is_ok() {
             // FIXME?