std.compress — Compressão e Descompressão
O módulo std.compress fornece implementações de algoritmos de compressão e descompressão de dados escritas em Zig puro. Ele suporta os formatos mais comuns da web e de sistemas — deflate, gzip, zlib e zstd — permitindo processar arquivos comprimidos, respostas HTTP comprimidas e dados serializados sem dependências externas de C.
Visão Geral
const std = @import("std");
const compress = std.compress;
Algoritmos Disponíveis
| Módulo | Formato | Uso Comum |
|---|---|---|
compress.flate | DEFLATE (RFC 1951) | Formato base para gzip/zlib |
compress.gzip | gzip (RFC 1952) | Arquivos .gz, HTTP |
compress.zlib | zlib (RFC 1950) | PNG, HTTP, protocolos |
compress.zstd | Zstandard | Compressão moderna de alto desempenho |
compress.lzma | LZMA/XZ | Arquivos .xz |
Interface Comum
Todos os descompressores seguem o padrão de Reader do Zig:
// Descompressão: envolvem um Reader e retornam outro Reader
pub fn decompressor(reader: anytype) Decompressor
// Compressão: envolvem um Writer e retornam outro Writer
pub fn compressor(writer: anytype, options: Options) Compressor
Exemplo 1: Compressão e Descompressão com Gzip
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const dados_originais = "Zig é uma linguagem de programação de sistemas " ++
"focada em segurança, desempenho e legibilidade. " ++
"Esta string será comprimida e depois descomprimida " ++
"para demonstrar o módulo std.compress. " ++
"A compressão é especialmente eficaz em textos repetitivos " ++
"como este, onde padrões comuns podem ser aproveitados." ** 3;
const stdout = std.io.getStdOut().writer();
try stdout.print("Dados originais: {d} bytes\n", .{dados_originais.len});
// Comprime com gzip
var buf_comprimido = std.ArrayList(u8).init(allocator);
defer buf_comprimido.deinit();
var compressor = try std.compress.gzip.compressor(buf_comprimido.writer(), .{});
try compressor.writer().writeAll(dados_originais);
try compressor.finish();
try stdout.print("Comprimido: {d} bytes\n", .{buf_comprimido.items.len});
const razao = @as(f64, @floatFromInt(buf_comprimido.items.len)) /
@as(f64, @floatFromInt(dados_originais.len)) * 100.0;
try stdout.print("Razão: {d:.1}%\n", .{razao});
// Descomprime
var stream = std.io.fixedBufferStream(buf_comprimido.items);
var decompressor = std.compress.gzip.decompressor(stream.reader());
var buf_descomprimido = std.ArrayList(u8).init(allocator);
defer buf_descomprimido.deinit();
const decompressor_reader = decompressor.reader();
var tmp: [4096]u8 = undefined;
while (true) {
const n = try decompressor_reader.read(&tmp);
if (n == 0) break;
try buf_descomprimido.appendSlice(tmp[0..n]);
}
try stdout.print("Descomprimido: {d} bytes\n", .{buf_descomprimido.items.len});
try stdout.print("Integridade: {}\n", .{
std.mem.eql(u8, dados_originais, buf_descomprimido.items),
});
}
Exemplo 2: Descompressão de Dados Zlib
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();
// Comprime dados com zlib
const texto = "Dados de exemplo para compressão zlib no Zig!";
var buf_comprimido = std.ArrayList(u8).init(allocator);
defer buf_comprimido.deinit();
var comp = try std.compress.zlib.compressor(buf_comprimido.writer(), .{});
try comp.writer().writeAll(texto);
try comp.finish();
try stdout.print("Original: {d} bytes -> zlib: {d} bytes\n", .{
texto.len,
buf_comprimido.items.len,
});
// Descomprime
var stream = std.io.fixedBufferStream(buf_comprimido.items);
var decomp = std.compress.zlib.decompressor(stream.reader());
var resultado: [256]u8 = undefined;
const reader = decomp.reader();
var total: usize = 0;
while (true) {
const n = try reader.read(resultado[total..]);
if (n == 0) break;
total += n;
}
try stdout.print("Descomprimido: {s}\n", .{resultado[0..total]});
try stdout.print("Correto: {}\n", .{std.mem.eql(u8, texto, resultado[0..total])});
}
Exemplo 3: Compressão Deflate de Baixo Nível
const std = @import("std");
fn comprimirDados(dados: []const u8, allocator: std.mem.Allocator) ![]u8 {
var buf = std.ArrayList(u8).init(allocator);
errdefer buf.deinit();
var comp = try std.compress.flate.compressor(buf.writer(), .{});
try comp.writer().writeAll(dados);
try comp.finish();
return try buf.toOwnedSlice();
}
fn descomprimirDados(comprimido: []const u8, allocator: std.mem.Allocator) ![]u8 {
var stream = std.io.fixedBufferStream(comprimido);
var decomp = std.compress.flate.decompressor(stream.reader());
var buf = std.ArrayList(u8).init(allocator);
errdefer buf.deinit();
var tmp: [4096]u8 = undefined;
const reader = decomp.reader();
while (true) {
const n = try reader.read(&tmp);
if (n == 0) break;
try buf.appendSlice(tmp[0..n]);
}
return try buf.toOwnedSlice();
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const stdout = std.io.getStdOut().writer();
// Testa com diferentes tipos de dados
const testes = [_]struct { nome: []const u8, dados: []const u8 }{
.{ .nome = "Texto repetitivo", .dados = "AAAAAAAAAA" ** 100 },
.{ .nome = "Texto natural", .dados = "O Zig compila para código nativo eficiente." },
.{ .nome = "Dados aleatórios", .dados = "jK8mN2pQ5rT" ** 10 },
};
try stdout.writeAll("=== Benchmark de Compressão (deflate) ===\n\n");
try stdout.print("{s:<25} {s:>8} {s:>10} {s:>8}\n", .{
"Tipo", "Original", "Comprimido", "Razão",
});
for (testes) |teste| {
const comprimido = try comprimirDados(teste.dados, allocator);
defer allocator.free(comprimido);
// Verifica integridade
const descomprimido = try descomprimirDados(comprimido, allocator);
defer allocator.free(descomprimido);
const razao = @as(f64, @floatFromInt(comprimido.len)) /
@as(f64, @floatFromInt(teste.dados.len)) * 100.0;
try stdout.print("{s:<25} {d:>7}B {d:>9}B {d:>6.1}%\n", .{
teste.nome,
teste.dados.len,
comprimido.len,
razao,
});
}
}
Módulos Relacionados
- std.io — Interfaces Reader/Writer
- std.fs — Leitura de arquivos comprimidos
- std.http — Respostas HTTP comprimidas
- std.crypto.hash — Checksums