From 877bd0eea2d310ca5775b0324e9c4f4881d114be Mon Sep 17 00:00:00 2001 From: Rene Schallner Date: Wed, 13 Sep 2023 13:43:33 +0200 Subject: [PATCH] refactored and simplified Mustache interface --- examples/mustache/mustache.zig | 8 ++--- src/mustache.zig | 59 +++++++++++++++++++++------------- src/tests/test_mustache.zig | 16 ++++----- 3 files changed, 48 insertions(+), 35 deletions(-) diff --git a/examples/mustache/mustache.zig b/examples/mustache/mustache.zig index f60c8d8..ded38e1 100644 --- a/examples/mustache/mustache.zig +++ b/examples/mustache/mustache.zig @@ -3,13 +3,13 @@ const zap = @import("zap"); fn on_request(r: zap.SimpleRequest) void { const template = "{{=<< >>=}}* Users:\r\n<<#users>><>. <<& name>> (<>)\r\n<>\r\nNested: <<& nested.item >>."; - const p = zap.MustacheData(template) catch return; - defer zap.MustacheFree(p); + const p = zap.mustacheData(template) catch return; + defer zap.mustacheFree(p); const User = struct { name: []const u8, id: isize, }; - const ret = zap.MustacheBuild(p, .{ + const ret = zap.mustacheBuild(p, .{ .users = [_]User{ .{ .name = "Rene", @@ -29,7 +29,7 @@ fn on_request(r: zap.SimpleRequest) void { if (ret.str()) |s| { r.sendBody(s) catch return; } else { - r.sendBody("

MustacheBuild() failed!

") catch return; + r.sendBody("

mustacheBuild() failed!

") catch return; } } else |err| { std.debug.print("Error while setting content type: {}\n", .{err}); diff --git a/src/mustache.zig b/src/mustache.zig index f285841..05edaa5 100644 --- a/src/mustache.zig +++ b/src/mustache.zig @@ -11,12 +11,22 @@ pub const enum_mustache_error_en = c_uint; pub const mustache_error_en = enum_mustache_error_en; pub const mustache_s = struct_mustache_s; -pub extern fn fiobj_mustache_new(args: MustacheLoadArgs) ?*mustache_s; +pub extern fn fiobj_mustache_new(args: MustacheLoadArgsFio) ?*mustache_s; pub extern fn fiobj_mustache_build(mustache: ?*mustache_s, data: fio.FIOBJ) fio.FIOBJ; pub extern fn fiobj_mustache_build2(dest: fio.FIOBJ, mustache: ?*mustache_s, data: fio.FIOBJ) fio.FIOBJ; pub extern fn fiobj_mustache_free(mustache: ?*mustache_s) void; -pub const MustacheLoadArgs = extern struct { +/// Mustache load args used in mustacheNew +pub const MustacheLoadArgs = struct { + /// optional filename, enables partial templates on filesystem + filename: ?[]const u8 = null, + + /// optional string data. should be used if no filename is specified. + data: ?[]const u8 = null, +}; + +// used internally for interfacing with fio +const MustacheLoadArgsFio = extern struct { filename: [*c]const u8, filename_len: usize, data: [*c]const u8, @@ -44,11 +54,24 @@ pub const MustacheError = error{ // pub extern fn fiobj_mustache_build2(dest: FIOBJ, mustache: ?*mustache_s, data: FIOBJ) FIOBJ; -pub fn MustacheNew(load_args: MustacheLoadArgs) MustacheError!*Mustache { +pub fn mustacheNew(load_args: MustacheLoadArgs) MustacheError!*Mustache { var err: mustache_error_en = undefined; - var args = load_args; - args.err = &err; + var args: MustacheLoadArgsFio = .{ + .filename = filn: { + if (load_args.filename) |filn| break :filn filn.ptr else break :filn null; + }, + .filename_len = filn_len: { + if (load_args.filename) |filn| break :filn_len filn.len else break :filn_len 0; + }, + .data = data: { + if (load_args.data) |data| break :data data.ptr else break :data null; + }, + .data_len = data_len: { + if (load_args.data) |data| break :data_len data.len else break :data_len 0; + }, + .err = &err, + }; var ret = fiobj_mustache_new(args); switch (err) { @@ -69,24 +92,14 @@ pub fn MustacheNew(load_args: MustacheLoadArgs) MustacheError!*Mustache { return MustacheError.MUSTACHE_ERR_UNKNOWN; } -pub fn MustacheData(data: []const u8) MustacheError!*Mustache { - var err: mustache_error_en = undefined; - var args: MustacheLoadArgs = .{ .filename = null, .filename_len = 0, .data = data.ptr, .data_len = data.len, .err = &err }; - - return MustacheNew(args); +/// Convenience function if you only want to use in-memory data (as opposed to file data) +pub fn mustacheData(data: []const u8) MustacheError!*Mustache { + return mustacheNew(.{ .data = data }); } -pub fn MustacheLoad(filename: []const u8) MustacheError!*Mustache { - var err: mustache_error_en = undefined; - var args: MustacheLoadArgs = .{ - .filename = filename.ptr, - .filename_len = filename.len, - .data = null, - .data_len = 0, - .err = &err, - }; - - return MustacheNew(args); +/// Convenience function if you only want to use file-based data (as opposed to in-memory data) +pub fn mustacheLoad(filename: []const u8) MustacheError!*Mustache { + return mustacheNew(.{ .filename = filename }); } // implement these: fiobj_mustache.c @@ -111,7 +124,7 @@ const MustacheBuildResult = struct { // this build is slow because it needs to translate to a FIOBJ data // object FIOBJ_T_HASH -pub fn MustacheBuild(mustache: *Mustache, data: anytype) MustacheBuildResult { +pub fn mustacheBuild(mustache: *Mustache, data: anytype) MustacheBuildResult { const T = @TypeOf(data); if (@typeInfo(T) != .Struct) { @compileError("No struct: '" ++ @typeName(T) ++ "'"); @@ -221,6 +234,6 @@ pub fn fiobjectify( unreachable; } -pub fn MustacheFree(m: ?*Mustache) void { +pub fn mustacheFree(m: ?*Mustache) void { fiobj_mustache_free(m); } diff --git a/src/tests/test_mustache.zig b/src/tests/test_mustache.zig index d5c9b6e..c1bfef9 100644 --- a/src/tests/test_mustache.zig +++ b/src/tests/test_mustache.zig @@ -22,22 +22,22 @@ const data = .{ }, }; -test "MustacheData" { +test "mustacheData" { const template = "{{=<< >>=}}* Users:\n<<#users>><>. <<& name>> (<>)\n<>\nNested: <<& nested.item >>."; - const p = try zap.MustacheData(template); - defer zap.MustacheFree(p); + const p = try zap.mustacheData(template); + defer zap.mustacheFree(p); - const ret = zap.MustacheBuild(p, data); + const ret = zap.mustacheBuild(p, data); defer ret.deinit(); try std.testing.expectEqualSlices(u8, "* Users:\n1. Rene (Rene)\n6. Caro (Caro)\nNested: nesting works.", ret.str().?); } -test "MustacheLoad" { - const p = try zap.MustacheLoad("./src/tests/testtemplate.html"); - defer zap.MustacheFree(p); +test "mustacheLoad" { + const p = try zap.mustacheLoad("./src/tests/testtemplate.html"); + defer zap.mustacheFree(p); - const ret = zap.MustacheBuild(p, data); + const ret = zap.mustacheBuild(p, data); defer ret.deinit(); try std.testing.expectEqualSlices(u8, "* Users:\n1. Rene (Rene)\n6. Caro (Caro)\nNested: nesting works.\n", ret.str().?);