Skip to main content

Bufferize

Bufferize losslessly encodes and decodes Roblox data types into buffer objects.

The module exposes a default encoder via the top-level encode / decode functions, along with helpers for serializing instances and deduplicating repeated values inside a table. For per-type encoding overrides, create a dedicated Encoder with Bufferize.custom.

local b = Bufferize.encode("Hello world!", 123, true, { foo = "bar" })
print(Bufferize.decode(b)) -- "Hello world!", 123, true, { foo = "bar" }

Properties​

VERSION​

Versioning
Bufferize.VERSION: string

The semantic version string of the running Bufferize module. This is the same value that gets written into the header of every buffer produced by encode. See the versioning guide in the readme for compatibility rules.

read​

Raw
Bufferize.read: Readers

A table of raw reader functions keyed by data type name (e.g. Bufferize.read.CFrame). Each reader has the signature (b: buffer, offset: number) -> (value, nextOffset) and reads a single value written by the matching Bufferize.write function.

Unlike decode, raw readers do not expect a version header or a type id — the caller is responsible for knowing which type is stored at each offset.

local b, offset = Bufferize.write.CFrame(buffer.create(0), 0, cf)
b, offset = Bufferize.write.Vector3(b, offset, v)

local cf2, nextOffset = Bufferize.read.CFrame(b, 0)
local v2 = Bufferize.read.Vector3(b, nextOffset)

Raw readers always use the default encoding and ignore any overrides registered on an Encoder.

write​

Raw
Bufferize.write: Writers

A table of raw writer functions keyed by data type name (e.g. Bufferize.write.CFrame). Each writer has the signature (b: buffer, offset: number, value) -> (buffer, nextOffset) and writes a single value without a version header or type id.

If the value fits inside b it is written in place and b is returned. Otherwise a larger copy of b is created and returned instead, so always use the returned buffer for subsequent writes.

Raw writers always use the default encoding and ignore any overrides registered on an Encoder.

Functions​

readVersion​

Versioning
Bufferize.readVersion(
b: buffer--

A buffer previously produced by Bufferize.encode.

) → string?--

The semantic version string written into the header, or nil if it could not be parsed.

Inspects the version that was written into a buffer's header without attempting to decode the body. Useful for migration code that needs to branch on the producing version before decoding.

isCompatible​

Versioning
Bufferize.isCompatible(
b: buffer--

A buffer previously produced by Bufferize.encode.

) → boolean--

true if the buffer's header version can be decoded by the running version of Bufferize.

Checks whether the running version of Bufferize is able to decode the given buffer. This is the same version check decode performs, so a false result means decode would raise an error rather than return a value.

if Bufferize.isCompatible(b) then
	local value = Bufferize.decode(b)
else
	-- migrate the data with an older version, or discard it
end

Only the version header is inspected — the body is not decoded, so a true result does not guarantee the rest of the buffer is well-formed. Buffers that were not produced by encode at all return false.

custom​

Bufferize.custom() → Encoder--

A new encoder with no overrides registered.

Creates a new Encoder that you can configure with custom read/write functions for individual data types via Encoder:override. The returned encoder is independent of the module-level encode / decode functions — you must use the same encoder for both halves of a round-trip.

See custom encoding in the readme for examples.

deduplicateTypeof​

Deduplication
Bufferize.deduplicateTypeof(
typeOfsSet: {[string]: boolean},--

Set of type names (e.g. "string", "CFrame") to consider for deduplication.

rootTbl: {[any]: any}--

The table to deduplicate.

) → {{[any]: any}}--

A { deduplicated, root } pair to pass to encode.

Scans rootTbl for keys and values whose typeof is in typeOfsSet and that appear more than once, and replaces each duplicate with a pointer to a single shared entry. Use this when you don't know up front which specific values are duplicated.

The returned table can be passed directly to Bufferize.encode. After decoding, use Bufferize.reduplicate to expand the pointers back into the original values.

See the deduplication guide for usage examples.

deduplicate​

Deduplication
Bufferize.deduplicate(
supportedSet: {[any]: boolean},--

Set of exact values that should be deduplicated.

rootTbl: {[any]: any}--

The table to deduplicate.

) → {{[any]: any}}--

A { deduplicated, root } pair to pass to encode.

Replaces every occurrence of each value in supportedSet (as a key or as a value) with a pointer into a shared array of deduplicated values. Use this when you know exactly which values you want to collapse.

The returned table can be passed directly to Bufferize.encode. After decoding, use Bufferize.reduplicate to expand the pointers back into the original values.

reduplicate​

Deduplication
Bufferize.reduplicate(
compressed: {{[any]: any}}--

A table previously produced by deduplicate / deduplicateTypeof, after a round-trip through encode / decode.

) → {[any]: any}--

The expanded table with deduplication pointers replaced by their original values.

Reverses Bufferize.deduplicate / Bufferize.deduplicateTypeof, producing a plain table you can use exactly as you would have used the input to the deduplication call.

serializeInstance​

Instances
Bufferize.serializeInstance(
rootInstance: Instance--

The root of the instance tree to serialize.

) → {any}--

A plain table representation that can be passed to encode.

Walks rootInstance and all of its descendants and produces a table that captures each instance's ClassName, non-default writable properties, attributes, and tags. References between instances within the tree are preserved; references to instances outside the tree are dropped.

See the instances guide for the full set of rules and examples.

deserializeInstance​

Instances
Bufferize.deserializeInstance(
serializedArr: {any}--

A table previously produced by serializeInstance, after a round-trip through encode / decode.

) → Instance--

The reconstructed root instance, with all descendants parented underneath.

Recreates the instance tree captured by Bufferize.serializeInstance. Properties, attributes, tags, and intra-tree references are restored on the new instances.

encode​

Bufferize.encode(
...: Supported--

One or more values of supported data types.

) → buffer--

A buffer that round-trips through Bufferize.decode to the same values.

Encodes the given values into a buffer using the module-level default encoder. The buffer is prefixed with the running Bufferize version so that decode can refuse to read data produced by an incompatible version.

Tables are walked recursively; shared sub-tables are preserved as shared references in the decoded output.

decode​

Bufferize.decode(
b: buffer--

A buffer previously produced by Bufferize.encode.

) → ...Supported--

The original values, in the same order they were passed to encode.

Decodes a buffer produced by Bufferize.encode. Raises an error if the buffer was encoded with an incompatible major version, or with a newer version of Bufferize than the one currently loaded.

encodeHeaderless​

Versioning
Bufferize.encodeHeaderless(
...: Supported--

One or more values of supported data types.

) → buffer--

A buffer that round-trips through Bufferize.decodeHeaderless to the same values.

Same as Bufferize.encode, but the version header is omitted. This saves a few bytes per buffer at the cost of the version compatibility checks, so it's best suited to short-lived data (e.g. networking) where both ends are guaranteed to be running the same version of Bufferize.

decodeHeaderless​

Versioning
Bufferize.decodeHeaderless(
b: buffer--

A buffer previously produced by Bufferize.encodeHeaderless.

) → ...Supported--

The original values, in the same order they were passed to encodeHeaderless.

Decodes a buffer produced by Bufferize.encodeHeaderless. No version checks are performed, so decoding a buffer produced by an incompatible version of Bufferize may error or return incorrect values.

Show raw api
{
    "functions": [
        {
            "name": "readVersion",
            "desc": "Inspects the version that was written into a buffer's header without\nattempting to decode the body. Useful for migration code that needs to\nbranch on the producing version before decoding.",
            "params": [
                {
                    "name": "b",
                    "desc": "A buffer previously produced by `Bufferize.encode`.",
                    "lua_type": "buffer"
                }
            ],
            "returns": [
                {
                    "desc": "The semantic version string written into the header, or `nil` if it could not be parsed.",
                    "lua_type": "string?"
                }
            ],
            "function_type": "static",
            "tags": [
                "Versioning"
            ],
            "source": {
                "line": 57,
                "path": "src/init.luau"
            }
        },
        {
            "name": "isCompatible",
            "desc": "Checks whether the running version of Bufferize is able to decode the given\nbuffer. This is the same version check `decode` performs, so a `false` result\nmeans `decode` would raise an error rather than return a value.\n\n```lua\nif Bufferize.isCompatible(b) then\n\tlocal value = Bufferize.decode(b)\nelse\n\t-- migrate the data with an older version, or discard it\nend\n```\n\nOnly the version header is inspected — the body is not decoded, so a `true`\nresult does not guarantee the rest of the buffer is well-formed. Buffers that\nwere not produced by `encode` at all return `false`.",
            "params": [
                {
                    "name": "b",
                    "desc": "A buffer previously produced by `Bufferize.encode`.",
                    "lua_type": "buffer"
                }
            ],
            "returns": [
                {
                    "desc": "`true` if the buffer's header version can be decoded by the running version of Bufferize.",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "tags": [
                "Versioning"
            ],
            "source": {
                "line": 82,
                "path": "src/init.luau"
            }
        },
        {
            "name": "custom",
            "desc": "Creates a new [Encoder] that you can configure with custom read/write\nfunctions for individual data types via [Encoder:override]. The returned\nencoder is independent of the module-level `encode` / `decode` functions —\nyou must use the same encoder for both halves of a round-trip.\n\nSee custom encoding in the readme for examples.",
            "params": [],
            "returns": [
                {
                    "desc": "A new encoder with no overrides registered.",
                    "lua_type": "Encoder"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 141,
                "path": "src/init.luau"
            }
        },
        {
            "name": "deduplicateTypeof",
            "desc": "Scans `rootTbl` for keys and values whose `typeof` is in `typeOfsSet` and\nthat appear more than once, and replaces each duplicate with a pointer to a\nsingle shared entry. Use this when you don't know up front which specific\nvalues are duplicated.\n\nThe returned table can be passed directly to `Bufferize.encode`. After\ndecoding, use [Bufferize.reduplicate] to expand the pointers back into the\noriginal values.\n\nSee the [deduplication guide](/docs/deduplication) for usage examples.",
            "params": [
                {
                    "name": "typeOfsSet",
                    "desc": "Set of type names (e.g. `\"string\"`, `\"CFrame\"`) to consider for deduplication.",
                    "lua_type": "{ [string]: boolean }"
                },
                {
                    "name": "rootTbl",
                    "desc": "The table to deduplicate.",
                    "lua_type": "{ [any]: any }"
                }
            ],
            "returns": [
                {
                    "desc": "A `{ deduplicated, root }` pair to pass to `encode`.",
                    "lua_type": "{ { [any]: any } }"
                }
            ],
            "function_type": "static",
            "tags": [
                "Deduplication"
            ],
            "source": {
                "line": 162,
                "path": "src/init.luau"
            }
        },
        {
            "name": "deduplicate",
            "desc": "Replaces every occurrence of each value in `supportedSet` (as a key or as a\nvalue) with a pointer into a shared array of deduplicated values. Use this\nwhen you know exactly which values you want to collapse.\n\nThe returned table can be passed directly to `Bufferize.encode`. After\ndecoding, use [Bufferize.reduplicate] to expand the pointers back into the\noriginal values.",
            "params": [
                {
                    "name": "supportedSet",
                    "desc": "Set of exact values that should be deduplicated.",
                    "lua_type": "{ [any]: boolean }"
                },
                {
                    "name": "rootTbl",
                    "desc": "The table to deduplicate.",
                    "lua_type": "{ [any]: any }"
                }
            ],
            "returns": [
                {
                    "desc": "A `{ deduplicated, root }` pair to pass to `encode`.",
                    "lua_type": "{ { [any]: any } }"
                }
            ],
            "function_type": "static",
            "tags": [
                "Deduplication"
            ],
            "source": {
                "line": 180,
                "path": "src/init.luau"
            }
        },
        {
            "name": "reduplicate",
            "desc": "Reverses [Bufferize.deduplicate] / [Bufferize.deduplicateTypeof], producing\na plain table you can use exactly as you would have used the input to the\ndeduplication call.",
            "params": [
                {
                    "name": "compressed",
                    "desc": "A table previously produced by `deduplicate` / `deduplicateTypeof`, after a round-trip through `encode` / `decode`.",
                    "lua_type": "{ { [any]: any } }"
                }
            ],
            "returns": [
                {
                    "desc": "The expanded table with deduplication pointers replaced by their original values.",
                    "lua_type": "{ [any]: any }"
                }
            ],
            "function_type": "static",
            "tags": [
                "Deduplication"
            ],
            "source": {
                "line": 193,
                "path": "src/init.luau"
            }
        },
        {
            "name": "serializeInstance",
            "desc": "Walks `rootInstance` and all of its descendants and produces a table that\ncaptures each instance's `ClassName`, non-default writable properties,\nattributes, and tags. References between instances within the tree are\npreserved; references to instances outside the tree are dropped.\n\nSee the [instances guide](/docs/instances) for the full set of rules and\nexamples.",
            "params": [
                {
                    "name": "rootInstance",
                    "desc": "The root of the instance tree to serialize.",
                    "lua_type": "Instance"
                }
            ],
            "returns": [
                {
                    "desc": "A plain table representation that can be passed to `encode`.",
                    "lua_type": "{ any }"
                }
            ],
            "function_type": "static",
            "tags": [
                "Instances"
            ],
            "source": {
                "line": 210,
                "path": "src/init.luau"
            }
        },
        {
            "name": "deserializeInstance",
            "desc": "Recreates the instance tree captured by [Bufferize.serializeInstance].\nProperties, attributes, tags, and intra-tree references are restored on the\nnew instances.",
            "params": [
                {
                    "name": "serializedArr",
                    "desc": "A table previously produced by `serializeInstance`, after a round-trip through `encode` / `decode`.",
                    "lua_type": "{ any }"
                }
            ],
            "returns": [
                {
                    "desc": "The reconstructed root instance, with all descendants parented underneath.",
                    "lua_type": "Instance"
                }
            ],
            "function_type": "static",
            "tags": [
                "Instances"
            ],
            "source": {
                "line": 223,
                "path": "src/init.luau"
            }
        },
        {
            "name": "encode",
            "desc": "Encodes the given values into a buffer using the module-level default\nencoder. The buffer is prefixed with the running Bufferize version so that\n`decode` can refuse to read data produced by an incompatible version.\n\nTables are walked recursively; shared sub-tables are preserved as shared\nreferences in the decoded output.",
            "params": [
                {
                    "name": "...",
                    "desc": "One or more values of supported data types.",
                    "lua_type": "Supported"
                }
            ],
            "returns": [
                {
                    "desc": "A buffer that round-trips through `Bufferize.decode` to the same values.",
                    "lua_type": "buffer"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 237,
                "path": "src/init.luau"
            }
        },
        {
            "name": "decode",
            "desc": "Decodes a buffer produced by `Bufferize.encode`. Raises an error if the\nbuffer was encoded with an incompatible major version, or with a newer\nversion of Bufferize than the one currently loaded.",
            "params": [
                {
                    "name": "b",
                    "desc": "A buffer previously produced by `Bufferize.encode`.",
                    "lua_type": "buffer"
                }
            ],
            "returns": [
                {
                    "desc": "The original values, in the same order they were passed to `encode`.",
                    "lua_type": "...Supported"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 250,
                "path": "src/init.luau"
            }
        },
        {
            "name": "encodeHeaderless",
            "desc": "Same as [Bufferize.encode], but the version header is omitted. This saves a\nfew bytes per buffer at the cost of the version compatibility checks, so\nit's best suited to short-lived data (e.g. networking) where both ends are\nguaranteed to be running the same version of Bufferize.",
            "params": [
                {
                    "name": "...",
                    "desc": "One or more values of supported data types.",
                    "lua_type": "Supported"
                }
            ],
            "returns": [
                {
                    "desc": "A buffer that round-trips through `Bufferize.decodeHeaderless` to the same values.",
                    "lua_type": "buffer"
                }
            ],
            "function_type": "static",
            "tags": [
                "Versioning"
            ],
            "source": {
                "line": 265,
                "path": "src/init.luau"
            }
        },
        {
            "name": "decodeHeaderless",
            "desc": "Decodes a buffer produced by [Bufferize.encodeHeaderless]. No version\nchecks are performed, so decoding a buffer produced by an incompatible\nversion of Bufferize may error or return incorrect values.",
            "params": [
                {
                    "name": "b",
                    "desc": "A buffer previously produced by `Bufferize.encodeHeaderless`.",
                    "lua_type": "buffer"
                }
            ],
            "returns": [
                {
                    "desc": "The original values, in the same order they were passed to `encodeHeaderless`.",
                    "lua_type": "...Supported"
                }
            ],
            "function_type": "static",
            "tags": [
                "Versioning"
            ],
            "source": {
                "line": 279,
                "path": "src/init.luau"
            }
        }
    ],
    "properties": [
        {
            "name": "VERSION",
            "desc": "The semantic version string of the running Bufferize module. This is the\nsame value that gets written into the header of every buffer produced by\n`encode`. See the versioning guide in the readme for compatibility\nrules.",
            "lua_type": "string",
            "tags": [
                "Versioning"
            ],
            "source": {
                "line": 44,
                "path": "src/init.luau"
            }
        },
        {
            "name": "read",
            "desc": "A table of raw reader functions keyed by data type name (e.g.\n`Bufferize.read.CFrame`). Each reader has the signature\n`(b: buffer, offset: number) -> (value, nextOffset)` and reads a single\nvalue written by the matching [Bufferize.write] function.\n\nUnlike `decode`, raw readers do not expect a version header or a type id —\nthe caller is responsible for knowing which type is stored at each offset.\n\n```lua\nlocal b, offset = Bufferize.write.CFrame(buffer.create(0), 0, cf)\nb, offset = Bufferize.write.Vector3(b, offset, v)\n\nlocal cf2, nextOffset = Bufferize.read.CFrame(b, 0)\nlocal v2 = Bufferize.read.Vector3(b, nextOffset)\n```\n\nRaw readers always use the default encoding and ignore any overrides\nregistered on an [Encoder].",
            "lua_type": "Readers",
            "tags": [
                "Raw"
            ],
            "source": {
                "line": 108,
                "path": "src/init.luau"
            }
        },
        {
            "name": "write",
            "desc": "A table of raw writer functions keyed by data type name (e.g.\n`Bufferize.write.CFrame`). Each writer has the signature\n`(b: buffer, offset: number, value) -> (buffer, nextOffset)` and writes a\nsingle value without a version header or type id.\n\nIf the value fits inside `b` it is written in place and `b` is returned.\nOtherwise a larger copy of `b` is created and returned instead, so always\nuse the returned buffer for subsequent writes.\n\nRaw writers always use the default encoding and ignore any overrides\nregistered on an [Encoder].",
            "lua_type": "Writers",
            "tags": [
                "Raw"
            ],
            "source": {
                "line": 127,
                "path": "src/init.luau"
            }
        }
    ],
    "types": [],
    "name": "Bufferize",
    "desc": "Bufferize losslessly encodes and decodes Roblox data types into\n[`buffer`](https://create.roblox.com/docs/reference/engine/libraries/buffer)\nobjects.\n\nThe module exposes a default encoder via the top-level `encode` / `decode`\nfunctions, along with helpers for serializing instances and deduplicating\nrepeated values inside a table. For per-type encoding overrides, create a\ndedicated [Encoder] with [Bufferize.custom].\n\n```lua\nlocal b = Bufferize.encode(\"Hello world!\", 123, true, { foo = \"bar\" })\nprint(Bufferize.decode(b)) -- \"Hello world!\", 123, true, { foo = \"bar\" }\n```",
    "source": {
        "line": 18,
        "path": "src/init.luau"
    }
}