much much much better(ish)

This commit is contained in:
Jeeves 2024-03-25 20:11:13 -06:00
parent 0c51038b98
commit fd8ab6b4e7

View file

@ -158,25 +158,109 @@ pub const Listener = struct {
} }
pub fn handle(self: *Router, event: *Listener.Event) !void { pub fn handle(self: *Router, event: *Listener.Event) !void {
const handlerFn = self.route(event.req.uri.path); const handlerFn = try self.route(event.req.uri.path);
try handlerFn(event); try handlerFn(event);
} }
pub fn addRoute(self: *Router, path: []const u8, handler: HandlerFn) !void { pub fn addRoute(self: *Router, path: []const u8, handler: HandlerFn) !void {
try self.addStaticRoute(path, handler); var is_static_route = true;
} var sections = mem.splitScalar(u8, path, '/');
var node = &self.root_node;
var unnamed_placeholder_ctr: usize = 0;
var matched_nodes = std.ArrayList(*Node).init(self.allocator);
defer matched_nodes.deinit();
try matched_nodes.append(node);
while (sections.next()) |section| {
if (section.len == 0) continue;
std.debug.print("adding section {s}\n", .{section});
if (node.children.get(section)) |child| {
node = child;
} else {
var child_node = try Node.init(self.allocator);
child_node.type = if (mem.startsWith(u8, section, "**"))
.wildcard
else if ((section.len > 0 and section[0] == ':') or mem.eql(u8, section, "*"))
.placeholder
else
.normal;
child_node.parent = node;
try node.children.put(section, child_node);
switch (child_node.type) {
.normal => {},
.wildcard => {
node.wildcard_child_node = child_node;
child_node.param_name = if (section.len > 3) section[3..] else "_";
is_static_route = false;
},
.placeholder => {
child_node.param_name = if (mem.eql(u8, section, "*")) blk: {
const s = try std.fmt.allocPrint(self.allocator, "_{d}", .{unnamed_placeholder_ctr}); // TODO: this will leak
unnamed_placeholder_ctr += 1;
break :blk s;
} else section[1..];
try node.placeholder_children.append(child_node);
is_static_route = false;
},
}
try matched_nodes.append(child_node);
node = child_node;
}
}
fn addStaticRoute(self: *Router, path: []const u8, handler: HandlerFn) !void {
const node = try Node.init(self.allocator);
node.handler = handler; node.handler = handler;
try self.static_routes.put(path, node);
if (is_static_route) try self.static_routes.put(path, node);
} }
// fn addNode(self: *Router, path: []const u8) !void {} pub fn route(self: *Router, path: []const u8) !HandlerFn {
pub fn route(self: *Router, path: []const u8) HandlerFn {
if (self.static_routes.get(path)) |rt| return rt.handler; if (self.static_routes.get(path)) |rt| return rt.handler;
if (self.root_node.wildcard_child_node) |node| return node.handler;
var params = std.StringHashMap([]const u8).init(self.allocator);
defer params.deinit();
var params_found = false;
var wildcard_node: ?*Node = null;
var node: *Node = &self.root_node;
var wildcard_param: ?[]const u8 = null;
// std.debug.print("{any}\n", .{node.handler});
var sections = mem.splitScalar(u8, path, '/');
while (sections.next()) |section| {
if (node.wildcard_child_node) |wildcard_child_node| {
wildcard_node = wildcard_child_node;
wildcard_param = sections.rest();
}
const next_node = node.children.get(section);
if (next_node) |child| {
node = child;
std.debug.print("found child_node {any}\n", .{child});
} else {
var child_node: ?*Node = null;
if (node.placeholder_children.items.len > 1) {
// TODO
} else if (node.placeholder_children.items.len == 1)
child_node = node.placeholder_children.items[0];
if (child_node) |n| {
std.debug.print("didn't find child_node {any}\n", .{child_node});
if (n.param_name) |name| try params.put(name, section);
params_found = true;
node = n;
} else break;
}
}
// std.debug.print("{any}\n", .{node.handler});
if (wildcard_node) |wildcard| {
node = wildcard;
try params.put("_", wildcard_param.?);
params_found = true;
}
return self.root_node.handler; return self.root_node.handler;
} }
@ -186,6 +270,7 @@ pub const Listener = struct {
parent: ?*Node = null, parent: ?*Node = null,
children: std.StringHashMap(*Node), children: std.StringHashMap(*Node),
handler: HandlerFn, handler: HandlerFn,
param_name: ?[]const u8 = null,
wildcard_child_node: ?*Node = null, wildcard_child_node: ?*Node = null,
placeholder_children: std.ArrayList(*Node), placeholder_children: std.ArrayList(*Node),