2022-09-09 22:55:34 +01:00
|
|
|
const io = @import("./io.zig");
|
|
|
|
const std = @import("std");
|
|
|
|
|
2022-09-27 21:45:32 +01:00
|
|
|
pub fn Fixed(comptime Element: type) type {
|
2022-09-09 22:55:34 +01:00
|
|
|
return struct {
|
2022-09-27 21:45:32 +01:00
|
|
|
filled: usize = 0,
|
2022-09-09 22:55:34 +01:00
|
|
|
buffer: []Element,
|
|
|
|
|
|
|
|
const Self = @This();
|
|
|
|
|
|
|
|
///
|
|
|
|
/// Wraps `self` and returns it in a [io.Writer] value.
|
|
|
|
///
|
|
|
|
/// Note that this will raise a compilation error if [Element] is not `u8`.
|
|
|
|
///
|
2022-09-30 09:48:32 +01:00
|
|
|
pub fn writer(self: *Self) io.Writer {
|
2022-09-09 22:55:34 +01:00
|
|
|
if (Element != u8) @compileError("Cannot coerce fixed stack of type " ++
|
|
|
|
@typeName(Element) ++ " into a Writer");
|
|
|
|
|
|
|
|
return io.Writer.wrap(Self, self, struct {
|
|
|
|
fn write(stack: *Self, buffer: []const u8) usize {
|
|
|
|
stack.pushAll(buffer) catch |err| switch (err) {
|
|
|
|
error.Overflow => return 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
return buffer.len;
|
|
|
|
}
|
|
|
|
}.write);
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
/// Clears all elements from `self`.
|
|
|
|
///
|
|
|
|
pub fn clear(self: *Self) void {
|
|
|
|
self.filled = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
/// Counts and returns the number of pushed elements in `self`.
|
|
|
|
///
|
|
|
|
pub fn count(self: Self) usize {
|
|
|
|
return self.filled;
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
/// Attempts to pop the tail-end of `self`, returning the element value or `null` if the
|
|
|
|
/// stack is empty.
|
|
|
|
///
|
|
|
|
pub fn pop(self: *Self) ?Element {
|
|
|
|
if (self.filled == 0) return null;
|
|
|
|
|
|
|
|
self.filled -= 1;
|
|
|
|
|
|
|
|
return self.buffer[self.filled];
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
2022-09-27 21:45:32 +01:00
|
|
|
/// Attempts to push `element` into `self`, returning a [FixedPushError] if it failed.
|
2022-09-09 22:55:34 +01:00
|
|
|
///
|
2022-09-27 21:45:32 +01:00
|
|
|
pub fn push(self: *Self, element: Element) FixedPushError!void {
|
2022-09-09 22:55:34 +01:00
|
|
|
if (self.filled == self.buffer.len) return error.Overflow;
|
|
|
|
|
|
|
|
self.buffer[self.filled] = element;
|
|
|
|
self.filled += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
2022-09-27 21:45:32 +01:00
|
|
|
/// Attempts to push all of `elements` into `self`, returning a [FixedPushError] if it
|
|
|
|
/// failed.
|
2022-09-09 22:55:34 +01:00
|
|
|
///
|
2022-09-27 21:45:32 +01:00
|
|
|
pub fn pushAll(self: *Self, elements: []const u8) FixedPushError!void {
|
2022-09-09 22:55:34 +01:00
|
|
|
const filled = (self.filled + elements.len);
|
|
|
|
|
|
|
|
if (filled > self.buffer.len) return error.Overflow;
|
|
|
|
|
|
|
|
std.mem.copy(u8, self.buffer[self.filled ..], elements);
|
|
|
|
|
|
|
|
self.filled = filled;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-09-30 09:48:32 +01:00
|
|
|
///
|
|
|
|
/// Potential errors that may occur while trying to push one or more elements into a stack of a
|
|
|
|
/// known maximum size.
|
|
|
|
///
|
|
|
|
/// [FinitePushError.Overflow] is returned if the stack does not have sufficient capacity to hold a
|
|
|
|
/// given set of elements.
|
|
|
|
///
|
|
|
|
pub const FixedPushError = error {
|
|
|
|
Overflow,
|
|
|
|
};
|
|
|
|
|
2022-10-03 22:58:33 +01:00
|
|
|
test {
|
2022-10-02 12:56:19 +01:00
|
|
|
const testing = std.testing;
|
2022-09-27 21:45:32 +01:00
|
|
|
var buffer = std.mem.zeroes([4]u8);
|
|
|
|
var stack = Fixed(u8){.buffer = &buffer};
|
2022-09-09 22:55:34 +01:00
|
|
|
|
2022-10-02 12:56:19 +01:00
|
|
|
try testing.expectEqual(stack.count(), 0);
|
|
|
|
try testing.expectEqual(stack.pop(), null);
|
2022-09-09 22:55:34 +01:00
|
|
|
try stack.push(69);
|
2022-10-02 12:56:19 +01:00
|
|
|
try testing.expectEqual(stack.count(), 1);
|
|
|
|
try testing.expectEqual(stack.pop(), 69);
|
2022-09-09 22:55:34 +01:00
|
|
|
try stack.pushAll(&.{42, 10, 95, 0});
|
2022-10-02 12:56:19 +01:00
|
|
|
try testing.expectEqual(stack.count(), 4);
|
|
|
|
try testing.expectError(FixedPushError.Overflow, stack.push(1));
|
|
|
|
try testing.expectError(FixedPushError.Overflow, stack.pushAll(&.{1, 11, 11}));
|
2022-09-09 22:55:34 +01:00
|
|
|
|
|
|
|
stack.clear();
|
|
|
|
|
2022-10-02 12:56:19 +01:00
|
|
|
try testing.expectEqual(stack.count(), 0);
|
2022-09-09 22:55:34 +01:00
|
|
|
|
2022-09-30 09:48:32 +01:00
|
|
|
const writer = stack.writer();
|
2022-09-09 22:55:34 +01:00
|
|
|
|
2022-10-02 12:56:19 +01:00
|
|
|
try testing.expectEqual(writer.write(&.{0, 0, 0, 0}), 4);
|
|
|
|
try testing.expectEqual(writer.writeByte(0), false);
|
2022-09-09 22:55:34 +01:00
|
|
|
}
|