# std.base64 (Zig 0.16.0) Base64 encoding/decoding per RFC 4648. Primary Zig 0.16 release-note source: https://ziglang.org/download/0.16.0/release-notes.html For examples that write encoded output to files/stdout, use `std.Io.Writer` and `std.Io.File.stdout().writer(io, &buf)`. ## Quick Reference | Codec | Use Case | |-------|----------| | `standard` | Standard RFC 4648 Base64 with `=` padding; MIME framing and line wrapping are separate | | `standard_no_pad` | Standard Base64 without padding | | `url_safe` | URL-safe Base64 with `=` padding | | `url_safe_no_pad` | URL-safe Base64 without padding (JWT, URLs) | ## Encoding ```zig const std = @import("std"); const base64 = std.base64; const data = "Hello, World!"; // Standard Base64 (with padding) var buf: [100]u8 = undefined; const encoded = base64.standard.Encoder.encode(&buf, data); // "SGVsbG8sIFdvcmxkIQ==" // URL-safe without padding (common for JWTs) const encoded = base64.url_safe_no_pad.Encoder.encode(&buf, data); // "SGVsbG8sIFdvcmxkIQ" // Calculate required buffer size const size = base64.standard.Encoder.calcSize(data.len); ``` ## Decoding ```zig const encoded = "SGVsbG8sIFdvcmxkIQ=="; // Decode to buffer var buf: [100]u8 = undefined; const decoded_len = try base64.standard.Decoder.calcSizeForSlice(encoded); const decoded = buf[0..decoded_len]; try base64.standard.Decoder.decode(decoded, encoded); // decoded = "Hello, World!" // Calculate max decoded size (before knowing padding) const max_size = try base64.standard.Decoder.calcSizeUpperBound(encoded.len); ``` ## Decoding with Ignored Characters Decode Base64 that contains whitespace or other characters to ignore: ```zig const encoded = "SGVs bG8s\nIFdv cmxk IQ=="; // with spaces and newlines // Create decoder that ignores whitespace const decoder = base64.standard.decoderWithIgnore(" \n"); var buf: [100]u8 = undefined; const max_size = decoder.calcSizeUpperBound(encoded.len); const decoded_len = try decoder.decode(buf[0..max_size], encoded); const decoded = buf[0..decoded_len]; // "Hello, World!" ``` ## Streaming Encoding This fragment assumes a caller-provided `io: std.Io` and `data: []const u8`: ```zig var buf: [4096]u8 = undefined; var writer = std.Io.File.stdout().writer(io, &buf); try base64.standard.Encoder.encodeWriter(&writer.interface, data); try writer.interface.flush(); ``` ## Codecs Detail ```zig // Standard alphabet: A-Z, a-z, 0-9, +, / base64.standard // with = padding base64.standard_no_pad // without padding // URL-safe alphabet: A-Z, a-z, 0-9, -, _ base64.url_safe // with = padding base64.url_safe_no_pad // without padding // Access alphabet characters directly base64.standard_alphabet_chars // [64]u8 base64.url_safe_alphabet_chars // [64]u8 ``` ## Error Handling ```zig base64.standard.Decoder.decode(dest, source) catch |err| switch (err) { error.InvalidCharacter => // character not in alphabet error.InvalidPadding => // incorrect padding error.NoSpaceLeft => // dest buffer too small (DecoderWithIgnore only) }; ``` ## Common Patterns ### Encode binary data for JSON/URLs ```zig fn encodeForUrl(data: []const u8, buf: []u8) []const u8 { std.debug.assert(buf.len >= std.base64.url_safe_no_pad.Encoder.calcSize(data.len)); return std.base64.url_safe_no_pad.Encoder.encode(buf, data); } ``` ### Decode JWT payload ```zig fn decodeJwtPayload(payload: []const u8, buf: []u8) ![]u8 { const decoder = std.base64.url_safe_no_pad.Decoder; const size = try decoder.calcSizeForSlice(payload); try decoder.decode(buf[0..size], payload); return buf[0..size]; } ``` ### Handle multi-line Base64 (PEM format) ```zig fn decodePemBody(base64_body: []const u8, buf: []u8) ![]u8 { // The caller must extract and validate the PEM header/footer first. This // helper only decodes the Base64 body while ignoring line breaks. const decoder = std.base64.standard.decoderWithIgnore("\n\r"); const max = decoder.calcSizeUpperBound(base64_body.len); const len = try decoder.decode(buf[0..max], base64_body); return buf[0..len]; } ``` ## Notes - Standard uses `+` and `/` which need URL encoding - URL-safe uses `-` and `_` which are safe in URLs - Padding (`=`) makes length divisible by 4 - `calcSizeForSlice` gives exact size; `calcSizeUpperBound` gives max (ignores padding) - Base64 operates on byte slices; integer endianness is not part of its public contract