diff --git a/src/renderer.zig b/src/renderer.zig index e761c47..63743fe 100644 --- a/src/renderer.zig +++ b/src/renderer.zig @@ -53,45 +53,59 @@ pub const Renderer = struct { } 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); - 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| { - 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) { .text => try writer.writeAll(node.text.?.content), .variable => { const var_name = node.variable.?.expr; var value: Value = self.context.get(var_name) orelse Value.null; - var buf = ArrayListUnmanaged(u8){}; - defer buf.deinit(self.allocator); var is_safe = false; for (node.variable.?.filters) |f| { - const filter_fn = builtin_filters.get(f.name) orelse continue; - value = try filter_fn(self.allocator, value, Value{.string = f.arg orelse ""}); + const filter_fn = builtin_filters.get(f.name) orelse return error.UnknownFilter; + + 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 (!is_safe) { 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); }, else => unreachable, } } - fn valueToString(self: *const Renderer, buf: *ArrayListUnmanaged(u8), value: Value) !void { - var w = buf.writer(self.allocator); + fn valueToString(self: *const Renderer, alloc: Allocator, buf: *ArrayListUnmanaged(u8), value: Value) !void { + _ = self; + var w = buf.writer(alloc); switch (value) { .null => try w.writeAll("null"), .bool => |b| try w.print("{}", .{b}),