Lua strings can contain arbitrary bytes, including zero. That makes them suitable for binary payloads, while Lua 5.3 and later provide native bitwise operators and packing functions.
Bitwise operations
1 | local flags = 0 |
Operators include AND (&), OR (|), exclusive OR (~), NOT (~), shifts (<<, >>), and integer floor division. Exact integer width depends on how Lua was compiled. Lua 5.2 commonly uses the bit32 library instead.
Bytes in strings
1 | local payload = string.char(0x41, 0x00, 0x42) |
Do not use APIs that assume zero-terminated C strings when transferring such data through native code.
Packing structured binary data
1 | local packet = string.pack(">I2I4c4", 7, 1024, "PING") |
The > prefix selects big-endian order; < selects little-endian. I2 and I4 are unsigned integers of two and four bytes, while c4 is a fixed four-byte string. Always specify byte order and widths in a protocol instead of relying on native layout.
Validate lengths before unpacking data received from outside the process, place upper bounds on allocations, and treat decoding errors as normal input failures. Binary formats are compact, but they require an explicit schema and versioning strategy.