From fa3c679b59544b228628b3cc1eaa9de95ee82baf Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 23 Nov 2021 16:44:59 +0800 Subject: [PATCH 1/4] Fix test output. --- codegen/ui_tests/non_clonable.stderr | 14 ++++++++++---- codegen/ui_tests/non_clonable_second.stderr | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/codegen/ui_tests/non_clonable.stderr b/codegen/ui_tests/non_clonable.stderr index 8874257c..cb0e05d1 100644 --- a/codegen/ui_tests/non_clonable.stderr +++ b/codegen/ui_tests/non_clonable.stderr @@ -1,5 +1,11 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied - --> ui_tests/non_clonable.rs:11:23 - | -11 | pub fn test_fn(input: NonClonable) -> bool { - | ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable` + --> ui_tests/non_clonable.rs:11:23 + | +11 | pub fn test_fn(input: NonClonable) -> bool { + | ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable` + | +note: required by a bound in `rhai::Dynamic::cast` + --> $WORKSPACE/src/types/dynamic.rs + | + | pub fn cast(self) -> T { + | ^^^^^ required by this bound in `rhai::Dynamic::cast` diff --git a/codegen/ui_tests/non_clonable_second.stderr b/codegen/ui_tests/non_clonable_second.stderr index e9d4fc80..359a145c 100644 --- a/codegen/ui_tests/non_clonable_second.stderr +++ b/codegen/ui_tests/non_clonable_second.stderr @@ -1,5 +1,11 @@ error[E0277]: the trait bound `NonClonable: Clone` is not satisfied - --> ui_tests/non_clonable_second.rs:11:27 - | -11 | pub fn test_fn(a: u32, b: NonClonable) -> bool { - | ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable` + --> ui_tests/non_clonable_second.rs:11:27 + | +11 | pub fn test_fn(a: u32, b: NonClonable) -> bool { + | ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable` + | +note: required by a bound in `rhai::Dynamic::cast` + --> $WORKSPACE/src/types/dynamic.rs + | + | pub fn cast(self) -> T { + | ^^^^^ required by this bound in `rhai::Dynamic::cast` From 1721d0dfa0cefb6d96218711bc985a0c23a8bf5b Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 24 Nov 2021 08:57:43 +0800 Subject: [PATCH 2/4] Bump version. --- CHANGELOG.md | 4 ++++ Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb1f352d..87c29f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ Rhai Release Notes ================== +Version 1.2.2 +============= + + Version 1.2.1 ============= diff --git a/Cargo.toml b/Cargo.toml index 24c73cd8..b6f7ffa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [".", "codegen"] [package] name = "rhai" -version = "1.2.1" +version = "1.2.2" edition = "2018" authors = ["Jonathan Turner", "Lukáš Hozda", "Stephen Chung", "jhwgh1968"] description = "Embedded scripting for Rust" From 65d17a7859b3b2a443fdf8abe116cd86b8811011 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Thu, 2 Dec 2021 12:49:57 +0800 Subject: [PATCH 3/4] Do not construct function pointer for invalid function names. --- src/optimizer.rs | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/optimizer.rs b/src/optimizer.rs index 1ac33788..822c11ee 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -9,13 +9,14 @@ use crate::func::hashing::get_hasher; use crate::tokenizer::Token; use crate::types::dynamic::AccessMode; use crate::{ - calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnPtr, ImmutableString, - Module, Position, Scope, StaticVec, AST, + calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnPtr, Module, Position, + Scope, StaticVec, AST, }; #[cfg(feature = "no_std")] use std::prelude::v1::*; use std::{ any::TypeId, + convert::TryFrom, hash::{Hash, Hasher}, mem, ops::DerefMut, @@ -894,7 +895,10 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) { *expr = mem::take(lhs); } // lhs && rhs - (lhs, rhs) => { optimize_expr(lhs, state, false); optimize_expr(rhs, state, false); } + (lhs, rhs) => { + optimize_expr(lhs, state, false); + optimize_expr(rhs, state, false); + } }, // lhs || rhs Expr::Or(ref mut x, _) => match (&mut x.lhs, &mut x.rhs) { @@ -916,7 +920,10 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) { *expr = mem::take(lhs); } // lhs || rhs - (lhs, rhs) => { optimize_expr(lhs, state, false); optimize_expr(rhs, state, false); } + (lhs, rhs) => { + optimize_expr(lhs, state, false); + optimize_expr(rhs, state, false); + } }, // eval! @@ -928,24 +935,20 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) { if !x.is_qualified() // Non-qualified && state.optimization_level == OptimizationLevel::Simple // simple optimizations && x.args.len() == 1 - && x.args[0].is_constant() && x.name == KEYWORD_FN_PTR + && x.args[0].is_constant() => { let fn_name = match x.args[0] { - Expr::Stack(slot, _) => Some(x.constants[slot].clone()), - Expr::StringConstant(ref s, _) => Some(s.clone().into()), - _ => None + Expr::Stack(slot, _) => x.constants[slot].clone(), + Expr::StringConstant(ref s, _) => s.clone().into(), + _ => Dynamic::UNIT }; - if let Some(fn_name) = fn_name { - if fn_name.is::() { - state.set_dirty(); - let fn_ptr = FnPtr::new_unchecked( - fn_name.as_str_ref().expect("`ImmutableString`").into(), - StaticVec::new() - ); - *expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos); - } + if let Ok(fn_ptr) = fn_name.into_immutable_string().map_err(|err| err.into()).and_then(FnPtr::try_from) { + state.set_dirty(); + *expr = Expr::DynamicConstant(Box::new(fn_ptr.into()), *pos); + } else { + optimize_expr(&mut x.args[0], state, false); } } From 068e8c647e7c419daa23a6568122f1ac1d48f593 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Thu, 2 Dec 2021 12:50:11 +0800 Subject: [PATCH 4/4] Support Option in from_dynamic. --- CHANGELOG.md | 5 +++++ src/serde/de.rs | 11 +++++++++-- tests/serde.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87c29f08..cb4a4bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ Rhai Release Notes Version 1.2.2 ============= +Bug fixes +--------- + +* `from_dynamic` now supports deserializing `Option`. + Version 1.2.1 ============= diff --git a/src/serde/de.rs b/src/serde/de.rs index 8c7420e2..d860c3e4 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -363,8 +363,15 @@ impl<'de> Deserializer<'de> for &mut DynamicDeserializer<'de> { self.type_error() } - fn deserialize_option>(self, _: V) -> Result> { - self.type_error() + fn deserialize_option>( + self, + visitor: V, + ) -> Result> { + if self.value.is::<()>() { + visitor.visit_none() + } else { + visitor.visit_some(self) + } } fn deserialize_unit>(self, visitor: V) -> Result> { diff --git a/tests/serde.rs b/tests/serde.rs index ac98dc37..95bde973 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -746,3 +746,32 @@ fn test_serde_json() -> serde_json::Result<()> { Ok(()) } + +#[test] +#[cfg(not(feature = "no_object"))] +fn test_serde_optional() -> Result<(), Box> { + #[derive(Debug, Clone, PartialEq, Eq, Deserialize)] + struct TestStruct { + foo: Option, + } + + let mut engine = Engine::new(); + engine.register_type_with_name::("TestStruct"); + + let r = engine.eval::("#{ foo: 'a' }")?; + + assert_eq!( + from_dynamic::(&r)?, + TestStruct { foo: Some('a') } + ); + + let r = engine.eval::("#{ foo: () }")?; + + assert_eq!(from_dynamic::(&r)?, TestStruct { foo: None }); + + let r = engine.eval::("#{ }")?; + + assert_eq!(from_dynamic::(&r)?, TestStruct { foo: None }); + + Ok(()) +}