BinaryReader

Read bytes back as numbers, strings and Vector3s, one value at a time, even while more bytes are still arriving.

BinaryReader.new(data, offset?, bigEndian?) reads a buffer in place, or a string. Reading past the end errors with the offset and moves nothing, so a stream reader reads a length, checks Contains, and Seeks back when the frame isn't complete yet. Append adds the bytes that came later. It reads what a BinaryWriter writes, width for width.

Example

Reading a save recordLuau
--!strict
-- Reading a save record back: each read moves Offset on; a read past the end errors and moves nothing.
local BinaryWriter = require("@shotsystem/BinaryWriter")
local BinaryReader = require("@shotsystem/BinaryReader")

local writer = BinaryWriter.new()
writer:WriteFixedString("SAVE")
writer:WriteU16(3)
writer:WriteString("Apple")
writer:WriteF32(2.5)

local reader = BinaryReader.new(writer:ToBuffer())
print(tostring(reader))
print("tag:", reader:ReadFixedString(4), "version:", reader:ReadU16())
print("name:", reader:ReadString(), "price:", reader:ReadF32())
print("offset:", reader.Offset, "length:", reader.Length, "remaining:", reader.Remaining)

reader:Seek(4)
print("version again:", reader:ReadU16())
reader:Skip(9) -- the name's count and its five bytes
print("price again:", reader:ReadF32())
local ok, why = pcall(function() reader:ReadU8() end)
print(ok, (string.gsub(tostring(why), "^.-:%d+: ", "")), reader.Offset)

-- a stream: Contains says whether the next bytes have arrived, Append adds the ones that came later
local stream = BinaryReader.new("\5\0\0\0Ap")
print("whole name here:", stream:Contains(4 + 5))
stream:Append("ple")
print("after Append:", stream:Contains(4 + 5), stream:ReadString())
print("big-endian:", BinaryReader.new("\0\7", 0, true):ReadU16())
What it printedOutput
BinaryReader(offset 0 of 19 bytes)
tag: SAVE version: 3
name: Apple price: 2.5
offset: 19 length: 19 remaining: 0
version again: 3
price again: 2.5
false BinaryReader: ReadU8 needs 1 byte at offset 19, 0 left 19
whole name here: false
after Append: true Apple
big-endian: 7

Constructors

NameArgumentsReturnsDescription
BinaryReader.new(data: buffer | string, offset: number?, bigEndian: boolean?)BinaryReaderReads data in place from offset, 0 by default; a buffer is never copied or written, so don't change it while reading.

Properties

NameTypeDefaultDescription
OffsetnumberWhere the next read starts, counted from 0; move it with Seek or Skip, never by setting it.
LengthnumberHow many bytes the reader holds; Append may drop bytes already read, so Length and Offset can both shrink.
Remainingnumber
BigEndianbooleanTrue for a reader made with bigEndian: every multi-byte read, counts included, is then big-endian; it can't be changed later.

Methods

NameArgumentsReturnsDescription
ReadU8()number
ReadI8()number
ReadU16()number
ReadI16()number
ReadU32()number
ReadI32()number
ReadF32()number
ReadF64()number
ReadNumber()numberReads 4 bytes as a whole number from 0 to 4294967295, what WriteNumber wrote.
ReadFloat()numberReads an 8-byte float, what WriteFloat wrote.
ReadBoolean()booleanReads 4 bytes, as WriteBoolean writes them; anything but 0 is true.
ReadString()stringReads a 4-byte length, then that many bytes; when they haven't all arrived it errors and moves nothing.
ReadBuffer()bufferReads a 4-byte length, then that many bytes as a new buffer.
ReadFixedString(count: number)stringReads exactly count bytes as a string, with no length before them; count must be a whole number, not negative.
ReadFixedBuffer(count: number)bufferReads exactly count bytes as a buffer, with no length before them.
ReadVector3()Vector3Reads three 4-byte floats as a Vector3's X, Y and Z, 12 bytes in all.
Skip(count: number)()Moves Offset forward by count bytes without reading them; skipping past the end is an error.
Seek(offset: number)()Moves Offset to a position from 0 to Length, counted from the start; anything else is an error.
Contains(count: number)booleanWhether the next count bytes have arrived, so a stream reader can check a whole frame is there before reading it.
Append(more: buffer | string)()Adds bytes that arrived later, never writing into your buffer; it may drop bytes already read, moving Offset back.