4.3 KiB
4.3 KiB
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
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
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:
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:
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
// 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
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
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
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)
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 calcSizeForSlicegives exact size;calcSizeUpperBoundgives max (ignores padding)- Base64 operates on byte slices; integer endianness is not part of its public contract