bytes/bytes.bend checks
raw source on the hub · import 0xbf477e663cf4acb1369a68e0f0fa713b/bytes/bytes.bend as Bytes
Byte buffers packed four bytes to a U32, with bounds-checked access.
1 import
import Base
Types
type Bytes source · line 9 · raw
Type
Bytes@len:U32 -> @buf:Array<U32> -> Bytes
Definitions
def b8 source · line 12 · raw
@+x:U32 -> U32
def shift source · line 15 · raw
@+i:U32 -> Nat
def words source · line 18 · raw
@+n:U32 -> U32
def depth.go source · line 22 · raw
@f:Nat -> @more:Bool -> @+w:U32 -> @+d:Nat -> @+cap:U32 -> Nat
The fewest d with 2^d >= w.
def depth source · line 33 · raw
@+w:U32 -> Nat
def alloc source · line 36 · raw
@+n:U32 -> Array<U32>
def peek.of source · line 40 · raw
@+sh:Nat -> @r:Pair(Array<U32>, U32) -> Pair(Array<U32>, U32)
Unchecked byte read and write. Callers keep i below len.
def peek source · line 44 · raw
@a:Array<U32> -> @+i:U32 -> Pair(Array<U32>, U32)
def poke.of source · line 47 · raw
@+i:U32 -> @+v:U32 -> @r:Pair(Array<U32>, U32) -> Array<U32>
def poke source · line 52 · raw
@a:Array<U32> -> @+i:U32 -> @+v:U32 -> Array<U32>
def copy.go source · line 56 · raw
@n:Nat -> @r:Pair(Array<U32>, U32) -> @dst:Array<U32> -> @+s:U32 -> @+d:U32 -> Pair(Array<U32>, Array<U32>)
n bytes from src[s..] to dst[d..], one byte at a time.
def copy.bytes source · line 65 · raw
@+m:U32 -> @src:Array<U32> -> @dst:Array<U32> -> @+s:U32 -> @+d:U32 -> Pair(Array<U32>, Array<U32>)
def copy.words source · line 69 · raw
@n:Nat -> @r:Pair(Array<U32>, U32) -> @dst:Array<U32> -> @+s:U32 -> @+d:U32 -> Pair(Array<U32>, Array<U32>)
n words from src[s..] to dst[d..] (word indexes).
def copy.shift source · line 80 · raw
@n:Nat -> @+lo:Nat -> @+hi:Nat -> @+prev:U32 -> @r:Pair(Array<U32>, U32) -> @dst:Array<U32> -> @+k:U32 -> @+d:U32 -> Pair(Array<U32>, Array<U32>)
m bytes to a word-aligned d from an unaligned s: each out word joins two source words. lo = 8*(s%4) and hi = 32 - lo; r holds source word k, prev the word before it.
def copy.shift.at source · line 89 · raw
@+w:U32 -> @+lo:U32 -> @+k:U32 -> @+d:U32 -> @r:Pair(Array<U32>, U32) -> @dst:Array<U32> -> Pair(Array<U32>, Array<U32>)
def copy.tail source · line 93 · raw
@+m:U32 -> @+s:U32 -> @+d:U32 -> @r:Pair(Array<U32>, Array<U32>) -> Pair(Array<U32>, Array<U32>)
def copy.pick source · line 97 · raw
@aligned:Bool -> @+m:U32 -> @src:Array<U32> -> @dst:Array<U32> -> @+s:U32 -> @+d:U32 -> Pair(Array<U32>, Array<U32>)
def copy.dst source · line 108 · raw
@daligned:Bool -> @+m:U32 -> @src:Array<U32> -> @dst:Array<U32> -> @+s:U32 -> @+d:U32 -> Pair(Array<U32>, Array<U32>)
def copy source · line 117 · raw
@+m:U32 -> @src:Array<U32> -> @dst:Array<U32> -> @+s:U32 -> @+d:U32 -> Pair(Array<U32>, Array<U32>)
m bytes from src[s..] to dst[d..]. Whole words when d is word-aligned, shifted when s is not. ponytail: an unaligned d (append after an odd length) copies bytes; merge into d's first word if that gets hot.
def new source · line 121 · raw
@+n:U32 -> Bytes
n zero bytes.
def length source · line 124 · raw
@b:Bytes -> Pair(Bytes, U32)
def get.some source · line 128 · raw
@+len:U32 -> @r:Pair(Array<U32>, U32) -> Pair(Bytes, Maybe<&2, U32>)
def get.if source · line 132 · raw
@ok:Bool -> @+len:U32 -> @buf:Array<U32> -> @+i:U32 -> Pair(Bytes, Maybe<&2, U32>)
def get source · line 140 · raw
@b:Bytes -> @+i:U32 -> Pair(Bytes, Maybe<&2, U32>)
Byte i, or None when i >= len.
def set.if source · line 144 · raw
@ok:Bool -> @+len:U32 -> @buf:Array<U32> -> @+i:U32 -> @+v:U32 -> Bytes
def set source · line 152 · raw
@b:Bytes -> @+i:U32 -> @+v:U32 -> Bytes
Byte i becomes v & 255. Nothing changes when i >= len.
def count source · line 157 · raw
@s:String -> @+n:U32 -> U32
String.length counts in Nat, which costs more than the walk itself.
def flush source · line 165 · raw
@full:Bool -> @a:Array<U32> -> @+k:U32 -> @+w:U32 -> Array<U32>
Bytes enter at the top of w and shift down, so a full word has byte 0 lowest.
def from.go source · line 172 · raw
@s:String -> @a:Array<U32> -> @+i:U32 -> @+w:U32 -> Array<U32>
def from_string source · line 183 · raw
@+s:String -> Bytes
A byte string (one Char per octet, as Wire and Http use) to Bytes. Each Char keeps its low 8 bits.
def to.go source · line 187 · raw
@n:Nat -> @r:Pair(Array<U32>, U32) -> @+i:U32 -> @acc:String -> String
def to_string source · line 196 · raw
@b:Bytes -> String
Bytes to a byte string, one Char per octet.
def slice.fin source · line 200 · raw
@+len:U32 -> @+m:U32 -> @r:Pair(Array<U32>, Array<U32>) -> Pair(Bytes, Bytes)
def slice.at source · line 204 · raw
@+len:U32 -> @buf:Array<U32> -> @+s:U32 -> @+m:U32 -> Pair(Bytes, Bytes)
def slice source · line 208 · raw
@b:Bytes -> @+start:U32 -> @+n:U32 -> Pair(Bytes, Bytes)
The buffer back, and a copy of up to n bytes from start. Both ends are clamped to len.
def append.fin source · line 213 · raw
@+n:U32 -> @r:Pair(Array<U32>, Array<U32>) -> Bytes
def append.two source · line 217 · raw
@+n:U32 -> @+la:U32 -> @+lb:U32 -> @bb:Array<U32> -> @r:Pair(Array<U32>, Array<U32>) -> Bytes
def append source · line 222 · raw
@a:Bytes -> @b:Bytes -> Bytes
a then b, in a new buffer.
def concat.total.con source · line 228 · raw
@x:Bytes -> @r:Pair(List<&1, Bytes>, U32) -> Pair(List<&1, Bytes>, U32)
def concat.total source · line 232 · raw
@xs:List<&1, Bytes> -> @+n:U32 -> Pair(List<&1, Bytes>, U32)
def concat.put source · line 240 · raw
@r:Pair(Array<U32>, Array<U32>) -> Array<U32>
def concat.go source · line 244 · raw
@xs:List<&1, Bytes> -> @out:Array<U32> -> @+at:U32 -> Array<U32>
def concat.of source · line 252 · raw
@r:Pair(List<&1, Bytes>, U32) -> Bytes
def concat source · line 257 · raw
@xs:List<&1, Bytes> -> Bytes
The pieces in order, in one new buffer: one copy per byte, however many pieces.
def at.go source · line 261 · raw
@needle:String -> @ok:Bool -> @r:Pair(Array<U32>, U32) -> @+j:U32 -> Pair(Array<U32>, Bool)
Does needle match at j? ok is the previous byte's result; the first mismatch stops the walk.
def at source · line 275 · raw
@a:Array<U32> -> @+needle:String -> @+j:U32 -> Pair(Array<U32>, Bool)
def find.go source · line 279 · raw
@f:Nat -> @r:Pair(Array<U32>, Bool) -> @+needle:String -> @+i:U32 -> Pair(Array<U32>, Maybe<&2, U32>)
ponytail: naive search; a mismatch costs one byte read per position, but a repetitive needle is O(len * needle). Add a SWAR scan or two-way search if find gets hot.
def find.fin source · line 292 · raw
@+len:U32 -> @r:Pair(Array<U32>, Maybe<&2, U32>) -> Pair(Bytes, Maybe<&2, U32>)
def find.at source · line 296 · raw
@big:Bool -> @+len:U32 -> @buf:Array<U32> -> @+needle:String -> @+m:U32 -> Pair(Bytes, Maybe<&2, U32>)
def find source · line 304 · raw
@b:Bytes -> @+needle:String -> Pair(Bytes, Maybe<&2, U32>)
Index of the first match of needle (a byte string), or None. An empty needle matches at 0.
def eq.go source · line 310 · raw
@n:Nat -> @same:Bool -> @r:Pair(Array<U32>, U32) -> @s:Pair(Array<U32>, U32) -> @+i:U32 -> Pair(Array<U32>, Pair(Array<U32>, Bool))
Compares whole words; same tells whether the previous pair matched.
def eq.fin source · line 327 · raw
@+la:U32 -> @+lb:U32 -> @r:Pair(Array<U32>, Pair(Array<U32>, Bool)) -> Pair(Bytes, Pair(Bytes, Bool))
def eq.len source · line 331 · raw
@same:Bool -> @+la:U32 -> @xa:Array<U32> -> @+lb:U32 -> @ya:Array<U32> -> Pair(Bytes, Pair(Bytes, Bool))
def eq source · line 339 · raw
@a:Bytes -> @b:Bytes -> Pair(Bytes, Pair(Bytes, Bool))
Both buffers back, and whether they hold the same bytes.