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 json_utils = @import("./json.zig");
|
||||||
const fields = @import("./fields.zig");
|
const fields = @import("./fields.zig");
|
||||||
|
|
||||||
|
const PathIter = util.PathIter;
|
||||||
|
|
||||||
/// Takes an iterable of middlewares and chains them together.
|
/// Takes an iterable of middlewares and chains them together.
|
||||||
pub fn apply(middlewares: anytype) Apply(@TypeOf(middlewares)) {
|
pub fn apply(middlewares: anytype) Apply(@TypeOf(middlewares)) {
|
||||||
return applyInternal(middlewares, std.meta.fields(@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 };
|
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
|
// helper function for doing route analysis
|
||||||
fn pathMatches(route: []const u8, path: []const u8) bool {
|
fn pathMatches(route: []const u8, path: []const u8) bool {
|
||||||
var path_iter = PathIter.from(path);
|
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 const testing = struct {
|
||||||
pub fn expectDeepEqual(expected: anytype, actual: @TypeOf(expected)) !void {
|
pub fn expectDeepEqual(expected: anytype, actual: @TypeOf(expected)) !void {
|
||||||
const T = @TypeOf(expected);
|
const T = @TypeOf(expected);
|
||||||
|
|
Loading…
Reference in a new issue