update: context
This commit is contained in:
parent
e9c042a654
commit
164e68e94c
3 changed files with 131 additions and 4 deletions
51
src/context.zig
Normal file
51
src/context.zig
Normal 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
76
src/context_test.zig
Normal 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);
|
||||
}
|
||||
8
todo.md
8
todo.md
|
|
@ -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.)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue