diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 73a91f1..6c68fb8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,6 +1,10 @@ name: build -on: [push, pull_request] +on: + push: + branches: + - main + pull_request: jobs: build: @@ -14,7 +18,9 @@ jobs: with: submodules: recursive fetch-depth: 0 - - uses: mlugg/setup-zig@v2 + - uses: zed-industries/setup-zig@node24 + with: + version: 0.17.0 - name: Testing run: zig run runall.zig @@ -23,5 +29,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - - uses: mlugg/setup-zig@v2 + - uses: zed-industries/setup-zig@node24 + with: + version: 0.17.0 - run: zig fmt --check --ast-check */*.zig diff --git a/README.md b/README.md index ac4343f..09aa417 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ ### How to build **Require:** -- [Zig v0.16.0 or higher](https://ziglang.org/download), self-hosting (stage3) compiler. +- [Zig v0.17.0 or higher](https://ziglang.org/download), self-hosting (stage3) compiler. ### Test all diff --git a/search/binarySearchTree.zig b/search/binarySearchTree.zig index cd18872..c4d5a7e 100644 --- a/search/binarySearchTree.zig +++ b/search/binarySearchTree.zig @@ -42,11 +42,11 @@ pub fn BinarySearchTree(comptime T: type) type { // Arguments: // key: T - the key to be removed from the tree pub fn remove(self: *Self, key: T) !void { - if (self.root == null) { - return; + var removed = false; + self.root = try self._remove(self.root, key, &removed); + if (removed) { + self.size -= 1; } - self.root = try self._remove(self.root, key); - self.size -= 1; } // Function to search if a key exists in the tree @@ -84,10 +84,8 @@ pub fn BinarySearchTree(comptime T: type) type { // Function that destroys the allocated memory of the whole tree // Uses the _destroy helper private function pub fn destroy(self: *Self) void { - if (self.root == null) { - return; - } self._destroy(self.root); + self.root = null; self.size = 0; } @@ -114,16 +112,17 @@ pub fn BinarySearchTree(comptime T: type) type { return root; } - fn _remove(self: *Self, root: ?*node, key: T) !?*node { + fn _remove(self: *Self, root: ?*node, key: T, removed: *bool) !?*node { if (root == null) { return root; } if (root.?.info < key) { - root.?.right = try self._remove(root.?.right, key); + root.?.right = try self._remove(root.?.right, key, removed); } else if (root.?.info > key) { - root.?.left = try self._remove(root.?.left, key); + root.?.left = try self._remove(root.?.left, key, removed); } else { + removed.* = true; if (root.?.left == null and root.?.right == null) { self.allocator.destroy(root.?); return null; @@ -139,7 +138,7 @@ pub fn BinarySearchTree(comptime T: type) type { var curr: ?*node = root.?.right; while (curr.?.left != null) : (curr = curr.?.left) {} root.?.info = curr.?.info; - root.?.right = try self._remove(root.?.right, curr.?.info); + root.?.right = try self._remove(root.?.right, curr.?.info, removed); } } @@ -282,4 +281,43 @@ test "Testing operations on empty trees" { try testing.expect(t.search(10) == false); try t.remove(10); try testing.expect(t.search(10) == false); + try testing.expect(t.size == 0); +} + +test "Testing removal of absent keys keeps size" { + var gpa = std.heap.DebugAllocator(.{}){}; + defer assert(gpa.deinit() == .ok); + var allocator = gpa.allocator(); + + var t = BinarySearchTree(i32){ .allocator = &allocator }; + defer t.destroy(); + + try t.insert(10); + try t.insert(5); + try t.insert(15); + + try t.remove(7); + try testing.expect(t.size == 3); + try t.remove(7); + try testing.expect(t.size == 3); + try testing.expect(t.search(10) == true); + + try t.remove(10); + try testing.expect(t.size == 2); +} + +test "Testing destroy leaves an empty reusable tree" { + var gpa = std.heap.DebugAllocator(.{}){}; + defer assert(gpa.deinit() == .ok); + var allocator = gpa.allocator(); + + var t = BinarySearchTree(i32){ .allocator = &allocator }; + defer t.destroy(); + + try t.insert(10); + t.destroy(); + try testing.expect(t.size == 0); + try testing.expect(t.root == null); + try t.insert(5); + try testing.expect(t.size == 1); } diff --git a/tiger_style/raft_consensus.zig b/tiger_style/raft_consensus.zig index 9f54218..1ac7d33 100644 --- a/tiger_style/raft_consensus.zig +++ b/tiger_style/raft_consensus.zig @@ -39,7 +39,7 @@ pub const NodeState = enum(u8) { pub fn validate(self: NodeState) void { // Ensure state is valid - assert(@intFromEnum(self) <= 2); + assert(@backingInt(self) <= 2); } }; diff --git a/tiger_style/two_phase_commit.zig b/tiger_style/two_phase_commit.zig index 1b420e4..f171cad 100644 --- a/tiger_style/two_phase_commit.zig +++ b/tiger_style/two_phase_commit.zig @@ -28,7 +28,7 @@ pub const CoordinatorState = enum(u8) { aborted, pub fn validate(self: CoordinatorState) void { - assert(@intFromEnum(self) <= 3); + assert(@backingInt(self) <= 3); } }; @@ -39,7 +39,7 @@ pub const ParticipantVote = enum(u8) { no_response, pub fn validate(self: ParticipantVote) void { - assert(@intFromEnum(self) <= 2); + assert(@backingInt(self) <= 2); } }; diff --git a/tiger_style/vsr_consensus.zig b/tiger_style/vsr_consensus.zig index 6bfc67e..1d3cd29 100644 --- a/tiger_style/vsr_consensus.zig +++ b/tiger_style/vsr_consensus.zig @@ -39,7 +39,7 @@ pub const ReplicaState = enum(u8) { recovering, // Replica recovering pub fn validate(self: ReplicaState) void { - assert(@intFromEnum(self) <= 2); + assert(@backingInt(self) <= 2); } };