update: create a suballocator for renderer

This commit is contained in:
Lucas F. 2026-01-11 11:41:55 -03:00
parent 0e74ddb278
commit 256898cb41

View file

@ -53,45 +53,59 @@ pub const Renderer = struct {
} }
pub fn renderString(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void { pub fn renderString(self: *const Renderer, template: []const u8, writer: anytype) RenderError!void {
var arena = std.heap.ArenaAllocator.init(self.allocator);
defer arena.deinit();
const alloc = arena.allocator();
var p = parser.Parser.init(template); var p = parser.Parser.init(template);
const nodes = try p.parse(self.allocator); const nodes = try p.parse(alloc);
defer {
for (nodes) |node| node.deinit(alloc);
alloc.free(nodes);
}
for (nodes) |node| { for (nodes) |node| {
try self.renderNode(node, writer); try self.renderNode(alloc, node, writer);
} }
} }
fn renderNode(self: *const Renderer, node: parser.Node, writer: anytype) RenderError!void { fn renderNode(self: *const Renderer, alloc: Allocator, node: parser.Node, writer: anytype) RenderError!void {
switch (node.type) { switch (node.type) {
.text => try writer.writeAll(node.text.?.content), .text => try writer.writeAll(node.text.?.content),
.variable => { .variable => {
const var_name = node.variable.?.expr; const var_name = node.variable.?.expr;
var value: Value = self.context.get(var_name) orelse Value.null; var value: Value = self.context.get(var_name) orelse Value.null;
var buf = ArrayListUnmanaged(u8){};
defer buf.deinit(self.allocator);
var is_safe = false; var is_safe = false;
for (node.variable.?.filters) |f| { for (node.variable.?.filters) |f| {
const filter_fn = builtin_filters.get(f.name) orelse continue; const filter_fn = builtin_filters.get(f.name) orelse return error.UnknownFilter;
value = try filter_fn(self.allocator, value, Value{.string = f.arg orelse ""});
const arg = if (f.arg) |a| Value{ .string = a } else null;
value = try filter_fn(alloc, value, arg);
if (std.mem.eql(u8, f.name, "safe")) is_safe = true; if (std.mem.eql(u8, f.name, "safe")) is_safe = true;
} }
if (!is_safe) { if (!is_safe) {
if (builtin_filters.get("escape")) |escape_fn| { if (builtin_filters.get("escape")) |escape_fn| {
value = try escape_fn(self.allocator, value, null); value = try escape_fn(alloc, value, null);
} }
} }
try self.valueToString(&buf, value); var buf = ArrayListUnmanaged(u8){};
defer buf.deinit(alloc);
try self.valueToString(alloc, &buf, value);
try writer.writeAll(buf.items); try writer.writeAll(buf.items);
}, },
else => unreachable, else => unreachable,
} }
} }
fn valueToString(self: *const Renderer, buf: *ArrayListUnmanaged(u8), value: Value) !void { fn valueToString(self: *const Renderer, alloc: Allocator, buf: *ArrayListUnmanaged(u8), value: Value) !void {
var w = buf.writer(self.allocator); _ = self;
var w = buf.writer(alloc);
switch (value) { switch (value) {
.null => try w.writeAll("null"), .null => try w.writeAll("null"),
.bool => |b| try w.print("{}", .{b}), .bool => |b| try w.print("{}", .{b}),