Commit 4d09803414

Zander Khan <git@zander.xyz>
2021-01-16 19:06:44
Fix edge cases in fromOwnedSlice
1 parent a162a21
lib/std/priority_dequeue.zig
@@ -349,19 +349,22 @@ pub fn PriorityDequeue(comptime T: type) type {
         /// allocated with `allocator`.
         /// De-initialize with `deinit`.
         pub fn fromOwnedSlice(allocator: *Allocator, lessThanFn: fn (T, T) bool, items: []T) Self {
-            var dequeue = Self{
+            var queue = Self{
                 .items = items,
                 .len = items.len,
                 .allocator = allocator,
                 .lessThanFn = lessThanFn,
             };
-            const half = (dequeue.len >> 1) - 1;
+
+            if (queue.len <= 1) return queue;
+
+            const half = (queue.len >> 1) - 1;
             var i: usize = 0;
             while (i <= half) : (i += 1) {
                 const index = half - i;
-                dequeue.siftDown(index);
+                queue.siftDown(index);
             }
-            return dequeue;
+            return queue;
         }
 
         pub fn ensureCapacity(self: *Self, new_capacity: usize) !void {
@@ -646,6 +649,26 @@ test "std.PriorityDequeue: addSlice max" {
     }
 }
 
+test "std.PriorityDequeue: fromOwnedSlice trivial case 0" {
+    const items = [0]u32{};
+    const heap_items = try testing.allocator.dupe(u32, &items);
+    var heap = Heap.fromOwnedSlice(testing.allocator, lessThanComparison, heap_items[0..]);
+    defer heap.deinit();
+    expectEqual(@as(usize, 0), heap.len);
+    expect(heap.removeMinOrNull() == null);
+}
+
+test "std.PriorityDequeue: fromOwnedSlice trivial case 1" {
+    const items = [1]u32{1};
+    const heap_items = try testing.allocator.dupe(u32, &items);
+    var heap = Heap.fromOwnedSlice(testing.allocator, lessThanComparison, heap_items[0..]);
+    defer heap.deinit();
+
+    expectEqual(@as(usize, 1), heap.len);
+    expectEqual(items[0], heap.removeMin());
+    expect(heap.removeMinOrNull() == null);
+}
+
 test "std.PriorityDequeue: fromOwnedSlice" {
     const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
     const heap_items = try testing.allocator.dupe(u32, items[0..]);
lib/std/priority_queue.zig
@@ -166,6 +166,9 @@ pub fn PriorityQueue(comptime T: type) type {
                 .allocator = allocator,
                 .compareFn = compareFn,
             };
+
+            if (queue.len <= 1) return queue;
+
             const half = (queue.len >> 1) - 1;
             var i: usize = 0;
             while (i <= half) : (i += 1) {
@@ -352,6 +355,26 @@ test "std.PriorityQueue: addSlice" {
     }
 }
 
+test "std.PriorityQueue: fromOwnedSlice trivial case 0" {
+    const items = [0]u32{};
+    const queue_items = try testing.allocator.dupe(u32, &items);
+    var queue = PQ.fromOwnedSlice(testing.allocator, lessThan, queue_items[0..]);
+    defer queue.deinit();
+    expectEqual(@as(usize, 0), queue.len);
+    expect(queue.removeOrNull() == null);
+}
+
+test "std.PriorityQueue: fromOwnedSlice trivial case 1" {
+    const items = [1]u32{1};
+    const queue_items = try testing.allocator.dupe(u32, &items);
+    var queue = PQ.fromOwnedSlice(testing.allocator, lessThan, queue_items[0..]);
+    defer queue.deinit();
+
+    expectEqual(@as(usize, 1), queue.len);
+    expectEqual(items[0], queue.remove());
+    expect(queue.removeOrNull() == null);
+}
+
 test "std.PriorityQueue: fromOwnedSlice" {
     const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
     const heap_items = try testing.allocator.dupe(u32, items[0..]);