rhai/doc/src/language/dynamic.md
2020-12-29 23:01:34 +08:00

3.4 KiB
Raw Blame History

Dynamic Values

{{#include ../links.md}}

A Dynamic value can be any type. However, under [sync], all types must be Send + Sync.

Use type_of() to Get Value Type

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.

let mystery = get_some_dynamic_value();

switch type_of(mystery) {
    "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))
}

Functions Returning Dynamic

In Rust, sometimes a Dynamic forms part of a returned value a good example is an [array] 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.

let list: Array = engine.eval("...")?;      // return type is 'Array'
let item = list[0];                         // an element in an 'Array' is 'Dynamic'

item.is::<i64>() == true;                   // 'is' returns whether a 'Dynamic' value is of a particular type

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

let value = item.try_cast::<i64>()?;        // 'try_cast' does not panic when the cast fails, but returns 'None'

Type Name

The type_name method gets the name of the actual type as a static string slice, which can be match-ed against.

let list: Array = engine.eval("...")?;      // return type is 'Array'
let item = list[0];                         // an element in an 'Array' is 'Dynamic'

match item.type_name() {                    // 'type_name' returns the name of the actual Rust type
    "i64" => ...
    "alloc::string::String" => ...
    "bool" => ...
    "crate::path::to::module::TestStruct" => ...
}

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.

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])
  • From<HashMap<String, T>> (into an [object map])
  • From<Instant> (into a [timestamp] if not [no_std])