moonbase

API Reference

Every public type, function, method and value in moonbase, grouped by package. Signatures come from pkg.generated.mbti; the notes come from the /// doc-comments in the sources.

@moonbase

The positional base-N core, the error types and the streaming engine. Every other package is a table of digits on top of this one.

struct
struct Alphabet

An ordered set of digit characters defining a positional numeral system. The character at index i is the digit of value i, so the first character is always the zero digit. Build one with [Alphabet::new] and hand it to [encode] / [decode]; the base58 and base62 packages are thin wrappers that pin a specific alphabet.

function
fn Alphabet::base(Self) -> Int32

The radix of this alphabet — the number of distinct digits.

function
fn Alphabet::char_of(Self, Int32) -> Char

The character for digit value v, where 0 <= v < base.

function
fn Alphabet::new(String) -> Self raise BadAlphabet

Build an [Alphabet] from its ordered digit characters, e.g. Alphabet::new("0123456789abcdef") for lowercase hexadecimal. Fails rather than aborts: an alphabet often comes from configuration, and a library has no business killing the program over a value it was handed.

function
fn Alphabet::of(String) -> Self

An alphabet written as a literal in source, where a mistake is a programming error rather than bad input. This is the one place the library still aborts: new exists for alphabets that arrive at runtime, and this one for the six that ship with the library and are covered by its tests.

function
fn Alphabet::value_of(Self, Char) -> Int32?

The digit value of c in this alphabet, or None if c is not one of its characters.

error
suberror BadAlphabet
NotAscii(at~ : Int32, char~ : Char)
Repeated(at~ : Int32, char~ : Char)
TooFew(count~ : Int32)

Why an alphabet could not be built. Separate from [Malformed] on purpose: a malformed input is the caller's data, a malformed alphabet is the caller's code.

error
suberror Malformed
Bad(at~ : Int32, char~ : Char)
Truncated(at~ : Int32)
Padding(at~ : Int32)
Checksum(at~ : Int32)

Why a string could not be decoded, and where. Decoding fails for four reasons and each of them names the offending index, because "it did not decode" is not enough to fix a malformed document. The old spelling returned None and said nothing; callers who only want that much can still write try? decode(s).

struct
struct Sink

A streaming encoder: bytes go in a chunk at a time, text comes out as it is produced. The one-shot [encode] needs the whole payload before it starts, which is fine for a token and wrong for a file or a socket. A Sink carries the half-finished character between chunks, so feeding b"foo" then b"bar" gives the same string as feeding b"foobar" — the tests check that against random splits, not just the obvious one. ``moonbit nocheck let sink = @base64.sink() sink.write(b"foo"[:]) sink.write(b"bar"[:]) sink.finish() // "Zm9vYmFy" ` This is the bit-packing engine, so it serves base2, base8, base16, base32, base45, base64 and base85, each of which decides its next character from the next few bits. The positional encodings (base10, base36, base58, base62) have no streaming face at all, and that is a decision rather than an omission: they read the payload as one big-endian integer, so the first digit of the answer depends on the last byte of the input. Nothing could be emitted before the whole payload had arrived, which is what [encode](#encode) already waits for. A face that only ever emitted at finish would add a name, not a capability, so those four take a whole value through encode_big / decode_big`.

function
fn Sink::drain(Self) -> String

Take what has been produced so far and forget it, for a caller writing to a socket who does not want to hold the whole output in memory. The half-finished character stays behind, so the next [write](#write) picks up where this one stopped.

function
fn Sink::finish(Self) -> String

Close the sink: flush the trailing bits, add the padding, and return everything that has not been drained yet. The trailing partial group is shifted up and filled with zero bits, exactly as the one-shot encoder does it. Writing after this call is a mistake with no defined result.

function
fn Sink::new(Int32, Array[Char], Bool) -> Self

A sink that emits one character per bits bits, drawn from digits. padding fills the last group with =, the way RFC 4648 does; the encodings that do not pad pass false.

function
fn Sink::write(Self, BytesView) -> Unit

Feed the next chunk. Nothing is emitted until there are enough bits for a whole character, so a chunk may produce no output at all.

struct
struct Source

A streaming decoder: text goes in a chunk at a time, bytes come out. The mirror of [Sink]. A character may straddle two chunks, so the decoder keeps the bits it cannot yet turn into a byte; and because it remembers how many characters it has seen, a failure found in the third chunk still names the index it would have had if the whole input had arrived at once.

function
fn Source::drain(Self) -> Bytes

Take the bytes decoded so far and forget them.

function
fn Source::finish(Self) -> Bytes raise Malformed

Close the source and return every byte that has not been drained. Fails if the input ends in the middle of a group — a whole character that cannot become a byte — with the same [Truncated](#Truncated) the one-shot decoder raises.

function
fn Source::new(Int32, Array[Int32], Bool) -> Self

A source that reads one character per bits bits out of lookup. lossy skips anything outside the alphabet instead of failing, the way [decode_lossy](#decode_lossy) does.

function
fn Source::write(Self, StringView) -> Unit raise Malformed

Feed the next chunk of text. Fails at the first character that is not in the alphabet, naming the index it has in the whole input rather than in the chunk.

function
fn decode(StringView, Alphabet) -> Bytes raise Malformed

Decode a string over alphabet back to the original bytes. Fails at the first character outside the alphabet, naming where it was. Round-trips with [encode].

function
fn decode_big(StringView, Alphabet) -> @bigint.BigInt raise Malformed

Read a whole number of any size in this base. Fails at the first character outside the alphabet, naming where it was, the same way [decode_int](#decode_int) does.

function
fn decode_bytes(BytesView, Alphabet) -> Bytes raise Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_int(StringView, Alphabet) -> UInt64 raise Malformed

Read a whole number in this base.

function
fn decode_lossy(StringView, Alphabet) -> Bytes

Decode, skipping anything outside the alphabet. Never fails, which is what a payload wrapped in newlines or punctuation needs. What it cannot do is tell you the input was wrong.

function
fn encode(BytesView, Alphabet) -> String

Encode raw bytes to a string over alphabet. Leading zero bytes map to leading zero-digit characters; the rest is read as a big-endian integer and rewritten in the target base. Round-trips with [decode].

function
fn encode_big(@bigint.BigInt, Alphabet) -> String

Write a whole number of any size in this base. [encode_int](#encode_int) stops at a UInt64, which is where most ids stop too — but a hash, a committee size or a Snowflake-style identifier is wider than that, and a positional encoding has no reason to be. Like encode_int this keeps no leading zeros: a number has none to keep. A sign is not part of any alphabet here, so a negative value is encoded as its magnitude. Ask with value.compare_int(0) first if the sign can vary.

function
fn encode_bytes(BytesView, Alphabet) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn encode_int(UInt64, Alphabet) -> String

Write a whole number in this base, without the leading-zero rule that the byte-oriented faces keep.

@base2

One bit a character — the multibase `0` prefix. Eight characters a byte, so no chunk ever waits and no padding exists.

function
fn decode(StringView) -> Bytes raise @moonbase.Malformed

Decode binary back to bytes. Fails at the first character that is not 0 or 1, or when the length is not a multiple of eight.

function
fn decode_bytes(BytesView) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_lossy(StringView) -> Bytes

Decode, skipping anything that is not a bit — the spaces in a hand-written bit string, the newlines in a wrapped one.

function
fn encode(BytesView) -> String

Encode bytes as binary, one bit a character. Eight characters per byte, most significant bit first. There is nothing to choose and nothing to pad: b"\xb5" is "10110101".

function
fn encode_bytes(BytesView) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn sink() -> @moonbase.Sink

A streaming encoder: feed bytes in pieces, get the bits as they are produced.

function
fn source(lossy? : Bool) -> @moonbase.Source

A streaming decoder.

@base8

Three bits a character, eight characters to three bytes — the multibase `7` prefix, which is a bit packing and not an octal of a number.

function
fn decode(StringView) -> Bytes raise @moonbase.Malformed

Decode octal back to bytes. Fails at the first character outside 0–7, or when the length cannot be a whole number of bytes.

function
fn decode_bytes(BytesView) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_lossy(StringView) -> Bytes

Decode, skipping anything outside the alphabet — chmod-style punctuation, spaces between groups.

function
fn encode(BytesView) -> String

Encode bytes as octal, three bits a character. Three bytes make eight characters, so the tail of a payload that is not a multiple of three is shifted up and filled with zero bits — 11 bytes become 30 characters, not 29⅓. There is no padding character: nothing in base8 needs one, because the length alone says where the tail starts.

function
fn encode_bytes(BytesView) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn sink() -> @moonbase.Sink

A streaming encoder: feed bytes in pieces, get the digits as they are produced.

function
fn source(lossy? : Bool) -> @moonbase.Source

A streaming decoder.

@base10

Decimal, the multibase `9` prefix: the bytes read as one big-endian integer, so a leading zero byte is a leading `0`.

value
let alphabet : @moonbase.Alphabet

The alphabet this encoding pins: the ten digits, in order.

function
fn decode(StringView) -> Bytes raise @moonbase.Malformed

Decode decimal back to bytes. Fails at the first character that is not a digit, naming where it was.

function
fn decode_big(StringView) -> @bigint.BigInt raise @moonbase.Malformed

Read a whole number of any size in decimal.

function
fn decode_bytes(BytesView) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_int(StringView) -> UInt64 raise @moonbase.Malformed

Read a whole number in decimal.

function
fn decode_lossy(StringView) -> Bytes

Decode, skipping anything that is not a digit — the separators in a written out number.

function
fn encode(BytesView) -> String

Encode bytes as decimal. The payload is read as one big-endian integer, so a leading zero byte becomes a leading 0 and b"\x00\x00\x01" is "0001".

function
fn encode_big(@bigint.BigInt) -> String

Write a whole number of any size in decimal.

function
fn encode_bytes(BytesView) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn encode_int(UInt64) -> String

Write a whole number in decimal. Unlike the byte faces this has no leading-zero rule, because a number has no leading zeros to keep.

@base16

RFC 4648 hexadecimal — byte-oriented, two characters per byte, with a colon form for fingerprints.

enum
enum Kind
Lower
Upper

Which case the digits are written in. Decoding accepts either whatever this says, since a hexadecimal document written by someone else is as likely to be upper case as lower.

function
fn decode(StringView) -> Bytes raise @moonbase.Malformed

Decode hexadecimal, in either case. Fails at the first character that is not a hexadecimal digit, or when the length is odd.

function
fn decode_bytes(BytesView) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_lossy(StringView) -> Bytes

Decode, skipping anything that is not a hexadecimal digit — colons in a fingerprint, spaces in a hex dump, newlines in a dump of a key.

function
fn encode(BytesView, kind? : Kind) -> String

Encode bytes as hexadecimal (RFC 4648 §8). Each byte becomes exactly two characters, so a leading 0x00 stays "00" — unlike a big-integer conversion, which drops leading zeros.

function
fn encode_bytes(BytesView, kind? : Kind) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn encode_colons(BytesView, kind? : Kind) -> String

Encode with a colon between every byte, the spelling certificate fingerprints and MAC addresses are written in.

function
fn sink(kind? : Kind) -> @moonbase.Sink

A streaming encoder: one byte is two characters, so no chunk ever has to wait for the next one.

function
fn source(lossy? : Bool) -> @moonbase.Source

A streaming decoder. The nibble that straddles two chunks is carried, so a chunk need not end on a byte boundary.

@base32

RFC 4648 base32 (A-Z2-7) and the extended-hex base32hex (0-9A-V), plus Crockford's human-oriented alphabet and z-base-32.

enum
enum Kind
Std
Hex
Crockford
Z

Which alphabet: the ordinary one, the extended-hex one whose characters sort in the same order as the bytes they encode, Crockford's, or z-base-32's.

function
fn decode(StringView, kind? : Kind, padding? : Bool, strict? : Bool) -> Bytes raise @moonbase.Malformed

Decode base32. Trailing = is optional; a character outside the alphabet or a length that cannot be a whole number of bytes fails, naming where. Both cases are accepted whatever kind says, and kind=Crockford also accepts the letters its specification aliases: O reads as zero, I and L as one. padding says whether trailing = must be there (true) or must not (false); left out, either is read. strict refuses what the default tolerates: an incomplete run of =, and spare bits after the last byte that are not zero (RFC 4648 §3.5). Together they accept exactly the one spelling encode writes, which is what a format that compares or signs the text needs.

function
fn decode_bytes(BytesView, kind? : Kind, padding? : Bool, strict? : Bool) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_lossy(StringView, kind? : Kind) -> Bytes

Decode, skipping anything outside the alphabet — newlines, spaces, the punctuation a wrapped document picks up.

function
fn encode(BytesView, kind? : Kind, padding? : Bool) -> String

Encode bytes as base32 (RFC 4648 §6, or §7 with kind=Hex). Five bits a character, padded to a multiple of eight unless told otherwise. kind=Crockford and kind=Z are never padded: neither specification has a padding character, so the padding argument has no effect on them.

function
fn encode_bytes(BytesView, kind? : Kind, padding? : Bool) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn sink(kind? : Kind, padding? : Bool) -> @moonbase.Sink

A streaming encoder of the same encoding, for a payload that arrives in pieces. Feeding it chunk by chunk gives the same string as [encode].

function
fn source(kind? : Kind, lossy? : Bool) -> @moonbase.Source

A streaming decoder of the same encoding.

@base36

Case-insensitive 0-9a-z over the base-N core, with an integer mode.

enum
enum Kind
Lower
Upper

Which case the digits are written in.

value
let alphabet : @moonbase.Alphabet

The lower-case alphabet, which is the one everything defaults to.

value
let alphabet_upper : @moonbase.Alphabet

The upper-case alphabet.

function
fn decode(StringView, kind? : Kind) -> Bytes raise @moonbase.Malformed

Decode back to bytes. Fails at the first character outside the alphabet, naming where it was.

function
fn decode_bytes(BytesView, kind? : Kind) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_int(StringView, kind? : Kind) -> UInt64 raise @moonbase.Malformed

Read a whole number in this base.

function
fn decode_lossy(StringView, kind? : Kind) -> Bytes

Decode, skipping anything outside the alphabet.

function
fn encode(BytesView, kind? : Kind) -> String

Encode bytes. Leading zero bytes become leading zero digits; the rest is read as one big-endian integer and rewritten in this base.

function
fn encode_bytes(BytesView, kind? : Kind) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn encode_int(UInt64, kind? : Kind) -> String

Write a whole number in this base. Unlike the byte faces, this one has no leading-zero rule: a number has no leading zeros to preserve.

@base45

RFC 9285: two bytes in three characters from the 45 that a QR code's alphanumeric mode can hold, with no padding at all.

struct
struct Sink

A streaming encoder: bytes go in two at a time, three characters come out. A chunk may end on an odd byte; that byte waits for the next chunk rather than being encoded early, so the output is the same as feeding the whole payload at once.

function
fn Sink::drain(Self) -> String

Take what has been produced so far and forget it.

function
fn Sink::finish(Self) -> String

Close the sink: write the odd trailing byte as two digits, if there is one.

function
fn Sink::new() -> Self

A sink that takes the payload a chunk at a time. A pair split across two write calls is joined before it becomes three characters, which is the whole reason the type exists.

function
fn Sink::write(Self, BytesView) -> Unit

Feed the next chunk.

struct
struct Source

A streaming decoder: characters go in, bytes come out. Three characters are one group, so up to two wait for the next chunk. The index in a failure is the one it has in the whole input, not in the chunk.

function
fn Source::drain(Self) -> Bytes

Take the bytes decoded so far and forget them.

function
fn Source::finish(Self) -> Bytes raise @moonbase.Malformed

Close the source and return every byte that has not been drained. Two characters left over are one byte; one character left over is a failure, the same [Truncated](#Truncated) the one-shot decoder raises.

function
fn Source::new() -> Self

A source that takes the string a chunk at a time. A triplet split across two write calls is joined before it becomes two bytes, and a failure names the index in the whole input rather than in the chunk.

function
fn Source::write(Self, StringView) -> Unit raise @moonbase.Malformed

Feed the next chunk.

function
fn decode(StringView) -> Bytes raise @moonbase.Malformed

Decode base45 back to bytes. Fails at a character outside the alphabet, at a length that ends one character short of a group, and at a three-digit group that is larger than 65535 — RFC 9285 §6 requires that last one, because GGW would otherwise decode to a number that does not fit in the two bytes it claims.

function
fn decode_bytes(BytesView) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_lossy(StringView) -> Bytes

Decode, skipping anything outside the alphabet — the line breaks a QR payload picks up when it is pasted.

function
fn encode(BytesView) -> String

Encode bytes as base45 (RFC 9285 §4). Two bytes are one number below 65536 and are written as three digits in base 45, least significant first. An odd trailing byte is written as two digits, because base45 has no padding character to reach for.

function
fn encode_bytes(BytesView) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn sink() -> Sink

A streaming encoder of this encoding.

function
fn source() -> Source

A streaming decoder of this encoding.

@base58

The Bitcoin, Flickr and Ripple alphabets over the base-N core — 0, O, I and l left out so a string survives being read aloud — and base58check.

enum
enum Kind
Bitcoin
Flickr
Ripple

Which of the three base58 alphabets is in use. All three leave out the characters a reader confuses — no 0, O, I or l — but they put the rest in a different order, so a string from one is not a string from another. Bitcoin's came first; Flickr reordered it to keep upper case out of the way of a URL; Ripple put the characters it uses most where the digits go.

value
let alphabet : @moonbase.Alphabet

The Bitcoin alphabet, which is also the one multibase calls base58btc.

value
let alphabet_flickr : @moonbase.Alphabet

The Flickr alphabet, which multibase calls base58flickr.

value
let alphabet_ripple : @moonbase.Alphabet

The Ripple alphabet.

function
fn decode(StringView, kind? : Kind) -> Bytes raise @moonbase.Malformed

Decode back to bytes. Fails at the first character outside the alphabet, naming where it was.

function
fn decode_big(StringView, kind? : Kind) -> @bigint.BigInt raise @moonbase.Malformed

Read a whole number of any size in this base.

function
fn decode_bytes(BytesView, kind? : Kind) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_check(StringView, kind? : Kind) -> Bytes raise @moonbase.Malformed

Decode the same form, checking the four-byte checksum on the way out. A checksum that does not match raises [Checksum](#Checksum) at the index the payload ends at — the whole string is a candidate for the error, and that is where the disagreement starts. Anything shorter than four bytes cannot carry a checksum at all and is [Truncated](#Truncated).

function
fn decode_int(StringView, kind? : Kind) -> UInt64 raise @moonbase.Malformed

Read a whole number in this base.

function
fn decode_lossy(StringView, kind? : Kind) -> Bytes

Decode, skipping anything outside the alphabet.

function
fn encode(BytesView, kind? : Kind) -> String

Encode bytes. Leading zero bytes become leading zero digits; the rest is read as one big-endian integer and rewritten in this base.

function
fn encode_big(@bigint.BigInt, kind? : Kind) -> String

Write a whole number of any size in this base.

function
fn encode_bytes(BytesView, kind? : Kind) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn encode_check(BytesView, kind? : Kind) -> String

Encode with a checksum: the payload, then the first four bytes of SHA-256(SHA-256(payload)), all in base58. This is what a Bitcoin address is (§4.5 of the Bitcoin book): the checksum is there so that a typo in a 34-character address is caught before it becomes a payment to nowhere. It is not a signature — anyone can produce a valid one.

function
fn encode_int(UInt64, kind? : Kind) -> String

Write a whole number in this base. Unlike the byte faces, this one has no leading-zero rule: a number has no leading zeros to preserve.

@base62

URL-safe 0-9A-Za-z over the base-N core, with an integer mode.

value
let alphabet : @moonbase.Alphabet

The alphabet this encoding pins.

function
fn decode(StringView) -> Bytes raise @moonbase.Malformed

Decode back to bytes. Fails at the first character outside the alphabet, naming where it was.

function
fn decode_bytes(BytesView) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_int(StringView) -> UInt64 raise @moonbase.Malformed

Read a whole number in this base.

function
fn decode_lossy(StringView) -> Bytes

Decode, skipping anything outside the alphabet.

function
fn encode(BytesView) -> String

Encode bytes. Leading zero bytes become leading zero digits; the rest is read as one big-endian integer and rewritten in this base.

function
fn encode_bytes(BytesView) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn encode_int(UInt64) -> String

Write a whole number in this base. Unlike the byte faces, this one has no leading-zero rule: a number has no leading zeros to preserve.

@base64

RFC 4648 standard (+/) and URL-safe (-_) base64.

enum
enum Kind
Std
Url

Which alphabet: the ordinary one, or the URL-safe one that trades +/ for -_ so the result survives a query string and a file name.

function
fn decode(StringView, kind? : Kind, padding? : Bool, strict? : Bool) -> Bytes raise @moonbase.Malformed

Decode base64. Trailing = is optional; a character outside the alphabet or an impossible length fails, naming where. padding says whether trailing = must be there (true) or must not (false); left out, either is read. strict refuses what the default tolerates: an incomplete run of =, and spare bits after the last byte that are not zero (RFC 4648 §3.5). Together they accept exactly the one spelling encode writes, which is what a format that compares or signs the text needs.

function
fn decode_any(StringView) -> Bytes raise @moonbase.Malformed

Decode either alphabet at once, for input whose spelling is not known in advance: -_ and +/ are accepted together, since no encoding uses both.

function
fn decode_bytes(BytesView, kind? : Kind, padding? : Bool, strict? : Bool) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_lossy(StringView, kind? : Kind) -> Bytes

Decode, skipping anything outside the alphabet — the newlines in a PEM body, the whitespace in a pasted token.

function
fn encode(BytesView, kind? : Kind, padding? : Bool) -> String

Encode bytes as base64 (RFC 4648 §4, or §5 with kind=Url). A JWT wants kind=Url, padding=false; an HTTP Basic credential wants the defaults.

function
fn encode_bytes(BytesView, kind? : Kind, padding? : Bool) -> Bytes

The same encoding, as the ASCII bytes it would be written with — what an HTTP header or a gRPC metadata value actually holds.

function
fn sink(kind? : Kind, padding? : Bool) -> @moonbase.Sink

A streaming encoder: three bytes are four characters, so up to two bytes wait for the next chunk and the total is the same at any chunking.

function
fn source(kind? : Kind, lossy? : Bool) -> @moonbase.Source

A streaming decoder. Up to three characters wait for the next chunk; a failure names the index in the whole input, not in the chunk.

@base85

Adobe's Ascii85, ZeroMQ's Z85 (RFC 32) and the IPv6 spelling of RFC 1924 — four bytes in five characters, three ways.

enum
enum Kind
Ascii85
Z85
Ipv6

Which of the three base85 spellings is in use. Ascii85 is Adobe's: it lives inside PostScript and PDF, writes a group of four zero bytes as a single z, and lets the last group be short. Z85 is ZeroMQ's (RFC 32): the same five-for-four arithmetic over an alphabet safe to put inside a string literal, but with no shortcuts, so the length must be a multiple of four. Ipv6 is RFC 1924's: the input is one 128-bit number, not a run of four-byte groups.

struct
struct Sink

A streaming encoder: four bytes are written as five characters, so up to three bytes wait for the next chunk. kind=Ipv6 reads its input as one number and therefore buffers the whole payload.

function
fn Sink::drain(Self) -> String

Take what has been produced so far and forget it.

function
fn Sink::finish(Self) -> String raise @moonbase.Malformed

Close the sink: write the trailing short group, or, for Ipv6, encode the whole payload now that there is one.

function
fn Sink::new(Kind) -> Self

A sink that takes the payload a chunk at a time, in the given alphabet. A group split across two write calls is joined before it becomes five characters.

function
fn Sink::write(Self, BytesView) -> Unit

Feed the next chunk.

struct
struct Source

A streaming decoder: five characters are four bytes; a partial group waits. kind=Ipv6 buffers the whole input, because the number is only known once the last digit has arrived.

function
fn Source::drain(Self) -> Bytes

Take the bytes decoded so far and forget them.

function
fn Source::finish(Self) -> Bytes raise @moonbase.Malformed

Close the source and return every byte that has not been drained.

function
fn Source::new(Kind) -> Self

A source that takes the string a chunk at a time, in the given alphabet. A group split across two write calls is joined before it becomes four bytes.

function
fn Source::write(Self, StringView) -> Unit raise @moonbase.Malformed

Feed the next chunk of text.

function
fn decode(StringView, kind? : Kind) -> Bytes raise @moonbase.Malformed

Decode base85 back to bytes. Ascii85 accepts z for a zero group and a short final group; Z85 requires a length that is a multiple of five; Ipv6 reads a 128-bit number and always gives back sixteen bytes.

function
fn decode_bytes(BytesView, kind? : Kind) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_lossy(StringView, kind? : Kind) -> Bytes

Decode, skipping anything outside the alphabet — the newlines Adobe wraps a PostScript stream with, the spaces in a pasted string.

function
fn encode(BytesView, kind? : Kind) -> String raise @moonbase.Malformed

Encode bytes as base85. Fails only for the two kinds that know how long their input is: Z85 with a length that is not a multiple of four, because ZeroMQ's frame is four bytes and it defines no short tail; and Ipv6 with a length that is not sixteen, because RFC 1924 is about addresses. Ascii85 shortens its last group instead, so it encodes whatever it is given.

function
fn encode_bytes(BytesView, kind? : Kind) -> Bytes raise @moonbase.Malformed

The same encoding, as the ASCII bytes it would be written with.

function
fn sink(kind? : Kind) -> Sink

A streaming encoder of this encoding.

function
fn source(kind? : Kind) -> Source

A streaming decoder of this encoding.

@bech32

BIP 173's bech32 and BIP 350's bech32m: a human-readable prefix, five-bit groups, and a BCH checksum that the two variants do not share.

struct
struct Decoded

A bech32 string taken apart: the prefix a human reads, and the data a machine reads.

enum
enum Kind
Bech32
Bech32m

Which checksum: the one BIP 173 defined, or the one BIP 350 amended it to. They are the same code with a different constant folded in at the end, so the two families of strings do not overlap: a string that verifies as one never verifies as the other. A witness version-0 output is bech32, everything from version 1 up is bech32m. A format that has never used bech32 at all — a lightning invoice, say — picks bech32m, because the amendment is the one that does not have the insertion weakness.

struct
struct Words

The same, before the five-bit groups have been turned back into bytes. This is the layer the specification actually defines: BIP 173 checksums the five-bit groups, and a string whose data is not a whole number of bytes is a perfectly valid bech32 string — abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw is one. Turning the groups into bytes is a separate, stricter step that a checksum verifier has no business doing.

function
fn bytes_of(BytesView) -> Bytes raise @moonbase.Malformed

Five-bit groups back to bytes, strictly. The leftover bits of the last partial byte must be fewer than five and all zero: a decoder that ignores them accepts four different strings for one payload, which is a malleability bug rather than a convenience.

function
fn decode(StringView, kind? : Kind) -> Decoded raise @moonbase.Malformed

Decode a bech32 string to the bytes its data part stands for. Fails if the checksum does not match, if the data does not fill whole bytes, or if the padding that completes the last byte is not zero. A segregated witness address does not fill whole bytes — its first group is a version, not the top of the program — so it fails here with [Padding](#Padding) and belongs in [decode_words](#decode_words). That is a property of addresses; bech32 itself never promised its data would be bytes.

function
fn decode_bytes(BytesView, kind? : Kind) -> Decoded raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_lossy(StringView, kind? : Kind) -> Decoded?

Decode, dropping the whitespace a pasted address picks up on the way. None rather than a failure, because this face is for input whose quality is already in doubt: a caller who wants to know what was wrong should use [decode](#decode).

function
fn decode_words(StringView, kind? : Kind) -> Words raise @moonbase.Malformed

Decode to five-bit groups without turning them into bytes. This is the check BIP 173 specifies: length, character range, one case throughout, a separator, at least six checksum characters, and a checksum that matches the constant of kind.

function
fn encode(StringView, BytesView, kind? : Kind) -> String raise @moonbase.Malformed

Encode bytes as a bech32 string. ``moonbit nocheck @bech32.encode("bc", program) // "bc1q…" @bech32.encode("tb", program, kind=Bech32m) ` The bytes are written as five-bit groups, zero-padded to a whole group, which is the same 1/2/3 to 2/4/5/7/8` expansion base32 does — the difference is that bech32 pads nothing back on the way in and puts a checksum on the end instead. The prefix is written lower case whatever case it arrives in: a bech32 string is either all lower case or all upper case, never both, and the checksum is computed over the lower-case form.

function
fn encode_bytes(StringView, BytesView, kind? : Kind) -> Bytes raise @moonbase.Malformed

The same encoding, as the ASCII bytes it would be written with.

function
fn encode_words(StringView, BytesView, kind? : Kind) -> String raise @moonbase.Malformed

Encode five-bit groups directly, for a format that has words of its own — a segregated witness program carries its version as a group, not as a byte.

function
fn words_of(BytesView) -> Bytes

Eight-bit bytes to five-bit groups, zero-padded, as bech32's data part wants.

@multibase

Multiformats' self-identifying encodings: a one-character prefix in front of any of the above, from `0` for base2 to a rocket for base256emoji.

enum
enum Base
Base2
Base8
Base10
Base16
Base16Upper
Base32Hex
Base32HexUpper
Base32HexPad
Base32HexPadUpper
Base32
Base32Upper
Base32Pad
Base32PadUpper
Base32Z
Base36
Base36Upper
Base45
Base58Btc
Base58Flickr
Base64
Base64Pad
Base64Url
Base64UrlPad
Base256Emoji

Every encoding in multibase's table that this module can write, named after the table's encoding column. The spellings that differ only in case are separate entries because the prefix differs: f and F are both hexadecimal, and a decoder has to know which one it was handed in order to write it back the same way. base256emoji is in the table too, even though a character standing for a byte is not a base at all in the bit-packing sense.

function
fn decode(StringView) -> Bytes raise @moonbase.Malformed

Decode a string whose first character says how the rest is encoded. The failure positions count from the start of the whole string, prefix included, so an error index can be used to point at the input the caller actually has.

function
fn decode_bytes(BytesView) -> Bytes raise @moonbase.Malformed

Decode from ASCII bytes, for callers who never had a string.

function
fn decode_lossy(StringView) -> Bytes

Decode, dropping the whitespace a pasted string picks up on the way.

function
fn detect(StringView) -> Base?

Which encoding a string claims to be in, without decoding it.

function
fn encode(BytesView, base? : Base) -> String

Encode bytes with a prefix in front that says which encoding was used. ``moonbit nocheck @multibase.encode(b"yes mani !") // "z7paNL19xttacUY" @multibase.encode(b"yes mani !", base=Base16) // "f796573206d616e692021" ``

function
fn encode_bytes(BytesView, base? : Base) -> Bytes

The same encoding, as the ASCII bytes it would be written with.

function
fn name(Base) -> String

The name multibase's table gives this encoding, for a message or a table cell.

function
fn of_prefix(Char) -> Base?

The encoding a prefix stands for, or None if this module does not write it. NUL, 1, Q and / are reserved by the table and are not encodings; p is proquint, which is a word encoding rather than a base, and is the one entry left out.

function
fn prefix(Base) -> Char

The prefix that identifies base, which is the one character a multibase string starts with.