Skip to main content

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() and Bytes.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:

ParameterTypeDescription
sizeintegerNumber 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
info

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:

ParameterTypeDescription
bufBytesByte 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:

ParameterTypeDescription
valueintegerValue 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:

ParameterTypeDescription
posintegerByte 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:

ParameterTypeDescription
posintegerByte index (0-based)
valueintegerValue 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)
caution

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:

ParameterTypeDescription
indexintegerPosition 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)
16-bit index units

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:

ParameterTypeDescription
indexintegerPosition in 16-bit units (0-based)
valueintegerValue 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)
caution

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:

ParameterTypeDescription
indexintegerPosition 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)
32-bit index units

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:

ParameterTypeDescription
indexintegerPosition in 32-bit units (0-based)
valueintegerValue 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:

MethodIndex unitBytes accessedValid range (N-byte buffer)
read / write1 byte1 byte0 to N-1
read16 / write162 bytes2 bytes0 to (N/2)-1
read32 / write324 bytes4 bytes0 to (N/4)-1

Supported Platforms​

PlatformSupport
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