What in the Value ?

Rust's core strength is its ability to provide memory safety and performance guarantees at compile-time, which is achieved through its ownership and borrowing system. But ability for the developer to handle a dynamic data types defined at run-time for the applications written in Rust is still important endeavor and it is improving versatility of the application while providing an ability to handle a wide range of use cases.

Various interpreted DSL languages created in Rust uses run-time dynamic data type system created for the specific language. Excellent crate Serde also implements trait Value that's allow to handle dynamic datatypes in run-time. But none of those solutions is not perfect for a Rust developers as they ether focus on specific DSL or handling JSON values.

rustdynamic is a crate, created for Rust language, implementing primitives that will be helping to Rust developer with the specific issue of handling dynamic data types defined at run-time. Currently, rustdynamic supports following data types:

Dynamic values are wrapped and stored inside a Value structure and could be cast-able back into original Rust value.

```rust use rust_dynamic::value::Value;

let mut value = Value::from(42).unwrap(); println!("Type of the stored value is {}", &value.typename()); println!("Dynamic value of the value is {:?}", &value.castinteger());

```

What are the properties of dynamically-typed objects

How to create a dynamically-typed values

rust_dynamic crate supports a number of function-primitives that will take a raw value and return a wrapped Dynamic object.

| Function name | Description | |---|---| | Value::fromfloat() | Create dynamic object from f64 float number | | Value::fromfloat32() | Create dynamic object from f32 float number | | Value::frominteger() | Create dynamic object from i64 float number | | Value::frominteger32() | Create dynamic object from i32 float number | | Value::frombool() | Create dynamic object from boolean value | | Value::fromstring() | Create dynamic object from Rust String | | Value::fromstr() | Create dynamic object from Rust &str | | Value::frombin() | Create dynamic object of type BINARY from Vec | | Value::pair() | Create dynamic object of type PAIR from the pair of values | | Value::list() | Create empty dynamic object of type LIST | | Value::from_list() | Create dynamic object of type LIST and initialize it from Vec | | Value::none() | Create dynamic object that wraps value of None | | Value::nodata() | Create dynamic object that contains no data |

There are generic function Value::from() that will automatically cast proper data type and ether return object or error message.

How to cast Rust value from dynamically-typed values

rust_dynamic supports a number of casting functions that will try to extract wrapped value from the object that holds dynamically-typed value.

| Function name | Description | |---|---| | Value::castfloat() | Return f64 number from FLOAT object | | Value::castinteger() | Return i64 number from INTEGER object | | Value::castbool() | Return boolean from BOOL object | | Value::caststring() | Return String from STRING object | | Value::castbin() | Return Vec from BINARY object | | Value::castlist() | Return Vec from LIST object |

Example:

```rust use rust_dynamic::value::Value;

// First we create a dynamically-typed value from a raw static value let mut value = Value::from(42).unwrap();

// Then we can cast raw value back from the dynamic object let rawvalue = value.castinteger().unwrap() ```

How to serialize and deserialize dynamically-typed values

There are two serialization formats that rust_dynamic presently supports: JSON and Bincode.

| Function name | Description | |---|---| | Value::tojson() | Return JSON representation of dynamically-typed value | | Value::tobinary() | Return Bincode representation of dynamically-typed value | | Value::fromjson() | Takes string containing JSON representation of the dynamically-typed object and return re-created Value object | | Value::frombinary() | Takes Vec containing Bincode representation of the dynamically-typed object and return re-created Value object |

Example:

rust // This call will create a new dynamic value let mut data = Value::from(42 as i64).unwrap(); // This call will serialize object to Bincode format let bin_out = data.to_binary().unwrap(); // This will re-create an object from it's Bincode representation let mut data2 = Value::from_binary(bin_out).unwrap();

Functional operations with dynamically-typed values

While rust_dynamic crate is not strive to provide a full-featured functional interface to the dynamic values, some functionality that specific to a Functional programming has been implemented.

| Function name | Description | |---|---| | Value::bind() | Takes a reference to a function that accepts Value as a parameter, that function is called with passed current object and new Value object returned | | Value::map() | Execute function to each element of the LIST or to the value and return new Value | | Value::map_float() | Execute function to each FLOAT element of the LIST or to the value and return new Value | | Value::push() | Ether add a new value to the list, or return a new Value |

How to use dynamically-typed objects as HashMap keys

```rust use std::collections::HashMap;

// This call will create a key object. Key object can be of any supported type let key = Value::from(42.0 as f64).unwrap();

// Then we are creating a HashMap let mut h: HashMap = HashMap::new();

// and store a key->value association h.insert(key, "value".to_string()); ```

How to iterate over dynamically-typed objects

rust let mut c = 0.0; // Let's create a object of LIST type and push two elements into list let v = Value::list() .push(Value::from(1.0 as f64).unwrap()) .push(Value::from(41.0 as f64).unwrap()); // We can iterate over dynamically-typed object for i in v { c += i.cast_float().unwrap(); }

How to map over dynamically-typed objects

In this example we are applying f64::sin function to all iterable values of the dynamically-typed object

rust let mut v = Value::from(42.0).unwrap(); v = v.map_float(f64::sin);