Terrace Rust
A Rust implementation of the Terrace language specification - a simple structured data syntax for configuration, content authoring, and DSLs.
Installation
Add this to your Cargo.toml:
[dependencies]
terrace = "0.1"
Usage
Basic Parsing
use terrace::{TerraceDocument, StringReader};
#[tokio::main]
async fn main() {
let content = r#"
config
database
host localhost
port 5432
server
port 3000
host 0.0.0.0
"#;
let reader = StringReader::new(content);
let mut doc = TerraceDocument::with_reader(reader);
while let Some(node) = doc.next().await {
println!("Level: {}, Head: '{}', Tail: '{}'",
node.level(), node.head(), node.tail());
}
}
Working with Nodes
use terrace::{TerraceDocument, StringReader};
#[tokio::main]
async fn main() {
let content = "user john_doe active";
let reader = StringReader::new(content);
let mut doc = TerraceDocument::with_reader(reader);
if let Some(node) = doc.next().await {
assert_eq!(node.head(), "user");
assert_eq!(node.tail(), "john_doe active");
assert_eq!(node.level(), 0);
assert!(node.is("user"));
}
}
Filtering and Mapping
use terrace::{TerraceDocument, StringReader};
#[tokio::main]
async fn main() {
let content = r#"
users
user alice active
user bob inactive
user charlie active
"#;
let reader = StringReader::new(content);
let doc = TerraceDocument::with_reader(reader);
// Find all active users
let active_users = doc.filter(|node| {
node.head() == "user" && node.tail().contains("active")
}).await;
println!("Found {} active users", active_users.len());
}
API Reference
TerraceDocument
The main document iterator that parses Terrace documents.
new(reader, indent)- Create a new document with custom indentationwith_reader(reader)- Create a new document with default space indentationnext()- Get the next node asynchronouslycollect()- Collect all nodes into a vectorfilter(predicate)- Filter nodes based on a predicatefind(predicate)- Find the first node matching a predicatemap(mapper)- Transform nodes using a mapper function
TerraceNode
Represents a single line/node in a Terrace document.
head()- Get the first word of the linetail()- Get everything after the first spacecontent()- Get the content after indentationlevel()- Get the indentation levelline_number()- Get the line numberis(value)- Check if head matches a valueis_empty()- Check if the line is emptyraw(offset)- Get raw content from an offset
Readers
StringReader- Read from a string or vector of stringsAsyncReader- Read from any async source
Features
- Async/Await Support: Built with Tokio for asynchronous processing
- Streaming: Process large documents without loading everything into memory
- Flexible Input: Support for strings, files, and custom readers
- Type Safe: Full type safety with Rust's type system
- Zero-Copy: Efficient parsing with minimal allocations
License
MIT