std.base64 em Zig — Referência e Exemplos

std.base64 — Codificação e Decodificação Base64

O módulo std.base64 oferece codificação e decodificação Base64 conforme as RFCs 4648 e 2045. Base64 é amplamente utilizado para representar dados binários em formato texto — em cabeçalhos HTTP, tokens JWT, codificação de imagens inline, transferência de dados em APIs e muito mais. O Zig oferece implementações tanto para o alfabeto padrão quanto para o URL-safe.

Visão Geral

const std = @import("std");
const base64 = std.base64;

Variantes Disponíveis

// Base64 padrão (RFC 4648 §4)
const standard = base64.standard;

// Base64 URL-safe (RFC 4648 §5) — usa '-' e '_' em vez de '+' e '/'
const url_safe = base64.url_safe;

Cada variante oferece sub-variantes com e sem padding:

// Com padding '=' (padrão)
standard.Encoder  // codifica
standard.Decoder  // decodifica

// Sem padding
standard.Encoder.no_pad
standard.Decoder.no_pad

Funções Principais

Codificação

// Calcula o tamanho da saída codificada
pub fn calcSize(source_len: usize) usize

// Codifica para um buffer de destino
pub fn encode(dest: []u8, source: []const u8) []u8

// Retorna o tamanho codificado
pub fn Encoder.calcSize(source_len: usize) usize

Decodificação

// Calcula o tamanho máximo da saída decodificada
pub fn calcSizeForSlice(encoded: []const u8) !usize

// Decodifica para um buffer de destino
pub fn decode(dest: []u8, source: []const u8) ![]u8

Exemplo 1: Codificação e Decodificação Básica

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    const texto = "Olá, Zig! Base64 é útil para codificar dados binários.";

    // Codificação
    const encoder = std.base64.standard.Encoder;
    var buf_encode: [256]u8 = undefined;
    const encoded = encoder.encode(&buf_encode, texto);

    try stdout.print("Original:    {s}\n", .{texto});
    try stdout.print("Base64:      {s}\n", .{encoded});

    // Decodificação
    const decoder = std.base64.standard.Decoder;
    var buf_decode: [256]u8 = undefined;
    const decoded = try decoder.decode(&buf_decode, encoded);

    try stdout.print("Decodificado: {s}\n", .{decoded});
    try stdout.print("Iguais:       {}\n", .{std.mem.eql(u8, texto, decoded)});
}

Exemplo 2: Base64 URL-Safe para Tokens

const std = @import("std");

fn codificarToken(dados: []const u8, buf: []u8) []u8 {
    const encoder = std.base64.url_safe_no_pad.Encoder;
    return encoder.encode(buf, dados);
}

fn decodificarToken(token: []const u8, buf: []u8) ![]u8 {
    const decoder = std.base64.url_safe_no_pad.Decoder;
    return decoder.decode(buf, token);
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // Simula um payload de token
    const payload = "{\"user_id\":42,\"role\":\"admin\",\"exp\":1708560000}";

    var buf_encode: [256]u8 = undefined;
    const token = codificarToken(payload, &buf_encode);

    try stdout.print("Payload:   {s}\n", .{payload});
    try stdout.print("Token:     {s}\n", .{token});

    // Decodifica o token
    var buf_decode: [256]u8 = undefined;
    const decoded = try decodificarToken(token, &buf_decode);
    try stdout.print("Decoded:   {s}\n", .{decoded});

    // Compara standard vs url_safe
    var buf_std: [256]u8 = undefined;
    const std_encoded = std.base64.standard.Encoder.encode(&buf_std, payload);
    try stdout.print("\nStandard:  {s}\n", .{std_encoded});
    try stdout.print("URL-safe:  {s}\n", .{token});
}

Exemplo 3: Codificação de Dados Binários

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const stdout = std.io.getStdOut().writer();

    // Dados binários (bytes arbitrários)
    const dados_binarios = [_]u8{
        0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, // Header PNG
        0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
        0xFF, 0xFE, 0xFD, 0x00, 0x01, 0x02, 0x03, 0x04,
    };

    // Codifica
    const encoder = std.base64.standard.Encoder;
    const tamanho_necessario = encoder.calcSize(dados_binarios.len);

    const encoded = try allocator.alloc(u8, tamanho_necessario);
    defer allocator.free(encoded);
    _ = encoder.encode(encoded, &dados_binarios);

    try stdout.print("Bytes originais: {d}\n", .{dados_binarios.len});
    try stdout.print("Base64 ({d} chars): {s}\n", .{ encoded.len, encoded });

    // Decodifica e verifica
    const decoder = std.base64.standard.Decoder;
    const tamanho_decode = try decoder.calcSizeForSlice(encoded);
    const decoded = try allocator.alloc(u8, tamanho_decode);
    defer allocator.free(decoded);
    const resultado = try decoder.decode(decoded, encoded);

    try stdout.print("Bytes decodificados: {d}\n", .{resultado.len});

    // Mostra como hex
    try stdout.writeAll("Hex: ");
    for (resultado) |byte| {
        try stdout.print("{x:0>2} ", .{byte});
    }
    try stdout.writeAll("\n");

    try stdout.print("Dados iguais: {}\n", .{
        std.mem.eql(u8, &dados_binarios, resultado),
    });
}

Referência Rápida

VarianteAlfabetoPaddingUso Comum
standardA-Z, a-z, 0-9, +, /=Email (MIME), PEM
standard_no_padA-Z, a-z, 0-9, +, /NãoAlgumas APIs
url_safeA-Z, a-z, 0-9, -, _=URLs
url_safe_no_padA-Z, a-z, 0-9, -, _NãoJWT, tokens

Módulos Relacionados

Tutoriais e Receitas Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.