diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval/html/Content.zig | 10 | ||||
| -rw-r--r-- | src/eval/html/Element.zig | 41 | ||||
| -rw-r--r-- | src/eval/html/Literal.zig | 10 | ||||
| -rw-r--r-- | src/eval/html/Root.zig | 13 | ||||
| -rw-r--r-- | src/eval/html/Void.zig | 10 |
5 files changed, 43 insertions, 41 deletions
diff --git a/src/eval/html/Content.zig b/src/eval/html/Content.zig index aed3a0e..96961da 100644 --- a/src/eval/html/Content.zig +++ b/src/eval/html/Content.zig @@ -28,12 +28,7 @@ pub fn init(alloc: Allocator, tag: []const u8) Error!*Self { } pub fn element(self: *Self) Element { - return .{ .vtable = .{ .render = render, .node = getNode }, .ptr = self }; -} - -fn getNode(context: *anyopaque) *Node { - const self: *Self = @ptrCast(@alignCast(context)); - return &self.node; + return (Element.Wrapper(Self){ .ptr = self }).element(); } fn fromNode(context: *anyopaque) Element { @@ -41,8 +36,7 @@ fn fromNode(context: *anyopaque) Element { return self.element(); } -fn render(context: *anyopaque, alloc: Allocator) Error![]const u8 { - const self: *Self = @ptrCast(@alignCast(context)); +pub fn render(self: *Self, alloc: Allocator) Error![]const u8 { var base = self.base; const b = try base.element().render(alloc); defer alloc.free(b); diff --git a/src/eval/html/Element.zig b/src/eval/html/Element.zig index cf5e74c..c44f4ef 100644 --- a/src/eval/html/Element.zig +++ b/src/eval/html/Element.zig @@ -11,9 +11,38 @@ pub const Root = @import("Root.zig"); pub const Error = html.Error || Allocator.Error; +pub fn Wrapper(comptime V: type) type { + comptime { + if (!@hasField(V, "node")) @compileError("missing field 'node' for " ++ @typeName(V)); + const nd = @FieldType(V, "node"); + if (nd != Node) @compileError("invalid node's type: " ++ @typeName(nd) ++ ", want " ++ @typeName(Node)); + if (!@hasDecl(V, "element")) @compileError("missing declaration 'element' for " ++ @typeName(V)); + if (!@hasDecl(V, "render")) @compileError("missing declaration 'render' for " ++ @typeName(V)); + } + return struct { + ptr: *V, + + const Self = @This(); + + fn node(context: *anyopaque) *Node { + const self: *V = @ptrCast(@alignCast(context)); + return &self.node; + } + + fn render(context: *anyopaque, alloc: Allocator) Error![]const u8 { + const self: *V = @ptrCast(@alignCast(context)); + return try self.render(alloc); + } + + pub fn element(self: Self) Element { + return .{ .ptr = self.ptr, .vtable = .{ .node = Self.node, .render = Self.render } }; + } + }; +} + pub const Node = struct { ptr: *anyopaque, - vtable: struct { element: *const fn (*anyopaque) Self }, + vtable: struct { element: *const fn (*anyopaque) Element }, node: std.DoublyLinkedList.Node = .{}, pub fn from(n: *std.DoublyLinkedList.Node) *Node { @@ -21,12 +50,12 @@ pub const Node = struct { return v; } - pub fn element(self: Node) Self { + pub fn element(self: Node) Element { return self.vtable.element(self.ptr); } }; -const Self = @This(); +const Element = @This(); vtable: struct { render: *const fn (*anyopaque, Allocator) Error![]const u8, @@ -34,15 +63,15 @@ vtable: struct { }, ptr: *anyopaque, -pub fn render(self: Self, alloc: Allocator) Error![]const u8 { +pub fn render(self: Element, alloc: Allocator) Error![]const u8 { return self.vtable.render(self.ptr, alloc); } -pub fn node(self: Self) *Node { +pub fn node(self: Element) *Node { return self.vtable.node(self.ptr); } -fn doTest(alloc: Allocator, el: Self, exp: []const u8) !void { +fn doTest(alloc: Allocator, el: Element, exp: []const u8) !void { const got = try el.render(alloc); defer alloc.free(got); std.testing.expect(eql(u8, got, exp)) catch |err| { diff --git a/src/eval/html/Literal.zig b/src/eval/html/Literal.zig index a75b16c..9d6d91e 100644 --- a/src/eval/html/Literal.zig +++ b/src/eval/html/Literal.zig @@ -28,12 +28,7 @@ pub fn initNoEscape(alloc: Allocator, literal: []const u8) Error!*Element.Litera } pub fn element(self: *Self) Element { - return .{ .vtable = .{ .render = render, .node = getNode }, .ptr = self }; -} - -fn getNode(context: *anyopaque) *Node { - const self: *Self = @ptrCast(@alignCast(context)); - return &self.node; + return (Element.Wrapper(Self){ .ptr = self }).element(); } fn fromNode(context: *anyopaque) Element { @@ -41,7 +36,6 @@ fn fromNode(context: *anyopaque) Element { return self.element(); } -fn render(context: *anyopaque, alloc: Allocator) Error![]const u8 { - const self: *Self = @ptrCast(@alignCast(context)); +pub fn render(self: *Self, alloc: Allocator) Error![]const u8 { return try alloc.dupe(u8, self.literal); } diff --git a/src/eval/html/Root.zig b/src/eval/html/Root.zig index 440667a..83859d4 100644 --- a/src/eval/html/Root.zig +++ b/src/eval/html/Root.zig @@ -28,10 +28,7 @@ pub fn deinit(self: *Self) void { } pub fn element(self: *Self) Element { - return .{ .vtable = .{ - .render = render, - .node = getNode, - }, .ptr = self }; + return (Element.Wrapper(Self){ .ptr = self }).element(); } pub fn allocator(self: *Self) Allocator { @@ -42,18 +39,12 @@ pub fn append(self: *Self, el: Element) void { self.content.append(&el.node().node); } -fn getNode(context: *anyopaque) *Node { - const self: *Self = @ptrCast(@alignCast(context)); - return &self.node; -} - fn fromNode(context: *anyopaque) Element { const self: *Self = @ptrCast(@alignCast(context)); return self.element(); } -fn render(context: *anyopaque, alloc: Allocator) Error![]const u8 { - const self: *Self = @ptrCast(@alignCast(context)); +pub fn render(self: *Self, alloc: Allocator) Error![]const u8 { if (self.content.first == null) return ""; var acc = try std.ArrayList(u8).initCapacity(alloc, 8); errdefer acc.deinit(alloc); diff --git a/src/eval/html/Void.zig b/src/eval/html/Void.zig index 99bc923..431536c 100644 --- a/src/eval/html/Void.zig +++ b/src/eval/html/Void.zig @@ -30,7 +30,7 @@ pub fn init(alloc: Allocator, tag: []const u8) Error!*Self { } pub fn element(self: *Self) Element { - return .{ .vtable = .{ .render = render, .node = getNode }, .ptr = self }; + return (Element.Wrapper(Self){ .ptr = self }).element(); } pub fn setAttribute(self: *Self, k: []const u8, v: []const u8) Error!void { @@ -57,18 +57,12 @@ pub fn removeClass(self: *Self, v: []const u8) void { self.class_list.remove(v); } -fn getNode(context: *anyopaque) *Node { - const self: *Self = @ptrCast(@alignCast(context)); - return &self.node; -} - fn fromNode(context: *anyopaque) Element { const self: *Self = @ptrCast(@alignCast(context)); return self.element(); } -fn render(context: *anyopaque, alloc: Allocator) Error![]const u8 { - const self: *Self = @ptrCast(@alignCast(context)); +pub fn render(self: *Self, alloc: Allocator) Error![]const u8 { const attr = try renderAttribute(alloc, &self.attributes, &self.class_list); defer if (attr) |it| alloc.free(it); var acc = try List(u8).initCapacity(alloc, self.tag.len + 2); |
