gRPC e Protocol Buffers com Zig
gRPC e Protocol Buffers são o padrão para comunicação eficiente entre microserviços. Embora Zig não tenha suporte nativo a gRPC, a interoperabilidade com C permite usar a biblioteca gRPC C Core, e serialização binária pode ser implementada nativamente em Zig com performance superior.
Serialização Binária em Zig
Antes de gRPC, precisamos serializar dados. Zig permite criar serialização binária compacta e eficiente:
const std = @import("std");
/// Serialização binária compatível com Protocol Buffers (simplificada)
fn Serializer(comptime T: type) type {
return struct {
pub fn serializar(valor: T, writer: anytype) !void {
const info = @typeInfo(T);
switch (info) {
.@"struct" => |s| {
inline for (s.fields, 1..) |field, tag| {
try serializarCampo(tag, @field(valor, field.name), writer);
}
},
else => @compileError("Tipo não suportado"),
}
}
fn serializarCampo(tag: u32, valor: anytype, writer: anytype) !void {
const T2 = @TypeOf(valor);
switch (@typeInfo(T2)) {
.int => {
// Wire type 0: Varint
try writer.writeByte(@intCast((tag << 3) | 0));
try escreverVarint(writer, @intCast(valor));
},
.pointer => |p| {
if (p.size == .Slice and p.child == u8) {
// Wire type 2: Length-delimited
try writer.writeByte(@intCast((tag << 3) | 2));
try escreverVarint(writer, valor.len);
try writer.writeAll(valor);
}
},
.bool => {
try writer.writeByte(@intCast((tag << 3) | 0));
try writer.writeByte(if (valor) 1 else 0);
},
else => {},
}
}
fn escreverVarint(writer: anytype, valor: usize) !void {
var v = valor;
while (v >= 0x80) {
try writer.writeByte(@intCast((v & 0x7F) | 0x80));
v >>= 7;
}
try writer.writeByte(@intCast(v));
}
};
}
const Pessoa = struct {
id: u32,
nome: []const u8,
email: []const u8,
ativo: bool,
};
test "serializar Pessoa" {
var buf: [256]u8 = undefined;
var stream = std.io.fixedBufferStream(&buf);
try Serializer(Pessoa).serializar(.{
.id = 42,
.nome = "Ana Silva",
.email = "ana@exemplo.com",
.ativo = true,
}, stream.writer());
const dados = stream.getWritten();
try std.testing.expect(dados.len > 0);
try std.testing.expect(dados.len < 50); // Muito compacto
}
gRPC via Interop com C
const c = @cImport({
@cInclude("grpc/grpc.h");
@cInclude("grpc/support/time.h");
});
const GrpcServer = struct {
server: *c.grpc_server,
pub fn init() !GrpcServer {
c.grpc_init();
const server = c.grpc_server_create(null, null) orelse
return error.ErroGrpc;
return .{ .server = server };
}
pub fn escutar(self: *GrpcServer, endereco: [*:0]const u8) !void {
const porta = c.grpc_server_add_insecure_http2_port(self.server, endereco);
if (porta == 0) return error.PortaIndisponivel;
c.grpc_server_start(self.server);
}
pub fn parar(self: *GrpcServer) void {
c.grpc_server_shutdown_and_notify(self.server, null, null);
c.grpc_server_destroy(self.server);
c.grpc_shutdown();
}
};
Conclusão
gRPC com Zig é possível via interop com a biblioteca C do gRPC, e Zig oferece vantagens para serialização binária personalizada com performance excepcional. Para novos projetos, considere se a serialização binária nativa do Zig não atende suas necessidades sem a complexidade do gRPC.
Conteúdo Relacionado
- Microserviços com Zig — Arquitetura
- API REST com Zig — Alternativa HTTP
- Event-Driven com Zig — Mensageria
- Interoperabilidade Zig-C — FFI
- Zig em Telecomunicações — Protocolos