DocsStandard library
Bytes.
Keep binary input unchanged and choose an explicit conversion when it becomes text.
Bytes is an immutable sequence of arbitrary bytes. A response body, an image, or a binary frame can all be bytes without being valid UTF-8, and byte operations never repair or normalize what they hold.
API reference: Bytes
Bytes.
import Bytes
main() =
data = Bytes.fromString "café"
print (Bytes.length data)
print (Bytes.toString (Bytes.slice 0 3 data))
print (Bytes.toString (Bytes.fromList [255]))
This prints 5, Just "caf", and Nothing. fromString gives you the string’s UTF-8 bytes. toString goes the other way, but it validates first and returns an optional string. If you’d rather have malformed bytes replaced with U+FFFD, say so explicitly with toStringLossy.
Index and slice.
Byte offsets count transport bytes, even when the data happens to be text:
import Bytes
main() =
data = Bytes.fromList [65, 256, -1]
print (Bytes.byteAt 0 data)
print (Bytes.byteAt 1 data)
print (Bytes.byteAt 2 data)
print (Bytes.byteAt 3 data)
Just 65
Just 0
Just 255
Nothing
fromList keeps the low eight bits of each integer. byteAt returns an integer from 0 to 255, or Nothing if the index is out of bounds. Building bytes from a list of integers is good for tiny binary test data, but not for bulk data.
slice start end bytes uses clamped, half-open bounds, so the byte at start is included and the byte at end isn’t. A slice that cuts through a multibyte character may not be valid UTF-8 any more. Slices can share storage, but every published value stays immutable.
Combine and search.
Use append to join two values and concat for a list of chunks. This example joins a split header and then searches it:
import Bytes
main() =
data = Bytes.concat [Bytes.fromString "Content-", Bytes.fromString "Type: text/plain"]
print (Bytes.indexOf (Bytes.fromString ": ") data)
print (Bytes.toString data)
Just 12
Just "Content-Type: text/plain"
A match is reported as a byte offset. indexOfFrom starts searching at an offset, clamped to the data, and an empty needle matches right at that start. When you’re collecting many chunks, use concat once instead of appending repeatedly to a growing value.
Displaying bytes gives an escaped form that’s meant for inspection. It isn’t a byte literal you could paste back into a program.
Source and Sink.
Bytes.Source e has a pull function that yields the next optional chunk, and Bytes.Sink e has a write function that accepts a chunk. Their effect row describes the underlying transport. Readers and writers add buffering and scoped cursors on top of these.
