~/bend-docscommunity

libs/wire/deps/bytes.bend checks

raw source on the hub · import 0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/bytes.bend as Bytes

Byte buffers packed four bytes to a U32, with bounds-checked access. Source: https://github.com/paymog/bend-kit/tree/main/bytes

2 imports
import Base
import ./int.bend as Int

Types

type Bytes source · line 11 · raw

Type

Definitions

def b8 source · line 14 · raw

@+x:U32 -> U32

def shift source · line 17 · raw

@+i:U32 -> Nat

def words source · line 20 · raw

@+n:U32 -> U32

def depth.go source · line 24 · raw

@f:Nat -> @more:Bool -> @+w:U32 -> @+d:Nat -> @+cap:U32 -> Nat

The fewest d with 2^d >= w.

def depth source · line 35 · raw

@+w:U32 -> Nat

def alloc source · line 38 · raw

@+n:U32 -> Array<U32>

def peek.of source · line 42 · 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 46 · raw

@a:Array<U32> -> @+i:U32 -> Pair(Array<U32>, U32)

def poke.of source · line 49 · raw

@+i:U32 -> @+v:U32 -> @r:Pair(Array<U32>, U32) -> Array<U32>

def poke source · line 54 · raw

@a:Array<U32> -> @+i:U32 -> @+v:U32 -> Array<U32>

def copy.go source · line 58 · 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 71 · raw

@+m:U32 -> @src:Array<U32> -> @dst:Array<U32> -> @+s:U32 -> @+d:U32 -> Pair(Array<U32>, Array<U32>)

def copy.words source · line 79 · 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 94 · 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 110 · 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 119 · raw

@+m:U32 -> @+s:U32 -> @+d:U32 -> @r:Pair(Array<U32>, Array<U32>) -> Pair(Array<U32>, Array<U32>)

def copy.pick source · line 123 · 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 139 · raw

@daligned:Bool -> @+m:U32 -> @src:Array<U32> -> @dst:Array<U32> -> @+s:U32 -> @+d:U32 -> Pair(Array<U32>, Array<U32>)

def copy source · line 153 · 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 157 · raw

@+n:U32 -> Bytes

n zero bytes.

def length source · line 160 · raw

@b:Bytes -> Pair(Bytes, U32)

def get.some source · line 164 · raw

@+len:U32 -> @r:Pair(Array<U32>, U32) -> Pair(Bytes, Maybe<&2, U32>)

def get.if source · line 168 · raw

@ok:Bool -> @+len:U32 -> @buf:Array<U32> -> @+i:U32 -> Pair(Bytes, Maybe<&2, U32>)

def get source · line 176 · raw

@b:Bytes -> @+i:U32 -> Pair(Bytes, Maybe<&2, U32>)

Byte i, or None when i >= len.

def set.if source · line 180 · raw

@ok:Bool -> @+len:U32 -> @buf:Array<U32> -> @+i:U32 -> @+v:U32 -> Bytes

def set source · line 188 · raw

@b:Bytes -> @+i:U32 -> @+v:U32 -> Bytes

Byte i becomes v & 255. Nothing changes when i >= len.

def step source · line 193 · raw

@+up:Bool -> @+i:U32 -> U32

The next index: one forward when up, one back when not.

def fits source · line 197 · raw

@+len:U32 -> @+i:U32 -> @+n:U32 -> Bool

Do n bytes from i fit in len?

def uint.go source · line 201 · raw

@n:Nat -> @r:Pair(Array<U32>, U32) -> @+j:U32 -> @+up:Bool -> @+acc:U32 -> Pair(Array<U32>, U32)

n bytes from j, each shifted in below the ones before: the first byte read is the most significant.

def uint.if source · line 211 · raw

@ok:Bool -> @+len:U32 -> @buf:Array<U32> -> @+i:U32 -> @+n:U32 -> @+be:Bool -> Pair(Bytes, Maybe<&2, U32>)

Big-endian reads forward from i; little-endian reads back from the last byte.

def uint source · line 224 · raw

@b:Bytes -> @+i:U32 -> @+n:U32 -> @+be:Bool -> Pair(Bytes, Maybe<&2, U32>)

def get.u16be source · line 230 · raw

@b:Bytes -> @+i:U32 -> Pair(Bytes, Maybe<&2, U32>)

Unsigned integers at byte i, or None when they run past len. be: most significant byte first (network order); le: least significant first.

def get.u16le source · line 233 · raw

@b:Bytes -> @+i:U32 -> Pair(Bytes, Maybe<&2, U32>)

def get.u32be source · line 236 · raw

@b:Bytes -> @+i:U32 -> Pair(Bytes, Maybe<&2, U32>)

def get.u32le source · line 239 · raw

@b:Bytes -> @+i:U32 -> Pair(Bytes, Maybe<&2, U32>)

def put.go source · line 243 · raw

@n:Nat -> @a:Array<U32> -> @+j:U32 -> @+up:Bool -> @+v:U32 -> Array<U32>

n bytes of v from j, least significant first.

def put.if source · line 251 · raw

@ok:Bool -> @+len:U32 -> @buf:Array<U32> -> @+i:U32 -> @+n:U32 -> @+be:Bool -> @+v:U32 -> Bytes

Little-endian writes forward from i; big-endian writes back from the last byte.

def put source · line 258 · raw

@b:Bytes -> @+i:U32 -> @+n:U32 -> @+be:Bool -> @+v:U32 -> Bytes

def set.u16be source · line 263 · raw

@b:Bytes -> @+i:U32 -> @+v:U32 -> Bytes

v's low 16 or 32 bits at byte i. Nothing changes when they would run past len.

def set.u16le source · line 266 · raw

@b:Bytes -> @+i:U32 -> @+v:U32 -> Bytes

def set.u32be source · line 269 · raw

@b:Bytes -> @+i:U32 -> @+v:U32 -> Bytes

def set.u32le source · line 272 · raw

@b:Bytes -> @+i:U32 -> @+v:U32 -> Bytes

def u64.of source · line 276 · raw

@be:Bool -> @+x:U32 -> @+y:U32 -> 0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64

The U64 whose words, in byte order, are x then y.

def u64.join source · line 283 · raw

@+be:Bool -> @x:Maybe<&2, U32> -> @y:Maybe<&2, U32> -> Maybe<&2, 0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64>

def u64.lo source · line 290 · raw

@+be:Bool -> @x:Maybe<&2, U32> -> @r:Pair(Bytes, Maybe<&2, U32>) -> Pair(Bytes, Maybe<&2, 0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64>)

def u64.hi source · line 294 · raw

@+i:U32 -> @+be:Bool -> @r:Pair(Bytes, Maybe<&2, U32>) -> Pair(Bytes, Maybe<&2, 0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64>)

def u64 source · line 298 · raw

@b:Bytes -> @+i:U32 -> @+be:Bool -> Pair(Bytes, Maybe<&2, 0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64>)

def get.u64be source · line 302 · raw

@b:Bytes -> @+i:U32 -> Pair(Bytes, Maybe<&2, 0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64>)

A U64 at byte i, or None when its 8 bytes run past len.

def get.u64le source · line 305 · raw

@b:Bytes -> @+i:U32 -> Pair(Bytes, Maybe<&2, 0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64>)

def put64.if source · line 309 · raw

@ok:Bool -> @+len:U32 -> @buf:Array<U32> -> @+i:U32 -> @+be:Bool -> @+x:U32 -> @+y:U32 -> Bytes

Writes words x then y at byte i, both in the same byte order.

def put64 source · line 316 · raw

@b:Bytes -> @+i:U32 -> @+be:Bool -> @+v:0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64 -> Bytes

def set.u64be source · line 323 · raw

@b:Bytes -> @+i:U32 -> @+v:0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64 -> Bytes

v at byte i. Nothing changes when its 8 bytes would run past len.

def set.u64le source · line 326 · raw

@b:Bytes -> @+i:U32 -> @+v:0x3d2147650fe101ae3c3e4a95333b4238/libs/wire/deps/int.U64 -> Bytes

def count source · line 330 · raw

@s:String -> @+n:U32 -> U32

String.length counts in Nat, which costs more than the walk itself.

def flush source · line 338 · 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 345 · raw

@s:String -> @a:Array<U32> -> @+i:U32 -> @+w:U32 -> Array<U32>

def from_string source · line 356 · raw

@+s:String -> Bytes

A byte string (one Char per octet, as Wire and HttpClient use) to Bytes. Each Char keeps its low 8 bits.

def to.go source · line 360 · raw

@n:Nat -> @r:Pair(Array<U32>, U32) -> @+i:U32 -> @acc:String -> String

def to_string source · line 369 · raw

@b:Bytes -> String

Bytes to a byte string, one Char per octet.

def slice.fin source · line 373 · raw

@+len:U32 -> @+m:U32 -> @r:Pair(Array<U32>, Array<U32>) -> Pair(Bytes, Bytes)

def slice.at source · line 377 · raw

@+len:U32 -> @buf:Array<U32> -> @+s:U32 -> @+m:U32 -> Pair(Bytes, Bytes)

def slice source · line 381 · 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 dst source · line 386 · raw

@r:Pair(Array<U32>, Array<U32>) -> Array<U32>

def room source · line 391 · raw

@+len:U32 -> @+n:U32 -> Bool

Does a buffer holding len bytes have room for n? Its 2^d words fit the fewest that hold len.

def grow.if source · line 394 · raw

@fits:Bool -> @+len:U32 -> @buf:Array<U32> -> @+n:U32 -> Array<U32>

def grow source · line 402 · raw

@+len:U32 -> @buf:Array<U32> -> @+n:U32 -> Array<U32>

buf, or a copy of its first len bytes in the fewest 2^d words that hold n.

def append source · line 407 · raw

@a:Bytes -> @b:Bytes -> Bytes

a then b. b is written into a's buffer while it has room, and the buffer at least doubles when it runs out, so building a buffer one piece at a time is O(total).

def concat.total.con source · line 413 · raw

@x:Bytes -> @r:Pair(List<&1, Bytes>, U32) -> Pair(List<&1, Bytes>, U32)

def concat.total source · line 417 · raw

@xs:List<&1, Bytes> -> @+n:U32 -> Pair(List<&1, Bytes>, U32)

def concat.go source · line 425 · raw

@xs:List<&1, Bytes> -> @out:Array<U32> -> @+at:U32 -> Array<U32>

def concat.of source · line 433 · raw

@r:Pair(List<&1, Bytes>, U32) -> Bytes

def concat source · line 438 · 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 442 · 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 456 · raw

@a:Array<U32> -> @+needle:String -> @+j:U32 -> Pair(Array<U32>, Bool)

def find.go source · line 461 · raw

@f:Nat -> @r:Pair(Array<U32>, Bool) -> @+needle:String -> @+i:U32 -> @+up:Bool -> 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. f counts the positions left after i.

def find.fin source · line 478 · raw

@+len:U32 -> @r:Pair(Array<U32>, Maybe<&2, U32>) -> Pair(Bytes, Maybe<&2, U32>)

def find.at source · line 482 · raw

@none:Bool -> @+len:U32 -> @buf:Array<U32> -> @+needle:String -> @+i:U32 -> @+f:U32 -> @+up:Bool -> Pair(Bytes, Maybe<&2, U32>)

def find.from source · line 497 · raw

@b:Bytes -> @+needle:String -> @+start:U32 -> Pair(Bytes, Maybe<&2, U32>)

Index of the first match of needle (a byte string) at or after start, or None. An empty needle matches at start when start <= len.

def find source · line 503 · 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 rfind source · line 507 · raw

@b:Bytes -> @+needle:String -> Pair(Bytes, Maybe<&2, U32>)

Index of the last match of needle, or None. An empty needle matches at len.

def at.fin source · line 512 · raw

@+len:U32 -> @r:Pair(Array<U32>, Bool) -> Pair(Bytes, Bool)

def at.if source · line 516 · raw

@fits:Bool -> @+len:U32 -> @buf:Array<U32> -> @+needle:String -> @+j:U32 -> Pair(Bytes, Bool)

def starts_with source · line 524 · raw

@b:Bytes -> @+prefix:String -> Pair(Bytes, Bool)

Does b begin with prefix (a byte string)?

def ends_with source · line 530 · raw

@b:Bytes -> @+suffix:String -> Pair(Bytes, Bool)

Does b end with suffix (a byte string)?

def split.scan source · line 537 · raw

@f:Nat -> @r:Pair(Array<U32>, Bool) -> @+sep:String -> @+m:U32 -> @+i:U32 -> @+skip:U32 -> @+cuts:List<&2, U32> -> Pair(Array<U32>, List<&2, U32>)

Match positions of sep, latest first, that do not overlap an earlier match. f counts the positions left; skip counts the bytes still inside the last match.

def snd source · line 554 · raw

@r:Pair(Bytes, Bytes) -> Bytes

def split.cut source · line 559 · raw

@cuts:List<&2, U32> -> @r:Pair(Bytes, Bytes) -> @+end:U32 -> @+m:U32 -> @acc:List<&1, Bytes> -> List<&1, Bytes>

r holds the buffer and the piece that ends at end; each earlier cut j starts one at j + m.

def split.of source · line 572 · raw

@cuts:List<&2, U32> -> @b:Bytes -> @+len:U32 -> @+m:U32 -> List<&1, Bytes>

def split.run source · line 579 · raw

@+len:U32 -> @+m:U32 -> @r:Pair(Array<U32>, List<&2, U32>) -> List<&1, Bytes>

def split.if source · line 583 · raw

@whole:Bool -> @+len:U32 -> @buf:Array<U32> -> @+sep:String -> @+m:U32 -> List<&1, Bytes>

def split source · line 592 · raw

@b:Bytes -> @+sep:String -> List<&1, Bytes>

The pieces between matches of sep (a byte string), left to right. n matches give n + 1 pieces, so a match at either end gives an empty piece. An empty sep gives b whole.

def eq.go source · line 598 · 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 619 · raw

@+la:U32 -> @+lb:U32 -> @r:Pair(Array<U32>, Pair(Array<U32>, Bool)) -> Pair(Bytes, Pair(Bytes, Bool))

def eq.len source · line 623 · raw

@same:Bool -> @+la:U32 -> @xa:Array<U32> -> @+lb:U32 -> @ya:Array<U32> -> Pair(Bytes, Pair(Bytes, Bool))

def eq source · line 631 · raw

@a:Bytes -> @b:Bytes -> Pair(Bytes, Pair(Bytes, Bool))

Both buffers back, and whether they hold the same bytes.

def bswap source · line 637 · raw

@+w:U32 -> U32

Byte 0 of w becomes the most significant, so words compare in byte order.

def cmp.go source · line 641 · raw

@n:Nat -> @c:Cmp -> @r:Pair(Array<U32>, U32) -> @s:Pair(Array<U32>, U32) -> @+i:U32 -> Pair(Array<U32>, Pair(Array<U32>, Cmp))

Compares whole words; c is the previous pair's order.

def cmp.len source · line 666 · raw

@c:Cmp -> @+la:U32 -> @+lb:U32 -> Cmp

def cmp.fin source · line 675 · raw

@+la:U32 -> @+lb:U32 -> @r:Pair(Array<U32>, Pair(Array<U32>, Cmp)) -> Pair(Bytes, Pair(Bytes, Cmp))

def cmp source · line 681 · raw

@a:Bytes -> @b:Bytes -> Pair(Bytes, Pair(Bytes, Cmp))

Both buffers back, and their order byte by byte; a prefix sorts first. The shorter buffer's bytes past its len are 0, so its last word compares low when only the longer one goes on.

def nibble source · line 686 · raw

@+n:U32 -> Char

def hex.go source · line 689 · raw

@n:Nat -> @r:Pair(Array<U32>, U32) -> @+i:U32 -> @acc:String -> String

def to_hex source · line 698 · raw

@b:Bytes -> String

Two lowercase hex digits per byte.

def in source · line 702 · raw

@+lo:U32 -> @+c:U32 -> @+hi:U32 -> Bool

def unnibble source · line 706 · raw

@+c:U32 -> U32

A hex digit's value, or 16.

def poke.when source · line 709 · raw

@write:Bool -> @a:Array<U32> -> @+i:U32 -> @+v:U32 -> Array<U32>

def unhex.go source · line 717 · raw

@s:String -> @a:Array<U32> -> @+i:U32 -> @+hi:U32 -> @+ok:Bool -> Pair(Array<U32>, Bool)

hi is the previous digit; an odd i completes a byte.

def decoded source · line 725 · raw

@+n:U32 -> @r:Pair(Array<U32>, Bool) -> Maybe<&1, Bytes>

def unhex.if source · line 733 · raw

@even:Bool -> @+s:String -> @+n:U32 -> Maybe<&1, Bytes>

def from_hex source · line 741 · raw

@+s:String -> Maybe<&1, Bytes>

Hex digits, either case, to bytes. None for an odd count or a non-hex char.

def b64.char source · line 746 · raw

@+i:U32 -> U32

RFC 4648 §4: the standard alphabet, padded with '='.

def b64.at source · line 750 · raw

@+v:U32 -> @+k:Nat -> Char

The six bits of v at k as a base64 char.

def b64.go source · line 754 · raw

@n:Nat -> @r:Pair(Array<U32>, U32) -> @+i:U32 -> @acc:String -> String

Groups of three bytes, last first; r holds the 24 bits of the group at i.

def b64.tail source · line 764 · raw

@+rem:U32 -> @+t:U32 -> @+q:U32 -> @r:Pair(Array<U32>, U32) -> String

The rem < 3 bytes after the last whole group, then the groups before them.

def to_base64 source · line 772 · raw

@b:Bytes -> String

Base64 (RFC 4648 §4) with '=' padding.

def b64.val source · line 779 · raw

@+c:U32 -> U32

A base64 char's value, 64 for '=', or 65.

def b64.pads source · line 783 · raw

@s:String -> @+run:U32 -> U32

The count of '=' at the end of s.

def b64.put source · line 791 · raw

@full:Bool -> @a:Array<U32> -> @+o:U32 -> @+w:U32 -> @+v:U32 -> Array<U32>

A whole group of four chars writes its bytes at o, as many as fit before len.

def unb64.go source · line 799 · raw

@s:String -> @a:Array<U32> -> @+i:U32 -> @+v:U32 -> @+ok:Bool -> @+len:U32 -> @+body:U32 -> Pair(Array<U32>, Bool)

v collects six bits per char. '=' is allowed only at body and after.

def unb64.if source · line 816 · raw

@ok:Bool -> @+s:String -> @+n:U32 -> @+pads:U32 -> Maybe<&1, Bytes>

def from_base64 source · line 826 · raw

@+s:String -> Maybe<&1, Bytes>

Padded base64 (RFC 4648 §4) to bytes. None for a length that is not a multiple of 4, more than two '=', '=' before the end, or a char outside the alphabet.