Browse Source

Fix serde deserializer to use deserialize_string and add test.

Kestrel 2 months ago
parent
commit
347904a453
3 changed files with 51 additions and 2 deletions
  1. 1 0
      .gitignore
  2. 1 1
      Cargo.toml
  3. 49 1
      src/lib.rs

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 /target
 /Cargo.lock
+/rust-analyzer.json

+ 1 - 1
Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "stringstore"
-version = "0.1.3"
+version = "0.1.4"
 edition = "2021"
 author = "kestrel <kestrel@flying-kestrel.ca>"
 repository = "https://git.flying-kestrel.ca/kestrel/stringstore"

+ 49 - 1
src/lib.rs

@@ -183,7 +183,7 @@ impl<'de, Tag> serde::de::Deserialize<'de> for StoredString<Tag> {
     where
         D: serde::Deserializer<'de>,
     {
-        deserializer.deserialize_str(StoredStringVisitor::<Tag>(std::marker::PhantomData))
+        deserializer.deserialize_string(StoredStringVisitor::<Tag>(std::marker::PhantomData))
     }
 }
 
@@ -242,6 +242,54 @@ mod test_stored_string {
         assert_eq!(ss, ss2);
         assert_eq!(ss, ss3);
     }
+
+    #[cfg(feature = "serde")]
+    #[test]
+    fn deserialization() {
+        use serde::Deserialize;
+        // mocked deserializer that provides exactly a single string
+        struct MockDeser<'de>(&'de mut usize);
+
+        impl<'de> serde::Deserializer<'de> for &'de mut MockDeser<'de> {
+            type Error = serde::de::value::Error;
+            fn deserialize_any<V: serde::de::Visitor<'de>>(
+                self,
+                _: V,
+            ) -> Result<V::Value, Self::Error> {
+                panic!()
+            }
+            fn deserialize_str<V: serde::de::Visitor<'de>>(
+                self,
+                visitor: V,
+            ) -> Result<V::Value, Self::Error> {
+                self.deserialize_string(visitor)
+            }
+            fn deserialize_string<V: serde::de::Visitor<'de>>(
+                self,
+                visitor: V,
+            ) -> Result<V::Value, Self::Error> {
+                *self.0 += 1;
+                if *self.0 == 1 {
+                    visitor.visit_string(String::from("string"))
+                } else {
+                    panic!(
+                        "trying to deserialize a second string; state is now {}",
+                        self.0
+                    )
+                }
+            }
+
+            serde::forward_to_deserialize_any!(
+                bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char bytes
+                byte_buf option unit unit_struct newtype_struct seq tuple
+                tuple_struct map struct enum identifier ignored_any
+            );
+        }
+
+        let mut state = 0;
+        let mut deser = MockDeser(&mut state);
+        assert_eq!(SST::deserialize(&mut deser), Ok(SST::new("string")));
+    }
 }
 
 static OS_STR_STORE: std::sync::LazyLock<