Move PathIter to util
This commit is contained in:
parent
9d38aaec38
commit
7b16fd6390
2 changed files with 54 additions and 52 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue