tref/lib.rs
1//! # TREF
2//!
3//! TREF is a plain text file format to describe trees in a human readable way.
4//!
5//! With TREF a human can write a tree and understand the structure by having a quick look, because it is designed to be both easy to read for humans and easy to parse for machines.
6//!
7//! Writing a tree in a file can be useful for many reasons: as a config file for an application, to store information that can be modified and read by an app and its user, to serialize tree-like memory structures, etc.
8//!
9//! A simple TREF file looks like:
10//!
11//! ```tref
12//! # A simple tree.
13//! [my_tree]
14//! + root_nodess
15//! + + child_1
16//! + + + child_1_1
17//! + + + child_1_2
18//! + + child_2
19//! + + + child_2_1
20//! + + child_3
21//! ```
22//! File `simpletree.tref`
23//!
24//! Check out the repo [README](https://github.com/asllop/tref/blob/master/README.md) for further details about the TREF format.
25//!
26//! # Examples
27//!
28//! To load this crate just use:
29//!
30//! ```
31//! use tref;
32//! ```
33//!
34//! Parse the `file.tref` file, traverse `my_tree`, modify tree and serialize:
35//!
36//! ```
37//! use std::{fs::File, io::{BufReader, BufWriter}};
38//! use tref::*;
39//!
40//! if let Ok(file) = File::open("file.tref") {
41//! // Parse document
42//! match <tref::Model>::parse(BufReader::new(file)) {
43//! Ok(mut forest) => {
44//! // Get the `my_tree` model.
45//! if let Some(tree) = forest.get_mut_tree("my_tree") {
46//! // Traverse the tree using the BFS algorithm
47//! for (n, _) in tree.iterators().bfs() {
48//! // Print the node content
49//! println!("{}", n.get_content_ref().get_val());
50//! }
51//!
52//! // Unlink node at index 1
53//! tree.unlink_node(1);
54//! }
55//!
56//! // Serialize the resulting forest back into a TREF file
57//! let f = File::create("serialized.tref").expect("Unable to create file");
58//! let mut buf_writer = BufWriter::new(f);
59//! match <tref::Model>::serialize(&forest, &mut buf_writer) {
60//! Ok(num_lines) => {
61//! println!("Tree serialized correctly, num lines = {}", num_lines);
62//! },
63//! Err(e) => {
64//! println!("Failed serializing tree: {}", e);
65//! }
66//! }
67//! },
68//! Err(e) => {
69//! println!("Could not parse TREF: {}", e)
70//! }
71//! }
72//! }
73//! ```
74//!
75//! The example above uses [`unlink_node()`][`socarel::Tree::unlink_node`] to disconnect a node from the tree. To know more about how to manupulate trees, please check out the [`socarel`] crate documentation.
76//!
77//! # Dialects
78//!
79//! TREF also supports user defined dialects, that are trees that have nodes with a specific format. This is achived using the [`NodeContent`][`socarel::NodeContent`] trait.
80//!
81//! For example, imagine we want to model a tree with nodes that can only have integer values. Something like:
82//!
83//! ```tref
84//! [my_dialect_tree]
85//! + 1000
86//! + + 800
87//! + + + 2500
88//! + + + 130
89//! ```
90//!
91//! First we have to define a [`NodeContent`][`socarel::NodeContent`] to parse our custom nodes:
92//!
93//! ```
94//! # use tref::*;
95//!
96//! pub struct IntegerNode {
97//! num: i32,
98//! content: String
99//! }
100//!
101//! impl IntegerNode {
102//! pub fn get_num(&self) -> i32 {
103//! self.num
104//! }
105//! }
106//!
107//! impl NodeContent for IntegerNode {
108//! fn new(content: &str) -> Option<Self> {
109//! // Try to parse the node content as integer
110//! match content.trim().parse() {
111//! Ok(num) => {
112//! let content = String::from(content);
113//! Some(IntegerNode { num, content })
114//! },
115//! Err(_) => None
116//! }
117//! }
118//!
119//! fn get_val(&self) -> &str {
120//! &self.content
121//! }
122//!
123//! fn gen_content(&self) -> String {
124//! String::from(self.get_val())
125//! }
126//! }
127//! ```
128//!
129//! And then use it to parse the tree:
130//!
131//! ```
132//! # use socarel::NodeContent;
133//! # use std::io::BufReader;
134//! # pub struct IntegerNode;
135//! # impl NodeContent for IntegerNode {
136//! # fn new(content: &str) -> Option<Self> { None }
137//! # fn get_val(&self) -> &str { "" }
138//! # fn gen_content(&self) -> String { String::new() }
139//! # }
140//! let tref =
141//! "[my_dialect_tree]\n\
142//! + 1000\n\
143//! + + 800\n\
144//! + + + 2500\n\
145//! + + + 130\n";
146//!
147//! let forest = tref::Model::<IntegerNode>::parse(BufReader::new(tref.as_bytes()));
148//! ```
149//!
150//! All nodes inside the tree will be of type `IntegerNode`.
151//!
152//! The [`NodeContent::new()`][`socarel::NodeContent::new()`] is called every time a node of the tree is parsed. It returns an [`Option`], that means it can be None, in which case the TREF parser will fail, returing an error.
153
154mod parser;
155mod stack;
156mod model;
157mod error;
158
159pub use model::*;
160pub use error::*;
161pub use socarel::NodeContent;
162
163#[cfg(test)]
164mod tests;