On this page
tecs.data
Typed stores, JSON, UTF-8, UUIDs, hashes, and checksums.
JSON
Encode and decode complete documents:
local text <const> = tecs.data.encodeJSON({
jsonrpc = "2.0",
id = 1,
result = {entities = {12, 24, 36}},
})
local value <const> = tecs.data.decodeJSON(text)Both functions raise on invalid input. Protect untrusted documents with pcall.
Lua needs sentinels for two JSON values:
local value <const> = tecs.data.decodeJSON('{"name":null,"rows":[]}')
assert(value.name == tecs.data.null)
local rows <const> = setmetatable({}, tecs.data.array_mt)
return tecs.data.encodeJSON({rows = rows})null preserves a present key whose JSON value equals null. An empty Lua table normally encodes as an object; empty_array and array_mt express an empty list. newJSON creates an independent configuration for protocols that must not share process-wide settings.
The sentinel and option names retain lua-cjson spelling because they belong to that library's compatibility surface.
UUIDs
Generate RFC 9562 identifiers without a central allocator:
local objectId <const> = tecs.data.uuid4()
local eventId <const> = tecs.data.uuid7()uuid4 draws its random bits from the operating system. uuid7 starts with the current Unix timestamp in milliseconds and orders calls made by this process, which makes it suitable for identifiers stored in an ordered index. Both return the canonical lowercase 8-4-4-4-12 representation.
UUIDs identify values; they do not authenticate a player or make an unguessable credential.
UTF-8
Codepoint operations live under tecs.data.utf8:
local utf8 <const> = tecs.data.utf8
local codepoint, nextOffset = utf8.decodeAt("A€", 2)
assert(codepoint == 0x20ac)
assert(nextOffset == 5)The child works over explicit byte lengths in strings and ByteViews, so embedded NUL is U+0000 rather than a terminator. Malformed bytes decode as U+FFFD and remain traversable. These are codepoint operations, not grapheme segmentation.
Hashes and checksums
fnv1a64 supplies fast process and build identity as 16 lowercase hexadecimal digits. sha256 supplies a cryptographic digest as 64 lowercase hexadecimal digits. adler32 and crc32 implement checksums required by formats that name them. Pass the checksum from one call as the second argument to continue over the next chunk without joining the chunks into one string:
local checksum = tecs.data.crc32(header)
checksum = tecs.data.crc32(body, checksum)SHA-256 authenticates nothing by itself. Verify downloaded artifacts against a digest obtained through a trusted channel or a signed manifest.
Typed stores
Create typed keys once and use them with independent stores:
local SPEED <const>: tecs.data.Key<number> = tecs.data.Store.newKey(
"game.speed"
)
local store <const> = tecs.data.newStore()
store[SPEED] = 120world.resources is a Store. Stores are in-memory and independent; a named key is the process-wide identity that lets hot reload and tooling find the same value again. Store.listKeys reports the named keys registered by the process.
Module contents
Submodules
| Submodule | Description |
|---|---|
tecs.data.utf8 |
UTF-8 codepoint decoding, encoding, validation, and truncation |
Constructors
| Constructor | Description |
|---|---|
newStore |
Creates an independent typed store. |
Types
| Type | Kind | Description |
|---|---|---|
ByteInput |
type | ByteInput accepts a Lua byte string or an open Buffer or ByteView. |
Key |
interface | Key identifies one typed store value across every store in the process. |
Store |
record | Store holds typed values under process-wide keys and exposes their process-wide registry. |
Functions
| Function | Kind | Description |
|---|---|---|
adler32 |
Static | Computes Adler-32 over the bytes of text as a number in [0, 2^32). |
crc32 |
Static | Computes CRC-32 over the bytes of text as a number in [0, 2^32). |
fnv1a64 |
Static | FNV-1a over the bytes of text, 64-bit, as sixteen lowercase hex digits. |
sha256 |
Static | Computes SHA-256 over the bytes of text. |
uuid4 |
Static | Generates a random RFC 9562 UUID version 4. |
uuid7 |
Static | Generates a time-ordered RFC 9562 UUID version 7. |
Constructors
tecs.data.newStore Static
Creates an independent typed store.
function tecs.data.newStore(): StoreArguments
None.
Returns
| Type | Description |
|---|---|
Store |
Returns an empty store. You own it and its values. |
Types
tecs.data.ByteInput type
ByteInput accepts a Lua byte string or an open Buffer or ByteView.
type tecs.data.ByteInput = string | ByteViewtecs.data.Key interface
Key identifies one typed store value across every store in the process.
interface tecs.data.Key<T>
endType Parameters
| Name | Constraint | Description |
|---|---|---|
T |
tecs.data.Store record
Store holds typed values under process-wide keys and exposes their process-wide registry.
record tecs.data.Store
findKey: function<T>(name: string): Key<T> | nil
listKeys: function(): {string: integer}
newKey: function<T>(name: string, forType: T): Key<T>
__index: function<T>(self, key: Key<T>): T
__newindex: function<T>(self, key: Key<T>, value: T)
endtecs.data.Store.findKey Static
Returns a named key created by newKey.
Type Parameters
| Name | Constraint | Description |
|---|---|---|
T |
Arguments
| Name | Type | Description |
|---|---|---|
name |
string |
The name used during key creation. |
Returns
| Type | Description |
|---|---|
Key<T> | nil |
Returns the existing key, or nil before any module creates it. |
tecs.data.Store.listKeys Static
Returns all named keys as name-to-id entries.
function tecs.data.Store.listKeys(): {string: integer}Arguments
None.
Returns
| Type | Description |
|---|---|
{string : integer} |
Returns a fresh process-wide table. |
tecs.data.Store.newKey Static
Creates a typed key.
Always pass a name. Named keys are discoverable through findKey and listKeys, and repeating a name returns the same key so values remain reachable when a module reloads.
Type Parameters
| Name | Constraint | Description |
|---|---|---|
T |
Arguments
| Name | Type | Description |
|---|---|---|
name |
string |
The namespaced identity, such as "game.state". Omitting it creates an anonymous key and warns. |
forType |
T |
Pass nil as T when Teal needs the value type carried explicitly. The function does not read it. |
Returns
| Type | Description |
|---|---|
Key<T> |
Returns the stable key for a name or a fresh anonymous key. |
tecs.data.Store:__index
Returns the value associated with a typed key. An unwritten key returns nil.
local SPEED <const>: tecs.data.Key<number> = tecs.data.Store.newKey(
"game.speed"
)
local store <const> = tecs.data.newStore()
local speed <const> = store[SPEED]Type Parameters
| Name | Constraint | Description |
|---|---|---|
T |
Arguments
| Name | Type | Description |
|---|---|---|
self |
Store |
The Store to index. |
key |
Key<T> |
The Key used to retrieve its value. |
Returns
| Type | Description |
|---|---|
T |
Returns the value for key, or nil when no value has been assigned. |
tecs.data.Store:__newindex
Associates a value with a typed key. Assigning nil removes the value.
local SPEED <const>: tecs.data.Key<number> = tecs.data.Store.newKey(
"game.speed"
)
local store <const> = tecs.data.newStore()
store[SPEED] = 120Type Parameters
| Name | Constraint | Description |
|---|---|---|
T |
Arguments
| Name | Type | Description |
|---|---|---|
self |
Store |
The Store to index. |
key |
Key<T> |
The Key used to associate the value. |
value |
T |
The value to associate with key. Passing nil removes the association. |
Returns
None.
Functions
tecs.data.adler32 Static
Computes Adler-32 over the bytes of text as a number in [0, 2^32).
The checksum RFC 1950 puts in a zlib stream's trailer, which is the only reason it is here. It is a poor content hash and is not offered as one: it is a sum of a sum, it barely mixes on short inputs, and two files that differ by reordering equal-length runs collide outright. Use fnv1a64 for identity and this only for the format that specifies it.
zlib computes it. The seed is 1, which is what RFC 1950 starts from and what zlib's own documentation says to pass for the first call. Pass the return value back as previous to continue the checksum over another chunk. An empty chunk leaves previous unchanged.
function tecs.data.adler32(
text: ByteInput, previous: integer
): integerArguments
| Name | Type | Description |
|---|---|---|
text |
ByteInput |
A byte string or open ByteView. NUL and bytes above 127 contribute like any other. |
previous |
integer |
The checksum returned after all preceding bytes. Omit it for the first chunk. Raises unless it is an unsigned 32-bit integer. |
Returns
| Type | Description |
|---|---|
integer |
The checksum after text, as an exact Lua number in [0, 2^32). |
tecs.data.crc32 Static
Computes CRC-32 over the bytes of text as a number in [0, 2^32).
The checksum PNG, gzip and ZIP put beside compressed bytes. It detects accidental corruption and is not a cryptographic digest; use it only where a format specifies CRC-32 or where an error-detecting checksum is enough. Pass the return value back as previous to continue the checksum over another chunk. An empty chunk leaves previous unchanged.
function tecs.data.crc32(
text: ByteInput, previous: integer
): integerArguments
| Name | Type | Description |
|---|---|---|
text |
ByteInput |
A byte string or open ByteView. NUL and bytes above 127 contribute like any other. |
previous |
integer |
The checksum returned after all preceding bytes. Omit it for the first chunk. Raises unless it is an unsigned 32-bit integer. |
Returns
| Type | Description |
|---|---|
integer |
The checksum after text, as an exact Lua number in [0, 2^32). |
tecs.data.fnv1a64 Static
FNV-1a over the bytes of text, 64-bit, as sixteen lowercase hex digits.
function tecs.data.fnv1a64(text: ByteInput): stringArguments
| Name | Type | Description |
|---|---|---|
text |
ByteInput |
A byte string or open ByteView. NUL and bytes above 127 hash like any other. |
Returns
| Type | Description |
|---|---|
string |
Sixteen hex digits, high half first, so hashes sort as their values do and two of them compare as strings. |
tecs.data.sha256 Static
Computes SHA-256 over the bytes of text.
SHA-256 detects whether bytes match a trusted digest. It does not prove who supplied either value, so artifact verification obtains the expected digest through a trusted channel or a signed manifest.
function tecs.data.sha256(text: ByteInput): stringArguments
| Name | Type | Description |
|---|---|---|
text |
ByteInput |
A byte string or open ByteView. NUL and bytes above 127 hash like any other. |
Returns
| Type | Description |
|---|---|
string |
Sixty-four lowercase hexadecimal digits, high byte first. |
tecs.data.uuid4 Static
Generates a random RFC 9562 UUID version 4.
function tecs.data.uuid4(): stringArguments
None.
Returns
| Type | Description |
|---|---|
string |
Returns a fresh UUID in canonical lowercase 8-4-4-4-12 form. |
tecs.data.uuid7 Static
Generates a time-ordered RFC 9562 UUID version 7.
Calls made by this process remain ordered even when more than one falls in the same millisecond. The timestamp makes the result unsuitable for hiding when an identifier was created.
function tecs.data.uuid7(): stringArguments
None.
Returns
| Type | Description |
|---|---|
string |
Returns a fresh UUID in canonical lowercase 8-4-4-4-12 form. |