Skip to main content

InfArray

A chunked array that bypasses Luau's internal table size limit of 2^26.

Values are stored across fixed-size chunks so a single logical array can hold up to 2^53 elements (the largest exact integer a Luau number can represent). Indices are 1-based and resolved with integer math.

Removals leave nil holes. Per-chunk logical lengths are tracked explicitly, so the implementation never relies on # over a chunk (which is undefined once the chunk contains holes). InfArray:Length reports the highest assigned index (holes included), while InfArray:Count reports the number of present elements.

local InfArray = require(path.to.InfArray)

local arr = InfArray.new()
arr:PushBack("a")
arr:PushBack("b")
print(arr:Get(1)) --> "a"
print(#arr)       --> 2

Several backwards-compatible aliases exist for the primary methods: get/GetValueAtIndex (Get), set/Replace (Set), InsertBack (PushBack), TransformRange (Transform), GetTotalLen (Count) and GetLength (Length).

Properties

LIMIT

This item is read only and cannot be modified. Read Onlystatic
InfArray.LIMIT: number

Maximum number of elements a single chunk can hold (2^26 = 67108864).

Functions

new

InfArray.new(
sizenumber?,--

Optional initial length; pre-allocates chunks.

valueany?--

Optional fill value written to every pre-allocated slot.

) → InfArray

Creates a new InfArray. When size is given, the array is pre-sized to size elements; if value is also provided, every slot is filled with it and InfArray:Count reflects the full size (otherwise the slots start as holes).

Get

InfArray:Get(
indexnumber--

1-based global index.

) → any?--

The value at index, or nil if unset or out of range.

Reads the value at index in O(1). Returns nil for holes and for indices whose chunk does not exist yet.

Set

InfArray:Set(
indexnumber,--

1-based global index within an existing chunk.

valueany?--

New value; pass nil to clear the slot into a hole.

) → boolean--

true if the write happened, false if it was a no-op.

In-range O(1) write that keeps InfArray:Count and InfArray:Length correct. Returns true when the write lands. This is a no-op returning false if the index's chunk does not exist yet — use InfArray:PushBack, InfArray.new with a size, or InfArray:SetChunk to grow the array first.

GetChunk

InfArray:GetChunk(
indexnumber--

1-based chunk index.

) → {any}?--

The raw backing table for that chunk, or nil.

Returns the raw chunk table by chunk index. The returned table may contain nil holes and is not length-safe under #; pair it with the chunk's tracked length (see InfArray:IterateChunks) when scanning it.

SetChunk

InfArray:SetChunk(
chunkIndexnumber,--

1-based chunk index to replace.

value{any},--

The new backing table for the chunk.

lennumber?--

Logical length of value; defaults to #value.

) → ()

Replaces an entire chunk in one call, recomputing InfArray:Count for the swapped range and extending InfArray:Length if the new chunk reaches further. Prefer this over per-element writes for bulk population.

GetChunkAndPosition

InfArray:GetChunkAndPosition(
indexnumber--

1-based global index.

) → (
{any}?,--

The chunk containing index, or nil if absent.

number--

The 1-based position of index within that chunk.

)

Resolves a global index to its chunk and in-chunk position in one call, useful for hot loops that want to read/write a slot without recomputing the location.

PushBack

InfArray:PushBack(
valueany--

Value to append at the end of the array.

) → number--

The global index the value was written to.

Appends value after the highest assigned index, allocating a new chunk when the current one fills up. Amortised O(1).

RemoveIndex

InfArray:RemoveIndex(
indexnumber--

1-based global index to clear.

) → ()

Clears the value at index, decrementing InfArray:Count. This leaves a nil hole — InfArray:Length is unchanged and later elements are not shifted.

Iterate

InfArray:Iterate(
callback(
indexnumber,
valueany
) → boolean?--

Called for each present element; return true to stop early.

) → ()

Iterates every present element in ascending index order, skipping holes. Return true from callback to break out early. For maximum bulk throughput, use InfArray:IterateChunks instead.

IterateChunks

InfArray:IterateChunks(
callback(
chunk{any},
basenumber,
lennumber
) → boolean?--

Called once per chunk; return true to stop early.

) → ()

Hands each raw chunk to callback along with its base global-index offset and tracked len. The fastest way to process the whole array in bulk. The caller must nil-check chunk[j] itself, since chunks may contain holes. Return true to stop early.

Find

InfArray:Find(
needleany--

Value to search for.

) → number?--

The first global index equal to needle, or nil.

Linearly scans in ascending order and returns the first global index whose value equals needle, or nil if not found. Scans to each chunk's tracked length so holes never cut the search short.

Transform

InfArray:Transform(
startnumber,--

First global index to visit (inclusive).

stopnumber,--

Last global index to visit (inclusive).

stepnumber,--

Stride between visited indices.

updateFunc(
indexnumber,
valueany
) → any--

Returns the new value for each visited slot.

) → ()

Applies updateFunc over the range [start, stop] by step, writing back each returned value. May turn holes into values (or values back into holes); InfArray:Count stays correct either way. Indices whose chunk does not exist are skipped.

Count

InfArray:Count() → number--

The number of present (non-nil) elements.

Returns how many elements are actually present, excluding holes. O(1).

Length

InfArray:Length() → number--

The highest assigned index (holes included).

Returns the logical length: the highest index ever assigned, counting holes. Equivalent to #arr. O(1).

Show raw api
{
    "functions": [
        {
            "name": "new",
            "desc": "Creates a new [InfArray]. When `size` is given, the array is pre-sized to `size`\nelements; if `value` is also provided, every slot is filled with it and\n[InfArray:Count] reflects the full size (otherwise the slots start as holes).",
            "params": [
                {
                    "name": "size",
                    "desc": "Optional initial length; pre-allocates chunks.",
                    "lua_type": "number?"
                },
                {
                    "name": "value",
                    "desc": "Optional fill value written to every pre-allocated slot.",
                    "lua_type": "any?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "InfArray"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 98,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "Get",
            "desc": "Reads the value at `index` in O(1). Returns `nil` for holes and for indices\nwhose chunk does not exist yet.",
            "params": [
                {
                    "name": "index",
                    "desc": "1-based global index.",
                    "lua_type": "number"
                }
            ],
            "returns": [
                {
                    "desc": "The value at `index`, or `nil` if unset or out of range.",
                    "lua_type": "any?"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 132,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "Set",
            "desc": "In-range O(1) write that keeps [InfArray:Count] and [InfArray:Length] correct.\nReturns `true` when the write lands. This is a **no-op** returning `false` if\nthe index's chunk does not exist yet — use [InfArray:PushBack],\n[InfArray.new] with a size, or [InfArray:SetChunk] to grow the array first.",
            "params": [
                {
                    "name": "index",
                    "desc": "1-based global index within an existing chunk.",
                    "lua_type": "number"
                },
                {
                    "name": "value",
                    "desc": "New value; pass `nil` to clear the slot into a hole.",
                    "lua_type": "any?"
                }
            ],
            "returns": [
                {
                    "desc": "`true` if the write happened, `false` if it was a no-op.",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 151,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "GetChunk",
            "desc": "Returns the raw chunk table by chunk index. The returned table may contain\n`nil` holes and is not length-safe under `#`; pair it with the chunk's tracked\nlength (see [InfArray:IterateChunks]) when scanning it.",
            "params": [
                {
                    "name": "index",
                    "desc": "1-based chunk index.",
                    "lua_type": "number"
                }
            ],
            "returns": [
                {
                    "desc": "The raw backing table for that chunk, or `nil`.",
                    "lua_type": "{any}?"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 190,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "SetChunk",
            "desc": "Replaces an entire chunk in one call, recomputing [InfArray:Count] for the\nswapped range and extending [InfArray:Length] if the new chunk reaches further.\nPrefer this over per-element writes for bulk population.",
            "params": [
                {
                    "name": "chunkIndex",
                    "desc": "1-based chunk index to replace.",
                    "lua_type": "number"
                },
                {
                    "name": "value",
                    "desc": "The new backing table for the chunk.",
                    "lua_type": "{any}"
                },
                {
                    "name": "len",
                    "desc": "Logical length of `value`; defaults to `#value`.",
                    "lua_type": "number?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 206,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "GetChunkAndPosition",
            "desc": "Resolves a global index to its chunk and in-chunk position in one call, useful\nfor hot loops that want to read/write a slot without recomputing the location.",
            "params": [
                {
                    "name": "index",
                    "desc": "1-based global index.",
                    "lua_type": "number"
                }
            ],
            "returns": [
                {
                    "desc": "The chunk containing `index`, or `nil` if absent.",
                    "lua_type": "{any}?"
                },
                {
                    "desc": "The 1-based position of `index` within that chunk.",
                    "lua_type": "number"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 244,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "PushBack",
            "desc": "Appends `value` after the highest assigned index, allocating a new chunk when\nthe current one fills up. Amortised O(1).",
            "params": [
                {
                    "name": "value",
                    "desc": "Value to append at the end of the array.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "The global index the value was written to.",
                    "lua_type": "number"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 259,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "RemoveIndex",
            "desc": "Clears the value at `index`, decrementing [InfArray:Count]. This leaves a `nil`\nhole — [InfArray:Length] is **unchanged** and later elements are not shifted.",
            "params": [
                {
                    "name": "index",
                    "desc": "1-based global index to clear.",
                    "lua_type": "number"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 286,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "__iter",
            "desc": "Generalized `for..in` iteration (`for index, value in arr do`). Holes are\nskipped. Prefer [InfArray:IterateChunks] for bulk throughput.",
            "params": [],
            "returns": [],
            "function_type": "method",
            "ignore": true,
            "source": {
                "line": 305,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "Iterate",
            "desc": "Iterates every present element in ascending index order, skipping holes. Return\n`true` from `callback` to break out early. For maximum bulk throughput, use\n[InfArray:IterateChunks] instead.",
            "params": [
                {
                    "name": "callback",
                    "desc": "Called for each present element; return `true` to stop early.",
                    "lua_type": "(index: number, value: any) -> boolean?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 348,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "IterateChunks",
            "desc": "Hands each raw chunk to `callback` along with its `base` global-index offset and\ntracked `len`. The fastest way to process the whole array in bulk. The caller\n**must** nil-check `chunk[j]` itself, since chunks may contain holes. Return\n`true` to stop early.",
            "params": [
                {
                    "name": "callback",
                    "desc": "Called once per chunk; return `true` to stop early.",
                    "lua_type": "(chunk: {any}, base: number, len: number) -> boolean?"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 377,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "Find",
            "desc": "Linearly scans in ascending order and returns the first global index whose value\nequals `needle`, or `nil` if not found. Scans to each chunk's tracked length so\nholes never cut the search short.",
            "params": [
                {
                    "name": "needle",
                    "desc": "Value to search for.",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "The first global index equal to `needle`, or `nil`.",
                    "lua_type": "number?"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 397,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "Transform",
            "desc": "Applies `updateFunc` over the range `[start, stop]` by `step`, writing back each\nreturned value. May turn holes into values (or values back into holes);\n[InfArray:Count] stays correct either way. Indices whose chunk does not exist\nare skipped.",
            "params": [
                {
                    "name": "start",
                    "desc": "First global index to visit (inclusive).",
                    "lua_type": "number"
                },
                {
                    "name": "stop",
                    "desc": "Last global index to visit (inclusive).",
                    "lua_type": "number"
                },
                {
                    "name": "step",
                    "desc": "Stride between visited indices.",
                    "lua_type": "number"
                },
                {
                    "name": "updateFunc",
                    "desc": "Returns the new value for each visited slot.",
                    "lua_type": "(index: number, value: any) -> any"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 427,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "Count",
            "desc": "Returns how many elements are actually present, excluding holes. O(1).",
            "params": [],
            "returns": [
                {
                    "desc": "The number of present (non-`nil`) elements.",
                    "lua_type": "number"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 475,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "Length",
            "desc": "Returns the logical length: the highest index ever assigned, counting holes.\nEquivalent to `#arr`. O(1).",
            "params": [],
            "returns": [
                {
                    "desc": "The highest assigned index (holes included).",
                    "lua_type": "number"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 488,
                "path": "InfArray.luau"
            }
        },
        {
            "name": "__len",
            "desc": "`#arr` returns the highest assigned index. See [InfArray:Length].",
            "params": [],
            "returns": [],
            "function_type": "method",
            "ignore": true,
            "source": {
                "line": 499,
                "path": "InfArray.luau"
            }
        }
    ],
    "properties": [
        {
            "name": "LIMIT",
            "desc": "Maximum number of elements a single chunk can hold (2^26 = 67108864).",
            "lua_type": "number",
            "tags": [
                "static"
            ],
            "readonly": true,
            "source": {
                "line": 86,
                "path": "InfArray.luau"
            }
        }
    ],
    "types": [],
    "name": "InfArray",
    "desc": "A chunked array that bypasses Luau's internal table size limit of 2^26.\n\nValues are stored across fixed-size chunks so a single logical array can hold\nup to 2^53 elements (the largest exact integer a Luau `number` can represent).\nIndices are 1-based and resolved with integer math.\n\nRemovals leave `nil` holes. Per-chunk logical lengths are tracked explicitly, so\nthe implementation never relies on `#` over a chunk (which is undefined once the\nchunk contains holes). [InfArray:Length] reports the highest assigned index\n(holes included), while [InfArray:Count] reports the number of present elements.\n\n```lua\nlocal InfArray = require(path.to.InfArray)\n\nlocal arr = InfArray.new()\narr:PushBack(\"a\")\narr:PushBack(\"b\")\nprint(arr:Get(1)) --> \"a\"\nprint(#arr)       --> 2\n```\n\nSeveral backwards-compatible aliases exist for the primary methods:\n`get`/`GetValueAtIndex` (Get), `set`/`Replace` (Set), `InsertBack` (PushBack),\n`TransformRange` (Transform), `GetTotalLen` (Count) and `GetLength` (Length).",
    "source": {
        "line": 75,
        "path": "InfArray.luau"
    }
}