Supported
Hover any icon for what it means in that column.Six supported datatypes have no schema constructor:
buffer, BrickColor, Region3, UDim,
UDim2 and TweenInfo. Under a schema, use T.Any() or write a
custom type.Not supported
Sending any of these logswarn("Unsupported type: ...") on the sender, and the receiver gets
nil.
Tables
Arrays, dense 1..n
Arrays, dense 1..n
Written as
TYPE_ARRAY plus a varint count. Round-trips exactly.Dictionaries
Dictionaries
Written as
TYPE_TABLE with alternating keys and values. Keys are themselves dynamically
encoded, so any serializable type works as a key.Mixed tables
Mixed tables
Fail the array test and take the dictionary path, which preserves both parts.
Sparse tables, reshaped
Sparse tables, reshaped
A table with gaps also takes the dictionary path, so it arrives as a dictionary with numeric
keys rather than an array.
#result is unreliable and ipairs stops at the first gap.Circular references, stack overflow
Circular references, stack overflow
Recursion has no visited-set and no depth limit.Break cycles before sending, or send an id and let the receiver rebuild.
Metatables and non-data fields
Metatables and non-data fields
Metatables are never transmitted, so a received table is always a plain table.
Function-valued fields become
nil with a warning, which means an OOP instance arrives as its
data fields only, without its methods.Numbers
The dynamic encoder narrows integers automatically.There is no automatic
f32 narrowing and no i8 selection. Every non-integer costs 8 bytes,
and small negatives cost 2 where the same magnitude positive costs 1. Declare T.Float32() or
T.Int8() in a schema to get those widths.Instances
varint index, 1 to 3 bytes
Instances ride in a side array passed alongside the buffer, and only an index is serialized.
Cheap regardless of tree depth, and deduplicated within a batch.
nil
If the receiver cannot see the instance, whether server-only, not replicated, or destroyed
before the flush, the index resolves to
nil. No error is raised.Multiple return values
OnInvoke may return any number of values, and all of them survive.
Invoke traffic always uses the dynamic encoder regardless of any schema, which is precisely why
a variable return count works without you declaring anything. See
Invocations.
Next steps
Known limits
Every rough edge in one place.
Serialization
Why the encoder makes these choices.
