tigerbeetle-node 0.11.12 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/README.md +212 -196
  2. package/dist/bin/aarch64-linux-gnu/client.node +0 -0
  3. package/dist/bin/aarch64-linux-musl/client.node +0 -0
  4. package/dist/bin/aarch64-macos/client.node +0 -0
  5. package/dist/bin/x86_64-linux-gnu/client.node +0 -0
  6. package/dist/bin/x86_64-linux-musl/client.node +0 -0
  7. package/dist/bin/x86_64-macos/client.node +0 -0
  8. package/dist/index.js +33 -1
  9. package/dist/index.js.map +1 -1
  10. package/package-lock.json +66 -0
  11. package/package.json +8 -17
  12. package/src/index.ts +56 -1
  13. package/src/node.zig +10 -9
  14. package/dist/.client.node.sha256 +0 -1
  15. package/scripts/build_lib.sh +0 -61
  16. package/scripts/download_node_headers.sh +0 -32
  17. package/src/tigerbeetle/scripts/benchmark.bat +0 -48
  18. package/src/tigerbeetle/scripts/benchmark.sh +0 -66
  19. package/src/tigerbeetle/scripts/confirm_image.sh +0 -44
  20. package/src/tigerbeetle/scripts/fuzz_loop.sh +0 -15
  21. package/src/tigerbeetle/scripts/fuzz_unique_errors.sh +0 -7
  22. package/src/tigerbeetle/scripts/install.bat +0 -7
  23. package/src/tigerbeetle/scripts/install.sh +0 -21
  24. package/src/tigerbeetle/scripts/install_zig.bat +0 -113
  25. package/src/tigerbeetle/scripts/install_zig.sh +0 -90
  26. package/src/tigerbeetle/scripts/lint.zig +0 -199
  27. package/src/tigerbeetle/scripts/pre-commit.sh +0 -9
  28. package/src/tigerbeetle/scripts/scripts/benchmark.bat +0 -48
  29. package/src/tigerbeetle/scripts/scripts/benchmark.sh +0 -66
  30. package/src/tigerbeetle/scripts/scripts/confirm_image.sh +0 -44
  31. package/src/tigerbeetle/scripts/scripts/fuzz_loop.sh +0 -15
  32. package/src/tigerbeetle/scripts/scripts/fuzz_unique_errors.sh +0 -7
  33. package/src/tigerbeetle/scripts/scripts/install.bat +0 -7
  34. package/src/tigerbeetle/scripts/scripts/install.sh +0 -21
  35. package/src/tigerbeetle/scripts/scripts/install_zig.bat +0 -113
  36. package/src/tigerbeetle/scripts/scripts/install_zig.sh +0 -90
  37. package/src/tigerbeetle/scripts/scripts/lint.zig +0 -199
  38. package/src/tigerbeetle/scripts/scripts/pre-commit.sh +0 -9
  39. package/src/tigerbeetle/scripts/scripts/shellcheck.sh +0 -5
  40. package/src/tigerbeetle/scripts/scripts/tests_on_alpine.sh +0 -10
  41. package/src/tigerbeetle/scripts/scripts/tests_on_ubuntu.sh +0 -14
  42. package/src/tigerbeetle/scripts/scripts/upgrade_ubuntu_kernel.sh +0 -48
  43. package/src/tigerbeetle/scripts/scripts/validate_docs.sh +0 -23
  44. package/src/tigerbeetle/scripts/scripts/vr_state_enumerate +0 -46
  45. package/src/tigerbeetle/scripts/shellcheck.sh +0 -5
  46. package/src/tigerbeetle/scripts/tests_on_alpine.sh +0 -10
  47. package/src/tigerbeetle/scripts/tests_on_ubuntu.sh +0 -14
  48. package/src/tigerbeetle/scripts/upgrade_ubuntu_kernel.sh +0 -48
  49. package/src/tigerbeetle/scripts/validate_docs.sh +0 -23
  50. package/src/tigerbeetle/scripts/vr_state_enumerate +0 -46
  51. package/src/tigerbeetle/src/benchmark.zig +0 -314
  52. package/src/tigerbeetle/src/config.zig +0 -234
  53. package/src/tigerbeetle/src/constants.zig +0 -436
  54. package/src/tigerbeetle/src/ewah.zig +0 -286
  55. package/src/tigerbeetle/src/ewah_benchmark.zig +0 -120
  56. package/src/tigerbeetle/src/ewah_fuzz.zig +0 -130
  57. package/src/tigerbeetle/src/fifo.zig +0 -120
  58. package/src/tigerbeetle/src/io/benchmark.zig +0 -213
  59. package/src/tigerbeetle/src/io/darwin.zig +0 -814
  60. package/src/tigerbeetle/src/io/linux.zig +0 -1062
  61. package/src/tigerbeetle/src/io/test.zig +0 -643
  62. package/src/tigerbeetle/src/io/windows.zig +0 -1183
  63. package/src/tigerbeetle/src/io.zig +0 -34
  64. package/src/tigerbeetle/src/iops.zig +0 -107
  65. package/src/tigerbeetle/src/lsm/README.md +0 -308
  66. package/src/tigerbeetle/src/lsm/binary_search.zig +0 -341
  67. package/src/tigerbeetle/src/lsm/bloom_filter.zig +0 -125
  68. package/src/tigerbeetle/src/lsm/compaction.zig +0 -603
  69. package/src/tigerbeetle/src/lsm/composite_key.zig +0 -77
  70. package/src/tigerbeetle/src/lsm/direction.zig +0 -11
  71. package/src/tigerbeetle/src/lsm/eytzinger.zig +0 -587
  72. package/src/tigerbeetle/src/lsm/eytzinger_benchmark.zig +0 -330
  73. package/src/tigerbeetle/src/lsm/forest.zig +0 -204
  74. package/src/tigerbeetle/src/lsm/forest_fuzz.zig +0 -401
  75. package/src/tigerbeetle/src/lsm/grid.zig +0 -573
  76. package/src/tigerbeetle/src/lsm/groove.zig +0 -972
  77. package/src/tigerbeetle/src/lsm/k_way_merge.zig +0 -474
  78. package/src/tigerbeetle/src/lsm/level_iterator.zig +0 -332
  79. package/src/tigerbeetle/src/lsm/manifest.zig +0 -617
  80. package/src/tigerbeetle/src/lsm/manifest_level.zig +0 -877
  81. package/src/tigerbeetle/src/lsm/manifest_log.zig +0 -789
  82. package/src/tigerbeetle/src/lsm/manifest_log_fuzz.zig +0 -691
  83. package/src/tigerbeetle/src/lsm/merge_iterator.zig +0 -106
  84. package/src/tigerbeetle/src/lsm/node_pool.zig +0 -235
  85. package/src/tigerbeetle/src/lsm/posted_groove.zig +0 -378
  86. package/src/tigerbeetle/src/lsm/segmented_array.zig +0 -1328
  87. package/src/tigerbeetle/src/lsm/segmented_array_benchmark.zig +0 -148
  88. package/src/tigerbeetle/src/lsm/segmented_array_fuzz.zig +0 -9
  89. package/src/tigerbeetle/src/lsm/set_associative_cache.zig +0 -850
  90. package/src/tigerbeetle/src/lsm/table.zig +0 -1031
  91. package/src/tigerbeetle/src/lsm/table_immutable.zig +0 -203
  92. package/src/tigerbeetle/src/lsm/table_iterator.zig +0 -340
  93. package/src/tigerbeetle/src/lsm/table_mutable.zig +0 -220
  94. package/src/tigerbeetle/src/lsm/test.zig +0 -438
  95. package/src/tigerbeetle/src/lsm/tree.zig +0 -1193
  96. package/src/tigerbeetle/src/lsm/tree_fuzz.zig +0 -474
  97. package/src/tigerbeetle/src/message_bus.zig +0 -1012
  98. package/src/tigerbeetle/src/message_pool.zig +0 -156
  99. package/src/tigerbeetle/src/ring_buffer.zig +0 -399
  100. package/src/tigerbeetle/src/simulator.zig +0 -569
  101. package/src/tigerbeetle/src/state_machine/auditor.zig +0 -577
  102. package/src/tigerbeetle/src/state_machine/workload.zig +0 -883
  103. package/src/tigerbeetle/src/state_machine.zig +0 -1881
  104. package/src/tigerbeetle/src/static_allocator.zig +0 -65
  105. package/src/tigerbeetle/src/stdx.zig +0 -162
  106. package/src/tigerbeetle/src/storage.zig +0 -393
  107. package/src/tigerbeetle/src/testing/cluster/message_bus.zig +0 -82
  108. package/src/tigerbeetle/src/testing/cluster/network.zig +0 -237
  109. package/src/tigerbeetle/src/testing/cluster/state_checker.zig +0 -169
  110. package/src/tigerbeetle/src/testing/cluster/storage_checker.zig +0 -202
  111. package/src/tigerbeetle/src/testing/cluster.zig +0 -443
  112. package/src/tigerbeetle/src/testing/fuzz.zig +0 -140
  113. package/src/tigerbeetle/src/testing/hash_log.zig +0 -66
  114. package/src/tigerbeetle/src/testing/id.zig +0 -99
  115. package/src/tigerbeetle/src/testing/packet_simulator.zig +0 -364
  116. package/src/tigerbeetle/src/testing/priority_queue.zig +0 -645
  117. package/src/tigerbeetle/src/testing/reply_sequence.zig +0 -139
  118. package/src/tigerbeetle/src/testing/state_machine.zig +0 -249
  119. package/src/tigerbeetle/src/testing/storage.zig +0 -757
  120. package/src/tigerbeetle/src/testing/table.zig +0 -247
  121. package/src/tigerbeetle/src/testing/time.zig +0 -84
  122. package/src/tigerbeetle/src/tigerbeetle.zig +0 -227
  123. package/src/tigerbeetle/src/time.zig +0 -112
  124. package/src/tigerbeetle/src/tracer.zig +0 -529
  125. package/src/tigerbeetle/src/unit_tests.zig +0 -42
  126. package/src/tigerbeetle/src/vopr.zig +0 -495
  127. package/src/tigerbeetle/src/vsr/README.md +0 -209
  128. package/src/tigerbeetle/src/vsr/client.zig +0 -544
  129. package/src/tigerbeetle/src/vsr/clock.zig +0 -853
  130. package/src/tigerbeetle/src/vsr/journal.zig +0 -2413
  131. package/src/tigerbeetle/src/vsr/journal_format_fuzz.zig +0 -111
  132. package/src/tigerbeetle/src/vsr/marzullo.zig +0 -309
  133. package/src/tigerbeetle/src/vsr/replica.zig +0 -6381
  134. package/src/tigerbeetle/src/vsr/replica_format.zig +0 -219
  135. package/src/tigerbeetle/src/vsr/superblock.zig +0 -1631
  136. package/src/tigerbeetle/src/vsr/superblock_client_table.zig +0 -256
  137. package/src/tigerbeetle/src/vsr/superblock_free_set.zig +0 -929
  138. package/src/tigerbeetle/src/vsr/superblock_free_set_fuzz.zig +0 -334
  139. package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +0 -390
  140. package/src/tigerbeetle/src/vsr/superblock_manifest.zig +0 -615
  141. package/src/tigerbeetle/src/vsr/superblock_quorums.zig +0 -394
  142. package/src/tigerbeetle/src/vsr/superblock_quorums_fuzz.zig +0 -314
  143. package/src/tigerbeetle/src/vsr.zig +0 -1352
@@ -1,156 +0,0 @@
1
- const std = @import("std");
2
- const builtin = @import("builtin");
3
- const assert = std.debug.assert;
4
- const mem = std.mem;
5
-
6
- const constants = @import("constants.zig");
7
-
8
- const vsr = @import("vsr.zig");
9
- const Header = vsr.Header;
10
-
11
- comptime {
12
- // message_size_max must be a multiple of sector_size for Direct I/O
13
- assert(constants.message_size_max % constants.sector_size == 0);
14
- }
15
-
16
- /// The number of full-sized messages allocated at initialization by the replica message pool.
17
- /// There must be enough messages to ensure that the replica can always progress, to avoid deadlock.
18
- pub const messages_max_replica = messages_max: {
19
- var sum: usize = 0;
20
-
21
- sum += constants.journal_iops_read_max; // Journal reads
22
- sum += constants.journal_iops_write_max; // Journal writes
23
- sum += constants.clients_max; // SuperBlock.client_table
24
- sum += 1; // Replica.loopback_queue
25
- sum += constants.pipeline_prepare_queue_max; // Replica.Pipeline{Queue|Cache}
26
- sum += constants.pipeline_request_queue_max; // Replica.Pipeline{Queue|Cache}
27
- sum += 1; // Replica.commit_prepare
28
- // Replica.do_view_change_from_all_replicas quorum:
29
- // Replica.recovery_response_quorum is only used for recovery and does not increase the limit.
30
- // All other quorums are bitsets.
31
- sum += constants.replicas_max;
32
- sum += constants.connections_max; // Connection.recv_message
33
- sum += constants.connections_max * constants.connection_send_queue_max_replica; // Connection.send_queue
34
- sum += 1; // Handle bursts (e.g. Connection.parse_message)
35
- // Handle Replica.commit_op's reply:
36
- // (This is separate from the burst +1 because they may occur concurrently).
37
- sum += 1;
38
-
39
- break :messages_max sum;
40
- };
41
-
42
- /// The number of full-sized messages allocated at initialization by the client message pool.
43
- pub const messages_max_client = messages_max: {
44
- var sum: usize = 0;
45
-
46
- sum += constants.replicas_max; // Connection.recv_message
47
- sum += constants.replicas_max * constants.connection_send_queue_max_client; // Connection.send_queue
48
- sum += constants.client_request_queue_max; // Client.request_queue
49
- // Handle bursts (e.g. Connection.parse_message, or sending a ping when the send queue is full).
50
- sum += 1;
51
-
52
- break :messages_max sum;
53
- };
54
-
55
- comptime {
56
- // These conditions are necessary (but not sufficient) to prevent deadlocks.
57
- assert(messages_max_replica > constants.replicas_max);
58
- assert(messages_max_client > constants.client_request_queue_max);
59
- }
60
-
61
- /// A pool of reference-counted Messages, memory for which is allocated only once during
62
- /// initialization and reused thereafter. The messages_max values determine the size of this pool.
63
- pub const MessagePool = struct {
64
- pub const Message = struct {
65
- // TODO: replace this with a header() function to save memory
66
- header: *Header,
67
- buffer: *align(constants.sector_size) [constants.message_size_max]u8,
68
- references: u32 = 0,
69
- next: ?*Message,
70
-
71
- /// Increment the reference count of the message and return the same pointer passed.
72
- pub fn ref(message: *Message) *Message {
73
- message.references += 1;
74
- return message;
75
- }
76
-
77
- pub fn body(message: *const Message) []align(@sizeOf(Header)) u8 {
78
- return message.buffer[@sizeOf(Header)..message.header.size];
79
- }
80
- };
81
-
82
- /// List of currently unused messages.
83
- free_list: ?*Message,
84
-
85
- messages_max: usize,
86
-
87
- pub fn init(allocator: mem.Allocator, process_type: vsr.ProcessType) error{OutOfMemory}!MessagePool {
88
- return MessagePool.init_capacity(allocator, switch (process_type) {
89
- .replica => messages_max_replica,
90
- .client => messages_max_client,
91
- });
92
- }
93
-
94
- pub fn init_capacity(allocator: mem.Allocator, messages_max: usize) error{OutOfMemory}!MessagePool {
95
- var pool: MessagePool = .{
96
- .free_list = null,
97
- .messages_max = messages_max,
98
- };
99
- {
100
- var i: usize = 0;
101
- while (i < messages_max) : (i += 1) {
102
- const buffer = try allocator.allocAdvanced(
103
- u8,
104
- constants.sector_size,
105
- constants.message_size_max,
106
- .exact,
107
- );
108
- const message = try allocator.create(Message);
109
- message.* = .{
110
- .header = mem.bytesAsValue(Header, buffer[0..@sizeOf(Header)]),
111
- .buffer = buffer[0..constants.message_size_max],
112
- .next = pool.free_list,
113
- };
114
- pool.free_list = message;
115
- }
116
- }
117
-
118
- return pool;
119
- }
120
-
121
- /// Frees all messages that were unused or returned to the pool via unref().
122
- pub fn deinit(pool: *MessagePool, allocator: mem.Allocator) void {
123
- var free_count: usize = 0;
124
- while (pool.free_list) |message| {
125
- pool.free_list = message.next;
126
- allocator.free(@as([]const u8, message.buffer));
127
- allocator.destroy(message);
128
- free_count += 1;
129
- }
130
- // If the MessagePool is being deinitialized, all messages should have already been
131
- // released to the pool.
132
- assert(free_count == pool.messages_max);
133
- }
134
-
135
- /// Get an unused message with a buffer of constants.message_size_max.
136
- /// The returned message has exactly one reference.
137
- pub fn get_message(pool: *MessagePool) *Message {
138
- const message = pool.free_list.?;
139
- pool.free_list = message.next;
140
- message.next = null;
141
- assert(message.references == 0);
142
-
143
- message.references = 1;
144
- return message;
145
- }
146
-
147
- /// Decrement the reference count of the message, possibly freeing it.
148
- pub fn unref(pool: *MessagePool, message: *Message) void {
149
- message.references -= 1;
150
- if (message.references == 0) {
151
- mem.set(u8, message.buffer, 0);
152
- message.next = pool.free_list;
153
- pool.free_list = message;
154
- }
155
- }
156
- };
@@ -1,399 +0,0 @@
1
- const std = @import("std");
2
- const assert = std.debug.assert;
3
- const math = std.math;
4
- const mem = std.mem;
5
-
6
- const stdx = @import("stdx.zig");
7
-
8
- /// A First In, First Out ring buffer holding at most `count_max` elements.
9
- pub fn RingBuffer(
10
- comptime T: type,
11
- comptime count_max_: usize,
12
- comptime buffer_type: enum { array, pointer },
13
- ) type {
14
- return struct {
15
- const Self = @This();
16
-
17
- pub const count_max = count_max_;
18
-
19
- buffer: switch (buffer_type) {
20
- .array => [count_max]T,
21
- .pointer => *[count_max]T,
22
- } = switch (buffer_type) {
23
- .array => undefined,
24
- .pointer => @compileError("init() must be used if buffer_type is .pointer!"),
25
- },
26
-
27
- /// The index of the slot with the first item, if any.
28
- index: usize = 0,
29
-
30
- /// The number of items in the buffer.
31
- count: usize = 0,
32
-
33
- pub usingnamespace switch (buffer_type) {
34
- .array => struct {},
35
- .pointer => struct {
36
- pub fn init(allocator: mem.Allocator) !Self {
37
- const buffer = try allocator.create([count_max]T);
38
- errdefer allocator.destroy(buffer);
39
- return Self{ .buffer = buffer };
40
- }
41
-
42
- pub fn deinit(self: *Self, allocator: mem.Allocator) void {
43
- allocator.destroy(self.buffer);
44
- }
45
- },
46
- };
47
-
48
- // TODO Add doc comments to these functions:
49
- pub inline fn head(self: Self) ?T {
50
- if (count_max == 0 or self.empty()) return null;
51
- return self.buffer[self.index];
52
- }
53
-
54
- pub inline fn head_ptr(self: *Self) ?*T {
55
- if (count_max == 0 or self.empty()) return null;
56
- return &self.buffer[self.index];
57
- }
58
-
59
- pub inline fn head_ptr_const(self: *const Self) ?*const T {
60
- if (count_max == 0 or self.empty()) return null;
61
- return &self.buffer[self.index];
62
- }
63
-
64
- pub inline fn tail(self: Self) ?T {
65
- if (count_max == 0 or self.empty()) return null;
66
- return self.buffer[(self.index + self.count - 1) % self.buffer.len];
67
- }
68
-
69
- pub inline fn tail_ptr(self: *Self) ?*T {
70
- if (count_max == 0 or self.empty()) return null;
71
- return &self.buffer[(self.index + self.count - 1) % self.buffer.len];
72
- }
73
-
74
- pub inline fn tail_ptr_const(self: *const Self) ?*const T {
75
- if (count_max == 0 or self.empty()) return null;
76
- return &self.buffer[(self.index + self.count - 1) % self.buffer.len];
77
- }
78
-
79
- pub inline fn get_ptr(self: *Self, index: usize) ?*T {
80
- if (count_max == 0) unreachable;
81
-
82
- if (index < self.count) {
83
- return &self.buffer[(self.index + index) % self.buffer.len];
84
- } else {
85
- assert(index < count_max);
86
- return null;
87
- }
88
- }
89
-
90
- pub inline fn next_tail(self: Self) ?T {
91
- if (count_max == 0 or self.full()) return null;
92
- return self.buffer[(self.index + self.count) % self.buffer.len];
93
- }
94
-
95
- pub inline fn next_tail_ptr(self: *Self) ?*T {
96
- if (count_max == 0 or self.full()) return null;
97
- return &self.buffer[(self.index + self.count) % self.buffer.len];
98
- }
99
-
100
- pub inline fn next_tail_ptr_const(self: *const Self) ?*const T {
101
- if (count_max == 0 or self.full()) return null;
102
- return &self.buffer[(self.index + self.count) % self.buffer.len];
103
- }
104
-
105
- pub inline fn advance_head(self: *Self) void {
106
- self.index += 1;
107
- self.index %= self.buffer.len;
108
- self.count -= 1;
109
- }
110
-
111
- pub inline fn advance_tail(self: *Self) void {
112
- assert(self.count < self.buffer.len);
113
- self.count += 1;
114
- }
115
-
116
- pub inline fn retreat_tail(self: *Self) void {
117
- self.count -= 1;
118
- }
119
-
120
- /// Returns whether the ring buffer is completely full.
121
- pub inline fn full(self: Self) bool {
122
- return self.count == self.buffer.len;
123
- }
124
-
125
- /// Returns whether the ring buffer is completely empty.
126
- pub inline fn empty(self: Self) bool {
127
- return self.count == 0;
128
- }
129
-
130
- // Higher level, less error-prone wrappers:
131
-
132
- /// Add an element to the RingBuffer. Returns an error if the buffer
133
- /// is already full and the element could not be added.
134
- pub fn push(self: *Self, item: T) error{NoSpaceLeft}!void {
135
- const ptr = self.next_tail_ptr() orelse return error.NoSpaceLeft;
136
- ptr.* = item;
137
- self.advance_tail();
138
- }
139
-
140
- /// Add an element to a RingBuffer, and assert that the capacity is sufficient.
141
- pub fn push_assume_capacity(self: *Self, item: T) void {
142
- self.push(item) catch |err| switch (err) {
143
- error.NoSpaceLeft => unreachable,
144
- };
145
- }
146
-
147
- pub fn push_slice(self: *Self, items: []const T) error{NoSpaceLeft}!void {
148
- if (count_max == 0) return error.NoSpaceLeft;
149
- if (self.count + items.len > self.buffer.len) return error.NoSpaceLeft;
150
-
151
- const pre_wrap_start = (self.index + self.count) % self.buffer.len;
152
- const pre_wrap_count = math.min(items.len, self.buffer.len - pre_wrap_start);
153
- const post_wrap_count = items.len - pre_wrap_count;
154
-
155
- stdx.copy_disjoint(.inexact, T, self.buffer[pre_wrap_start..], items[0..pre_wrap_count]);
156
- stdx.copy_disjoint(.exact, T, self.buffer[0..post_wrap_count], items[pre_wrap_count..]);
157
-
158
- self.count += items.len;
159
- }
160
-
161
- /// Remove and return the next item, if any.
162
- pub fn pop(self: *Self) ?T {
163
- const result = self.head() orelse return null;
164
- self.advance_head();
165
- return result;
166
- }
167
-
168
- /// Remove and return the last item, if any.
169
- pub fn pop_tail(self: *Self) ?T {
170
- const result = self.tail() orelse return null;
171
- self.retreat_tail();
172
- return result;
173
- }
174
-
175
- pub const Iterator = struct {
176
- ring: *const Self,
177
- count: usize = 0,
178
-
179
- pub fn next(it: *Iterator) ?T {
180
- if (count_max == 0) return null;
181
- // TODO Use next_ptr() internally to avoid duplicating this code.
182
- assert(it.count <= it.ring.count);
183
- if (it.count == it.ring.count) return null;
184
- defer it.count += 1;
185
- return it.ring.buffer[(it.ring.index + it.count) % it.ring.buffer.len];
186
- }
187
-
188
- pub fn next_ptr(it: *Iterator) ?*const T {
189
- assert(it.count <= it.ring.count);
190
- if (count_max == 0) return null;
191
- if (it.count == it.ring.count) return null;
192
- defer it.count += 1;
193
- return &it.ring.buffer[(it.ring.index + it.count) % it.ring.buffer.len];
194
- }
195
- };
196
-
197
- /// Returns an iterator to iterate through all `count` items in the ring buffer.
198
- /// The iterator is invalidated if the ring buffer is advanced.
199
- pub fn iterator(self: *const Self) Iterator {
200
- return .{ .ring = self };
201
- }
202
-
203
- pub const IteratorMutable = struct {
204
- ring: *Self,
205
- count: usize = 0,
206
-
207
- pub fn next_ptr(it: *IteratorMutable) ?*T {
208
- assert(it.count <= it.ring.count);
209
- if (count_max == 0) return null;
210
- if (it.count == it.ring.count) return null;
211
- defer it.count += 1;
212
- return &it.ring.buffer[(it.ring.index + it.count) % it.ring.buffer.len];
213
- }
214
- };
215
-
216
- // TODO Add to tests.
217
- pub fn iterator_mutable(self: *Self) IteratorMutable {
218
- return .{ .ring = self };
219
- }
220
- };
221
- }
222
-
223
- const testing = std.testing;
224
-
225
- fn test_iterator(comptime T: type, ring: *T, values: []const u32) !void {
226
- const ring_index = ring.index;
227
-
228
- var loops: usize = 0;
229
- while (loops < 2) : (loops += 1) {
230
- var iterator = ring.iterator();
231
- var index: usize = 0;
232
- while (iterator.next()) |item| {
233
- try testing.expectEqual(values[index], item);
234
- index += 1;
235
- }
236
- try testing.expectEqual(values.len, index);
237
- }
238
-
239
- try testing.expectEqual(ring_index, ring.index);
240
- }
241
-
242
- fn test_low_level_interface(comptime Ring: type, ring: *Ring) !void {
243
- try ring.push_slice(&[_]u32{});
244
- try test_iterator(Ring, ring, &[_]u32{});
245
-
246
- try testing.expectError(error.NoSpaceLeft, ring.push_slice(&[_]u32{ 1, 2, 3 }));
247
-
248
- try ring.push_slice(&[_]u32{1});
249
- try testing.expectEqual(@as(?u32, 1), ring.tail());
250
- try testing.expectEqual(@as(u32, 1), ring.tail_ptr().?.*);
251
- ring.advance_head();
252
-
253
- try testing.expectEqual(@as(usize, 1), ring.index);
254
- try testing.expectEqual(@as(usize, 0), ring.count);
255
- try ring.push_slice(&[_]u32{ 1, 2 });
256
- try test_iterator(Ring, ring, &[_]u32{ 1, 2 });
257
- ring.advance_head();
258
- ring.advance_head();
259
-
260
- try testing.expectEqual(@as(usize, 1), ring.index);
261
- try testing.expectEqual(@as(usize, 0), ring.count);
262
- try ring.push_slice(&[_]u32{1});
263
- try testing.expectEqual(@as(?u32, 1), ring.tail());
264
- try testing.expectEqual(@as(u32, 1), ring.tail_ptr().?.*);
265
- ring.advance_head();
266
-
267
- try testing.expectEqual(@as(?u32, null), ring.head());
268
- try testing.expectEqual(@as(?*u32, null), ring.head_ptr());
269
- try testing.expectEqual(@as(?u32, null), ring.tail());
270
- try testing.expectEqual(@as(?*u32, null), ring.tail_ptr());
271
-
272
- ring.next_tail_ptr().?.* = 0;
273
- ring.advance_tail();
274
- try testing.expectEqual(@as(?u32, 0), ring.tail());
275
- try testing.expectEqual(@as(u32, 0), ring.tail_ptr().?.*);
276
- try test_iterator(Ring, ring, &[_]u32{0});
277
-
278
- ring.next_tail_ptr().?.* = 1;
279
- ring.advance_tail();
280
- try testing.expectEqual(@as(?u32, 1), ring.tail());
281
- try testing.expectEqual(@as(u32, 1), ring.tail_ptr().?.*);
282
- try test_iterator(Ring, ring, &[_]u32{ 0, 1 });
283
-
284
- try testing.expectEqual(@as(?u32, null), ring.next_tail());
285
- try testing.expectEqual(@as(?*u32, null), ring.next_tail_ptr());
286
-
287
- try testing.expectEqual(@as(?u32, 0), ring.head());
288
- try testing.expectEqual(@as(u32, 0), ring.head_ptr().?.*);
289
- ring.advance_head();
290
- try test_iterator(Ring, ring, &[_]u32{1});
291
-
292
- ring.next_tail_ptr().?.* = 2;
293
- ring.advance_tail();
294
- try testing.expectEqual(@as(?u32, 2), ring.tail());
295
- try testing.expectEqual(@as(u32, 2), ring.tail_ptr().?.*);
296
- try test_iterator(Ring, ring, &[_]u32{ 1, 2 });
297
-
298
- ring.advance_head();
299
- try test_iterator(Ring, ring, &[_]u32{2});
300
-
301
- ring.next_tail_ptr().?.* = 3;
302
- ring.advance_tail();
303
- try testing.expectEqual(@as(?u32, 3), ring.tail());
304
- try testing.expectEqual(@as(u32, 3), ring.tail_ptr().?.*);
305
- try test_iterator(Ring, ring, &[_]u32{ 2, 3 });
306
-
307
- try testing.expectEqual(@as(?u32, 2), ring.head());
308
- try testing.expectEqual(@as(u32, 2), ring.head_ptr().?.*);
309
- ring.advance_head();
310
- try test_iterator(Ring, ring, &[_]u32{3});
311
-
312
- try testing.expectEqual(@as(?u32, 3), ring.head());
313
- try testing.expectEqual(@as(u32, 3), ring.head_ptr().?.*);
314
- ring.advance_head();
315
- try test_iterator(Ring, ring, &[_]u32{});
316
-
317
- try testing.expectEqual(@as(?u32, null), ring.head());
318
- try testing.expectEqual(@as(?*u32, null), ring.head_ptr());
319
- try testing.expectEqual(@as(?u32, null), ring.tail());
320
- try testing.expectEqual(@as(?*u32, null), ring.tail_ptr());
321
- }
322
-
323
- test "RingBuffer: low level interface" {
324
- const ArrayRing = RingBuffer(u32, 2, .array);
325
- var array_ring: ArrayRing = .{};
326
- try test_low_level_interface(ArrayRing, &array_ring);
327
-
328
- const PointerRing = RingBuffer(u32, 2, .pointer);
329
- var pointer_ring = try PointerRing.init(testing.allocator);
330
- defer pointer_ring.deinit(testing.allocator);
331
- try test_low_level_interface(PointerRing, &pointer_ring);
332
- }
333
-
334
- test "RingBuffer: push/pop high level interface" {
335
- var fifo = RingBuffer(u32, 3, .array){};
336
-
337
- try testing.expect(!fifo.full());
338
- try testing.expect(fifo.empty());
339
- try testing.expectEqual(@as(?*u32, null), fifo.get_ptr(0));
340
- try testing.expectEqual(@as(?*u32, null), fifo.get_ptr(1));
341
- try testing.expectEqual(@as(?*u32, null), fifo.get_ptr(2));
342
-
343
- try fifo.push(1);
344
- try testing.expectEqual(@as(?u32, 1), fifo.head());
345
- try testing.expectEqual(@as(u32, 1), fifo.get_ptr(0).?.*);
346
- try testing.expectEqual(@as(?*u32, null), fifo.get_ptr(1));
347
-
348
- try testing.expect(!fifo.full());
349
- try testing.expect(!fifo.empty());
350
-
351
- try fifo.push(2);
352
- try testing.expectEqual(@as(?u32, 1), fifo.head());
353
- try testing.expectEqual(@as(u32, 2), fifo.get_ptr(1).?.*);
354
-
355
- try fifo.push(3);
356
- try testing.expectError(error.NoSpaceLeft, fifo.push(4));
357
-
358
- try testing.expect(fifo.full());
359
- try testing.expect(!fifo.empty());
360
-
361
- try testing.expectEqual(@as(?u32, 1), fifo.head());
362
- try testing.expectEqual(@as(?u32, 1), fifo.pop());
363
- try testing.expectEqual(@as(u32, 2), fifo.get_ptr(0).?.*);
364
- try testing.expectEqual(@as(u32, 3), fifo.get_ptr(1).?.*);
365
- try testing.expectEqual(@as(?*u32, null), fifo.get_ptr(2));
366
-
367
- try testing.expect(!fifo.full());
368
- try testing.expect(!fifo.empty());
369
-
370
- try fifo.push(4);
371
-
372
- try testing.expectEqual(@as(?u32, 2), fifo.pop());
373
- try testing.expectEqual(@as(?u32, 3), fifo.pop());
374
- try testing.expectEqual(@as(?u32, 4), fifo.pop());
375
- try testing.expectEqual(@as(?u32, null), fifo.pop());
376
-
377
- try testing.expect(!fifo.full());
378
- try testing.expect(fifo.empty());
379
- }
380
-
381
- test "RingBuffer: pop_tail" {
382
- var lifo = RingBuffer(u32, 3, .array){};
383
- try lifo.push(1);
384
- try lifo.push(2);
385
- try lifo.push(3);
386
- try testing.expect(lifo.full());
387
-
388
- try testing.expectEqual(@as(?u32, 3), lifo.pop_tail());
389
- try testing.expectEqual(@as(?u32, 1), lifo.head());
390
- try testing.expectEqual(@as(?u32, 2), lifo.pop_tail());
391
- try testing.expectEqual(@as(?u32, 1), lifo.head());
392
- try testing.expectEqual(@as(?u32, 1), lifo.pop_tail());
393
- try testing.expectEqual(@as(?u32, null), lifo.pop_tail());
394
- try testing.expect(lifo.empty());
395
- }
396
-
397
- test "RingBuffer: count_max=0" {
398
- std.testing.refAllDecls(RingBuffer(u32, 0, .array));
399
- }