aboutsummaryrefslogtreecommitdiff
path: root/src/peek.zig
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-05-28 23:00:32 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-05-28 23:00:32 +0200
commit7b85276fc98643b1138df6f322b8bd657339ea96 (patch)
tree3d36e1d4961f92caa0fe0e00bb8e27a0fd1242b5 /src/peek.zig
downloadhuginn-7b85276fc98643b1138df6f322b8bd657339ea96.tar.gz
initial commit
Diffstat (limited to 'src/peek.zig')
-rw-r--r--src/peek.zig51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/peek.zig b/src/peek.zig
new file mode 100644
index 0000000..58911e9
--- /dev/null
+++ b/src/peek.zig
@@ -0,0 +1,51 @@
+pub fn peekable(iterator: anytype) Peekable(@TypeOf(iterator)) {
+ return .{ .iterator = iterator };
+}
+
+pub fn Peekable(Iterator: type) type {
+ const ActualIterator = switch (@typeInfo(Iterator)) {
+ .pointer => |p| p.child,
+ else => Iterator,
+ };
+ const Next = @typeInfo(@TypeOf(ActualIterator.next)).@"fn";
+ const Item = switch (@typeInfo(Next.return_type.?)) {
+ .optional => |o| o.child,
+ else => |i| i,
+ };
+ return struct {
+ iterator: Iterator,
+ peeked: ?Item = null,
+
+ pub fn peek(self: *Self) ?Item {
+ if (self.peeked) |peeked| return peeked;
+ const item = self.iterator.next();
+ self.peeked = item;
+ return item;
+ }
+
+ pub fn next(self: *Self) ?Item {
+ const item = if (self.peeked) |peeked| peeked else self.iterator.next();
+ self.peeked = null;
+ return item;
+ }
+
+ const Self = @This();
+ };
+}
+
+test peekable {
+ const expect = std.testing.expect;
+ // std.meta.de
+
+ var it = std.mem.window(u8, &[_]u8{ 1, 2, 3 }, 1, 1);
+ var peek = peekable(&it);
+ try expect(peek.next().?[0] == 1);
+ try expect(peek.peek().?[0] == 2);
+ try expect(peek.peek().?[0] == 2);
+ try expect(peek.next().?[0] == 2);
+ try expect(peek.next().?[0] == 3);
+ try expect(peek.peek() == null);
+ try expect(peek.next() == null);
+}
+
+const std = @import("std");