nested-text
A fully spec-compliant NestedText v3.8 parser and serializer for Rust.
Compliance
nested-text passes 100% of the official NestedText test suite (KenKundert/nestedtext_tests):
- 146/146 load tests — including full validation of error messages, line numbers, column numbers, and source line text for all 68 error cases
- 80/80 roundtrip dump tests — every successfully loaded document survives a dump/load cycle with identical output
- 2 tests skipped (non-UTF-8 encoding tests — NestedText is a UTF-8 format)
The implementation mirrors the architecture of the Python reference implementation by Ken Kundert: a line-based lexer feeding a recursive descent parser.
Installation
Add to your Cargo.toml:
[]
= "0.1"
serde support is enabled by default. To disable it:
[]
= { = "0.1", = false }
Usage
Direct API
use ;
// Parse a NestedText string
let input = "name: Alice\nage: 30\nitems:\n - one\n - two\n";
let value = loads.unwrap.unwrap;
// Access values
assert_eq!;
assert_eq!;
// Serialize back to NestedText
let output = dumps;
let roundtripped = loads.unwrap.unwrap;
assert_eq!;
Top-level type constraint
use ;
// Require a specific top-level type
let dict = loads.unwrap;
let list = loads.unwrap;
let string = loads.unwrap;
// Empty documents return a default value for the given type
let empty_dict = loads.unwrap; // Some(Dict([]))
let empty_any = loads.unwrap; // None
serde integration
use ;
let input = "\
name: my-app
debug: true
port: 8080
tags:
- web
- api
";
// Deserialize — numeric and boolean fields are parsed from strings
let config: Config = from_str.unwrap;
assert_eq!;
assert_eq!;
assert_eq!;
// Serialize back to NestedText
let output = to_string.unwrap;
Reading from files
use ;
use File;
let file = open.unwrap;
let value = load.unwrap;
Error handling
Errors include location information matching the reference implementation:
use ;
match loads
Building values directly
use ;
let value = Dict;
let nt = dumps;
// name: Alice
// scores:
// - 95
// - 87
API Reference
Parsing
| Function | Description |
|---|---|
loads(input, top) -> Result<Option<Value>> |
Parse a NestedText string |
load(reader, top) -> Result<Option<Value>> |
Parse from any Read implementor |
from_str<T>(input) -> Result<T> |
Deserialize via serde (requires serde feature) |
Serialization
| Function | Description |
|---|---|
dumps(value, options) -> String |
Serialize a Value to NestedText |
dump(value, options, writer) -> Result<()> |
Serialize to any Write implementor |
to_string(value) -> Result<String> |
Serialize via serde (requires serde feature) |
to_string_with_options(value, options) -> Result<String> |
Serialize via serde with custom options |
Types
Value—String(String),List(Vec<Value>),Dict(Vec<(String, Value)>)- Dicts preserve insertion order using
Vec<(String, Value)> - Convenience methods:
as_str(),as_list(),as_dict(),get(key),is_string(),is_list(),is_dict()
- Dicts preserve insertion order using
Top—Dict,List,String,AnyDumpOptions—indent: usize(default 4),sort_keys: bool(default false)Error—message,lineno(0-based),colno(0-based),line,kind
NestedText format
NestedText is a data format similar to YAML but with no type ambiguity — all leaf values are strings. No quoting, no escaping, no type coercion surprises.
# This is a comment
server:
host: localhost
port: 8080
features:
- logging
- metrics
database:
> postgres://localhost
> :5432/mydb
For the full specification, see nestedtext.org.
Validating compliance
Clone with the official test suite submodule and run:
To see detailed pass/fail counts:
This runs the full official NestedText test suite automatically:
- Load tests — decodes each test case from
tests.json, parses the input, and compares the result againstload_out. For error cases, validates the error message, line number, column number, and source line text againstload_err. - Roundtrip dump tests — for every successful load test, serializes the parsed value back to NestedText, parses it again, and verifies the result is identical.
If you already cloned without --recurse-submodules:
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.