Move PathIter to util

This commit is contained in:
jaina heartles 2022-12-09 04:30:38 -08:00
parent 9d38aaec38
commit 7b16fd6390
2 changed files with 54 additions and 52 deletions

View file

@ -20,6 +20,8 @@ const urlencode = @import("./urlencode.zig");
const json_utils = @import("./json.zig");
const fields = @import("./fields.zig");
const PathIter = util.PathIter;
/// Takes an iterable of middlewares and chains them together.
pub fn apply(middlewares: anytype) Apply(@TypeOf(middlewares)) {
return applyInternal(middlewares, std.meta.fields(@TypeOf(middlewares)));
@ -350,58 +352,6 @@ pub fn router(routes: anytype) Router(@TypeOf(routes)) {
return Router(@TypeOf(routes)){ .routes = routes };
}
pub const PathIter = struct {
is_first: bool,
iter: std.mem.SplitIterator(u8),
pub fn from(path: []const u8) PathIter {
return .{ .is_first = true, .iter = std.mem.split(u8, path, "/") };
}
pub fn next(self: *PathIter) ?[]const u8 {
defer self.is_first = false;
while (self.iter.next()) |it| if (it.len != 0) {
return it;
};
if (self.is_first) return self.iter.rest();
return null;
}
pub fn first(self: *PathIter) []const u8 {
std.debug.assert(self.is_first);
return self.next().?;
}
pub fn rest(self: *PathIter) []const u8 {
return self.iter.rest();
}
};
test "PathIter" {
const testCase = struct {
fn case(path: []const u8, segments: []const []const u8) !void {
var iter = PathIter.from(path);
for (segments) |s| {
try std.testing.expectEqualStrings(s, iter.next() orelse return error.TestExpectedEqual);
}
try std.testing.expect(iter.next() == null);
}
}.case;
try testCase("", &.{""});
try testCase("*", &.{"*"});
try testCase("/", &.{""});
try testCase("/ab/cd", &.{ "ab", "cd" });
try testCase("/ab/cd/", &.{ "ab", "cd" });
try testCase("/ab/cd//", &.{ "ab", "cd" });
try testCase("ab", &.{"ab"});
try testCase("/ab", &.{"ab"});
try testCase("ab/", &.{"ab"});
try testCase("ab//ab//", &.{ "ab", "ab" });
}
// helper function for doing route analysis
fn pathMatches(route: []const u8, path: []const u8) bool {
var path_iter = PathIter.from(path);

View file

@ -219,6 +219,58 @@ pub fn comptimeToCrlf(comptime str: []const u8) []const u8 {
}
}
pub const PathIter = struct {
is_first: bool,
iter: std.mem.SplitIterator(u8),
pub fn from(path: []const u8) PathIter {
return .{ .is_first = true, .iter = std.mem.split(u8, path, "/") };
}
pub fn next(self: *PathIter) ?[]const u8 {
defer self.is_first = false;
while (self.iter.next()) |it| if (it.len != 0) {
return it;
};
if (self.is_first) return self.iter.rest();
return null;
}
pub fn first(self: *PathIter) []const u8 {
std.debug.assert(self.is_first);
return self.next().?;
}
pub fn rest(self: *PathIter) []const u8 {
return self.iter.rest();
}
};
test "PathIter" {
const testCase = struct {
fn case(path: []const u8, segments: []const []const u8) !void {
var iter = PathIter.from(path);
for (segments) |s| {
try std.testing.expectEqualStrings(s, iter.next() orelse return error.TestExpectedEqual);
}
try std.testing.expect(iter.next() == null);
}
}.case;
try testCase("", &.{""});
try testCase("*", &.{"*"});
try testCase("/", &.{""});
try testCase("/ab/cd", &.{ "ab", "cd" });
try testCase("/ab/cd/", &.{ "ab", "cd" });
try testCase("/ab/cd//", &.{ "ab", "cd" });
try testCase("ab", &.{"ab"});
try testCase("/ab", &.{"ab"});
try testCase("ab/", &.{"ab"});
try testCase("ab//ab//", &.{ "ab", "ab" });
}
pub const testing = struct {
pub fn expectDeepEqual(expected: anytype, actual: @TypeOf(expected)) !void {
const T = @TypeOf(expected);