#typed #stringly #run-time #values #updating #indexing #type

no-std stringly_typed

一个用于在运行时更新值并对 Rust 类型进行索引的crate

1 个不稳定版本

使用旧的Rust 2015

0.1.0 2018年4月17日

#11 in #updating

MIT 协议

13KB
221 代码行,不包括注释

Stringly-Typed Rust

Build Status

一个使用字符串类型API更新值的crate。

典型用例

想象你正在开发一个使用大量运行时配置来改变应用程序行为的系统。出于某种原因,停止整个系统来更新单个配置键并不实际,因此你需要能够动态更新配置...你将如何做到这一点?

  • 每次更改都重新上传整个配置文件
  • 调用者只发送他们想要更新的键值对,然后你通过以下方式执行更新
    • 序列化为更宽松的类型形式(例如 serde_json::Value),进行更新(例如 config["foo"]["bar"][3] = 42),然后反序列化为原始类型
    • 编写一个巨大的switch-case语句,根据提供的键更新不同的字段(例如 match key { "foo.bar" => config.foo.bar = value }

在难度方面,第一种方法相当不错。你只需用 RWLock 包装你的 config,所有配置更新问题都会消失,但你现在要付出序列化/反序列化和网络传输的代价。而且,仅仅为了改变一个键就复制整个文件,这感觉非常浪费。

待办事项:提及序列化/反序列化很昂贵

待办事项:提及这实际上是在自动化巨大的switch-case语句

#[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);

特性

  • no_std 兼容
  • 支持枚举
  • 支持数组

基准测试

这个crate的主要目标 不是 性能,但是与“通常”的静态赋值(即带有点操作符的正常Rust)相比,它表现得相当不错,并且仍然优于序列化-更新-反序列化方法。

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)

与任何基准测试一样,我们只比较了三个人为的用例,所以请对这些数字持保留态度。

依赖关系

~2MB
~48K SLoC