Use Uuids for id
This commit is contained in:
parent
20af2c82c8
commit
ad6f1454a6
4 changed files with 34 additions and 17 deletions
|
@ -1,10 +1,11 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const util = @import("util");
|
||||||
|
|
||||||
const db = @import("./db.zig");
|
const db = @import("./db.zig");
|
||||||
|
|
||||||
pub const models = @import("./models.zig");
|
pub const models = @import("./models.zig");
|
||||||
pub const free = db.free;
|
pub const free = db.free;
|
||||||
pub const Id = []const u8;
|
pub const Uuid = util.Uuid;
|
||||||
|
|
||||||
pub fn CreateInfo(comptime T: type) type {
|
pub fn CreateInfo(comptime T: type) type {
|
||||||
const t_fields = std.meta.fields(T);
|
const t_fields = std.meta.fields(T);
|
||||||
|
@ -26,7 +27,7 @@ pub fn CreateInfo(comptime T: type) type {
|
||||||
} });
|
} });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reify(comptime T: type, id: Id, val: CreateInfo(T)) T {
|
fn reify(comptime T: type, id: Uuid, val: CreateInfo(T)) T {
|
||||||
var result: T = undefined;
|
var result: T = undefined;
|
||||||
result.id = id;
|
result.id = id;
|
||||||
inline for (std.meta.fields(CreateInfo(T))) |f| {
|
inline for (std.meta.fields(CreateInfo(T))) |f| {
|
||||||
|
@ -35,23 +36,25 @@ fn reify(comptime T: type, id: Id, val: CreateInfo(T)) T {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ApiServer = struct {
|
pub const ApiServer = struct {
|
||||||
db: db.Database,
|
db: db.Database,
|
||||||
|
prng: std.rand.DefaultPrng,
|
||||||
last_id: u64 = 0,
|
last_id: u64 = 0,
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator) !ApiServer {
|
pub fn init(alloc: std.mem.Allocator) !ApiServer {
|
||||||
return ApiServer{
|
return ApiServer{
|
||||||
.db = try db.Database.init(alloc),
|
.db = try db.Database.init(alloc),
|
||||||
|
.prng = std.rand.DefaultPrng.init(1998),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn genId(self: *ApiServer, alloc: std.mem.Allocator) ![]const u8 {
|
fn genUuid(self: *ApiServer, alloc: std.mem.Allocator) ![]const u8 {
|
||||||
self.last_id += 1;
|
self.last_id += 1;
|
||||||
return std.fmt.allocPrint(alloc, "{}", .{self.last_id});
|
return std.fmt.allocPrint(alloc, "{}", .{self.last_id});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createNote(self: *ApiServer, info: CreateInfo(models.Note), alloc: std.mem.Allocator) !models.Note {
|
pub fn createNote(self: *ApiServer, info: CreateInfo(models.Note)) !Uuid {
|
||||||
const id = try self.genId(alloc);
|
const id = Uuid.randV4(self.prng.random());
|
||||||
|
|
||||||
const note = reify(models.Note, id, info);
|
const note = reify(models.Note, id, info);
|
||||||
try self.db.putNote(note);
|
try self.db.putNote(note);
|
||||||
|
@ -59,7 +62,7 @@ const ApiServer = struct {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getNote(self: *ApiServer, id: Id, alloc: std.mem.Allocator) !?models.Note {
|
pub fn getNote(self: *ApiServer, id: Uuid, alloc: std.mem.Allocator) !?models.Note {
|
||||||
return self.db.getNote(id, alloc);
|
return self.db.getNote(id, alloc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const util = @import("util");
|
||||||
|
const Uuid = util.Uuid;
|
||||||
|
|
||||||
const models = @import("./models.zig");
|
const models = @import("./models.zig");
|
||||||
const Id = []const u8;
|
|
||||||
|
|
||||||
// Clones a struct and its fields to a single layer of depth.
|
// Clones a struct and its fields to a single layer of depth.
|
||||||
// Caller owns memory, can be freed using free below
|
// Caller owns memory, can be freed using free below
|
||||||
|
@ -14,8 +15,11 @@ fn clone(alloc: std.mem.Allocator, val: anytype) !@TypeOf(val) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline for (std.meta.fields(@TypeOf(val))) |f| {
|
inline for (std.meta.fields(@TypeOf(val))) |f| {
|
||||||
|
// TODO
|
||||||
if (f.field_type == []u8 or f.field_type == []const u8) {
|
if (f.field_type == []u8 or f.field_type == []const u8) {
|
||||||
@field(result, f.name) = try cloneString(alloc, @field(val, f.name));
|
@field(result, f.name) = try cloneString(alloc, @field(val, f.name));
|
||||||
|
} else if (f.field_type == Uuid) {
|
||||||
|
@field(result, f.name) = @field(val, f.name);
|
||||||
} else {
|
} else {
|
||||||
@compileError("unsupported field type " ++ @typeName(f.field_type));
|
@compileError("unsupported field type " ++ @typeName(f.field_type));
|
||||||
}
|
}
|
||||||
|
@ -33,8 +37,11 @@ fn cloneString(alloc: std.mem.Allocator, str: []const u8) ![]const u8 {
|
||||||
// Frees a struct and its fields returned by clone
|
// Frees a struct and its fields returned by clone
|
||||||
pub fn free(alloc: std.mem.Allocator, val: anytype) void {
|
pub fn free(alloc: std.mem.Allocator, val: anytype) void {
|
||||||
inline for (std.meta.fields(@TypeOf(val))) |f| {
|
inline for (std.meta.fields(@TypeOf(val))) |f| {
|
||||||
|
// TODO
|
||||||
if (f.field_type == []u8 or f.field_type == []const u8) {
|
if (f.field_type == []u8 or f.field_type == []const u8) {
|
||||||
alloc.free(@field(val, f.name));
|
alloc.free(@field(val, f.name));
|
||||||
|
} else if (f.field_type == Uuid) {
|
||||||
|
// nothing
|
||||||
} else {
|
} else {
|
||||||
@compileError("unsupported field type " ++ @typeName(f.field_type));
|
@compileError("unsupported field type " ++ @typeName(f.field_type));
|
||||||
}
|
}
|
||||||
|
@ -43,16 +50,16 @@ pub fn free(alloc: std.mem.Allocator, val: anytype) void {
|
||||||
|
|
||||||
pub const Database = struct {
|
pub const Database = struct {
|
||||||
internal_alloc: std.mem.Allocator,
|
internal_alloc: std.mem.Allocator,
|
||||||
notes: std.StringHashMap(models.Note),
|
notes: std.AutoHashMap(Uuid, models.Note),
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator) !Database {
|
pub fn init(alloc: std.mem.Allocator) !Database {
|
||||||
var db = Database{
|
var db = Database{
|
||||||
.internal_alloc = alloc,
|
.internal_alloc = alloc,
|
||||||
.notes = std.StringHashMap(models.Note).init(alloc),
|
.notes = std.AutoHashMap(Uuid, models.Note).init(alloc),
|
||||||
};
|
};
|
||||||
|
|
||||||
try db.putNote(models.Note{
|
try db.putNote(models.Note{
|
||||||
.id = "1",
|
.id = Uuid{ .data = @bitCast([16]u8, @as(u128, 1)) },
|
||||||
.content = "abcd",
|
.content = "abcd",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -68,13 +75,13 @@ pub const Database = struct {
|
||||||
self.notes.deinit();
|
self.notes.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn containsNote(self: *Database, id: Id) !bool {
|
pub fn containsNote(self: *Database, id: Uuid) !bool {
|
||||||
return self.notes.contains(id);
|
return self.notes.contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns a copy of the note data from storage. memory is allocated with the provided
|
// returns a copy of the note data from storage. memory is allocated with the provided
|
||||||
// allocator. can be freed using free() above
|
// allocator. can be freed using free() above
|
||||||
pub fn getNote(self: *Database, id: Id, alloc: std.mem.Allocator) !?models.Note {
|
pub fn getNote(self: *Database, id: Uuid, alloc: std.mem.Allocator) !?models.Note {
|
||||||
const note = self.notes.get(id) orelse return null;
|
const note = self.notes.get(id) orelse return null;
|
||||||
return try clone(alloc, note);
|
return try clone(alloc, note);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const http = @import("http");
|
const http = @import("http");
|
||||||
|
const util = @import("util");
|
||||||
|
|
||||||
const api = @import("./api.zig");
|
const api = @import("./api.zig");
|
||||||
const models = @import("./models.zig");
|
const models = @import("./models.zig");
|
||||||
|
const Uuid = util.Uuid;
|
||||||
|
|
||||||
// this thing is overcomplicated and weird. stop this
|
// this thing is overcomplicated and weird. stop this
|
||||||
const Router = http.Router(*RequestServer);
|
const Router = http.Router(*RequestServer);
|
||||||
|
@ -50,15 +53,17 @@ fn createNote(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !voi
|
||||||
const body = ctx.request.body orelse return respondJson(ctx, .bad_request, .{ .@"error" = "no note body provided" }, srv.alloc);
|
const body = ctx.request.body orelse return respondJson(ctx, .bad_request, .{ .@"error" = "no note body provided" }, srv.alloc);
|
||||||
var tokens = std.json.TokenStream.init(body);
|
var tokens = std.json.TokenStream.init(body);
|
||||||
const note = try std.json.parse(api.CreateInfo(models.Note), &tokens, .{ .allocator = srv.alloc });
|
const note = try std.json.parse(api.CreateInfo(models.Note), &tokens, .{ .allocator = srv.alloc });
|
||||||
defer std.json.parseFree(models.Note, note, .{ .allocator = srv.alloc });
|
defer std.json.parseFree(api.CreateInfo(models.Note), note, .{ .allocator = srv.alloc });
|
||||||
|
|
||||||
try srv.api.createNote(note);
|
// TODO
|
||||||
|
_ = try srv.api.createNote(note);
|
||||||
|
|
||||||
try respondJson(ctx, .created, note, srv.alloc);
|
try respondJson(ctx, .created, note, srv.alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getNote(srv: *RequestServer, ctx: *http.server.Context, args: RouteArgs) !void {
|
fn getNote(srv: *RequestServer, ctx: *http.server.Context, args: RouteArgs) !void {
|
||||||
const id = args.get("id") orelse return error.NotFound;
|
const id_str = args.get("id") orelse return error.NotFound;
|
||||||
|
const id = Uuid.parse(id_str) catch return respondJson(ctx, .bad_request, .{ .@"error" = "invalid id" }, srv.alloc);
|
||||||
const note = (try srv.api.getNote(id, srv.alloc)) orelse return error.NotFound;
|
const note = (try srv.api.getNote(id, srv.alloc)) orelse return error.NotFound;
|
||||||
defer api.free(srv.alloc, note);
|
defer api.free(srv.alloc, note);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
const Uuid = @import("util").Uuid;
|
||||||
|
|
||||||
pub const Note = struct {
|
pub const Note = struct {
|
||||||
id: []const u8,
|
id: Uuid,
|
||||||
content: []const u8,
|
content: []const u8,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue