Store path segments instead of path

This commit is contained in:
jaina heartles 2022-05-20 22:48:43 -07:00
parent d885dc5fc8
commit c19cc267bf
1 changed files with 40 additions and 15 deletions

View File

@ -45,33 +45,44 @@ const PathIter = struct {
}
};
fn splitPath(comptime path: []const u8) []const []const u8 {
comptime {
var segments: [path.len][]const u8 = undefined;
var iter = PathIter.from(path);
var it = iter.next();
var count = 0;
while (it != null) : (it = iter.next()) {
segments[count] = it.?;
count += 1;
}
return segments[0..count];
}
}
fn RouteWithContext(comptime Context: type) type {
return struct {
const Self = @This();
pub const Handler = fn (Context) void;
path: []const u8,
path_segments: []const []const u8,
method: http.Method,
handler: Handler,
pub fn bind(method: http.Method, comptime path: []const u8, handler: Handler) Self {
return .{ .method = method, .path = path, .handler = handler };
return .{ .method = method, .path_segments = splitPath(path), .handler = handler };
}
fn matchesPath(self: *const Self, path: []const u8) bool {
var route_segs = PathIter.from(self.path);
var path_segs = PathIter.from(path);
fn matchesPath(self: *const Self, request_path: []const u8) bool {
var request_segments = PathIter.from(request_path);
var r = route_segs.next();
var p = path_segs.next();
while (r != null and p != null) : ({
r = route_segs.next();
p = path_segs.next();
}) {
if (!ciutf8.eql(r.?, p.?)) return false;
for (self.path_segments) |route_seg| {
const request_seg = request_segments.next() orelse return false;
if (!ciutf8.eql(route_seg, request_seg)) return false;
}
return r == null and p == null;
return request_segments.next() == null;
}
};
}
@ -125,10 +136,24 @@ const _tests = struct {
try std.testing.expectEqual(@as(?[]const u8, null), it.next());
}
fn expectEqualSegments(expected: []const []const u8, actual: []const []const u8) !void {
try std.testing.expectEqual(expected.len, actual.len);
for (expected) |_, i| {
try std.testing.expectEqualStrings(expected[i], actual[i]);
}
}
test "splitPath" {
const path = "//ab/c/de";
const segments = splitPath(path);
try expectEqualSegments(&[_][]const u8{ "ab", "c", "de" }, segments);
}
fn expectEqualRoute(expected: RouteWithContext(Context), actual: RouteWithContext(Context)) !void {
try std.testing.expectEqual(expected.method, actual.method);
try std.testing.expectEqual(expected.handler, actual.handler);
try std.testing.expectEqualStrings(expected.path, actual.path);
try expectEqualSegments(expected.path_segments, actual.path_segments);
}
test "RouteWithContext(T).bind" {
@ -137,7 +162,7 @@ const _tests = struct {
try expectEqualRoute(R{
.method = .GET,
.path = "//ab//cd",
.path_segments = &[_][]const u8{ "ab", "cd" },
.handler = dummyHandler,
}, r);
}