update: context

This commit is contained in:
Lucas F. 2026-01-04 00:39:20 -03:00
parent e9c042a654
commit 164e68e94c
3 changed files with 131 additions and 4 deletions

51
src/context.zig Normal file
View file

@ -0,0 +1,51 @@
const std = @import("std");
pub const Value = union(enum) {
null,
bool: bool,
int: i64,
float: f64,
string: []const u8,
list: []const Value,
dict: std.StringHashMapUnmanaged(Value),
pub fn deinit(self: Value) void {
_ = self; // nada a arena libera tudo
}
};
pub const Context = struct {
arena: std.heap.ArenaAllocator,
map: std.StringHashMapUnmanaged(Value),
pub fn init(child_allocator: std.mem.Allocator) Context {
const arena = std.heap.ArenaAllocator.init(child_allocator);
return .{
.arena = arena,
.map = .{},
};
}
pub fn allocator(self: *Context) std.mem.Allocator {
return self.arena.allocator();
}
pub fn deinit(self: *Context) void {
self.arena.deinit();
}
pub fn set(self: *Context, key: []const u8, value: Value) !void {
const gop = try self.map.getOrPut(self.allocator(), key);
if (gop.found_existing) {
// opcional: deinit value antigo se necessário
// mas como arena libera tudo, não precisa
} else {
gop.key_ptr.* = try self.allocator().dupe(u8, key);
}
gop.value_ptr.* = value;
}
pub fn get(self: *const Context, key: []const u8) ?Value {
return self.map.get(key);
}
};

76
src/context_test.zig Normal file
View file

@ -0,0 +1,76 @@
const std = @import("std");
const testing = std.testing;
const Context = @import("context.zig").Context;
const Value = @import("context.zig").Value;
test "context com arena" {
const allocator = testing.allocator;
var ctx = Context.init(allocator);
defer ctx.deinit();
try ctx.set("nome", Value{ .string = "Lucas" }); // sem dupe!
try ctx.set("idade", Value{ .int = 30 });
try testing.expectEqualStrings("Lucas", ctx.get("nome").?.string);
try testing.expectEqual(@as(i64, 30), ctx.get("idade").?.int);
}
test "context todos os tipos" {
const allocator = testing.allocator;
var ctx = Context.init(allocator);
defer ctx.deinit();
// null
try ctx.set("nulo", Value{ .null = {} });
try testing.expectEqual(ctx.get("nulo").?, .null);
// bool
try ctx.set("verdadeiro", Value{ .bool = true });
try ctx.set("falso", Value{ .bool = false });
try testing.expect(ctx.get("verdadeiro").?.bool == true);
try testing.expect(ctx.get("falso").?.bool == false);
// int
try ctx.set("idade", Value{ .int = 30 });
try testing.expect(ctx.get("idade").?.int == 30);
// float
try ctx.set("preco", Value{ .float = 99.99 });
try testing.expectApproxEqAbs(@as(f64, 99.99), ctx.get("preco").?.float, 0.001);
// string
try ctx.set("nome", Value{ .string = "Lucas" });
try testing.expectEqualStrings("Lucas", ctx.get("nome").?.string);
// list
var list = try allocator.alloc(Value, 3);
defer allocator.free(list);
list[0] = Value{ .int = 1 };
list[1] = Value{ .int = 2 };
list[2] = Value{ .int = 3 };
try ctx.set("numeros", Value{ .list = list });
const numeros = ctx.get("numeros").?.list;
try testing.expectEqual(@as(usize, 3), numeros.len);
try testing.expect(numeros[0].int == 1);
try testing.expect(numeros[1].int == 2);
try testing.expect(numeros[2].int == 3);
// dict
var dict = std.StringHashMapUnmanaged(Value){};
try dict.put(ctx.allocator(), "chave1", Value{ .string = "valor1" });
try dict.put(ctx.allocator(), "chave2", Value{ .int = 42 });
try ctx.set("config", Value{ .dict = dict });
const config = ctx.get("config").?.dict;
try testing.expectEqualStrings("valor1", config.get("chave1").?.string);
try testing.expect(config.get("chave2").?.int == 42);
}
test "failback" {
const allocator = testing.allocator;
var ctx = Context.init(allocator);
defer ctx.deinit();
try testing.expectEqual(ctx.get("nome"), null);
}

View file

@ -22,10 +22,10 @@
- [x] regroup
- [x] resetcycle
- [x] spaceless
- [ ] templatetag
- [x] templatetag
- [x] url
- [x] verbatim
- [ ] widthratio
- [x] widthratio
- [x] with
@ -114,8 +114,8 @@ ___
- [x] querystring
- [x] regroup
- [x] resetcycle
- [ ] templatetag
- [ ] widthratio
- [x] templatetag
- [x] widthratio
2 - projetar o Context com calma:
- Estrutura hierárquica (escopos aninhados para with, for, etc.)