Módulo Bytes
El módulo Bytes proporciona un buffer de memoria de bytes de tamaño fijo, optimizado para trabajar con datos binarios de bajo nivel. Es especialmente útil en comunicaciones con hardware, construcción de tramas de protocolo, manipulación de datos de imagen o cualquier operación que requiera acceso directo a memoria por posición.
Uso
use Bytes
Arquitectura del módulo
El módulo tiene dos niveles:
- Funciones del módulo —
Bytes.new()yBytes.clone()para crear buffers. - Métodos del objeto — operaciones sobre el buffer creado (
read,write,fill,size, etc.).
use Bytes
var buf = Bytes.new(16) // Crear buffer de 16 bytes
buf.write(0, 0xFF) // Escribir en posición 0
var valor = buf.read(0) // Leer desde posición 0
println(valor) // 255
Funciones del módulo
new
Crea un nuevo buffer de bytes de tamaño fijo.
var buf = Bytes.new(tamaño)
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
tamaño | integer | Número de bytes a reservar |
Retorna: Un objeto buffer de bytes listo para usar.
Ejemplo:
use Bytes
var buf = Bytes.new(64) // Buffer de 64 bytes
buf.fill(0) // Inicializar a cero
println(buf.size()) // 64
El contenido inicial del buffer no está garantizado. Usa fill(0) para inicializarlo a cero antes de operar con él.
clone
Crea una copia independiente de un buffer de bytes existente.
var copia = Bytes.clone(buf)
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
buf | Bytes | Buffer de bytes a clonar |
Retorna: Un nuevo objeto bytes con el mismo tamaño y contenido que el original. Modificar la copia no afecta al original.
Ejemplo:
use Bytes
var original = Bytes.new(4)
original.write(0, 0xAB)
original.write(1, 0xCD)
var copia = Bytes.clone(original)
copia.write(0, 0x00) // No afecta a original
println(original.read(0)) // 171 (0xAB)
println(copia.read(0)) // 0
Métodos del objeto Bytes
fill
Rellena todos los bytes del buffer con un mismo valor.
buf.fill(valor)
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
valor | integer | Valor entre 0 y 255 con el que rellenar |
Ejemplo:
use Bytes
var buf = Bytes.new(8)
buf.fill(0xFF) // Todos los bytes a 255
buf.fill(0) // Limpiar el buffer
size
Devuelve el tamaño del buffer en bytes.
var n = buf.size()
Retorna: Un entero con el número de bytes del buffer.
Ejemplo:
use Bytes
var buf = Bytes.new(32)
println(buf.size()) // 32
read
Lee un byte en la posición indicada.
var valor = buf.read(pos)
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
pos | integer | Índice del byte (0-based) |
Retorna: Un entero entre 0 y 255. Lanza una excepción si el índice está fuera de rango.
Ejemplo:
use Bytes
var buf = Bytes.new(4)
buf.write(2, 0x42)
println(buf.read(2)) // 66 (0x42)
write
Escribe un byte en la posición indicada.
buf.write(pos, valor)
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
pos | integer | Índice del byte (0-based) |
valor | integer | Valor entre 0 y 255 |
Lanza una excepción si el índice está fuera de rango.
Ejemplo:
use Bytes
var buf = Bytes.new(4)
buf.write(0, 0xDE)
buf.write(1, 0xAD)
buf.write(2, 0xBE)
buf.write(3, 0xEF)
Solo se almacena el byte bajo del valor. Si el valor supera 255, los bits superiores se descartan.
read16
Lee un valor de 16 bits (2 bytes) en el índice indicado. El índice se expresa en unidades de 16 bits, no en bytes.
var valor = buf.read16(indice)
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
indice | integer | Posición en unidades de 16 bits (0-based) |
Retorna: Un entero entre 0 y 65535. Lanza una excepción si el índice está fuera de rango.
Ejemplo:
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) accede a los bytes 2-3, no al byte 1. Para un buffer de N bytes, el rango de índices válido es 0 a (N/2) - 1.
write16
Escribe un valor de 16 bits (2 bytes) en el índice indicado. El índice se expresa en unidades de 16 bits.
buf.write16(indice, valor)
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
indice | integer | Posición en unidades de 16 bits (0-based) |
valor | integer | Valor entre 0 y 65535 |
Lanza una excepción si el índice está fuera de rango.
Ejemplo:
use Bytes
var buf = Bytes.new(8)
buf.write16(0, 0x0102)
buf.write16(1, 0x0304)
buf.write16(2, 0x0506)
buf.write16(3, 0x0708)
Solo se almacenan los 16 bits bajos del valor. Si el valor supera 65535, los bits superiores se descartan.
read32
Lee un valor de 32 bits (4 bytes) en el índice indicado. El índice se expresa en unidades de 32 bits.
var valor = buf.read32(indice)
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
indice | integer | Posición en unidades de 32 bits (0-based) |
Retorna: Un entero de 32 bits sin signo. Lanza una excepción si el índice está fuera de rango.
Ejemplo:
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) accede a los bytes 4-7, no al byte 1. Para un buffer de N bytes, el rango de índices válido es 0 a (N/4) - 1.
write32
Escribe un valor de 32 bits (4 bytes) en el índice indicado. El índice se expresa en unidades de 32 bits.
buf.write32(indice, valor)
Parámetros:
| Parámetro | Tipo | Descripción |
|---|---|---|
indice | integer | Posición en unidades de 32 bits (0-based) |
valor | integer | Valor entre 0 y 4294967295 (0x00000000 a 0xFFFFFFFF) |
Lanza una excepción si el índice está fuera de rango.
Ejemplo:
use Bytes
var buf = Bytes.new(16)
buf.write32(0, 0x00FF00FF)
buf.write32(1, 0xFF00FF00)
Resumen de índices
La diferencia clave entre los métodos de lectura/escritura es la unidad del índice:
| Método | Unidad del índice | Bytes accedidos | Rango válido (buffer de N bytes) |
|---|---|---|---|
read / write | 1 byte | 1 byte | 0 a N-1 |
read16 / write16 | 2 bytes | 2 bytes | 0 a (N/2)-1 |
read32 / write32 | 4 bytes | 4 bytes | 0 a (N/4)-1 |
Plataformas soportadas
| Plataforma | Soporte |
|---|---|
| Windows | ✅ |
| ESP32 | ✅ |
| Web (Emscripten) | ✅ |
Ejemplo completo: Construir una trama de protocolo
use Bytes
// Trama: [cabecera 2B][longitud 2B][dato0 1B][dato1 1B][checksum 4B]
var trama = Bytes.new(10)
trama.fill(0)
// Escribir cabecera 0xAA55 en posición 0 (16 bits)
trama.write16(0, 0xAA55)
// Escribir longitud = 2 en posición 1 (16 bits → bytes 2-3)
trama.write16(1, 2)
// Escribir datos en bytes 4 y 5
trama.write(4, 0x2A)
trama.write(5, 0x7F)
// Escribir checksum en posición 1 (32 bits → bytes 4-7... ojo al solapamiento)
// Usar posición 1 de 32 bits = bytes 4-7 solo si el diseño de trama lo permite
// En este ejemplo lo ponemos al final (bytes 6-9)
// Para bytes 6-9 sería índice 32bit = 1 (offset 4 bytes desde el inicio, no aplica)
// Mejor calcularlo byte a byte:
var checksum = 0xAA55 + 2 + 0x2A + 0x7F
trama.write(6, checksum % 256)
trama.write(7, (checksum / 256) % 256)
// Verificar
println("Cabecera: ", trama.read16(0)) // 43605 (0xAA55)
println("Longitud: ", trama.read16(1)) // 2
println("Dato 0: ", trama.read(4)) // 42 (0x2A)
println("Dato 1: ", trama.read(5)) // 127 (0x7F)
println("Tamaño: ", trama.size()) // 10
Ejemplo: Buffer de píxeles para Display
use Bytes
use Display
var display = Display
var draw = display.draw
var ancho = 320
var alto = 240
display.open(ancho, alto)
var buf = Bytes.new(ancho * alto)
var palette[256]
// Escala de rojo
for (var i = 0;i < 256;i++)
palette[i] = i << 16
end
for (var y = 0;y < alto;y++)
for (var x = 0;x < ancho;x++)
var c = int((x * 255) / (ancho - 1))
buf.write((y * ancho) + x, c)
end
end
while (true)
draw.bytes(0, 0, ancho, alto, buf, palette)
display.update()
pause(32)
end