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 functionsBytes.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