Skip to content

Latest commit

 

History

History
542 lines (399 loc) · 10.8 KB

File metadata and controls

542 lines (399 loc) · 10.8 KB

TOML.lua API Documentation

Complete API reference for the TOML.lua library.


Table of Contents


Overview

local toml = require("toml")

The TOML.lua module provides functions for parsing TOML data into Lua tables and encoding Lua tables into TOML format.


Parsing Functions

toml.parse(input)

Parse a TOML string into a Lua table.

Parameters:

  • input (string) - TOML document as a string

Returns:

  • table|nil - Parsed data as a Lua table, or nil on error
  • string|nil - Error message if parsing failed

Raises: None (errors are returned as second return value)

Example:

local data, err = toml.parse('name = "Tom"\nage = 42')

if data then
  print(data.name)  -- "Tom"
  print(data.age)   -- 42
else
  print("Error:", err)
end

Supported TOML Features:

  • Strings (basic, literal, multi-line)
  • Numbers (integers, floats, hex, octal, binary)
  • Booleans
  • Arrays (nested, mixed types)
  • Tables (headers, dotted keys)
  • Inline tables
  • Array of tables

toml.parse_file(path)

Parse a TOML file into a Lua table.

Parameters:

  • path (string) - Path to the TOML file

Returns:

  • table|nil - Parsed data as a Lua table, or nil on error
  • string|nil - Error message if parsing failed

Raises: None (errors are returned as second return value)

Example:

local config, err = toml.parse_file("config.toml")

if config then
  print(config.title)
  print(config.database.host)
else
  print("Failed to read config:", err)
end

Error Conditions:

  • File doesn't exist
  • File cannot be read (permissions)
  • Invalid TOML syntax

Encoding Functions

toml.encode(data, options)

Encode a Lua table into TOML format string.

Parameters:

  • data (table) - Lua table to encode
  • options (table, optional) - Encoding options

Returns:

  • string - TOML formatted string

Raises: Error if data is not a table

Encoding Options:

Option Type Default Description
indent number 2 Number of spaces for indentation
sort_keys boolean false Sort keys alphabetically
use_table_headers boolean false Use [header] syntax for nested tables
inline_max_keys number 3 Max keys for inline table format
use_array_table_format boolean true Use [[array]] format for arrays of tables

Default Encoding Behavior:

By default, toml.encode() uses human-readable format:

  • Arrays of tables use [[array]] syntax (like [[proxies]])
  • Nested tables use dotted keys (like auth.method = "token")
  • Proper blank lines between sections
  • File ends with newline

This makes the output easier to read and edit, especially for configuration files.

Example:

local data = {
  name = "Tom",
  age = 42,
  items = {"a", "b", "c"}
}

-- Basic encoding
local toml_string = toml.encode(data)
-- Output: age = 42\nname = "Tom"\nitems = ["a", "b", "c"]

-- With sorted keys
local sorted = toml.encode(data, {sort_keys = true})

-- With table headers
local with_headers = toml.encode({
  database = {host = "localhost", port = 5432}
}, {use_table_headers = true})
-- Output: \n[database]\n  host = "localhost"\n  port = 5432

Encoding Behavior:

  • Simple values: Encoded as key = value
  • Primitive arrays: Encoded as key = [v1, v2, v3]
  • Arrays of tables (default): Encoded as [[key]] format with each element on separate lines
  • Arrays of tables (compact): When use_array_table_format = false, encoded as inline: key = [{k1=v1}, {k2=v2}]
  • Small nested tables (< inline_max_keys): Encoded as key = {k1 = v1, k2 = v2}
  • Large nested tables: Encoded as dotted keys (parent.child.key = value)
  • With use_table_headers: Uses TOML section headers

toml.encode_file(data, path, options)

Encode a Lua table and write to a TOML file.

Parameters:

  • data (table) - Lua table to encode
  • path (string) - Output file path
  • options (table, optional) - Encoding options (same as toml.encode)

Returns:

  • boolean - true on success
  • string|nil - Error message if failed

Raises: None (errors are returned as second return value)

Example:

local data = {
  title = "My App",
  version = "1.0.0"
}

local ok, err = toml.encode_file(data, "config.toml")

if ok then
  print("Config saved successfully")
else
  print("Failed to save:", err)
end

Error Conditions:

  • data is not a table
  • path is not writable (permissions, directory doesn't exist)
  • Disk full

Validation Functions

toml.validate(data)

Validate parsed TOML data structure.

Parameters:

  • data (any) - Data to validate

Returns:

  • boolean - true if valid
  • string|nil - Error message if invalid

Example:

local valid, err = toml.validate({name = "Tom"})

if valid then
  print("Data is valid")
else
  print("Validation failed:", err)
end

Validation Rules:

  • Data must be a table
  • Currently performs basic validation
  • Future versions will add more validation rules

Error Handling

Parse Errors

Parse errors include detailed location information:

local data, err = toml.parse('name =')

-- err contains:
-- "Parse error: Parse error at line 1, column 6: Expected value"

File Errors

File errors include OS-level error information:

local data, err = toml.parse_file("nonexistent.toml")

-- err contains:
-- "Cannot open file: nonexistent.toml: No such file or directory"

Encode Errors

Encode errors are raised as Lua errors:

local ok, err = pcall(function()
  toml.encode("not a table")  -- Raises error
end)

if not ok then
  print("Encode error:", err)
end

Advanced Usage

Roundtrip Conversion

Parse and encode while preserving data:

local original = {
  name = "Tom",
  config = {
    debug = true,
    port = 8080
  }
}

-- Encode to TOML
local toml_string = toml.encode(original)

-- Parse back
local parsed = toml.parse(toml_string)

-- Data is preserved
assert(parsed.name == original.name)
assert(parsed.config.port == original.config.port)

Custom Formatting

Control TOML output formatting:

local data = {
  z = 1,
  a = 2,
  database = {
    host = "localhost",
    port = 5432
  }
}

-- Sorted keys, no indentation
local compact = toml.encode(data, {
  sort_keys = true,
  indent = 0
})

-- With table headers and indentation
local formatted = toml.encode(data, {
  sort_keys = true,
  use_table_headers = true,
  indent = 4
})

Array Table Format (Default)

Default behavior - Uses human-readable [[array]] format:

local config = {
  server = "example.com",
  services = {
    {name = "web", port = 80, enabled = true},
    {name = "db", port = 5432, enabled = true}
  },
  auth = {
    method = "token",
    key = "secret"
  }
}

-- Default encoding (human-readable format)
local toml_string = toml.encode(config)
-- Output:
-- server = "example.com"
-- auth.method = "token"
-- auth.key = "secret"
--
-- [[services]]
--   name = "web"
--   port = 80
--   enabled = true
-- [[services]]
--   name = "db"
--   port = 5432
--   enabled = true

-- Compact encoding (inline arrays)
local toml_compact = toml.encode(config, {
  use_array_table_format = false
})
-- Output:
-- server = "example.com"
-- auth = {method = "token", key = "secret"}
-- services = [{name = "web", port = 80, enabled = true}, {name = "db", port = 5432, enabled = true}]

When to use each format:

  • Default ([[array]]): Configuration files, human-readable output, version control
  • Compact (inline): Data interchange, automated processing, minimal output

Working with Arrays

Parse and manipulate arrays:

local toml_string = [[
items = ["apple", "banana", "orange"]
numbers = [1, 2, 3, 4, 5]
]]

local data = toml.parse(toml_string)

-- Access array elements
print(data.items[1])      -- "apple"
print(data.numbers[3])    -- 3

-- Add to array
table.insert(data.items, "grape")

-- Encode back
local updated = toml.encode(data)

Nested Table Structures

Work with complex nested structures:

local toml_string = [[
[database]
host = "localhost"
port = 5432

[database.credentials]
username = "admin"
password = "secret"
]]

local data = toml.parse(toml_string)

-- Access nested values
print(data.database.host)              -- "localhost"
print(data.database.credentials.username) -- "admin"

-- Modify nested values
data.database.port = 3306
data.database.timeout = 30

-- Encode back
local updated = toml.encode(data)

Inline Table Preference

Control when inline tables are used:

local data = {
  server = {
    host = "localhost",
    port = 8080,
    ssl = true
  }
}

-- Default: uses inline table (3 keys <= inline_max_keys)
local toml1 = toml.encode(data)
-- Output: server = {host = "localhost", port = 8080, ssl = true}

-- Force table headers
local toml2 = toml.encode(data, {
  inline_max_keys = 0,
  use_table_headers = true
})
-- Output: \n[server]\n  host = "localhost"\n  port = 8080\n  ssl = true

Data Type Mapping

TOML to Lua

TOML Type Lua Type Example
String string "hello"
Integer number 42
Float number 3.14
Boolean boolean true
Array table [1, 2, 3]
Table table [section]
Inline Table table {key = value}

Lua to TOML

Lua Type TOML Type Example
string String "hello"
number (int) Integer 42
number (float) Float 3.14
boolean Boolean true
table (array) Array [1, 2, 3]
table (map) Table key = value

Best Practices

1. Always Check Return Values

local data, err = toml.parse_file("config.toml")
if not data then
  -- Handle error
  return nil, err
end

2. Use Roundtrip for Configuration Updates

-- Read config
local config = toml.parse_file("config.toml")

-- Modify
config.new_setting = true

-- Write back (preserves comments in future versions)
toml.encode_file(config, "config.toml")

3. Validate Input

if type(input) ~= "string" then
  return nil, "Input must be a string"
end

local data = toml.parse(input)

4. Use Options for Readable Output

local toml_string = toml.encode(data, {
  sort_keys = true,
  indent = 2
})

Limitations

  1. Comment Preservation: Comments are lost during roundtrip (planned for future versions)
  2. Table Order: Key order is not guaranteed (unless sort_keys = true)

Version History

  • 0.2.0-alpha: Added serialization (encode, encode_file)
  • 0.1.0-alpha: Initial release with parsing support

For more examples, see examples/ directory.