Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rukai/treeflection
A rust library that provides pseudo-reflection for structs and enums
https://github.com/rukai/treeflection
Last synced: about 2 months ago
JSON representation
A rust library that provides pseudo-reflection for structs and enums
- Host: GitHub
- URL: https://github.com/rukai/treeflection
- Owner: rukai
- License: mit
- Created: 2016-10-29T00:37:30.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2020-10-02T12:17:19.000Z (about 4 years ago)
- Last Synced: 2024-10-14T11:49:27.258Z (about 2 months ago)
- Language: Rust
- Homepage:
- Size: 137 KB
- Stars: 22
- Watchers: 3
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: readme.md
- License: license.txt
Awesome Lists containing this project
- AwesomeCppGameDev - treeflection - reflection for structs and enums (Rust)
README
# Treeflection [![Build Status](https://travis-ci.org/rukai/treeflection.svg?branch=master)](https://travis-ci.org/rukai/treeflection) [![Crates.io](https://img.shields.io/crates/v/treeflection.svg)](https://crates.io/crates/treeflection) [![Docs](https://docs.rs/treeflection/badge.svg)](https://docs.rs/treeflection)
## treeflection_derive [![Crates.io](https://img.shields.io/crates/v/treeflection_derive.svg)](https://crates.io/crates/treeflection_derive) [![Docs](https://docs.rs/treeflection_derive/badge.svg)](https://docs.rs/treeflection_derive)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](commandManual.md)
## 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
```rust
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.
```rust
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 [Canon Collision](https://github.com/rukai/canon_collision).
Pull requests are welcome but if the changes go against the needs of Canon Collision you will be stuck with your own fork. :)