encoding
import encoding from "encoding";
let b: string = encoding.base64_encode("foobar"); // "Zm9vYmFy"
let t: string = encoding.base64url_encode("\xFB\xFF"); // "-_8"
let h: string = encoding.hex_encode("tape"); // "74617065"
let q: string = encoding.percent_encode("a b/ü"); // "a%20b%2F%C3%BC"
let raw: string = encoding.base64_decode(b) or {
io.println("bad base64: {err}");
return 1;
};encoding turns bytes into text and back:
| Encoding | Alphabet | Used for |
|---|---|---|
| base64 | A-Z a-z 0-9 + /, padded with = | binary data in text formats, email, data URLs |
| base64url | A-Z a-z 0-9 - _, no padding | tokens, file names, URLs (JWT) |
| hex | 0-9 a-f | dumps, hashes, IDs |
| percent | unreserved characters kept, everything else %XX | URL paths and query strings |
encoding is a pure module.
Functions
Each encoding has an encoder and a decoder, and each of those comes in two
forms: one returns a new string, the _to one writes into a buffer you
pass and returns how many bytes it wrote (as in fmt).
| Function | Returns |
|---|---|
base64_encode(data), base64_encode_to(dst, data) | base64 text, padded |
base64_decode(s), base64_decode_to(dst, s) | the bytes, or DecodeError |
base64url_encode(data), base64url_encode_to(dst, data) | base64url text, unpadded |
base64url_decode(s), base64url_decode_to(dst, s) | the bytes; padded input is accepted too |
hex_encode(data), hex_encode_to(dst, data) | lowercase hex, two digits per byte |
hex_decode(s), hex_decode_to(dst, s) | the bytes; either case accepted |
percent_encode(s), percent_encode_to(dst, s) | s with every byte but A-Z a-z 0-9 - . _ ~ as %XX |
percent_decode(s), percent_decode_to(dst, s) | s with each %XX turned back into its byte |
Decoded data comes back as a string, tape’s byte buffer: it can hold any
bytes, not just text.
A _to function stops the program with a
trap when the buffer is too small. These
give a size that is always enough:
| Function | Size |
|---|---|
base64_encoded_len(n) | base64 of n bytes: 4 * ceil(n / 3) |
base64url_encoded_len(n) | base64url of n bytes: ceil(4 * n / 3) |
base64_decoded_len(n) | at most this many bytes from n characters of either base64 |
percent_encoded_len(s) | exactly what percent_encode(s) writes |
Hex is 2 * n characters for n bytes; decoding percent-encoding never
gives more bytes than the text has.
var buf: [64]u8;
let n: i64 = encoding.base64_encode_to(buf[..], "id-42");
let text: []const u8 = buf[0..n]; // "aWQtNDI=", no allocationErrors
Decoding is strict: nothing is skipped or guessed, so every byte string has
exactly one accepted encoding. Decoders return DecodeError:
DecodeError | When |
|---|---|
InvalidCharacter | A byte outside the alphabet: a space or line break in base64, + in base64url, g in hex, % without two hex digits |
InvalidLength | A length the encoding can’t produce: base64 not a multiple of 4, an odd number of hex digits |
InvalidPadding | = in the wrong place or too many, or leftover bits that aren’t zero ("Zh==" instead of "Zg==") |
Percent-decoding leaves + alone: it is not a space here (that’s HTML form
encoding). Base64 with line breaks (MIME, PEM) must have them removed
before decoding.
Last modified: