# 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`: ```toml [dependencies] terrace = "0.1" ``` ## Usage ### Basic Parsing ```rust 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 ```rust 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 ```rust 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 indentation - `with_reader(reader)` - Create a new document with default space indentation - `next()` - Get the next node asynchronously - `collect()` - Collect all nodes into a vector - `filter(predicate)` - Filter nodes based on a predicate - `find(predicate)` - Find the first node matching a predicate - `map(mapper)` - Transform nodes using a mapper function ### TerraceNode Represents a single line/node in a Terrace document. - `head()` - Get the first word of the line - `tail()` - Get everything after the first space - `content()` - Get the content after indentation - `level()` - Get the indentation level - `line_number()` - Get the line number - `is(value)` - Check if head matches a value - `is_empty()` - Check if the line is empty - `raw(offset)` - Get raw content from an offset ### Readers - `StringReader` - Read from a string or vector of strings - `AsyncReader` - 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