Joshua Bemenderfer 9d9757e868 Updates.
2025-09-08 16:24:38 -04:00

3.1 KiB

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 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