A rust library that provides pseudo-reflection for structs and enums
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
treeflection
treeflection_derive
.gitignore
.travis.yml
Cargo.toml
commandManual.md
license.txt
readme.md
rust-toolchain

readme.md

Treeflection Build Status dependency status

Treeflection runs a command stored as a string on a tree of structs, collections and primitive types.

Commands

A command to set an int in a Vec in a struct in another struct in a Hashmap to the value 50 looks like: someHashMap["key"].someChild.anotherChild[0]:set 50

For the full syntax take a look at the Command Manual

Usage

The Node trait must be implemented for every type in the tree. Then a new NodeRunner is created using the command string and passed to the node_step method of the root node. The NodeRunner is then passed to the children specified in the command and then runs the command on the final specified child. Use the treeflection_derive crate to #[Derive(Node)] your own structs or write your own handlers.

Vec example

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");
}

Custom struct example

Use the treeflection_derive crate to #[Derive(Node)] your own structs or write your own handlers. Your structs also need to impl the traits Serialize, Deserialize, Default and Clone as well as extern crate serde_json. This is because serde_json is used to get/set entire structs.

Currently use treeflection::{NodeRunner, Node, NodeToken}; must be included so the macro can access these types.

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'");
}

Contributing

This library is designed around the specific needs of PF Sandbox. Pull requests are welcome but if the changes go against the needs of PF Sandbox you will be stuck with your own fork. :)