mirror of
https://github.com/zigzap/zap.git
synced 2025-10-20 15:14:08 +00:00
132 lines
3.6 KiB
Zig
132 lines
3.6 KiB
Zig
const std = @import("std");
|
|
|
|
alloc: std.mem.Allocator = undefined,
|
|
users: std.AutoHashMap(usize, InternalUser) = undefined,
|
|
lock: std.Thread.Mutex = undefined,
|
|
count: usize = 0,
|
|
|
|
pub const Self = @This();
|
|
|
|
const InternalUser = struct {
|
|
id: usize = 0,
|
|
firstnamebuf: [64]u8,
|
|
firstnamelen: usize,
|
|
lastnamebuf: [64]u8,
|
|
lastnamelen: usize,
|
|
};
|
|
|
|
pub const User = struct {
|
|
id: usize = 0,
|
|
first_name: []const u8,
|
|
last_name: []const u8,
|
|
};
|
|
|
|
pub fn init(a: std.mem.Allocator) Self {
|
|
return .{
|
|
.alloc = a,
|
|
.users = std.AutoHashMap(usize, InternalUser).init(a),
|
|
.lock = std.Thread.Mutex{},
|
|
};
|
|
}
|
|
|
|
// the request will be freed (and its mem reused by facilio) when it's
|
|
// completed, so we take copies of the names
|
|
pub fn addByName(self: *Self, first: ?[]const u8, last: ?[]const u8) !usize {
|
|
var user: InternalUser = undefined;
|
|
user.firstnamelen = 0;
|
|
user.lastnamelen = 0;
|
|
if (first) |firstname| {
|
|
std.mem.copy(u8, user.firstnamebuf[0..], firstname);
|
|
user.firstnamelen = firstname.len;
|
|
}
|
|
if (last) |lastname| {
|
|
std.mem.copy(u8, user.lastnamebuf[0..], lastname);
|
|
user.lastnamelen = lastname.len;
|
|
}
|
|
|
|
// We lock only on insertion, deletion, and listing
|
|
self.lock.lock();
|
|
defer self.lock.unlock();
|
|
self.count = self.count + 1;
|
|
user.id = self.count;
|
|
try self.users.put(user.id, user);
|
|
return user.id;
|
|
}
|
|
|
|
pub fn delete(self: *Self, id: usize) bool {
|
|
// We lock only on insertion, deletion, and listing
|
|
self.lock.lock();
|
|
defer self.lock.unlock();
|
|
return self.users.remove(id);
|
|
}
|
|
|
|
pub fn get(self: *Self, id: usize) ?User {
|
|
// we don't care about locking here, as our usage-pattern is unlikely to
|
|
// get a user by id that is not known yet
|
|
if (self.users.getPtr(id)) |pUser| {
|
|
return .{
|
|
.id = pUser.id,
|
|
.first_name = pUser.firstnamebuf[0..pUser.firstnamelen],
|
|
.last_name = pUser.lastnamebuf[0..pUser.lastnamelen],
|
|
};
|
|
}
|
|
return null;
|
|
}
|
|
|
|
pub fn update(
|
|
self: *Self,
|
|
id: usize,
|
|
first: ?[]const u8,
|
|
last: ?[]const u8,
|
|
) bool {
|
|
// we don't care about locking here
|
|
if (self.users.getPtr(id)) |pUser| {
|
|
pUser.firstnamelen = 0;
|
|
pUser.lastnamelen = 0;
|
|
if (first) |firstname| {
|
|
std.mem.copy(u8, pUser.firstnamebuf[0..], firstname);
|
|
pUser.firstnamelen = firstname.len;
|
|
}
|
|
if (last) |lastname| {
|
|
std.mem.copy(u8, pUser.lastnamebuf[0..], lastname);
|
|
pUser.lastnamelen = lastname.len;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// populate the list
|
|
pub fn list(self: *Self, out: *std.ArrayList(User)) !void {
|
|
// We lock only on insertion, deletion, and listing
|
|
self.lock.lock();
|
|
defer self.lock.unlock();
|
|
var it = JsonUserIterator.init(&self.users);
|
|
while (it.next()) |user| {
|
|
try out.append(user);
|
|
}
|
|
}
|
|
|
|
const JsonUserIterator = struct {
|
|
it: std.AutoHashMap(usize, InternalUser).ValueIterator = undefined,
|
|
const This = @This();
|
|
|
|
// careful:
|
|
// - Self refers to the file's struct
|
|
// - This refers to the JsonUserIterator struct
|
|
pub fn init(internal_users: *std.AutoHashMap(usize, InternalUser)) This {
|
|
return .{
|
|
.it = internal_users.valueIterator(),
|
|
};
|
|
}
|
|
|
|
pub fn next(this: *This) ?User {
|
|
if (this.it.next()) |pUser| {
|
|
return User{
|
|
.id = pUser.id,
|
|
.first_name = pUser.firstnamebuf[0..pUser.firstnamelen],
|
|
.last_name = pUser.lastnamebuf[0..pUser.lastnamelen],
|
|
};
|
|
}
|
|
return null;
|
|
}
|
|
};
|