Skip to main content

Rust Guide

The ttoon-core crate is the canonical TTOON engine. Both the Python and JavaScript SDKs delegate to this crate for parsing and serialization.

Installation

cargo add ttoon-core

Batch Operations

Deserialize: from_ttoon()

use ttoon_core::{from_ttoon, from_ttoon_with_mode, ParseMode};

// Auto-detect format, default compat mode
let node = from_ttoon("name: \"Alice\"\nage: 30")?;

// Strict mode
let node = from_ttoon_with_mode("{\"key\": 42}", ParseMode::Strict)?;

Returns ir::Node — the internal representation tree.

Note: from_ttoon() explicitly uses ParseMode::Compat. This is separate from ParseMode::default(), which is Strict.

Serialize: to_ttoon() / to_tjson()

use ttoon_core::{to_ttoon, to_tjson, BinaryFormat, Delimiter, TjsonOptions, TtoonOptions};

let text = to_ttoon(&node, None)?;

let opts = TtoonOptions {
binary_format: BinaryFormat::B64,
indent_size: 4,
delimiter: Delimiter::Tab,
};
let text = to_ttoon(&node, Some(&opts))?;
let json = to_tjson(&node, None)?;

TtoonOptions:

FieldTypeDefaultDescription
binary_formatBinaryFormatHexHex or B64
indent_sizeu82Indentation width
delimiterDelimiterCommaComma, Tab, or Pipe

Format Detection

use ttoon_core::detect_format;
use ttoon_core::format_detect::Format;

let fmt = detect_format("{\"key\": 42}");
assert_eq!(fmt, Format::Tjson);

let fmt = detect_format("key: 42");
assert_eq!(fmt, Format::TypedUnit);

Arrow Path

use ttoon_core::{read_arrow, arrow_to_ttoon, arrow_to_tjson};

// Text → Arrow
let table = read_arrow(text)?;

// Arrow → T-TOON tabular
let ttoon = arrow_to_ttoon(&table, None)?;

// Arrow → T-JSON
let tjson = arrow_to_tjson(&table, None)?;

read_arrow() auto-detects format. Input must be a list of uniform objects with scalar field values.

Direct Transcode

use ttoon_core::{tjson_to_ttoon, ttoon_to_tjson, ParseMode};

// T-JSON → T-TOON (always strict parse)
let ttoon = tjson_to_ttoon(r#"{"key": 42}"#, None)?;

// T-TOON → T-JSON (configurable parse mode)
let tjson = ttoon_to_tjson("key: 42", ParseMode::Compat, None)?;

Streaming

Schema Definition

use ttoon_core::{StreamSchema, FieldType, ScalarType};

let schema = StreamSchema::new([
("name", FieldType::new(ScalarType::String)),
("score", FieldType::new(ScalarType::Int)),
("amount", FieldType::new(ScalarType::decimal(10, 2))),
("active", FieldType::nullable(ScalarType::Bool)),
]);

Stream Reader (T-TOON)

use std::io::Cursor;

use ttoon_core::{ParseMode, StreamReader};

let text = "[1]{name,score,amount,active}:\n\"Alice\", 95, 123.45m, true\n";
let reader = StreamReader::new(Cursor::new(text), schema.clone());
let strict_reader = StreamReader::with_mode(Cursor::new(text), schema, ParseMode::Strict);
for row in reader {
let row = row?;
// row is IndexMap<String, Node>
}

Stream Writer (T-TOON)

use std::io::Cursor;

use ttoon_core::{StreamReader, StreamWriter, TtoonOptions};

let text = "[1]{name,score,amount,active}:\n\"Alice\", 95, 123.45m, true\n";
let row = StreamReader::new(Cursor::new(text), schema.clone())
.next()
.transpose()?
.unwrap();
let mut writer = StreamWriter::new(Vec::new(), schema, TtoonOptions::default());
writer.write(&row)?;
let result = writer.close()?;
println!("rows emitted: {}", result.rows_emitted);

T-JSON Streaming

use std::io::Cursor;

use ttoon_core::{TjsonOptions, TjsonStreamReader, TjsonStreamWriter};

// Same pattern as above, but for T-JSON format
let reader = TjsonStreamReader::new(Cursor::new(r#"[{"name": "Alice"}]"#), schema.clone());
let mut writer = TjsonStreamWriter::new(Vec::new(), schema, TjsonOptions::default());

Arrow Streaming

use std::io::Cursor;

use ttoon_core::{ArrowStreamReader, ArrowStreamWriter, ParseMode, TtoonOptions, read_arrow};

let text = "[1]{name,score,amount,active}:\n\"Alice\", 95, 123.45m, true\n";
let reader = ArrowStreamReader::new(Cursor::new(text), schema.clone(), batch_size)?;
let strict_reader =
ArrowStreamReader::with_mode(Cursor::new(text), schema.clone(), batch_size, ParseMode::Strict)?;
for batch in reader {
let batch = batch?; // Arrow RecordBatch
}

let batch = read_arrow(text)?.batches.into_iter().next().unwrap();
let mut writer = ArrowStreamWriter::new(Vec::new(), schema, TtoonOptions::default())?;
writer.write_batch(&batch)?;
let result = writer.close()?;

All 8 streaming variants are available: StreamReader, StreamWriter, TjsonStreamReader, TjsonStreamWriter, ArrowStreamReader, ArrowStreamWriter, TjsonArrowStreamReader, TjsonArrowStreamWriter.

Error Handling

use ttoon_core::{ErrorKind, from_ttoon};

match from_ttoon(text) {
Ok(node) => { /* ... */ }
Err(e) => {
match e.kind {
ErrorKind::ParseError => {
if let Some(span) = e.span {
println!("Parse error at {}:{}: {}", span.line, span.column, e.message);
} else {
println!("Parse error: {}", e.message);
}
}
ErrorKind::ArrowError => println!("Arrow error: {}", e.message),
_ => println!("Error: {:?}", e),
}
}
}

Next Steps