#schema-validation #aot #formatter #alias #mapping #schema-define #catch #lsp

aam-rs

A Rust implementation of the Abstract Alias Mapping (AAM) framework for aliasing and maping aam files

21 stable releases

Uses new Rust 2024

new 2.0.4 Apr 17, 2026
2.0.3 Apr 12, 2026
1.4.0 Mar 12, 2026
1.2.0 Feb 27, 2026

#246 in Data structures


Used in aam

MIT/Apache

415KB
9K SLoC

AAM (Abstract Alias Mapping)

A robust and lightweight configuration library for Rust built around the new pipeline-backed AAM API. It parses .aam files (key = value), supports directives (@import, @derive, @schema, @type), and provides fast query and formatting utilities.

The Origin Story: AAM was born out of necessity during the development of rustgames. I needed a configuration format that lived entirely outside the codebase, supported high-speed bidirectional search, and was optimized for extreme performance. What started as a specialized tool for game engine internals eventually evolved into a robust configuration ecosystem with schemas, imports, and AOT compilation.

Why AAM?

AAM was designed to solve the "configuration fatigue" in large-scale Rust projects. While formats like TOML are great for simple key-value pairs, they often fall short when your config grows. AAM introduces:

  • Type Safety & Schemas: Define @type aliases and @schema structures directly in the config. No more "guessing" what a value should be.
  • Modular Architecture: Use @import to split massive configs into clean, manageable modules.
  • AOT Performance: Optional Ahead-of-Time compilation "cooks" your .aam files into a binary format for near-instant loading.
  • Developer-Centric: Built-in LSP support and formatting help you catch errors before you run the code.

AAM vs TOML

Feature AAM TOML
Schema Validation Native (@schema) External tools only
Modular Imports Native (@import) Not supported
Type Aliasing Native (@type) No
Performance High (AOT/Binary) Standard (Text parsing)
Extensibility Pipeline-backed Static

What changed in 2.x

  • AAM is now the primary API.
  • Parsing/loading returns Result<_, Vec<AamlError>> to preserve full diagnostics.
  • Query methods are now centered around get, find, find_by, deep_search, and reverse_search.
  • Pipeline formatter and LSP helper methods are available directly on AAM.
  • AAML remains available for backward compatibility, but is deprecated.

Features

  • Simple key = value syntax.
  • Directive support: @import, @derive, @schema, @type.
  • Schema/type validation via pipeline.
  • Search helpers for key lookup, reverse lookup, and predicate filtering.
  • Formatter utilities (format, format_range) and LSP assist (lsp_assist).
  • Optional AOT loading (.aam.bin) for fast startup (aot feature; enabled by default).
  • Fluent config generation with AAMBuilder.

Format

You can find syntax documentation and examples at: https://aam.ininids.in.rs/

Installation

Add the crate to your Cargo.toml:

[dependencies]
aam-rs = "2.0.4"

Configuration syntax (.aam)

# Comments are supported
host = "localhost"
port = 8080

@import database.aam
@import theme.aam

@type port_t = i32
@schema Service {
    host: string
    port: port_t
}

Usage (new AAM API)

1) Parse and load

use aam_rs::aam::AAM;
use aam_rs::error::AamlError;

fn print_errors(errors: &[AamlError]) {
    for err in errors {
        eprintln!("{err}");
    }
}

fn main() {
    let inline = "host = localhost\nport = 8080";

    match AAM::parse(inline) {
        Ok(cfg) => {
            if let Some(host) = cfg.get("host") {
                println!("host = {host}");
            }
        }
        Err(errors) => {
            print_errors(&errors);
        }
    }
}

2) Lookups and queries

use aam_rs::aam::AAM;

let cfg = AAM::parse(
    "
app_mode = production
backup_mode = production
api_port = 8080
"
).unwrap();

// O(1) key lookup
assert_eq!(cfg.get("api_port"), Some("8080"));

// key-first lookup, then reverse lookup by value
let found = cfg.find("production");
assert_eq!(found.len(), 2);

// reverse lookup only
let keys = cfg.reverse_search("production");
assert_eq!(keys.len(), 2);

// key pattern search
let deep = cfg.deep_search("mode");
assert_eq!(deep.len(), 2);

// custom predicate
let filtered = cfg.find_by(|k, v| k.ends_with("_port") && v == "8080");
assert_eq!(filtered, vec![("api_port", "8080")]);

3) Iteration and extraction

use aam_rs::aam::AAM;

let cfg = AAM::parse("a = 1\nb = 2").unwrap();

for (k, v) in cfg.iter() {
    println!("{k} = {v}");
}

let keys = cfg.keys();
let map = cfg.to_map();
assert!(keys.contains(&"a"));
assert_eq!(map.get("b"), Some(&"2".to_string()));

4) Formatting and LSP helper

use aam_rs::aam::AAM;
use aam_rs::pipeline::{FormatRange, FormattingOptions};

let cfg = AAM::new();
let src = "host=localhost\nport=8080";

let formatted = cfg.format(src, &FormattingOptions::default()).unwrap();
let _range = cfg
    .format_range(
        src,
        FormatRange { start_line: 1, end_line: 1 },
        &FormattingOptions::default(),
    )
    .unwrap();

let assist = AAM::lsp_assist(&formatted, &FormattingOptions::default());
assert!(assist.diagnostics.is_empty());

5) Builder (AAMBuilder)

use aam_rs::builder::{AAMBuilder, SchemaField};

let mut builder = AAMBuilder::new();
builder
    .comment("Server configuration")
    .type_alias("port_t", "i32")
    .schema("Server", [
        SchemaField::required("host", "string"),
        SchemaField::required("port", "port_t"),
        SchemaField::optional("debug", "bool"),
    ])
    .add_line("host", "2.0.4.1")
    .add_line("port", "8080");

println!("{}", builder.as_string());
builder.to_file("generated_config.aam").unwrap();

Legacy API (AAML, deprecated)

AAML is still available for compatibility and supports methods such as:

  • parse, load
  • merge_content, merge_file
  • find_obj, find_key, find_deep
  • validate_value, apply_schema, validate_schemas_completeness

For migration guidance, see docs/AAML_TO_AAM_MIGRATION.md.

Bindings

Node.js / N-API

npm install aam-nodejs

C# / .NET

dotnet add package aam-csharp

Quick verification commands

cargo test
cargo run --example standard
cargo run --example advanced

API reference (high-level)

AAM

  • Constructors/loaders: new, parse, load, from_pipeline
  • Query: get, find, find_by, deep_search, reverse_search
  • Iteration/export: iter, keys, to_map
  • Introspection: schemas, get_schema, types, get_type
  • Formatting/LSP: format, format_range, lsp_assist
  • AOT (feature-gated): cook, load_fast

AAMBuilder

  • new, with_capacity
  • add_line, comment
  • schema, schema_multiline, derive, import, type_alias
  • to_file, build, as_string

AamlError

Typed errors used across parser, validator, and runtime paths.

Ecosystem Tooling

AAM CLI

For managing, formatting, and "cooking" your configuration files, check out the aam-cli.

Installation:

cargo install aam-cli

Key features:

  • Cook: Convert .aam to binary .aam.bin for AOT loading.
  • Format: Keep your config files clean and consistent.
  • Check: Validate syntax and schema integrity from the terminal.

AAM Examples

If you need more examples, check aam-examples repository

License

See LICENSE-MIT and LICENSE-APACHE.

Full documentation

Dependencies

~0.4–4.5MB
~81K SLoC