toonfmt

R Bindings for TOON (Token-Oriented Object Notation) Format

Overview

toonfmt provides fast R bindings for reading and writing TOON format files. TOON is a lightweight, human-readable data serialization format that combines the simplicity of YAML with the structure of JSON. This package uses Rust for high-performance parsing and encoding via rextendr.

Installation

System Requirements

Install from source

# Install from GitHub
# install.packages("pak")
# pak::pak("DyfanJones/toonfmt")
install.packages("toonfmt", repos = c('https://dyfanjones.r-universe.dev', 'https://cloud.r-project.org'))

Quick Start

library(toonfmt)

# Create some data
data <- list(
  name = "Alice",
  age = 30,
  scores = c(85, 90, 95)
)

# Convert to TOON string
toon_str <- write_toon_str(data)
cat(toon_str)
#> name: Alice
#> age: 30
#> scores[3]: 85,90,95

# Parse TOON string back to R object
result <- read_toon_str(toon_str)

Main Functions

Writing TOON

Reading TOON

Features

Delimiters

TOON supports different delimiters for array elements:

data <- list(items = c("a", "b", "c"))

# Comma delimiter (default)
write_toon_str(data, delimiter = ",")
#> items[3]: a,b,c

# Pipe delimiter
write_toon_str(data, delimiter = "|")
#> items[3|]: a|b|c

# Tab delimiter
write_toon_str(data, delimiter = "\t")
#> items[3	]: a	b	c

Pretty Formatting

Use pretty = TRUE for indented output, especially important for nested structures:

data <- list(
  user = list(
    name = "Bob",
    settings = list(theme = "dark", notifications = TRUE)
  )
)

# Compact output (default)
write_toon_str(data, pretty = FALSE)
#> user:
#> name: Bob
#> settings:
#> theme: dark
#> notifications: true

# Pretty output with indentation
write_toon_str(data, pretty = TRUE)
#> user:
#>   name: Bob
#>   settings:
#>     theme: dark
#>     notifications: true

Important: Nested structures require pretty = TRUE for proper round-tripping. Without indentation, TOON format flattens nested structures.

File I/O

# Write to file
data <- list(
  project = "toonfmt",
  version = "0.1.0",
  authors = c("Alice", "Bob")
)

write_toon_file(data, "config.toon", delimiter = "|", pretty = TRUE)

# Read from file
config <- read_toon_file("config.toon")

Data Types

toonfmt handles common R data types:

data <- list(
  integer = 42L,
  double = 3.14,
  logical = TRUE,
  string = "hello",
  vector_int = c(1L, 2L, 3L),
  vector_string = c("a", "b", "c"),
  nested = list(x = 1, y = 2)
)

toon <- write_toon_str(data, pretty = TRUE)
result <- read_toon_str(toon)

Tabular Data (List of Lists)

users <- list(
  users = list(
    list(name = "Alice", age = 30, active = TRUE),
    list(name = "Bob", age = 25, active = FALSE),
    list(name = "Carol", age = 35, active = TRUE)
  )
)

# Write with pretty formatting (required for tabular data)
toon <- write_toon_str(users, pretty = TRUE)
cat(toon)
#> users[3]{name,age,active}:
#>   Alice,30,true
#>   Bob,25,false
#>   Carol,35,true

# Round-trip preserves structure
result <- read_toon_str(toon)

Decode Options

Strict Mode

Control parsing strictness:

# Strict mode (default) - enforces TOON format rules
read_toon_str(toon_str, strict = TRUE)

# Relaxed mode - more lenient parsing
read_toon_str(toon_str, strict = FALSE)

Type Coercion

Control automatic type coercion during parsing:

# With type coercion (default) - automatically converts types
read_toon_str(toon_str, coerce_types = TRUE)

# Without type coercion - preserves literal values
read_toon_str(toon_str, coerce_types = FALSE)

Examples

Simple Configuration File

config <- list(
  app_name = "MyApp",
  version = "1.0.0",
  settings = list(
    port = 8080,
    debug = TRUE,
    allowed_hosts = c("localhost", "example.com")
  )
)

write_toon_file(config, "config.toon", pretty = TRUE)

# Later...
app_config <- read_toon_file("config.toon")

Data Export/Import

# Export R data
results <- list(
  experiment = "A001",
  measurements = c(1.23, 4.56, 7.89),
  metadata = list(
    date = "2024-01-20",
    researcher = "Alice"
  )
)

write_toon_file(results, "results.toon", pretty = TRUE)

# Import in another session
data <- read_toon_file("results.toon")

Important Notes

  1. Nested Structures: Use pretty = TRUE when working with nested lists to ensure proper round-tripping. Without indentation, nested structures are flattened.

  2. Delimiter Auto-Detection: When reading TOON files, the delimiter is automatically detected from the file metadata. You only need to specify the delimiter when writing.

  3. Integer Preservation: TOON format preserves integer types, unlike JSON which converts everything to doubles.

Performance

toonfmt uses Rust for parsing and encoding, providing significant performance benefits over pure R implementations, especially for large files.

Links

License

MIT License