Commit c3d8b1ffeb

Andrew Kelley <andrew@ziglang.org>
2019-12-10 21:08:10
remove iterator API from std.ArrayList
This is not a meaningful abstraction. Use a for loop on the result of `toSlice` or `toSliceConst`. An iterator can be implemented on top of ArrayList by applications which want additional functionality, such as removing elements while iterating. Closes #3037.
1 parent f30af12
Changed files (2)
lib/std/http/headers.zig
@@ -133,8 +133,7 @@ pub const Headers = struct {
             self.index.deinit();
         }
         {
-            var it = self.data.iterator();
-            while (it.next()) |entry| {
+            for (self.data.toSliceConst()) |entry| {
                 entry.deinit();
             }
             self.data.deinit();
@@ -144,27 +143,20 @@ pub const Headers = struct {
     pub fn clone(self: Self, allocator: *Allocator) !Self {
         var other = Headers.init(allocator);
         errdefer other.deinit();
-        try other.data.ensureCapacity(self.data.count());
+        try other.data.ensureCapacity(self.data.len);
         try other.index.initCapacity(self.index.entries.len);
-        var it = self.data.iterator();
-        while (it.next()) |entry| {
+        for (self.data.toSliceConst()) |entry| {
             try other.append(entry.name, entry.value, entry.never_index);
         }
         return other;
     }
 
-    pub fn count(self: Self) usize {
-        return self.data.count();
-    }
-
-    pub const Iterator = HeaderList.Iterator;
-
-    pub fn iterator(self: Self) Iterator {
-        return self.data.iterator();
+    pub fn toSlice(self: Self) []const HeaderEntry {
+        return self.data.toSliceConst();
     }
 
     pub fn append(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
-        const n = self.data.count() + 1;
+        const n = self.data.len + 1;
         try self.data.ensureCapacity(n);
         var entry: HeaderEntry = undefined;
         if (self.index.get(name)) |kv| {
@@ -190,7 +182,7 @@ pub const Headers = struct {
     pub fn upsert(self: *Self, name: []const u8, value: []const u8, never_index: ?bool) !void {
         if (self.index.get(name)) |kv| {
             const dex = kv.value;
-            if (dex.count() != 1)
+            if (dex.len != 1)
                 return error.CannotUpsertMultiValuedField;
             var e = &self.data.at(dex.at(0));
             try e.modify(value, never_index);
@@ -209,7 +201,7 @@ pub const Headers = struct {
         if (self.index.remove(name)) |kv| {
             var dex = &kv.value;
             // iterate backwards
-            var i = dex.count();
+            var i = dex.len;
             while (i > 0) {
                 i -= 1;
                 const data_index = dex.at(i);
@@ -232,18 +224,18 @@ pub const Headers = struct {
         const removed = self.data.orderedRemove(i);
         const kv = self.index.get(removed.name).?;
         var dex = &kv.value;
-        if (dex.count() == 1) {
+        if (dex.len == 1) {
             // was last item; delete the index
             _ = self.index.remove(kv.key);
             dex.deinit();
             removed.deinit();
             self.allocator.free(kv.key);
         } else {
-            dex.shrink(dex.count() - 1);
+            dex.shrink(dex.len - 1);
             removed.deinit();
         }
         // if it was the last item; no need to rebuild index
-        if (i != self.data.count()) {
+        if (i != self.data.len) {
             self.rebuild_index();
         }
     }
@@ -254,18 +246,18 @@ pub const Headers = struct {
         const removed = self.data.swapRemove(i);
         const kv = self.index.get(removed.name).?;
         var dex = &kv.value;
-        if (dex.count() == 1) {
+        if (dex.len == 1) {
             // was last item; delete the index
             _ = self.index.remove(kv.key);
             dex.deinit();
             removed.deinit();
             self.allocator.free(kv.key);
         } else {
-            dex.shrink(dex.count() - 1);
+            dex.shrink(dex.len - 1);
             removed.deinit();
         }
         // if it was the last item; no need to rebuild index
-        if (i != self.data.count()) {
+        if (i != self.data.len) {
             self.rebuild_index();
         }
     }
@@ -289,10 +281,9 @@ pub const Headers = struct {
     pub fn get(self: Self, allocator: *Allocator, name: []const u8) !?[]const HeaderEntry {
         const dex = self.getIndices(name) orelse return null;
 
-        const buf = try allocator.alloc(HeaderEntry, dex.count());
-        var it = dex.iterator();
+        const buf = try allocator.alloc(HeaderEntry, dex.len);
         var n: usize = 0;
-        while (it.next()) |idx| {
+        for (dex.toSliceConst()) |idx| {
             buf[n] = self.data.at(idx);
             n += 1;
         }
@@ -314,9 +305,8 @@ pub const Headers = struct {
 
         // adapted from mem.join
         const total_len = blk: {
-            var sum: usize = dex.count() - 1; // space for separator(s)
-            var it = dex.iterator();
-            while (it.next()) |idx|
+            var sum: usize = dex.len - 1; // space for separator(s)
+            for (dex.toSliceConst()) |idx|
                 sum += self.data.at(idx).value.len;
             break :blk sum;
         };
@@ -348,10 +338,9 @@ pub const Headers = struct {
             }
         }
         { // fill up indexes again; we know capacity is fine from before
-            var it = self.data.iterator();
-            while (it.next()) |entry| {
+            for (self.data.toSliceConst()) |entry, i| {
                 var dex = &self.index.get(entry.name).?.value;
-                dex.appendAssumeCapacity(it.count);
+                dex.appendAssumeCapacity(i);
             }
         }
     }
@@ -369,8 +358,7 @@ pub const Headers = struct {
         comptime Errors: type,
         output: fn (@TypeOf(context), []const u8) Errors!void,
     ) Errors!void {
-        var it = self.iterator();
-        while (it.next()) |entry| {
+        for (self.toSlice()) |entry| {
             try output(context, entry.name);
             try output(context, ": ");
             try output(context, entry.value);
@@ -386,8 +374,7 @@ test "Headers.iterator" {
     try h.append("cookie", "somevalue", null);
 
     var count: i32 = 0;
-    var it = h.iterator();
-    while (it.next()) |e| {
+    for (h.toSlice()) |e| {
         if (count == 0) {
             testing.expectEqualSlices(u8, "foo", e.name);
             testing.expectEqualSlices(u8, "bar", e.value);
@@ -420,10 +407,10 @@ test "Headers.delete" {
     try h.append("cookie", "somevalue", null);
 
     testing.expectEqual(false, h.delete("not-present"));
-    testing.expectEqual(@as(usize, 3), h.count());
+    testing.expectEqual(@as(usize, 3), h.toSlice().len);
 
     testing.expectEqual(true, h.delete("foo"));
-    testing.expectEqual(@as(usize, 2), h.count());
+    testing.expectEqual(@as(usize, 2), h.toSlice().len);
     {
         const e = h.at(0);
         testing.expectEqualSlices(u8, "baz", e.name);
@@ -448,7 +435,7 @@ test "Headers.orderedRemove" {
     try h.append("cookie", "somevalue", null);
 
     h.orderedRemove(0);
-    testing.expectEqual(@as(usize, 2), h.count());
+    testing.expectEqual(@as(usize, 2), h.toSlice().len);
     {
         const e = h.at(0);
         testing.expectEqualSlices(u8, "baz", e.name);
@@ -471,7 +458,7 @@ test "Headers.swapRemove" {
     try h.append("cookie", "somevalue", null);
 
     h.swapRemove(0);
-    testing.expectEqual(@as(usize, 2), h.count());
+    testing.expectEqual(@as(usize, 2), h.toSlice().len);
     {
         const e = h.at(0);
         testing.expectEqualSlices(u8, "cookie", e.name);
lib/std/array_list.zig
@@ -84,11 +84,6 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
             self.items[i] = item;
         }
 
-        /// Return length of the list.
-        pub fn count(self: Self) usize {
-            return self.len;
-        }
-
         /// Return the maximum number of items the list can hold
         /// without allocating more memory.
         pub fn capacity(self: Self) usize {
@@ -114,7 +109,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
             return result;
         }
 
-        /// Insert `item` at index `n`. Moves `list[n .. list.count()]`
+        /// Insert `item` at index `n`. Moves `list[n .. list.len]`
         /// to make room.
         pub fn insert(self: *Self, n: usize, item: T) !void {
             try self.ensureCapacity(self.len + 1);
@@ -125,7 +120,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
         }
 
         /// Insert slice `items` at index `n`. Moves
-        /// `list[n .. list.count()]` to make room.
+        /// `list[n .. list.len]` to make room.
         pub fn insertSlice(self: *Self, n: usize, items: SliceConst) !void {
             try self.ensureCapacity(self.len + items.len);
             self.len += items.len;
@@ -222,7 +217,7 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
         }
 
         pub fn addOneAssumeCapacity(self: *Self) *T {
-            assert(self.count() < self.capacity());
+            assert(self.len < self.capacity());
             const result = &self.items[self.len];
             self.len += 1;
             return result;
@@ -240,31 +235,6 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type {
             if (self.len == 0) return null;
             return self.pop();
         }
-
-        pub const Iterator = struct {
-            list: *const Self,
-            // how many items have we returned
-            count: usize,
-
-            pub fn next(it: *Iterator) ?T {
-                if (it.count >= it.list.len) return null;
-                const val = it.list.at(it.count);
-                it.count += 1;
-                return val;
-            }
-
-            pub fn reset(it: *Iterator) void {
-                it.count = 0;
-            }
-        };
-
-        /// Return an iterator over the list.
-        pub fn iterator(self: *const Self) Iterator {
-            return Iterator{
-                .list = self,
-                .count = 0,
-            };
-        }
     };
 }
 
@@ -275,7 +245,7 @@ test "std.ArrayList.init" {
     var list = ArrayList(i32).init(allocator);
     defer list.deinit();
 
-    testing.expect(list.count() == 0);
+    testing.expect(list.len == 0);
     testing.expect(list.capacity() == 0);
 }
 
@@ -284,7 +254,7 @@ test "std.ArrayList.initCapacity" {
     const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
     var list = try ArrayList(i8).initCapacity(allocator, 200);
     defer list.deinit();
-    testing.expect(list.count() == 0);
+    testing.expect(list.len == 0);
     testing.expect(list.capacity() >= 200);
 }
 
@@ -426,35 +396,6 @@ test "std.ArrayList.swapRemoveOrError" {
     testing.expectError(error.OutOfBounds, list.swapRemoveOrError(2));
 }
 
-test "std.ArrayList.iterator" {
-    var list = ArrayList(i32).init(debug.global_allocator);
-    defer list.deinit();
-
-    try list.append(1);
-    try list.append(2);
-    try list.append(3);
-
-    var count: i32 = 0;
-    var it = list.iterator();
-    while (it.next()) |next| {
-        testing.expect(next == count + 1);
-        count += 1;
-    }
-
-    testing.expect(count == 3);
-    testing.expect(it.next() == null);
-    it.reset();
-    count = 0;
-    while (it.next()) |next| {
-        testing.expect(next == count + 1);
-        count += 1;
-        if (count == 2) break;
-    }
-
-    it.reset();
-    testing.expect(it.next().? == 1);
-}
-
 test "std.ArrayList.insert" {
     var list = ArrayList(i32).init(debug.global_allocator);
     defer list.deinit();