From f2b5566c0b536fdb56eb10a0d6067f72d32e2c7f Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Mon, 23 May 2022 16:40:49 +0200 Subject: [PATCH] use smartstring's deserializer to support non borrowed strings The map visitor for Dynamic was expecting a &str for the key, but the serde_json deserializer internally uses a Cow string, which can be Borrowed or Owned. In the case of Owned, the serde_json key deserializer is calling visit_string on the Visitor, which for &str will result in the error: Error("invalid type: string \"a\", expected a borrowed string", line: 0, column: 0) smartstring actually has its own Visitor implementation that handles both cases, so we can use it instead of an explicit conversion. --- Cargo.toml | 2 ++ src/serde/deserialize.rs | 4 ++-- tests/serde.rs | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c103eabf..5c710ef4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ rustyline = { version = "9", optional = true } [dev-dependencies] serde_bytes = "0.11" +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } [features] default = [] @@ -56,6 +57,7 @@ unicode-xid-ident = ["unicode-xid"] # allow Unicode Standard Annex #31 for ident metadata = ["serde", "serde_json", "rhai_codegen/metadata", "smartstring/serde"] # enable exporting functions metadata internals = [] # expose internal data structures debugging = ["internals"] # enable debugging +serde = ["dep:serde", "smartstring/serde"] # implement serde for rhai types # compiling for no-std no_std = ["no-std-compat", "num-traits/libm", "core-error", "libm", "ahash/compile-time-rng"] diff --git a/src/serde/deserialize.rs b/src/serde/deserialize.rs index 320a01f4..2f79ef6a 100644 --- a/src/serde/deserialize.rs +++ b/src/serde/deserialize.rs @@ -143,8 +143,8 @@ impl<'d> Visitor<'d> for DynamicVisitor { fn visit_map>(self, mut map: M) -> Result { let mut m = crate::Map::new(); - while let Some((k, v)) = map.next_entry::<&str, _>()? { - m.insert(k.into(), v); + while let Some((k, v)) = map.next_entry()? { + m.insert(k, v); } Ok(m.into()) diff --git a/tests/serde.rs b/tests/serde.rs index b6541d3d..3d5b7ff7 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -5,6 +5,7 @@ use rhai::{ Dynamic, Engine, EvalAltResult, ImmutableString, INT, }; use serde::{Deserialize, Serialize}; +use serde_json::json; #[cfg(not(feature = "no_index"))] use rhai::Array; @@ -814,3 +815,10 @@ fn test_serde_blob() -> Result<(), Box> { Ok(()) } + +#[test] +fn test_serde_json_borrowed_string() { + let value = json!({ "a": "b" }); + println!("value: {:?}", value); + let _: Dynamic = serde_json::from_value(value).unwrap(); +}