refactor iterators/adapters to wrap inner structs in Iterator internally

This commit is contained in:
Luuk Machielse 2025-12-10 16:59:30 +01:00
parent 1e9bd2454e
commit 0843f9f17c

View file

@ -3,7 +3,7 @@ const assert = std.debug.assert;
pub fn iter(comptime T: type) type { pub fn iter(comptime T: type) type {
return struct { return struct {
pub fn fromSlice(slice: anytype) Iterator(SliceIter(T, .value)) { pub fn fromSlice(slice: anytype) SliceIter(T, .value) {
return .{ .inner = .{ .slice = slice } }; return .{ .inner = .{ .slice = slice } };
} }
@ -19,19 +19,19 @@ pub fn iter(comptime T: type) type {
try expectEqual(null, it.next()); try expectEqual(null, it.next());
} }
pub fn range(start: T, end: T) Iterator(Range(T, .exclusive)) { pub fn range(start: T, end: T) Range(T, .exclusive) {
return .{ .inner = .{ .current = start, .end = end } }; return .{ .inner = .{ .current = start, .end = end } };
} }
pub fn rangeInclusive(start: T, end: T) Iterator(Range(T, .inclusive)) { pub fn rangeInclusive(start: T, end: T) Range(T, .inclusive) {
return .{ .inner = .{ .current = start, .end = end } }; return .{ .inner = .{ .current = start, .end = end } };
} }
pub fn once(value: T) Iterator(Once(T)) { pub fn once(value: T) Once(T) {
return .{ .inner = .{ .value = value } }; return .{ .inner = .{ .value = value } };
} }
pub const empty: Iterator(Empty(T)) = .{ .inner = .{} }; pub const empty: Empty(T) = .{ .inner = .{} };
test empty { test empty {
var it = iter(i32).empty; var it = iter(i32).empty;
@ -106,11 +106,11 @@ pub fn Iterator(comptime Inner: type) type {
self: Self, self: Self,
comptime T: type, comptime T: type,
f: fn (Item) T, f: fn (Item) T,
) Iterator(adapters.Map(Self, T, f)) { ) adapters.Map(Self, T, f) {
return .{ .inner = .{ .inner = self } }; return .{ .inner = .{ .inner = self } };
} }
pub fn filter(self: Self, predicate: fn (Item) bool) Iterator(adapters.Filter(Self, predicate)) { pub fn filter(self: Self, predicate: fn (Item) bool) adapters.Filter(Self, predicate) {
return .{ .inner = .{ .inner = self } }; return .{ .inner = .{ .inner = self } };
} }
@ -118,18 +118,18 @@ pub fn Iterator(comptime Inner: type) type {
self: Self, self: Self,
comptime T: type, comptime T: type,
f: anytype, f: anytype,
) Iterator(adapters.FilterMap(Self, T, f)) { ) adapters.FilterMap(Self, T, f) {
return .{ .inner = .{ .inner = self } }; return .{ .inner = .{ .inner = self } };
} }
pub fn take( pub fn take(
self: Self, self: Self,
n: usize, n: usize,
) Iterator(adapters.Take(Self)) { ) adapters.Take(Self) {
return .{ .inner = .{ .inner = self, .n = n } }; return .{ .inner = .{ .inner = self, .n = n } };
} }
pub fn enumerate(self: Self) Iterator(adapters.Enumerate(Self)) { pub fn enumerate(self: Self) adapters.Enumerate(Self) {
return .{ .inner = .{ .inner = self } }; return .{ .inner = .{ .inner = self } };
} }
@ -176,11 +176,11 @@ pub fn Iterator(comptime Inner: type) type {
}.some); }.some);
} }
pub fn chain(self: Self, other: anytype) Iterator(adapters.Chain(Self, @TypeOf(other))) { pub fn chain(self: Self, other: anytype) adapters.Chain(Self, @TypeOf(other)) {
return .{ .inner = .{ .first = self, .second = other } }; return .{ .inner = .{ .first = self, .second = other } };
} }
pub fn zip(self: Self, other: anytype) Iterator(adapters.Zip(Self, @TypeOf(other))) { pub fn zip(self: Self, other: anytype) adapters.Zip(Self, @TypeOf(other)) {
return .{ .inner = .{ .a = self, .b = other } }; return .{ .inner = .{ .a = self, .b = other } };
} }
@ -215,7 +215,7 @@ pub const adapters = struct {
comptime T: type, comptime T: type,
comptime f: fn (Inner.Item) T, comptime f: fn (Inner.Item) T,
) type { ) type {
return struct { return Iterator(struct {
inner: Inner, inner: Inner,
pub const Item = T; pub const Item = T;
@ -225,11 +225,11 @@ pub const adapters = struct {
pub fn next(self: *Self) ?Item { pub fn next(self: *Self) ?Item {
return if (self.inner.next()) |val| f(val) else null; return if (self.inner.next()) |val| f(val) else null;
} }
}; });
} }
pub fn Filter(comptime Inner: type, comptime predicate: fn (Inner.Item) bool) type { pub fn Filter(comptime Inner: type, comptime predicate: fn (Inner.Item) bool) type {
return struct { return Iterator(struct {
inner: Inner, inner: Inner,
pub const Item = Inner.Item; pub const Item = Inner.Item;
@ -243,11 +243,11 @@ pub const adapters = struct {
return null; return null;
} }
}; });
} }
pub fn FilterMap(comptime Inner: type, comptime T: type, comptime f: fn (Inner.Item) ?T) type { pub fn FilterMap(comptime Inner: type, comptime T: type, comptime f: fn (Inner.Item) ?T) type {
return struct { return Iterator(struct {
inner: Inner, inner: Inner,
pub const Item = T; pub const Item = T;
@ -261,11 +261,11 @@ pub const adapters = struct {
return null; return null;
} }
}; });
} }
pub fn Take(comptime Inner: type) type { pub fn Take(comptime Inner: type) type {
return struct { return Iterator(struct {
i: usize = 0, i: usize = 0,
n: usize, n: usize,
inner: Inner, inner: Inner,
@ -279,11 +279,11 @@ pub const adapters = struct {
defer self.i += 1; defer self.i += 1;
return self.inner.next(); return self.inner.next();
} }
}; });
} }
pub fn Enumerate(comptime Inner: type) type { pub fn Enumerate(comptime Inner: type) type {
return struct { return Iterator(struct {
inner: Inner, inner: Inner,
i: usize = 0, i: usize = 0,
@ -299,12 +299,12 @@ pub const adapters = struct {
return null; return null;
} }
}; });
} }
pub fn Chain(comptime First: type, comptime Second: type) type { pub fn Chain(comptime First: type, comptime Second: type) type {
comptime assert(First.Item == Second.Item); comptime assert(First.Item == Second.Item);
return struct { return Iterator(struct {
first: First, first: First,
second: Second, second: Second,
@ -319,11 +319,11 @@ pub const adapters = struct {
pub fn sizeHint(self: *const Self) usize { pub fn sizeHint(self: *const Self) usize {
return self.first.sizeHint() + self.second.sizeHint(); return self.first.sizeHint() + self.second.sizeHint();
} }
}; });
} }
pub fn Zip(comptime A: type, comptime B: type) type { pub fn Zip(comptime A: type, comptime B: type) type {
return struct { return Iterator(struct {
a: A, a: A,
b: B, b: B,
@ -336,14 +336,14 @@ pub const adapters = struct {
const y = self.b.next() orelse return null; const y = self.b.next() orelse return null;
return .{ x, y }; return .{ x, y };
} }
}; });
} }
}; };
pub const RangeEndType = enum { exclusive, inclusive }; pub const RangeEndType = enum { exclusive, inclusive };
pub fn Range(comptime T: type, end_type: RangeEndType) type { pub fn Range(comptime T: type, end_type: RangeEndType) type {
return struct { return Iterator(struct {
current: T, current: T,
end: T, end: T,
@ -362,11 +362,11 @@ pub fn Range(comptime T: type, end_type: RangeEndType) type {
pub fn sizeHint(self: *const Self) usize { pub fn sizeHint(self: *const Self) usize {
return @intCast(self.end - self.current + @intFromBool(end_type == .inclusive)); return @intCast(self.end - self.current + @intFromBool(end_type == .inclusive));
} }
}; });
} }
pub fn Once(comptime T: type) type { pub fn Once(comptime T: type) type {
return struct { const Inner = struct {
value: ?T, value: ?T,
pub const Item = T; pub const Item = T;
@ -382,12 +382,14 @@ pub fn Once(comptime T: type) type {
return @intFromBool(self.value != null); return @intFromBool(self.value != null);
} }
}; };
return Iterator(Inner);
} }
pub const SliceItemType = enum { value, ptr, const_ptr }; pub const SliceItemType = enum { value, ptr, const_ptr };
pub fn SliceIter(comptime T: type, comptime item_type: SliceItemType) type { pub fn SliceIter(comptime T: type, comptime item_type: SliceItemType) type {
return struct { const Inner = struct {
slice: switch (item_type) { slice: switch (item_type) {
.value, .const_ptr => []const T, .value, .const_ptr => []const T,
.ptr => []T, .ptr => []T,
@ -415,18 +417,24 @@ pub fn SliceIter(comptime T: type, comptime item_type: SliceItemType) type {
return self.slice.len - self.i; return self.slice.len - self.i;
} }
}; };
return Iterator(Inner);
} }
pub fn Empty(comptime T: type) type { pub fn Empty(comptime T: type) type {
return struct { const Inner = struct {
pub const Item = T; pub const Item = T;
pub fn next(_: *Empty(T)) ?Item { const Self = @This();
pub fn next(_: *Self) ?Item {
return null; return null;
} }
pub fn sizeHint(_: *const Empty(T)) usize { pub fn sizeHint(_: *const Self) usize {
return 0; return 0;
} }
}; };
return Iterator(Inner);
} }