Terbin transmits all data as raw binary over named pipes. The serialization layer is designed around three goals: zero heap allocation on the hot path,Documentation Index
Fetch the complete documentation index at: https://mintlify.com/FarlandsModdingTeam/TerbinProyect/llms.txt
Use this file to discover all available pages before exploring further.
Span<byte>-based reads and writes, and explicit control over layout via the IStructSerializable interface. Every packet, header, and payload is encoded and decoded through the APIs described on this page.
IStructSerializable — The Serialization Contract
Any type that participates in Terbin’s packet system implements this interface:
Returns the exact number of bytes this instance will occupy when serialized. Used to pre-allocate buffers without over-allocation.
Writes the instance’s fields sequentially into the provided
Span<byte> starting at offset 0. No length prefix is included — the caller is responsible for knowing the size.Populates the instance’s fields by reading from the provided
ReadOnlySpan<byte> starting at offset 0.PacketRequest, IdArray, and other packet-level structs all implement IStructSerializable.
ThreeQuartersInt — 3-Byte Array Length Encoding
Serialized arrays in Terbin use a 3-byte length prefix instead of the standard 4-byte int. This custom type saves 1 byte per array and supports lengths up to 16,777,215 elements:
ThreeQuartersInt implicitly converts to and from int and uint, and it integrates with MemoryMarshal.Write / MemoryMarshal.Read through its sequential 3-byte layout.
The first
ThreeQuartersInt.Size (3) bytes of any serialized array are the element count header — but they encode the byte count of the elements, not the element count. For example, a float[] with 4 elements writes 4 * sizeof(float) = 16 into the prefix, not 4. Serialineitor.GetArraySize<T>(int length) handles this calculation automatically.Serialineitor — Static and Instance Serialization
Serialineitor provides both a fluent instance API (append-and-grow) and a static API (direct, no instance state) for all common serialization tasks.
Static Methods
Unmanaged Scalars
int, ushort, float, a blittable struct) to/from a byte[] using MemoryMarshal.Write / MemoryMarshal.Read — no boxing, no intermediate copies.
IStructSerializable Structs
byte[] of pStruct.GetSize() bytes, calls WriteTo (or creates a new T() and calls ReadFrom). Used internally by StreamWriteStruct and StreamReadStruct to encode/decode every PacketRequest written to the pipe.
Array Helpers
CastToByte
object[] — typically enum values from [TerbinExecutable(params object[])] — to a byte[] using Convert.ToByte. Throws ArgumentException if any element cannot be safely cast to byte.
Splice
Instance (Fluent) API
The instanceSerialineitor maintains an internal auto-growing byte[] buffer and an _offset cursor:
| Method | What it adds |
|---|---|
Add<T>(T value) | A single unmanaged value |
AddArray<T>(T[] array) | A ThreeQuartersInt length prefix followed by the element bytes |
AddStruct<T>(T struct) | An IStructSerializable struct via SerializeStructRaw |
Serialize() / ToArray() | Returns the filled portion of the buffer as a new byte[] |
Clear() | Resets the offset (zeroes the buffer) for reuse |
BufferWriter — Span-Based Sequential Writes
BufferWriter (static class) writes into a pre-allocated Span<byte> and advances an int offset by reference:
Serialineitor internally. They validate buffer capacity and throw ArgumentOutOfRangeException if the span is too small.
BufferWriterExtension — Slicing Variants
BufferWriterExtension provides two extension method families on Span<byte>:
Slicing variants (ref Span<byte>) — advance the span itself so no offset variable is needed:
BufferErrorCode (Succes, BufferSmall, or SurpassesMax) instead of throwing.
Offset variants (non-ref Span<byte>, ref int pOffset) — keep the original span intact and advance only the index:
BufferReader and BufferReaderExtension — Span-Based Sequential Reads
BufferReader (static class) reads from ReadOnlySpan<byte> with an int offset:
BufferReaderExtension adds extension methods to ReadOnlySpan<byte>:
PacketRequest.ReadFrom and IdArray.ReadFrom to deserialize the wire bytes back into structs.
BufferErrorCode Enum
Returned by the slicing BufferWriterExtension methods to signal write failures without exceptions:
| Value | Meaning |
|---|---|
Succes (1) | Write completed successfully |
BufferSmall (3) | The destination span was too small for the data |
SurpassesMax (2) | The array length exceeded ThreeQuartersInt.MaxValue |
AutoStructSerializable — Source Generator (Disabled)
AutoStructSerializable is a Roslyn IIncrementalGenerator that would automatically generate GetSize(), WriteTo(), and ReadFrom() implementations for any struct implementing IAutoSerializable. It is currently disabled (#if false). All IStructSerializable implementations in the framework are handwritten.