Bytes Module
The Bytes module provides a fixed-size byte memory buffer optimized for low-level binary data operations. It is especially useful for hardware communication, building protocol frames, image data manipulation, or any operation that requires direct memory access by position.
Usage
use Bytes
Module Architecture
The module has two levels:
- Module functions —
Bytes.new()andBytes.clone()to create buffers. - Object methods — operations on the created buffer (
read,write,fill,size, etc.).
use Bytes
var buf = Bytes.new(16) // Create a 16-byte buffer
buf.write(0, 0xFF) // Write at position 0
var value = buf.read(0) // Read from position 0
println(value) // 255
Module Functions
new
Creates a new fixed-size byte buffer.
var buf = Bytes.new(size)
Parameters:
| Parameter | Type | Description |
|---|---|---|
size | integer | Number of bytes to allocate |
Returns: A byte buffer object ready to use.
Example:
use Bytes
var buf = Bytes.new(64) // 64-byte buffer
buf.fill(0) // Initialize to zero
println(buf.size()) // 64
The initial content of the buffer is not guaranteed. Use fill(0) to initialize it to zero before operating on it.
clone
Creates an independent copy of an existing byte buffer.
var copy = Bytes.clone(buf)
Parameters:
| Parameter | Type | Description |
|---|---|---|
buf | Bytes | Byte buffer to clone |
Returns: A new Bytes object with the same size and content as the original. Modifying the copy does not affect the original.
Example:
use Bytes
var original = Bytes.new(4)
original.write(0, 0xAB)
original.write(1, 0xCD)
var copy = Bytes.clone(original)
copy.write(0, 0x00) // Does not affect original
println(original.read(0)) // 171 (0xAB)
println(copy.read(0)) // 0
Bytes Object Methods
fill
Fills all bytes in the buffer with the same value.
buf.fill(value)
Parameters:
| Parameter | Type | Description |
|---|---|---|
value | integer | Value between 0 and 255 to fill with |
Example:
use Bytes
var buf = Bytes.new(8)
buf.fill(0xFF) // Set all bytes to 255
buf.fill(0) // Clear the buffer
size
Returns the size of the buffer in bytes.
var n = buf.size()
Returns: An integer with the number of bytes in the buffer.
Example:
use Bytes
var buf = Bytes.new(32)
println(buf.size()) // 32
read
Reads a single byte at the given position.
var value = buf.read(pos)
Parameters:
| Parameter | Type | Description |
|---|---|---|
pos | integer | Byte index (0-based) |
Returns: An integer between 0 and 255. Throws an exception if the index is out of range.
Example:
use Bytes
var buf = Bytes.new(4)
buf.write(2, 0x42)
println(buf.read(2)) // 66 (0x42)
write
Writes a single byte at the given position.
buf.write(pos, value)
Parameters:
| Parameter | Type | Description |
|---|---|---|
pos | integer | Byte index (0-based) |
value | integer | Value between 0 and 255 |
Throws an exception if the index is out of range.
Example:
use Bytes
var buf = Bytes.new(4)
buf.write(0, 0xDE)
buf.write(1, 0xAD)
buf.write(2, 0xBE)
buf.write(3, 0xEF)
Only the lower byte of the value is stored. If the value exceeds 255, the upper bits are discarded.
read16
Reads a 16-bit value (2 bytes) at the given index. The index is expressed in 16-bit units, not bytes.
var value = buf.read16(index)
Parameters:
| Parameter | Type | Description |
|---|---|---|
index | integer | Position in 16-bit units (0-based) |
Returns: An integer between 0 and 65535. Throws an exception if the index is out of range.
Example:
use Bytes
var buf = Bytes.new(4)
buf.write16(0, 0x1234) // Bytes 0-1
buf.write16(1, 0xABCD) // Bytes 2-3
println(buf.read16(0)) // 4660 (0x1234)
println(buf.read16(1)) // 43981 (0xABCD)
read16(1) accesses bytes 2-3, not byte 1. For a buffer of N bytes, the valid index range is 0 to (N/2) - 1.
write16
Writes a 16-bit value (2 bytes) at the given index. The index is expressed in 16-bit units.
buf.write16(index, value)
Parameters:
| Parameter | Type | Description |
|---|---|---|
index | integer | Position in 16-bit units (0-based) |
value | integer | Value between 0 and 65535 |
Throws an exception if the index is out of range.
Example:
use Bytes
var buf = Bytes.new(8)
buf.write16(0, 0x0102)
buf.write16(1, 0x0304)
buf.write16(2, 0x0506)
buf.write16(3, 0x0708)
Only the lower 16 bits of the value are stored. If the value exceeds 65535, the upper bits are discarded.
read32
Reads a 32-bit value (4 bytes) at the given index. The index is expressed in 32-bit units.
var value = buf.read32(index)
Parameters:
| Parameter | Type | Description |
|---|---|---|
index | integer | Position in 32-bit units (0-based) |
Returns: An unsigned 32-bit integer. Throws an exception if the index is out of range.
Example:
use Bytes
var buf = Bytes.new(8)
buf.write32(0, 0xDEADBEEF)
buf.write32(1, 0x12345678)
println(buf.read32(0)) // 3735928559 (0xDEADBEEF)
println(buf.read32(1)) // 305419896 (0x12345678)
read32(1) accesses bytes 4-7, not byte 1. For a buffer of N bytes, the valid index range is 0 to (N/4) - 1.
write32
Writes a 32-bit value (4 bytes) at the given index. The index is expressed in 32-bit units.
buf.write32(index, value)
Parameters:
| Parameter | Type | Description |
|---|---|---|
index | integer | Position in 32-bit units (0-based) |
value | integer | Value between 0 and 4294967295 (0x00000000 to 0xFFFFFFFF) |
Throws an exception if the index is out of range.
Example:
use Bytes
var buf = Bytes.new(16)
buf.write32(0, 0x00FF00FF)
buf.write32(1, 0xFF00FF00)
Index Units Summary
The key difference between the read/write methods is the index unit:
| Method | Index unit | Bytes accessed | Valid range (N-byte buffer) |
|---|---|---|---|
read / write | 1 byte | 1 byte | 0 to N-1 |
read16 / write16 | 2 bytes | 2 bytes | 0 to (N/2)-1 |
read32 / write32 | 4 bytes | 4 bytes | 0 to (N/4)-1 |
Supported Platforms
| Platform | Support |
|---|---|
| Windows | ✅ |
| ESP32 | ✅ |
| Web (Emscripten) | ✅ |
Full Example: Building a Protocol Frame
use Bytes
// Frame: [header 2B][length 2B][data0 1B][data1 1B][checksum 4B]
var frame = Bytes.new(10)
frame.fill(0)
// Write header 0xAA55 at 16-bit index 0 (bytes 0-1)
frame.write16(0, 0xAA55)
// Write length = 2 at 16-bit index 1 (bytes 2-3)
frame.write16(1, 2)
// Write data bytes at positions 4 and 5
frame.write(4, 0x2A)
frame.write(5, 0x7F)
// Write checksum at 32-bit index 1 (bytes 4-7... watch for overlap)
// Use 32-bit index 1 = bytes 4-7 only if the frame design allows it
// In this example we place it at the end (bytes 6-9)
// For bytes 6-9, 32-bit index 1 would be offset 4 bytes from start — not applicable
// Better to calculate byte by byte:
var checksum = 0xAA55 + 2 + 0x2A + 0x7F
frame.write(6, checksum % 256)
frame.write(7, (checksum / 256) % 256)
// Verify
println("Header: ", frame.read16(0)) // 43605 (0xAA55)
println("Length: ", frame.read16(1)) // 2
println("Data 0: ", frame.read(4)) // 42 (0x2A)
println("Data 1: ", frame.read(5)) // 127 (0x7F)
println("Size: ", frame.size()) // 10
Example: Pixel Buffer for Display
use Bytes
use Display
var display = Display
var draw = display.draw
var width = 320
var height = 240
display.open(width, height)
var buf = Bytes.new(width * height)
var palette[256]
// Red gradient palette
for (var i = 0;i < 256;i++)
palette[i] = i << 16
end
for (var y = 0;y < height;y++)
for (var x = 0;x < width;x++)
var c = int((x * 255) / (width - 1))
buf.write((y * width) + x, c)
end
end
while (true)
draw.bytes(0, 0, width, height, buf, palette)
display.update()
pause(32)
end