APIBytes
Bytes
Immutable byte sequences.
String is valid UTF-8 by contract, so a response body, an image, or a
framed record has no String to live in; Bytes holds any bytes, and
indexes and slices by byte rather than by character. It also declares
Source and Sink, the leaves that buffered readers and writers are
built on.
Bytes
type BytesSource
An immutable sequence of bytes. Values come from empty, fromString,
fromList, and the operations here; nothing ever writes into one after it
is built, so slices share storage safely.
Bytes compare lexicographically by unsigned value, a prefix ordering before
what extends it. show gives a quoted form in which printable ASCII passes
through, \\, \", \n, \t, and \r are escapes, and every other byte
is \xNN in uppercase hex. It is a display form: there is no Bytes
literal.
import Bytes
Bytes.fromString "ab" < Bytes.fromString "abc"
Bytes.fromList [255] > Bytes.fromList [1, 2]
show (Bytes.fromList [104, 105, 10, 200]) == "\"hi\\n\\xC8\""
Instances:
Eq Bytes
Ord Bytes
Show Bytes
Sink
type Sink e = { write : Bytes ->{e} () }Source
A consumer of byte chunks whose writes perform e. Writer buffers one.
It has no close: the scope that owns the underlying file or socket closes
it.
Source
type Source e = { pull : () ->{e} Maybe Bytes }Source
A producer of byte chunks whose reads perform e. Reader buffers one.
It has no close: the scope that owns the underlying file or socket closes
it.
append
append : Bytes -> Bytes -> BytesSource
The first sequence followed by the second.
import Bytes
Bytes.append (Bytes.fromString "ab") (Bytes.fromString "c") == Bytes.fromString "abc"
byteAt
byteAt : Int -> Bytes -> Maybe IntSource
The byte at a zero-based index, as an Int from 0 to 255, or Nothing
when the index is out of range.
import Bytes
Bytes.byteAt 0 (Bytes.fromString "A") == Just 65
Bytes.byteAt 1 (Bytes.fromString "A") == Nothing
concat
concat : List Bytes -> BytesSource
The sequences joined in list order, allocated once for the whole result.
import Bytes
Bytes.concat [Bytes.fromString "a", Bytes.empty, Bytes.fromString "bc"] == Bytes.fromString "abc"
empty
empty : BytesSource
The empty sequence.
fromList
fromList : List Int -> BytesSource
The bytes of a list of integers, each truncated to its low eight bits. It
is meant for fixtures and binary framing rather than bulk data, since a
List Int takes eight bytes per byte.
import Bytes
Bytes.toList (Bytes.fromList [256, -1, 65]) == [0, 255, 65]
fromString
fromString : String -> BytesSource
The UTF-8 encoding of the text.
import Bytes
Bytes.toList (Bytes.fromString "é") == [195, 169]
indexOf
indexOf : Bytes -> Bytes -> Maybe IntSource
The first index at which needle occurs, or Nothing. The empty needle
occurs at index 0 of every sequence. The scan runs natively and allocates
nothing per match.
import Bytes
Bytes.indexOf (Bytes.fromString "c") (Bytes.fromString "abcabc") == Just 2
Bytes.indexOf (Bytes.fromString "x") (Bytes.fromString "abc") == Nothing
Bytes.indexOf Bytes.empty Bytes.empty == Just 0
indexOfFrom
indexOfFrom : Int -> Bytes -> Bytes -> Maybe IntSource
indexOf beginning at a clamped index start, where the empty needle
occurs. Resuming where an earlier search stopped keeps repeated searches
over a growing buffer linear in its size.
import Bytes
Bytes.indexOfFrom 3 (Bytes.fromString "c") (Bytes.fromString "abcabc") == Just 5
length
length : Bytes -> IntSource
The number of bytes.
import Bytes
Bytes.length (Bytes.fromString "naïve") == 6
slice
slice : Int -> Int -> Bytes -> BytesSource
The bytes from index start up to but not including end. Indices are
clamped to the sequence, and the result is empty when end is not greater
than start. A slice shares the storage it was cut from, so it costs the
same however large the original is.
import Bytes
Bytes.slice 1 3 (Bytes.fromString "abcd") == Bytes.fromString "bc"
Bytes.slice (-5) 2 (Bytes.fromString "abcd") == Bytes.fromString "ab"
Bytes.slice 3 1 (Bytes.fromString "abcd") == Bytes.empty
startsWith
startsWith : Bytes -> Bytes -> BoolSource
Whether bytes begins with prefix. The empty prefix begins everything.
import Bytes
Bytes.startsWith (Bytes.fromString "ab") (Bytes.fromString "abc")
toList
toList : Bytes -> List IntSource
The bytes as integers from 0 to 255, in order.
import Bytes
Bytes.toList (Bytes.fromString "hi") == [104, 105]
toString
toString : Bytes -> Maybe StringSource
The text these bytes encode, or Nothing when they are not valid UTF-8,
so input that is not text is never silently rewritten.
import Bytes
Bytes.toString (Bytes.fromList [104, 105]) == Just "hi"
Bytes.toString (Bytes.fromList [255]) == Nothing
toStringLossy
toStringLossy : Bytes -> StringSource
The text these bytes encode, with U+FFFD in place of each malformed byte. It is meant for reporting what was received, not for conversion.
import Bytes
Bytes.toStringLossy (Bytes.fromList [104, 255, 105]) == "h�i"
