Text, Bytes & PAD

Choose persistent Text, evaluation-scoped Bytes, or the single 64-byte PAD scratch buffer.


Frothy has three byte-oriented tools with deliberately different lifetimes:

KindBest forLifetime in the ESP32 plain profile
Textdurable strings and copied I/O resultsobject value; persistable
Byteslive I/O and temporary binary transformscurrent evaluation or loop iteration
PADone tiny hand-built scratch sequenceone shared 64-byte buffer until reset

Choose the shortest lifetime that fits, and cross into Text explicitly with text.pack or pad.pack when data must persist.

Copy An HTTP Body Into Text

An I/O read returns Bytes. It cannot be installed in a top-level binding:

body is text.pack: (http.get: "http://example.com/")
text.length: body

Inside a word, a here local can hold Bytes for the duration of the call:

to fetch-size with url [
  here body is http.get: url
  bytes.length: body
]

Text

WordResultUse
text.lengthIntByte length
text.equals?BoolByte-for-byte equality
text.concatTextNew joined Text
text.atIntByte at an index
text.from-intTextDecimal integer rendering
text.packTextCopy Bytes into Text storage

Text is immutable and indexed by byte, not Unicode character. Source literals support \n, \r, \t, \", and \\. In the ESP32 plain profile, one Text value is limited to 4096 bytes and the text pool holds 8192 bytes in total.

greeting is text.concat: "hello, ", "Frothy"
text.at: greeting, 0
text.equals?: greeting, "hello, Frothy"

Creating unique Text consumes the bounded text pool. Reuse stable values and use transient Bytes for working I/O rather than packing every intermediate.

Bytes

WordResultUse
bytes.from-textBytesCopy Text into the transient arena
bytes.from-byteBytesCreate one byte from 0..255
bytes.from-intBytesDecimal integer as ASCII bytes
bytes.lengthIntBuffer length
bytes.atIntByte at an index
bytes.equals?BoolByte-for-byte equality
bytes.concatBytesJoin two transient buffers

The ESP32 plain runtime provides eight Bytes entries backed by a 4096-byte arena. A buffer is reset at the end of the outer prompt evaluation, after boot, and at loop back-edges. Do not carry one across iterations.

Bytes cannot be written to top-level slots, Cells, or record fields, and cannot be saved. Consume them immediately, keep them in a here local during one call, or pack them:

to make-frame [
  here head is bytes.from-text: "value="
  here value is bytes.from-int: 42
  here frame is bytes.concat: head, value
  text.pack: frame
]

frame-text is make-frame:

Words such as print, i2c.write, tcp.write, and BLE write operations accept Text or Bytes directly. i2c.read, tcp.read, http.get, and BLE read operations return Bytes.

PAD

PAD is one global scratch buffer. It is useful when bytes are assembled one at a time without allocating a Bytes entry:

pad.reset:
pad.emit-byte: 65
pad.emit-byte: 84
pad.type:
command is pad.pack:
WordResultUse
pad.resetnilEmpty the PAD
pad.emit-bytenilAppend one 0..255 byte
pad.lenIntCurrent byte count
pad.peek-byteIntRead one byte by index
pad.typenilWrite PAD bytes to the console
pad.packTextCopy PAD into persistent Text

The current PAD holds 64 bytes. pad.emit-byte reports capacity when full; pad.peek-byte reports range for an invalid index. pad.pack does not clear the PAD, so call pad.reset before constructing the next value.