2020-06-20 12:06:17 +08:00
|
|
|
Dynamic Values
|
|
|
|
==============
|
|
|
|
|
|
|
|
{{#include ../links.md}}
|
|
|
|
|
|
|
|
A `Dynamic` value can be _any_ type. However, under [`sync`], all types must be `Send + Sync`.
|
|
|
|
|
|
|
|
|
2020-09-19 12:14:02 +08:00
|
|
|
Use `type_of()` to Get Value Type
|
|
|
|
--------------------------------
|
2020-06-20 12:06:17 +08:00
|
|
|
|
|
|
|
Because [`type_of()`] a `Dynamic` value returns the type of the actual value,
|
|
|
|
it is usually used to perform type-specific actions based on the actual value's type.
|
|
|
|
|
2020-11-13 18:32:18 +08:00
|
|
|
```c
|
2020-06-20 12:06:17 +08:00
|
|
|
let mystery = get_some_dynamic_value();
|
|
|
|
|
2020-12-16 14:57:28 +08:00
|
|
|
switch type_of(mystery) {
|
2020-11-13 18:32:18 +08:00
|
|
|
"i64" => print("Hey, I got an integer here!"),
|
|
|
|
"f64" => print("Hey, I got a float here!"),
|
|
|
|
"string" => print("Hey, I got a string here!"),
|
|
|
|
"bool" => print("Hey, I got a boolean here!"),
|
|
|
|
"array" => print("Hey, I got an array here!"),
|
|
|
|
"map" => print("Hey, I got an object map here!"),
|
|
|
|
"Fn" => print("Hey, I got a function pointer here!"),
|
|
|
|
"TestStruct" => print("Hey, I got the TestStruct custom type here!"),
|
|
|
|
_ => print("I don't know what this is: " + type_of(mystery))
|
2020-06-20 12:06:17 +08:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Functions Returning `Dynamic`
|
|
|
|
----------------------------
|
|
|
|
|
2020-12-29 23:01:34 +08:00
|
|
|
In Rust, sometimes a `Dynamic` forms part of a returned value – a good example is an [array]
|
2020-06-20 12:06:17 +08:00
|
|
|
which contains `Dynamic` elements, or an [object map] which contains `Dynamic` property values.
|
|
|
|
|
|
|
|
To get the _real_ values, the actual value types _must_ be known in advance.
|
|
|
|
There is no easy way for Rust to decide, at run-time, what type the `Dynamic` value is
|
|
|
|
(short of using the `type_name` function and match against the name).
|
|
|
|
|
|
|
|
|
|
|
|
Type Checking and Casting
|
|
|
|
------------------------
|
|
|
|
|
|
|
|
A `Dynamic` value's actual type can be checked via the `is` method.
|
|
|
|
|
|
|
|
The `cast` method then converts the value into a specific, known type.
|
|
|
|
|
|
|
|
Alternatively, use the `try_cast` method which does not panic but returns `None` when the cast fails.
|
|
|
|
|
|
|
|
```rust
|
2020-09-28 22:14:19 +08:00
|
|
|
let list: Array = engine.eval("...")?; // return type is 'Array'
|
|
|
|
let item = list[0]; // an element in an 'Array' is 'Dynamic'
|
2020-06-20 12:06:17 +08:00
|
|
|
|
2020-09-28 22:14:19 +08:00
|
|
|
item.is::<i64>() == true; // 'is' returns whether a 'Dynamic' value is of a particular type
|
2020-06-20 12:06:17 +08:00
|
|
|
|
2020-09-28 22:14:19 +08:00
|
|
|
let value = item.cast::<i64>(); // if the element is 'i64', this succeeds; otherwise it panics
|
|
|
|
let value: i64 = item.cast(); // type can also be inferred
|
2020-06-20 12:06:17 +08:00
|
|
|
|
2020-09-28 22:14:19 +08:00
|
|
|
let value = item.try_cast::<i64>()?; // 'try_cast' does not panic when the cast fails, but returns 'None'
|
2020-06-20 12:06:17 +08:00
|
|
|
```
|
|
|
|
|
|
|
|
Type Name
|
|
|
|
---------
|
|
|
|
|
|
|
|
The `type_name` method gets the name of the actual type as a static string slice,
|
|
|
|
which can be `match`-ed against.
|
|
|
|
|
|
|
|
```rust
|
2020-09-28 22:14:19 +08:00
|
|
|
let list: Array = engine.eval("...")?; // return type is 'Array'
|
|
|
|
let item = list[0]; // an element in an 'Array' is 'Dynamic'
|
2020-06-20 12:06:17 +08:00
|
|
|
|
2020-09-28 22:14:19 +08:00
|
|
|
match item.type_name() { // 'type_name' returns the name of the actual Rust type
|
2020-06-20 12:06:17 +08:00
|
|
|
"i64" => ...
|
|
|
|
"alloc::string::String" => ...
|
|
|
|
"bool" => ...
|
2020-09-28 22:14:19 +08:00
|
|
|
"crate::path::to::module::TestStruct" => ...
|
2020-06-20 12:06:17 +08:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2020-09-28 22:14:19 +08:00
|
|
|
**Note:** `type_name` always returns the _full_ Rust path name of the type, even when the type
|
|
|
|
has been registered with a friendly name via `Engine::register_type_with_name`. This behavior
|
|
|
|
is different from that of the [`type_of`][`type_of()`] function in Rhai.
|
|
|
|
|
2020-06-20 12:06:17 +08:00
|
|
|
|
|
|
|
Conversion Traits
|
|
|
|
----------------
|
|
|
|
|
|
|
|
The following conversion traits are implemented for `Dynamic`:
|
|
|
|
|
|
|
|
* `From<i64>` (`i32` if [`only_i32`])
|
|
|
|
* `From<f64>` (if not [`no_float`])
|
|
|
|
* `From<bool>`
|
|
|
|
* `From<rhai::ImmutableString>`
|
|
|
|
* `From<String>`
|
|
|
|
* `From<char>`
|
|
|
|
* `From<Vec<T>>` (into an [array])
|
2020-09-28 22:14:19 +08:00
|
|
|
* `From<HashMap<String, T>>` (into an [object map])
|
|
|
|
* `From<Instant>` (into a [timestamp] if not [`no_std`])
|