diff --git a/src/main/db.zig b/src/main/db.zig new file mode 100644 index 0000000..6700545 --- /dev/null +++ b/src/main/db.zig @@ -0,0 +1,53 @@ +const std = @import("std"); + +const models = @import("./models.zig"); + +// Clones a struct and its fields to a single layer of depth. +// Caller owns memory, can be freed using free below +// TODO: check that this is a struct, etc etc +fn clone(alloc: std.mem.Allocator, val: anytype) !@TypeOf(val) { + var result: @TypeOf(val) = undefined; + + errdefer { + @panic("memory leak in deep clone, fix this"); + } + + inline for (std.meta.fields(@TypeOf(val))) |f| { + if (f.field_type == []u8 or f.field_type == []const u8) { + var copy = try alloc.alloc(u8, @field(val, f.name).len); + std.mem.copy(u8, copy, @field(val, f.name)); + @field(result, f.name) = copy; + } else { + @compileError("unsupported field type " ++ @typeName(f.field_type)); + } + } + + return result; +} + +// Frees a struct and its fields returned by clone +pub fn free(alloc: std.mem.Allocator, val: anytype) void { + inline for (std.meta.fields(@TypeOf(val))) |f| { + if (f.field_type == []u8 or f.field_type == []const u8) { + alloc.free(@field(val, f.name)); + } else { + @compileError("unsupported field type " ++ @typeName(f.field_type)); + } + } +} + +pub fn getNote(alloc: std.mem.Allocator) !models.Note { + return try clone(alloc, models.Note{ + .content = "abcd", + }); +} + +test "clone" { + const T = struct { + name: []const u8, + value: []const u8, + }; + + const copy = try clone(std.testing.allocator, T{ .name = "myName", .value = "myValue" }); + free(std.testing.allocator, copy); +} diff --git a/src/main/main.zig b/src/main/main.zig index 409aaa6..7a9fc0d 100644 --- a/src/main/main.zig +++ b/src/main/main.zig @@ -1,6 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); const http = @import("http"); +const db = @import("./db.zig"); // this thing is overcomplicated and weird. stop this const Router = http.Router(*RequestServer); @@ -9,6 +10,7 @@ const RouteArgs = http.RouteArgs; const router = Router{ .routes = &[_]Route{ Route.new(.GET, "/healthcheck", healthcheck), + Route.new(.GET, "/", getNote), }, }; @@ -25,6 +27,22 @@ const json_options = if (builtin.mode == .Debug) }, }; +fn getNote(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !void { + const alloc = srv.alloc; + const headers = http.Headers.init(alloc); + + const note = try db.getNote(alloc); + defer db.free(alloc, note); + + var stream = try ctx.openResponse(&headers, .ok); + defer stream.close(); + + const writer = stream.writer(); + try std.json.stringify(note, json_options, writer); + + try stream.finish(); +} + fn healthcheck(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !void { const alloc = srv.alloc; const headers = http.Headers.init(alloc); diff --git a/src/main/models.zig b/src/main/models.zig new file mode 100644 index 0000000..75d9a89 --- /dev/null +++ b/src/main/models.zig @@ -0,0 +1,3 @@ +pub const Note = struct { + content: []const u8, +};