Introdução
Base64 é um esquema de codificação que converte dados binários em texto ASCII, usando 64 caracteres imprimíveis. É amplamente usado em e-mails (MIME), tokens JWT, incorporação de imagens em HTML e transmissão de dados em APIs. Zig oferece suporte a Base64 na biblioteca padrão via std.base64.
Nesta receita, você aprenderá a codificar e decodificar dados em Base64.
Pré-requisitos
- Zig instalado (versão 0.13+). Veja o guia de instalação
- Conhecimento básico de Zig. Consulte a introdução ao Zig
Codificar para Base64
const std = @import("std");
pub fn main() !void {
const encoder = std.base64.standard.Encoder;
// Codificar string
const texto = "Olá, Zig Brasil!";
var buf: [256]u8 = undefined;
const encoded = encoder.encode(&buf, texto);
std.debug.print("Original: {s}\n", .{texto});
std.debug.print("Base64: {s}\n", .{encoded});
// Codificar bytes arbitrários
const bytes = [_]u8{ 0x00, 0xFF, 0x42, 0x13, 0x37, 0xAB, 0xCD, 0xEF };
var buf2: [256]u8 = undefined;
const encoded2 = encoder.encode(&buf2, &bytes);
std.debug.print("\nBytes: ", .{});
for (bytes) |b| std.debug.print("{X:0>2} ", .{b});
std.debug.print("\nBase64: {s}\n", .{encoded2});
}
Saída esperada
Original: Olá, Zig Brasil!
Base64: T2zDoSwgWmlnIEJyYXNpbCE=
Decodificar de Base64
const std = @import("std");
pub fn main() !void {
const decoder = std.base64.standard.Decoder;
// Decodificar string Base64
const encoded = "T2zDoSwgWmlnIEJyYXNpbCE=";
var buf: [256]u8 = undefined;
const decoded = decoder.decode(&buf, encoded) catch |err| {
std.debug.print("Erro ao decodificar: {}\n", .{err});
return;
};
std.debug.print("Base64: {s}\n", .{encoded});
std.debug.print("Decodificado: {s}\n", .{decoded});
// Decodificar com alocador
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const encoded2 = "SGVsbG8gV29ybGQh";
const calc_len = try decoder.calcSizeForSlice(encoded2);
const decoded_buf = try allocator.alloc(u8, calc_len);
defer allocator.free(decoded_buf);
const resultado = decoder.decode(decoded_buf, encoded2) catch |err| {
std.debug.print("Erro: {}\n", .{err});
return;
};
std.debug.print("\n{s} -> {s}\n", .{ encoded2, resultado });
}
Codificação URL-Safe
A variante URL-safe usa - e _ em vez de + e /:
const std = @import("std");
pub fn main() !void {
const dados = "dados com +/= especiais?sim&outro=valor";
// Codificação padrão
var buf_std: [256]u8 = undefined;
const standard = std.base64.standard.Encoder.encode(&buf_std, dados);
// Codificação URL-safe
var buf_url: [256]u8 = undefined;
const url_safe = std.base64.url_safe.Encoder.encode(&buf_url, dados);
std.debug.print("Original: {s}\n", .{dados});
std.debug.print("Standard: {s}\n", .{standard});
std.debug.print("URL-safe: {s}\n", .{url_safe});
}
Exemplo Prático: Codificar Credenciais HTTP Basic
const std = @import("std");
fn gerarBasicAuth(buf: []u8, usuario: []const u8, senha: []const u8) ![]const u8 {
// Construir "usuario:senha"
var cred_buf: [256]u8 = undefined;
const credenciais = try std.fmt.bufPrint(&cred_buf, "{s}:{s}", .{ usuario, senha });
// Codificar em Base64
const encoder = std.base64.standard.Encoder;
const encoded = encoder.encode(buf, credenciais);
return encoded;
}
pub fn main() !void {
var buf: [256]u8 = undefined;
const auth = try gerarBasicAuth(&buf, "admin", "senha123");
std.debug.print("Authorization: Basic {s}\n", .{auth});
// Verificar decodificando
const decoder = std.base64.standard.Decoder;
var dec_buf: [256]u8 = undefined;
const decoded = try decoder.decode(&dec_buf, auth);
std.debug.print("Decodificado: {s}\n", .{decoded});
}
Calcular Tamanho do Buffer
const std = @import("std");
pub fn main() !void {
const encoder = std.base64.standard.Encoder;
const decoder = std.base64.standard.Decoder;
// Calcular tamanho do encode
const tamanhos = [_]usize{ 1, 3, 10, 100, 1000 };
std.debug.print("{s:>10} {s:>15}\n", .{ "Input", "Base64" });
for (tamanhos) |t| {
const encoded_len = encoder.calcSize(t);
std.debug.print("{d:>10} {d:>15}\n", .{ t, encoded_len });
}
// Calcular tamanho do decode
const encoded = "SGVsbG8gV29ybGQh"; // "Hello World!"
const decoded_len = try decoder.calcSizeForSlice(encoded);
std.debug.print("\n\"{s}\" decodifica para {d} bytes\n", .{ encoded, decoded_len });
}
Dicas e Boas Práticas
Use URL-safe para URLs e tokens: Evita problemas com
+,/e=em URLs.Calcule o tamanho do buffer: Use
calcSizepara alocar o buffer correto.Base64 aumenta o tamanho em ~33%: Cada 3 bytes viram 4 caracteres.
Trate erros de decode: Dados Base64 inválidos causam erros ao decodificar.
Não é criptografia: Base64 é codificação, não encriptação. Os dados são facilmente reversíveis.
Receitas Relacionadas
- Hex Encoding/Decoding - Codificação hexadecimal
- Hashing SHA256/MD5 - Hashing de dados
- HTTP GET Request - Autenticação HTTP
- Formatar Strings com std.fmt - Formatação