Closed MaximeLassalleHub closed 1 year ago
I don't think you're missing anything... a Dynamic
can hold any data type including your BigDecimal
.
So what you described is correct behaviour.
Maybe if you can share a snippet to demonstrate what you are trying to achieve.
Hi @schungx ,
I've written a few tests to show you up the problem (sorry for the bad indentation due to copy / paste).
So it looks like evaluating a big decimal works if the return value is typed as BigDecimal
but not as Dynamic
.
On my side , I really need to execute evaluations in a generic manner and it's not an option to provide an explicit type unfortunately.
As you can observe , it works fine with RustDecimal
even with Dynamic
return value type (when enabling the "decimal" feature flag only).
I assume something needs to be done to make that work with a custom crate like BigDecimal
.
Thanks for helping out,
Regards,
Maxime.
mod test_decimal {
// bigdecimal = { version = "0.4", features = [ "serde" ] }
use bigdecimal::BigDecimal;
// rhai = { version = "1.13.0", features = [ "decimal", "serde", "sync" ] }
use rhai::{serde::to_dynamic, Dynamic, Engine, Scope};
#[test]
// fails for bigdecimal when return value is Dynamic
fn evaluates_dynamic_big_decimal_correctly() {
let mut rhai_engine = Engine::new();
rhai_engine.register_fn("get_bigdec", |value: i64| BigDecimal::from(value));
let res: Result<Dynamic, Box<rhai::EvalAltResult>> =
rhai_engine.eval_expression_with_scope(&mut Scope::new(), "get_bigdec(14)");
println!("res {:?}", res);
// output:
// res Ok(bigdecimal::BigDecimal)
// displays the type name (why ?!)
// is there something I need to add to the engine so it can retrieve the actual bigdecimal value from the Dynamic result
assert_eq!(
res.unwrap().to_string(),
to_dynamic(BigDecimal::from(14)).unwrap().to_string()
);
}
#[test]
// works for rust_decimal when return value is Dynamic
fn evaluates_dynamic_rust_decimal_correctly() {
let mut rhai_engine = Engine::new();
rhai_engine.register_fn("get_dec", |value: i64| rust_decimal::Decimal::from(value));
let res: Result<Dynamic, Box<rhai::EvalAltResult>> =
rhai_engine.eval_expression_with_scope(&mut Scope::new(), "get_dec(14)");
println!("res {:?}", res);
// output:
// res Ok(14)
assert_eq!(
res.unwrap().to_string(),
to_dynamic(rust_decimal::Decimal::from(14))
.unwrap()
.to_string()
);
}
#[test]
// works for bigdecimal when return value is explicit BigDecimal
fn evaluates_explictly_typed_dynamic_big_decimal_correctly() {
let mut rhai_engine = Engine::new();
rhai_engine.register_fn("get_bigdec", |value: i64| BigDecimal::from(value));
let res: Result<BigDecimal, Box<rhai::EvalAltResult>> =
rhai_engine.eval_expression_with_scope(&mut Scope::new(), "get_bigdec(14)");
println!("res {:?}", res);
// output:
// res Ok(BigDecimal("14"))
assert_eq!(
res.unwrap().to_string(),
to_dynamic(BigDecimal::from(14)).unwrap().to_string()
);
}
}
Right away, I see that you're using to_dynamic
which uses serde
to serialize data. It is most likely NOT what you want, and you don't need to use serde
to convert to Dynamic
. Your problem probably came from no serde
support for BigDecimal
?
To convert a BigDecimal
to Dynamic
:
let value = BigDecimal::from(42);
let dynamic = Dynamic::from(value);
To convert a Dynamic
into BigDecimal
:
let dynamic = ....; // get a Dynamic value, from script perhaps?
let value: BigDecimal = dynamic.cast();
// or...
let value: BigDecimal = dynamic.try_cast()?;
Now, printing a BigDecimal
outside of Rhai is problematic, as you'd have to do it yourself. BigDecimal
is treated as a custom type (since it is not a built-in Rhai data type). There is no facility in Dynamic
to detect whether a custom type can be printed or not, so it defaults to just printing the name.
You need to get the value inside the Dynamic
and print it yourself, most likely using Dynamic::read_lock
.
For details on what you can use on Dynamic
, see: https://rhai.rs/book/language/dynamic-rust.html
Is this issue resolved?
OK closing this now. If you have any further issues, feel free to reopen.
Hi there,
I'm integrating BigDecimal with Rhai in a project.
I'm perfectly able to call native functions with BigDecimal parameters.
The problem is the values returned from these functions in BigDecimal type seem to fail to be converted to Dynamic at some point.
I get the type name "bigdecimal::BigDecimal" in scope when getting the Dynamic value of a BigDecimal passed to the engine via engine.eval_expression_with_scope.
I've tried to build a custom type but it didn't help.
What am I missing please ?
Thanks