# Stringly-Typed Rust
[![Build Status](https://travis-ci.org/Michael-F-Bryan/stringly-typed.svg?branch=master)](https://travis-ci.org/Michael-F-Bryan/stringly-typed)
A crate for updating values using a stringly-typed API.
## Typical Use Case
Imagine you're working on a system that uses a lot of runtime configuration to
alter the behaviour of the application. For whatever reason it isn't practical
to stop the entire system just to update a single configuration key, so you need
the ability to update configuration on the fly... How do you do it?
- Re-upload the entire configuration file for every change
- The caller sends just the key-value pair they want to update and you execute
the update by:
- Serializing to a more loosly-typed form (e.g. `serde_json::Value`), make the
update (e.g. `config["foo"]["bar"][3] = 42`), then deserialize back to the
original type
- Write a massive switch-case statement which will update different fields
depending on the provided key (e.g. `match key { "foo.bar" => config.foo.bar = value }`)
In terms of difficulty the first option is quite nice. You just wrap your
`config` with a `RWLock` and all your configuration update issues go away,
however you now pay the price of serializing/deserializing and network transfer.
Plus it can feel awfully wasteful to copy around an entire file just to change
one key.
TODO: Mention how serialize-deserialize is expensive
TODO: Mention this is essentially automating the massive switch-case statement
```rust
#[macro_use]
extern crate stringly_typed;
use stringly_typed::{StringlyTyped, Value};
#[derive(StringlyTyped)]
struct Config {
motion_parameters: MotionParameters,
target_bed_temp: f64,
version: String,
...
}
#[derive(StringlyTyped)]
struct MotionParameters {
max_translation_velocity: f64,
max_vertical_velocity: f64,
}
// Assume we were told which key and value to update over the network or some
// other dynamic source
let key = "motion_parameters.max_vertical_velocity";
let value = Value::Double(40.0);
cfg.set(key, value)?;
assert_eq!(cfg.motion_parameters.max_vertical_velocity, 40.0);
```
## Features
- [x] Works with `no_std`
- [ ] Supports enums
- [ ] Supports arrays
## Benchmarks
The main goal of this crate *isn't* performance, however it performs quite well
compared to the "usual" static assignment (i.e. normal Rust with the dot
operator), and still beats the serialize-update-deserialize method.
```text
test static_assign ... bench: 81 ns/iter (+/- 6)
test stringly_update ... bench: 167 ns/iter (+/- 12)
test serialize_deserialize ... bench: 1,243 ns/iter (+/- 343)
```
As with any benchmark, we're only comparing three contrived use cases so take
these numbers with a grain of salt.