Luau Bindings — data

The require("data") script API — encoding, decoding, and hashing: JSON, base64, hex, checksums, and the magnetic-disk codecs. The glue between raw bytes and Lua values. Every function is [antos]. Design & native core: antos_data. (Signing, HMAC, and the TLS CA store split into crypto.)

local data = require("data")
local t = data.json.decode('{"a":1,"b":[2,3]}')

Decode functions return value, or nil, err on malformed input.


JSON — data.json.*

Function Behaviour
data.json.encode(value [, pretty]) Lua value → JSON string; pretty = true for indented output.
data.json.decode(str) JSON string → Lua value, or nil, err. null → the data.json.null sentinel.

Encodings — data.base64.* / data.hex.*

Function Behaviour
data.base64.encode(str) · data.base64.decode(str) Standard base64.
data.base64.encode_url(str) · data.base64.decode_url(str) URL-safe base64 (-/_, no padding).
data.hex.encode(str) · data.hex.decode(str) Hex string ↔ bytes.

Hashing & checksums

Function Behaviour
data.sha256(str) SHA-256 → 64-char hex string.
data.md5(str) MD5 → 32-char hex string (legacy interop).
data.crc32(str [, init]) CRC-32 integer (the checksum DBFS catalogues with).
data.crc16(str [, init]) CRC-16/CCITT integer. Also the IBM MFM sector CRC — pass init = 0xFFFF.
print(data.sha256("hello"))                 -- 2cf24dba5fb0a30e...
print(data.base64.encode_url(raw_bytes))    -- token-safe

These are plain hashes, not secrets — kept in data because they're used everywhere. Keyed MACs (hmac) and signatures live in crypto.


Disk codecs — data.mfm.* / data.gcr.*

The bit-cell encodings real floppy disks are written in. Pure transforms — bytes in, bit cells out and back — with no device, session or state, which is why they live here rather than in floppy. floppy handles everything they deliberately leave out: clock recovery, sync hunting, track segmentation, weak bits.

Bit cells are passed as byte strings, packed MSB-first.

MFM — data.mfm.*

Function Behaviour
data.mfm.encode(str [, prev]) Bytes → MFM bit cells. prev is the last cell of the preceding run, so encoding a track in pieces stays continuous.
data.mfm.decode(str) MFM bit cells → bytes. Returns nil, err on an illegal cell pattern.
data.mfm.encode_amiga(str) Amiga odd/even split encoding — all odd bits, then all even.
data.mfm.decode_amiga(odd, even) Reassemble an Amiga odd/even pair into bytes.
data.mfm.sync(word) Build a sync pattern (0x4489 is the Amiga/IBM one) as bit cells.

GCR — data.gcr.*

Function Behaviour
data.gcr.encode(str, variant) Bytes → GCR. variant: "6and2" (Commodore, Apple 3.5 / late 5.25), "5and3" (early Apple 5.25), "4and4" (headers).
data.gcr.decode(str, variant) GCR → bytes, or nil, err on an invalid code.
data.gcr.variants() Supported variant names.

Format checksums

Function Behaviour
data.checksum.amiga(str) Amiga sector header / data checksum (32-bit XOR of longwords).
data.checksum.cbm(str) Commodore GCR block checksum (8-bit XOR).

For IBM MFM sectors use data.crc16(bytes, 0xFFFF) — same algorithm, already here.

-- Amiga sector data: 512 bytes as an odd/even MFM pair
local odd, even = data.mfm.encode_amiga(sector)
local sum       = data.checksum.amiga(sector)

Related

Important: The Ant64 family of home computers are at early design/prototype stage, everything you see here is subject to change.