BinaryWriter
A growable binary buffer, writes values one after another at any bit position.
The exact inverse of BinaryReader : the same bit layout (LSB-first, as pack and Source's bf_write), the same cursor counted in bits from 0, and big endian by default:
lua Copy
local writer = BinaryWriter ()
writer:writeBit ( 1 )
writer:writeUInt ( 2 , 7 , true )
writer:writeUInt ( 300 , 16 , true )
writer:compile () --> "\5\44\1" Lua strings can't be changed in place, so bytes are kept in a buffer (bytes) until compile (or tostring) joins them: a string.buffer written in place when FFI and string.buffer are available (appends and compile are memcpy), a growable FFI uint8_t array when only FFI is, or a table otherwise, where large aligned appends at the end are kept as string chunks and writing before them joins everything back into bytes.
Writing overwrites the data under the cursor, bits next to a field in the same byte are kept. The size grows to the furthest position written or moved to (seek, skip, align), bytes that were never written are 0 in the result.
Integers are written as their lowest bit_count bits, the same way as bitpack.write , so writeUInt and writeInt accept both unsigned and negative values and never throw on overflow.
Constructor BinaryWriter (data : any ?): BinaryWriter Fields Name Type Description positioninteger The cursor position in bits. bytesBinaryWriter.Buffer The written bytes, 1-indexed from base, a table may have gaps. baseinteger The position in bits of bytes[ 1 ], the size of chunks (table backend), 0 otherwise. capacitynumber The size of bytes in bits, math.huge for a table. bufferstring.buffer | nil The string.buffer that holds the data (string.buffer backend). chunksstring[] | nil The data before base (table backend). chunk_countinteger | nil The number of chunks (table backend). has_gapsboolean true if a table has bytes that were never written.data_lengthinteger The size of the data in bits.
Operators Operator Operand Result leninteger concat any string
Methods alignMoves the cursor forward to the next multiple of bit_boundary, padding with 0 bits. compileJoins everything written so far into a string. isAlignedChecks if the cursor is at a multiple of bit_boundary. isEndOfFileChecks if the cursor is at the end of the data, so the next write appends. openReplaces the data of the writer and moves the cursor to its end, so the next writes append. remainingReturns the size of the data after the cursor, that the next writes overwrite. seekMoves the cursor to the absolute position. sizeReturns the size of the data. skipMoves the cursor relative to its position, moving after the end grows the data (zero-filled). tellReturns the cursor position. writeWrites the string as is, the cursor doesn't have to be aligned. writeBitWrites one bit. writeBooleanWrites one bit as a boolean, same as net.WriteBool. writeBytesWrites bytes, the cursor doesn't have to be aligned. writeCountedStringWrites the string prefixed with its length, read it back with BinaryReader:readCountedString. writeDateWrites date in DOS format (16 bits), see bytepack.writeDate. writeDoubleWrites signed 8-byte (64 bit) float, the cursor doesn't have to be aligned. writeFixedPointWrites signed fixed-point number (Qm.n), rounded to the nearest step. writeFixedStringWrites the string of a fixed size, shorter data is padded with \0 and longer data is cut, same as pack.writeFixedString. writeFloatWrites signed 4-byte (32 bit) float, the cursor doesn't have to be aligned. writeIntWrites signed (two's complement) integer of any size, read it back with BinaryReader:readInt. writeLineWrites the line, the string followed by \n. writeObjectWrites the object with its serialize( writer, ... ) method, read it back with BinaryReader:readObject or BinaryReader:r… writeStringWrites C-style string, the string followed by the null terminator (\0), same as net.WriteString. writeTerminatedStringWrites the string followed by the terminator byte, read it back with BinaryReader:readTerminatedString. writeTimeWrites time in DOS format (16 bits), see bytepack.writeTime. writeUIntWrites unsigned integer of any size, read it back with BinaryReader:readUInt. writeUnsignedFixedPointWrites unsigned fixed-point number (UQm.n), rounded to the nearest step.
function BinaryWriter:align (bit_boundary? : integer ): integer
Moves the cursor forward to the next multiple of bit_boundary, padding with 0 bits.
Parameters
Name Type Description bit_boundaryoptional integer The boundary in bits, 8 (byte) by default.
Returns
Type Name Description integer positionThe new position in bits.
function BinaryWriter:compile (): string
Joins everything written so far into a string.
The last byte is padded with 0 bits if the size isn't a whole number of bytes.
Returns
Type Name Description string dataThe binary data.
function BinaryWriter:isAligned (bit_boundary? : integer ): boolean
Checks if the cursor is at a multiple of bit_boundary.
Parameters
Name Type Description bit_boundaryoptional integer The boundary in bits, 8 (byte) by default.
Returns
Type Name Description boolean is_alignedtrue if the cursor is aligned.
# BinaryWriter:isEndOfFile
function BinaryWriter:isEndOfFile (): boolean
Checks if the cursor is at the end of the data, so the next write appends.
Returns
Type Name Description boolean is_eoftrue if there is no data after the cursor.
function BinaryWriter:open (data : any )
Replaces the data of the writer and moves the cursor to its end, so the next writes append.
Use seek() after it to overwrite the data from the start.
Parameters
Name Type Description dataany The data, converted to a string with tostring.
function BinaryWriter:remaining (as_bytes? : boolean ): integer
Returns the size of the data after the cursor, that the next writes overwrite.
Parameters
Name Type Description as_bytesoptional boolean true to return the number of whole bytes, false (bits) by default.
Returns
Type Name Description integer remainingThe size of the data after the cursor.
function BinaryWriter:seek (position? : integer , as_bytes? : boolean ): integer
Moves the cursor to the absolute position.
Positions after the end grow the data (zero-filled), negative positions count back from the end.
Parameters
Name Type Description positionoptional integer The new position, 0 by default. as_bytesoptional boolean true if position is in bytes, false (bits) by default.
Returns
Type Name Description integer positionThe new position in bits.
function BinaryWriter:size (as_bytes? : boolean ): integer
Returns the size of the data.
Parameters
Name Type Description as_bytesoptional boolean true to return the size of the compiled string in bytes, false (bits) by default.
Returns
Type Name Description integer sizeThe size of the data.
function BinaryWriter:skip (length? : integer , as_bytes? : boolean ): integer
Moves the cursor relative to its position, moving after the end grows the data (zero-filled).
lua Copy
local length_position = writer:tell ()
writer:skip ( 4 , true ) -- reserve 4 bytes for the length
writer:write ( payload )
local end_position = writer:tell ()
writer:seek ( length_position )
writer:writeUInt ( #payload, 32 )
writer:seek ( end_position )
Parameters
Name Type Description lengthoptional integer The distance to move, negative to move back, 1 by default. as_bytesoptional boolean true if length is in bytes, false (bits) by default.
Returns
Type Name Description integer positionThe new position in bits.
function BinaryWriter:tell (as_bytes? : boolean ): integer
Returns the cursor position.
Parameters
Name Type Description as_bytesoptional boolean true to return the number of whole bytes before the cursor, false (bits) by default.
Returns
Type Name Description integer positionThe cursor position.
function BinaryWriter:write (data : string ): integer
Writes the string as is, the cursor doesn't have to be aligned.
Parameters
Name Type Description datastring The bytes.
Returns
Type Name Description integer byte_countThe number of bytes written.
function BinaryWriter:writeBit (value : 0 | 1 | boolean )
Parameters
Name Type Description value0 | 1 | boolean The bit.
# BinaryWriter:writeBoolean
function BinaryWriter:writeBoolean (value : boolean )
Writes one bit as a boolean, same as net.WriteBool.
Parameters
Name Type Description valueboolean The boolean.
function BinaryWriter:writeBytes (... : integer ): integer
Writes bytes, the cursor doesn't have to be aligned.
Parameters
Name Type Description ...integer The bytes (0 - 255).
Returns
Type Name Description integer byte_countThe number of bytes written.
# BinaryWriter:writeCountedString
function BinaryWriter:writeCountedString (data : string , bit_count : integer , is_little_endian? : boolean ): integer
Writes the string prefixed with its length, read it back with BinaryReader:readCountedString .
Throws an error if the string is too long for the length size.
lua Copy
writer:writeCountedString ( "abc" , 8 ) --> "\3abc"
Parameters
Name Type Description datastring The string. bit_countinteger The size of the length in bits (1 - 64). is_little_endianoptional boolean true to write the length as little endian, false by default.
Returns
Type Name Description integer byte_countThe size of the string in bytes.
function BinaryWriter:writeDate (day? : integer , month? : integer , year? : integer , is_little_endian? : boolean )
Writes date in DOS format (16 bits), see bytepack.writeDate .
DOS date layout Bits Field Range 15 - 9 year - 1980 0 - 127 (1980 - 2107)8 - 5 month 1 - 124 - 0 day 1 - 31
Parameters
Name Type Description dayoptional integer The day. monthoptional integer The month. yearoptional integer The year (1980 - 2107). is_little_endianoptional boolean true for little endian, false by default.
# BinaryWriter:writeDouble
function BinaryWriter:writeDouble (value : number , is_little_endian? : boolean )
Writes signed 8-byte (64 bit) float, the cursor doesn't have to be aligned.
IEEE 754 layout Bits Field Notes 63 sign 1 is negative62 - 52 exponent (11 bits) biased by 1023, 2047 is inf / nan 51 - 0 mantissa (52 bits) ~15-17 significant decimal digits
Range: 2.2250738585072014e-308 - 1.7976931348623157e308 (normal), Lua numbers are doubles, so nothing is lost.
Parameters
Name Type Description valuenumber The double. is_little_endianoptional boolean true for little endian (as net.WriteDouble), false by default.
# BinaryWriter:writeFixedPoint
function BinaryWriter:writeFixedPoint (value : number , m : integer , n : integer , is_little_endian? : boolean )
Writes signed fixed-point number (Qm.n ), rounded to the nearest step.
Unlike bytepack.writeFixedPoint , m + n doesn't have to be a whole number of bytes.
Commonly Used Qm.n Formats (signed ) Format Range Precision (Step) Q8.8 -128.0 - 127.9960.00390625 (1/256)Q10.6 -512.0 - 511.9843750.015625 (1/64)Q12.4 -2048.0 - 2047.93750.0625 (1/16)Q16.16 -32768.0 - 32767.999980.0000152588 (1/65536)Q24.8 -8388608.0 - 8388607.9960.00390625 (1/256)Q32.16 -2147483648.0 - 2147483647.999980.0000152588 (1/65536)
m + n is the size of the field in bits (1 - 64), so the range is limited to 53 bits.
Parameters
Name Type Description valuenumber The signed fixed-point number. minteger The number of integer bits, including the sign bit. ninteger The number of fractional bits. is_little_endianoptional boolean true for little endian, false by default.
# BinaryWriter:writeFixedString
function BinaryWriter:writeFixedString (data : string , byte_count : integer )
Writes the string of a fixed size, shorter data is padded with \0 and longer data is cut, same as pack.writeFixedString .
Parameters
Name Type Description datastring The string. byte_countinteger The size of the string in bytes.
function BinaryWriter:writeFloat (value : number , is_little_endian? : boolean )
Writes signed 4-byte (32 bit) float, the cursor doesn't have to be aligned.
IEEE 754 layout Bits Field Notes 31 sign 1 is negative30 - 23 exponent (8 bits) biased by 127, 255 is inf / nan 22 - 0 mantissa (23 bits) ~6-9 significant decimal digits
Range: 1.1754944e-38 - 3.4028235e38 (normal), integers are exact up to 16777216.
Parameters
Name Type Description valuenumber The float, precision is reduced to float. is_little_endianoptional boolean true for little endian (as net.WriteFloat), false by default.
function BinaryWriter:writeInt (value : integer , bit_count : integer , is_little_endian? : boolean )
Writes signed (two's complement) integer of any size, read it back with BinaryReader:readInt .
Signed Integers limits for bit count Bit count Min Value (-2^(n-1)) Max Value (2^(n-1) - 1) 1 -1 0 2 -2 1 3 -4 3 4 -8 7 5 -16 15 6 -32 31 7 -64 63 8 -128 127 9 -256 255 10 -512 511 11 -1,024 1,023 12 -2,048 2,047 13 -4,096 4,095 14 -8,192 8,191 15 -16,384 16,383 16 -32,768 32,767 17 -65,536 65,535 18 -131,072 131,071 19 -262,144 262,143 20 -524,288 524,287 21 -1,048,576 1,048,575 22 -2,097,152 2,097,151 23 -4,194,304 4,194,303 24 -8,388,608 8,388,607 25 -16,777,216 16,777,215 26 -33,554,432 33,554,431 27 -67,108,864 67,108,863 28 -134,217,728 134,217,727 29 -268,435,456 268,435,455 30 -536,870,912 536,870,911 31 -1,073,741,824 1,073,741,823 32 -2,147,483,648 2,147,483,647 40 -549,755,813,888 549,755,813,887 48 -140,737,488,355,328 140,737,488,355,327 64 -9,223,372,036,854,775,808 9,223,372,036,854,775,807
Valid values without loss of precision: -9007199254740991 - 9007199254740991 (53 bits), all values above will have problems when working with them.
Parameters
Name Type Description valueinteger The signed integer, only the lowest bit_count bits are written. bit_countinteger The size of the integer in bits (1 - 64), 0 writes nothing. is_little_endianoptional boolean true for little endian, false by default.
function BinaryWriter:writeLine (data : string )
Writes the line, the string followed by \n.
Throws an error if the string contains \n.
Parameters
Name Type Description datastring The line.
# BinaryWriter:writeObject
function BinaryWriter:writeObject (obj : Object , ... : any )
Parameters
Name Type Description objObject The object. ...any The arguments passed to __serialize.
# BinaryWriter:writeString
function BinaryWriter:writeString (data : string )
Writes C-style string, the string followed by the null terminator (\0), same as net.WriteString.
Throws an error if the string contains \0.
Parameters
Name Type Description datastring The string.
# BinaryWriter:writeTerminatedString
function BinaryWriter:writeTerminatedString (data : string , terminator : integer )
Parameters
Name Type Description datastring The string. terminatorinteger The terminator byte (0 - 255).
function BinaryWriter:writeTime (hours? : integer , minutes? : integer , seconds? : integer , is_little_endian? : boolean )
Writes time in DOS format (16 bits), see bytepack.writeTime .
DOS time layout Bits Field Range 15 - 11 hours 0 - 2310 - 5 minutes 0 - 594 - 0 seconds / 2 0 - 29 (0 - 58 seconds)
Parameters
Name Type Description hoursoptional integer The number of hours. minutesoptional integer The number of minutes. secondsoptional integer The number of seconds, rounded down to even. is_little_endianoptional boolean true for little endian, false by default.
function BinaryWriter:writeUInt (value : integer , bit_count : integer , is_little_endian? : boolean )
Writes unsigned integer of any size, read it back with BinaryReader:readUInt .
Unsigned Integers limits for bit count Bit count Max Value (2^n - 1) 1 1 2 3 3 7 4 15 5 31 6 63 7 127 8 255 9 511 10 1,023 11 2,047 12 4,095 13 8,191 14 16,383 15 32,767 16 65,535 17 131,071 18 262,143 19 524,287 20 1,048,575 21 2,097,151 22 4,194,303 23 8,388,607 24 16,777,215 25 33,554,431 26 67,108,863 27 134,217,727 28 268,435,455 29 536,870,911 30 1,073,741,823 31 2,147,483,647 32 4,294,967,295 40 1,099,511,627,775 48 281,474,976,710,655 64 18,446,744,073,709,551,615
Valid values without loss of precision: 0 - 9007199254740991 (53 bits), all values above will have problems when working with them.
lua Copy
writer:writeUInt ( 0xFF , 8 ) -- byte
writer:writeUInt ( 300 , 32 , true ) -- same as `net.WriteUInt( 300, 32 )`
Parameters
Name Type Description valueinteger The unsigned integer, only the lowest bit_count bits are written. bit_countinteger The size of the integer in bits (1 - 64), 0 writes nothing. is_little_endianoptional boolean true for little endian, false by default.
# BinaryWriter:writeUnsignedFixedPoint
function BinaryWriter:writeUnsignedFixedPoint (value : number , m : integer , n : integer , is_little_endian? : boolean )
Writes unsigned fixed-point number (UQm.n ), rounded to the nearest step.
Unlike bytepack.writeFixedPoint , m + n doesn't have to be a whole number of bytes.
Commonly Used UQm.n Formats (unsigned ) Format Range Precision (Step) UQ8.8 0 - 255.9960.00390625 (1/256)UQ10.6 0 - 1023.9843750.015625 (1/64)UQ12.4 0 - 4095.93750.0625 (1/16)UQ16.16 0 - 65535.999980.0000152588 (1/65536)UQ24.8 0 - 16777215.9960.00390625 (1/256)UQ32.16 0 - 4294967295.999980.0000152588 (1/65536)
m + n is the size of the field in bits (1 - 64), so the range is limited to 53 bits.
Parameters
Name Type Description valuenumber The unsigned fixed-point number. minteger The number of integer bits. ninteger The number of fractional bits. is_little_endianoptional boolean true for little endian, false by default.