1
0
Fork 0
mirror of https://github.com/zigzap/zap.git synced 2025-10-20 15:14:08 +00:00
zap/examples/endpoint/users.zig
2023-01-19 20:34:47 +01:00

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;
}
};