36 个版本

0.1.35 2020年10月2日
0.1.33 2020年7月26日
0.1.32 2019年10月26日
0.1.31 2017年11月30日
0.1.9 2016年11月26日

#802数据结构


3 crates 中使用

MIT 许可证

70KB
1.5K SLoC

Treeflection 构建状态 Crates.io 文档

treeflection_derive Crates.io 文档

Treeflection 在结构体、集合和原始类型树上执行存储为字符串的命令。

命令

将一个结构体中的 Vec 的 int 设置为 50 的命令如下:someHashMap["key"].someChild.anotherChild[0]:set 50

有关完整语法,请参阅命令手册

用法

必须为树中的每个类型实现 Node 特性。然后使用命令字符串创建一个新的 NodeRunner,并将其传递给根节点的 node_step 方法。然后将 NodeRunner 传递给命令中指定的子节点,并在指定的最终子节点上执行命令。使用 treeflection_derive crate 来为您的结构体 #[Derive(Node)] 或编写自己的处理程序。

Vec 示例

extern crate treeflection;
use treeflection::{NodeRunner, Node};

pub fn main() {
    let mut test_vec = vec!(0, 413, 358, 42);

    let command = "[1]:get";
    let result = test_vec.node_step(NodeRunner::new(command).unwrap());
    assert_eq!(result, "413");

    let command = "[1]:set 1111";
    let result = test_vec.node_step(NodeRunner::new(command).unwrap());
    assert_eq!(result, "");

    let command = "[1]:get";
    let result = test_vec.node_step(NodeRunner::new(command).unwrap());
    assert_eq!(result, "1111");
}

自定义结构体示例

使用treeflection_derive crate来#[Derive(Node)]您的自定义结构体或编写自己的处理器。您的结构体还需要实现Serialize、Deserialize、Default和Clone特质,以及extern crate serde_json。这是因为serde_json用于获取/设置整个结构体。

目前必须包含use treeflection::{NodeRunner, Node, NodeToken};,以便宏可以访问这些类型。

extern crate treeflection;
#[macro_use] extern crate treeflection_derive;
#[macro_use] extern crate serde_derive;
extern crate serde_json;

use treeflection::{NodeRunner, Node, NodeToken};

#[derive(Node, Serialize, Deserialize, Default, Clone)]
struct SolarSystem {
    pub mercury:  Planet,
    pub earth:    Planet,
    pub mars:     Planet,
        planet_x: Planet,
}

impl SolarSystem {
    pub fn new() -> SolarSystem {
        SolarSystem {
            mercury:  Planet { radius: 2440.0 },
            earth:    Planet { radius: 6371.0 },
            mars:     Planet { radius: 3390.0 },
            planet_x: Planet { radius: 1337.0 },
        }
    }
}

#[NodeActions(
    // we want the function circumference to be accessible via treeflection by the same name
    NodeAction(function="circumference", return_string),

    // we want the function explode_internal_naming_scheme to be accessible via treeflection
    // by the name explode and we want to ignore its return value so that it will compile despite not returning a String
    NodeAction(action="explode", function="explode_internal_naming_scheme"),
)]
#[derive(Node, Serialize, Deserialize, Default, Clone)]
struct Planet {
    pub radius: f32
}

impl Planet {
    pub fn circumference(&self) -> String {
        (self.radius * 2.0 * std::f32::consts::PI).to_string()
    }

    pub fn explode_internal_naming_scheme(&mut self) {
        self.radius = 0.0;
    }
}


pub fn main() {
    let mut ss = SolarSystem::new();

    // serialize the whole struct into json
    let command = ":get";
    let result = ss.node_step(NodeRunner::new(command).unwrap());
    assert_eq!(result,
r#"{
  "mercury": {
    "radius": 2440.0
  },
  "earth": {
    "radius": 6371.0
  },
  "mars": {
    "radius": 3390.0
  },
  "planet_x": {
    "radius": 1337.0
  }
}"#);

    // access properties
    let command = "earth.radius:get";
    let result = ss.node_step(NodeRunner::new(command).unwrap());
    assert_eq!(result, "6371");

    // call methods on the struct
    let command = "earth:circumference";
    let result = ss.node_step(NodeRunner::new(command).unwrap());
    assert_eq!(result, "40030.176");

    let command = "earth:explode";
    let result = ss.node_step(NodeRunner::new(command).unwrap());
    assert_eq!(result, "");
    assert_eq!(ss.earth.radius, 0.0);

    // private properties are not accessible via treeflection
    let command = "planet_x:get";
    let result = ss.node_step(NodeRunner::new(command).unwrap());
    assert_eq!(result, "SolarSystem does not have a property 'planet_x'");
}

贡献

这个库是为Canon Collision的具体需求而设计的。欢迎提交拉取请求,但如果更改与Canon Collision的需求相冲突,您将只能坚持使用自己的分支。:)

依赖关系

~1.1–2MB
~42K SLoC