BinaryWriter

Write numbers, strings, booleans and Vector3s into bytes at exact widths, for a file format or a byte stream.

Make one with BinaryWriter.new(bigEndian?): little-endian unless you ask. Integer writes check the range and that the value is whole, and never wrap. WriteString and WriteBuffer put a 4-byte length first; the Fixed forms write only the bytes. The writer grows as you go, and ToBuffer copies what is written so far, so you can keep writing. A BinaryReader reads it all back.

Example

Writing a save recordLuau
--!strict
-- A save record written as bytes: fixed widths, a counted string, a float.
local BinaryWriter = require("@shotsystem/BinaryWriter")

local writer = BinaryWriter.new()
writer:WriteFixedString("SAVE") -- four bytes, no count
writer:WriteU16(3) -- a version
writer:WriteString("Apple") -- a u32 byte count, then the bytes
writer:WriteF32(2.5)
writer:WriteBoolean(true) -- a u32 1: four bytes
print(tostring(writer), writer.Length)

-- the bytes so far as hex
local bytes = writer:ToBuffer()
local hex = table.create(buffer.len(bytes))
for i = 0, buffer.len(bytes) - 1 do
	hex[i + 1] = string.format("%02x", buffer.readu8(bytes, i))
end
print(table.concat(hex, " "))

-- the same U16 in each byte order
local big = BinaryWriter.new(true)
big:WriteU16(3)
local little = BinaryWriter.new()
little:WriteU16(3)
print("big-endian:", big.BigEndian, buffer.readu8(big:ToBuffer(), 1), "little-endian:", buffer.readu8(little:ToBuffer(), 0))

-- integer widths check their range instead of wrapping
local ok, why = pcall(function() writer:WriteU8(300) end)
print(ok, (string.gsub(tostring(why), "^.-:%d+: ", "")))
What it printedOutput
BinaryWriter(23 bytes) 23
53 41 56 45 03 00 05 00 00 00 41 70 70 6c 65 00 00 20 40 01 00 00 00
big-endian: true 3 little-endian: 3
false BinaryWriter: WriteU8 takes a whole number from 0 to 255, got 300

Constructors

NameArgumentsReturnsDescription
BinaryWriter.new(bigEndian: boolean?)BinaryWriterAn empty writer, little-endian unless bigEndian is true.

Properties

NameTypeDefaultDescription
LengthnumberHow many bytes are written so far; it grows as you write and can't be set.
BigEndianbooleanTrue for a writer made with BinaryWriter.new(true): every multi-byte value, counts included, is then big-endian; it can't be changed later.

Methods

NameArgumentsReturnsDescription
WriteU8(n: number)()Writes one byte; anything but a whole number from 0 to 255 is an error, never wrapped.
WriteI8(n: number)()Writes one signed byte; anything but a whole number from -128 to 127 is an error.
WriteU16(n: number)()Writes 2 bytes; anything but a whole number from 0 to 65535 is an error.
WriteI16(n: number)()Writes 2 bytes, signed; anything but a whole number from -32768 to 32767 is an error.
WriteU32(n: number)()Writes 4 bytes; anything but a whole number from 0 to 4294967295 is an error.
WriteI32(n: number)()Writes 4 bytes, signed; anything but a whole number from -2147483648 to 2147483647 is an error.
WriteF32(n: number)()Writes a 4-byte float, so the number is rounded to single precision; only its type is checked.
WriteF64(n: number)()Writes an 8-byte float; only the value's type is checked.
WriteNumber(n: number)()Writes a whole number from 0 to 4294967295 as 4 bytes, like WriteU32; a negative one is an error, never wrapped.
WriteFloat(n: number)()Writes a number as an 8-byte float, like WriteF64; ReadFloat reads it back.
WriteBoolean(b: boolean)()Writes 4 bytes, 1 or 0, not one byte; ReadBoolean reads anything but 0 as true.
WriteString(s: string)()Writes the string's length in bytes, not characters, as 4 bytes, then the bytes themselves.
WriteBuffer(b: buffer)()Writes the buffer's length as 4 bytes, then its bytes; ReadBuffer reads it back.
WriteFixedString(s: string)()Writes only the string's bytes, with no length before them; ReadFixedString needs the length to read it back.
WriteFixedBuffer(b: buffer)()Writes only the buffer's bytes, with no length before them.
WriteVector3(v: Vector3)()Writes X, Y and Z as three 4-byte floats, 12 bytes in all.
ToBuffer()bufferA copy of exactly the bytes written so far; the writer can go on writing.