toon-rust
Library Featured
Token-Oriented Object Notation (TOON) - a token-efficient JSON alternative for LLM prompts
- Downloads
- 160,383
- Dependents
- 67
- Stars
- 190
- Forks
- 28
- Contributors
- 10
- Commits
- 80
- Latest release
- 0.7.0 ·
About
TOON Format for Rust
Token-Oriented Object Notation (TOON) is a compact, human-readable format designed for passing structured data to Large Language Models with significantly reduced token usage.
This crate provides the official, spec-compliant Rust implementation of TOON, offering both a library (toon-format) and a full-featured command-line tool (toon).
toon-spec: 4.4 – this implementation targets TOON Specification v4.4.
Quick Example
JSON (16 tokens, 40 bytes):
{
"users": [
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
]
}
TOON (13 tokens, 28 bytes) - 18.75% token savings:
users[2]{id,name}:
1,Alice
2,Bob
Features
- Generic API: Works with any
Serialize/Deserializetype - custom structs, enums, JSON values, and more - Spec-Compliant: Fully compliant with TOON Specification v4.4, including comment lines, keyed tabular form, and nested field groups
- Safe & Performant: Built with safe, fast Rust
- Powerful CLI: Full-featured command-line tool
- Strict Validation: Enforces all spec rules (configurable)
- Well-Tested: Comprehensive test suite with unit tests, spec fixtures, and real-world scenarios
Read the full README
Experimental Cargo Features
layout(experimental, off by default): Exposes decoder layout metadata (tabular vs list vs inline, declared[N]lengths, field descriptors) viadecode_with_layout. Scoped to independent exploration of schema and tooling use cases (validators, formatters, linters); not part of the TOON specification and may evolve independently of the core decoder.
Installation
As a Library
cargo add toon-format
As a CLI Tool
cargo install toon-format
Library Usage
Basic Encode & Decode
The encode and decode functions work with any type implementing Serialize/Deserialize:
With custom structs:
use serde::{Serialize, Deserialize};
use toon_format::{encode_default, decode_default};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct User {
name: String,
age: u32,
email: String,
}
fn main() -> Result<(), toon_format::ToonError> {
let user = User {
name: "Alice".to_string(),
age: 30,
email: "alice@example.com".to_string(),
};
// Encode to TOON
let toon = encode_default(&user)?;
println!("{}", toon);
// Output:
// name: Alice
// age: 30
// email: alice@example.com
// Decode back to struct
let decoded: User = decode_default(&toon)?;
assert_eq!(user, decoded);
Ok(())
}
With JSON values:
use serde_json::{json, Value};
use toon_format::{encode_default, decode_default};
fn main() -> Result<(), toon_format::ToonError> {
let data = json!({
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
});
// Encode to TOON
let toon_str = encode_default(&data)?;
println!("{}", toon_str);
// Output:
// users[2]{id,name}:
// 1,Alice
// 2,Bob
// Decode back to JSON
let decoded: Value = decode_default(&toon_str)?;
assert_eq!(decoded, data);
Ok(())
}
API Reference
Encoding
encode<T: Serialize>(&value, &options) -> Result<String, ToonError>
Encode any serializable type to TOON format. Works with custom structs, enums, collections, and serde_json::Value.
use toon_format::{encode, EncodeOptions, Delimiter, Indent};
use serde_json::json;
let data = json!({"items": ["a", "b", "c"]});
// Default encoding
let toon = encode(&data, &EncodeOptions::default())?;
// items[3]: a,b,c
// Custom delimiter
let opts = EncodeOptions::new()
.with_delimiter(Delimiter::Pipe);
let toon = encode(&data, &opts)?;
// items[3|]: a|b|c
// Custom indentation
let opts = EncodeOptions::new()
.with_indent(Indent::Spaces(4));
let toon = encode(&data, &opts)?;
EncodeOptions
| Method | Description | Default |
|---|---|---|
with_delimiter(d) | Set delimiter: Comma, Tab, or Pipe | Comma |
with_indent(i) | Set indentation (spaces only) | Spaces(2) |
with_spaces(n) | Shorthand for Indent::Spaces(n) | 2 |
json_stream Feature
The optional json_stream feature adds conveniences for encoding JSON from a
Read source to a Write target. Spec v4.4 selects the encoded form from a
value's whole shape (tabular and keyed tabular headers depend on every element
of their subtree), so the input is parsed in full before encoding; these
functions are I/O conveniences, not bounded-memory streaming.
cargo add toon-format --features json_stream
use std::io::Cursor;
use toon_format::{encode_json_stream_default};
let input = Cursor::new(br#"{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]}"#);
let mut output = Vec::new();
encode_json_stream_default(input, &mut output)?;
let toon = String::from_utf8(output)?;
assert!(toon.contains("users[2]{id,name}:"));
Decoding
decode<T: Deserialize>(&input, &options) -> Result<T, ToonError>
Decode TOON format into any deserializable type. Works with custom structs, enums, collections, and serde_json::Value.
With custom structs:
use serde::Deserialize;
use toon_format::{decode, DecodeOptions};
#[derive(Deserialize)]
struct Config {
host: String,
port: u16,
}
let toon = "host: localhost\nport: 8080";
let config: Config = decode(toon, &DecodeOptions::default())?;
With JSON values:
use serde_json::Value;
use toon_format::{decode, DecodeOptions};
let toon = "name: Alice\nage: 30";
// Default (strict) decode
let json: Value = decode(toon, &DecodeOptions::default())?;
// Non-strict mode
let opts = DecodeOptions::new().with_strict(false);
let json: Value = decode(toon, &opts)?;
Helper functions:
encode_default<T>(&value)- Encode with default optionsdecode_default<T>(&input)- Decode with default options
DecodeOptions
| Method | Description | Default |
|---|---|---|
with_strict(b) | Enable strict validation | true |
with_indent(i) | Set spaces per indentation level | Spaces(2) |
With with_strict(false), the decoder recovers from exactly five conditions
(spec §14.4) and errors on everything else, as strict mode does:
- A declared
[N]is advisory: fewer or more items, rows, or entries thanNstill decode, but a row's width must match its fields. - Duplicate keys and repeated field names resolve last-write-wins.
- Indentation may use tabs or non-multiples of the indent size: each tab is one level, spaces are floored.
- Blank lines inside an array or keyed tabular object are ignored.
- A block whose first line starts too deep takes that line's depth.
Spec v4.1 Highlights
Comment Lines (Decoder)
Lines whose first non-space character is # are comments, removed before any
structural interpretation. Encoders never emit them.
# server inventory
servers[2]{host,port}:
a.example.com,8080
b.example.com,9090
Keyed Tabular Form
An object whose values are uniform non-empty objects collapses into a keyed header with one entry row per entry:
servers[2:]{host,port}:
alpha: a.example.com,8080
beta: b.example.com,9090
Nested Field Groups
A uniform nested-object column collapses into the header, its leaf cells laid out by a depth-first walk:
orders[2]{id,customer{name,country},total}:
1,Ada,DK,99
2,Bob,UK,149
Empty Arrays
Empty arrays encode as key: [] in field position and [] at the root; the
legacy key[0]: and [0]: forms are still accepted by the decoder.
Interactive TUI
TOON includes a full-featured Terminal User Interface for interactive conversions!
# Launch interactive mode
toon --interactive
# or
toon -i
Features:
- Real-time conversion as you type
- Live statistics (tokens, bytes, savings)
- Interactive settings - adjust all options on-the-fly
- File browser with visual navigation
- Side-by-side diff viewer
- Conversion history tracking
- File operations (open, save, new)
- Clipboard integration (copy/paste)
- REPL mode for command-line interaction
- Round-trip testing
- Theme support (Dark/Light)
- Built-in help with keyboard shortcuts
Perfect for:
- Learning TOON format interactively
- Testing conversions in real-time
- Experimenting with different settings
- Visual before/after comparisons
- Quick data transformations
See docs/TUI.md for complete documentation and keyboard shortcuts!
CLI Usage
Basic Commands
# Auto-detect from extension
toon data.json # Encode
toon data.toon # Decode
# Force mode
toon -e data.txt # Force encode
toon -d output.txt # Force decode
# Pipe from stdin
cat data.json | toon
echo '{"name": "Alice"}' | toon -e
Encode Options
# Custom delimiter
toon data.json --delimiter pipe
toon data.json --delimiter tab
# Custom indentation
toon data.json --indent 4
# Show statistics
toon data.json --stats
Decode Options
# Pretty-print JSON
toon data.toon --json-indent 2
# Relaxed validation
toon data.toon --no-strict
Full Example
$ echo '{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]}' | toon --stats
users[2]{id,name}:
1,Alice
2,Bob
Stats:
+--------------+------+------+---------+
| Metric | JSON | TOON | Savings |
+======================================+
| Tokens | 20 | 19 | 5.00% |
|--------------+------+------+---------|
| Size (bytes) | 58 | 36 | 37.93% |
+--------------+------+------+---------+
Testing
The library includes a comprehensive test suite covering core functionality, edge cases, spec compliance, and real-world scenarios.
# Run all tests
cargo test
# Run specific test suites
cargo test --test spec_fixtures
cargo test --lib
# With output
cargo test -- --nocapture
Error Handling
All operations return Result<T, ToonError> with descriptive error messages:
use serde_json::Value;
use toon_format::{decode_strict, ToonError};
match decode_strict::<Value>("items[3]: a,b") {
Ok(value) => println!("Success: {:?}", value),
Err(ToonError::ParseError { line, message, .. }) => {
eprintln!("Parse error on line {}: {}", line, message);
}
Err(e) => eprintln!("Error: {}", e),
}
Error Types
ParseError- Syntax, structural, and strict-mode errors with line infoTypeMismatch- Unexpected value typeInvalidStructure- Malformed TOON structureSerializationError/DeserializationError- Conversion failures
Examples
Run with cargo run --example examples to see all examples:
structs.rs- Custom struct serializationtabular.rs- Tabular array formattingarrays.rs- Various array formatsarrays_of_arrays.rs- Nested arraysobjects.rs- Object encodingmixed_arrays.rs- Mixed-type arraysdelimiters.rs- Custom delimitersround_trip.rs- Encode/decode round-tripsdecode_strict.rs- Strict validationempty_and_root.rs- Edge cases
Resources
- 📖 TOON Specification v4.4
- 📦 Crates.io Package
- 📚 API Documentation
- 🔧 Main Repository (JS/TS)
- 🎯 Benchmarks & Performance
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
Development
# Clone the repository
git clone https://github.com/your-org/toon-rust.git
cd toon-rust
# Run tests
cargo test --all
# Run lints
cargo clippy -- -D warnings
# Format code
cargo fmt
# Build docs
cargo doc --open
License
MIT License © 2025-PRESENT Johann Schopplich and Shreyas K S
Compatibility
- Runs on
- GPU support unknown
What shows it
- no dependency or feature matches a backend row
- Native code
- None found
- No native code found
- Python bindings
- No Python binding crate found
- License
- MIT
Compare with similar projects
Order: strongest tier first, then most downloads, then name, with unmeasured values last. A library counts downloads over 30 days. An app counts binary downloads per release. An app with none counts its crate downloads over 30 days. ML Rust runs this catalogue, so its closest project always gets a row.
| Project | Downloads | Dependents | Stars | Latest release | Runs on (GPU) | Native code | License |
|---|---|---|---|---|---|---|---|
|
Token-Oriented Object Notation (TOON) - a token-efficient JSON alternative for LLM prompts |
160,383 downloads over 30 days | 67 | 190 | 0.7.0 | GPU support unknown | No native code found | MIT |
|
pdf_oxide Featured
The fastest Rust PDF library — 0.8ms mean, 5× faster than the industry leaders, 100% pass rate on 3,830 real-world PDFs. Text extraction, Markdown/HTML conversion, PDF creation and editing. Python bindings |
316,729 downloads over 30 days | 30 | 1,180 | 0.3.78 | GPU support unknown | Binds native code: aws-lc-rs (feature fips), lcms2-sys (feature icc-lcms2), ort-sys (feature gpu) | Apache-2.0 OR MIT |
|
Pure Rust PDF library for AI/RAG: structure-aware chunking, no ML, no C deps. |
62,285 downloads over 30 days | Not applicable | 194 | 5.5.7 | GPU support unknown | No native code found | MIT |
|
Token-Oriented Object Notation – a token-efficient JSON alternative for LLM prompts |
8,018 downloads over 30 days | 5 | 22 | 0.1.2 | GPU support unknown | No native code found | MIT |
|
serde_toon Listed
A Serde-compatible TOON (Token-Oriented Object Notation) serialization library |
2,384 downloads over 30 days | 4 | 13 | 0.3.0 | GPU support unknown | No native code found | Apache-2.0 OR MIT |
|
Inference server for LLMs, speech and embeddings: OpenAI-compatible routes with streaming, plus speech synthesis (TTS) and transcription (ASR). Serves Llama, Mistral, Qwen, Mamba2, MLA+MoE and hybrid models from SafeTensors, AWQ, GPTQ and GGUF. |
8 binary downloads per release | Not applicable | 7 | 0.7.1 | CUDA, WebGPU | Binds native code: ring (feature distributed) | Apache-2.0 |
|
Vision infrastructure to turn complex documents into LLM-ready data |
0 binary downloads per release | Not applicable | 4,157 | Not measured | Not measured | AGPL-3.0 |
Why FeaturedIt passes every Featured gate.
What it meets
- It has 46 active dependents and 46 new dependents in 365 days. Featured needs 11 active dependents or 9 new dependents in 365 days.
- Active dependents are at 100% of their peak. Featured needs at least 50%.
- Docs are present. The release commit or a manifest ties the crate to the repository.
- No vulnerability advisory stays unpatched past the grace window. At least one version is neither a prerelease nor 0.0.x.
- The last activity is on 12 Oct 2026, 28 days ago. The rules expect an update within 560 days. Dormancy rule
Exact rules: Featured library. The check on applied thresholds version 9.
Every rule outcome, as the check records it
expected-interval: version 0.7.0 base 140, doubled for 160383 downloads per month, doubled for 46 active users: E = 560 daysdormancy: last activity 2026-10-12, 28 days ago, E = 560: activefeatured: featured: active_users 46, new_adopters 46, former_glory 1
Measurements and sources
Each signal row shows the raw value, its source and the fetch date. The Sources list gathers every distinct source on this page. Movement needs more history.
Sources6 sources
- Description: the crates.io description
- crates.io database dump, fetched
- RustSec advisory database, fetched
- GitHub repository, fetched
- crates.io package, fetched
- GitHub contributors, fetched
Adoption46 active dependents, 46 new dependents in 365 days1 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Active dependents | 46 | crates.io database dump | Yes | |
| New dependents (365 days) | 46 | crates.io database dump | Yes | |
| Peak active dependents | 46 | crates.io database dump | Yes | |
| Active dependents as a share of the peak | 1 | crates.io database dump | Yes | |
| Binary downloads per release | Not measured | Yes |
MaintenanceLatest human commit: 28 days ago3 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Latest human commit | 2026-10-12 | GitHub repository | Yes | |
| Latest release | 2026-10-12 | crates.io database dump | Yes | |
| First release | 2025-11-01 | crates.io database dump | Yes | |
| Latest version | 0.7.0 | crates.io database dump | Yes | |
| Days the oldest outside issue waits for a reply | 0 | GitHub repository | Yes | |
| Maintainer replies over 365 days | 32 | GitHub repository | Yes | |
| Repository archived | false | GitHub repository | Yes | |
| Repository gone | false | GitHub repository | Yes | |
| Release commit or manifest in the repo | true | crates.io package | Yes | |
| Published docs | true | crates.io database dump | Yes | |
| Latest release fails cargo check | Not measured | Yes | ||
| Build check date | Not measured | Yes | ||
| Build check toolchain | Not measured | Yes |
SecurityUnpatched vulnerabilities: none
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Unpatched vulnerabilities past the grace window | none | RustSec advisory database | Yes | |
| RustSec unmaintained advisory | none | RustSec advisory database | Yes | |
| Deprecation notice | none | crates.io database dump | Yes | |
| Deprecated requirement | none | crates.io database dump | Yes |
Distribution25 releases, 160,383 downloads over 30 days5 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Releases | 25 | crates.io database dump | Yes | |
| Downloads over 30 days | 160383 | crates.io database dump | Yes | |
| Binary downloads over the last 3 releases | Not measured | Yes | ||
| Homebrew installs on request over 365 days | Not measured | Yes | ||
| Repology repository families | Not measured | Yes | ||
| Docker pull growth over 90 days | Not measured | Yes | ||
| Docker pulls at the growth baseline | Not measured | Yes | ||
| Every version a prerelease | false | crates.io database dump | Yes | |
| Every version 0.0.x | false | crates.io database dump | Yes | |
| Every version yanked | false | crates.io database dump | Yes | |
| Crate deleted from crates.io | false | crates.io database dump | Yes |
Repository190 stars, 28 forks, 10 contributors, 80 commits. Stars alone never qualify a project.
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| GitHub stars | 190 | GitHub repository | Yes — one part of the repository route | |
| GitHub forks | 28 | GitHub repository | Yes — one part of the repository route | |
| Contributors with a GitHub account | 10 | GitHub contributors | Yes — one part of the repository route | |
| Commits on the default branch | 80 | GitHub repository | No | |
| Repository's main crate left out of the entry | none | crates.io database dump | Yes |
Facts that never count
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| License | MIT | crates.io database dump | No | |
| Runs on, from listed crates and their direct dependencies | GPU support unknown | crates.io database dump | No | |
| What shows each backend | no dependency or feature matches a backend row | crates.io database dump | No | |
| Native code, from listed crates and their dependencies | No native code found | crates.io database dump | No | |
| Python bindings, from direct dependencies of listed crates | No Python binding crate found | crates.io database dump | No | |
| Crates that depend on a listed crate directly | 67 | crates.io database dump | No |
Corrections and review history
No correction applies to this entry.
Judgments
A judgment enters only through an approved issue and a merged pull request.
No judgment applies to this entry.