summaryrefslogtreecommitdiff
path: root/src/estd/cursor.zig
blob: c0a4a328744afe8b07fadcf5c7dc0c2a9ec5240a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
const std = @import("std");

pub const ReadError = error {
    EndOfBuffer
};

pub fn Cursor(comptime T: type) type {
    return struct {
        const Self = @This();

        buffer: []const T,
        index: usize,
        touched_index: usize,

        pub fn init(buffer: []const T) Self {
            return .{
                .buffer = buffer,
                .index = 0,
                .touched_index = 0,
            };
        }

        pub fn peek(self: Self, amount: usize) ReadError![]const T {
            if (self.index + amount > self.buffer.len) {
                return ReadError.EndOfBuffer;
            }

            return self.buffer[self.index..self.index + amount];
        }

        pub fn consume(self: *Self, amount: usize) ReadError![]const T {
            const slice = try self.peek(amount);
            self.index += amount;
            self.touched_index = self.index;
            return slice;
        }

        pub fn snapshot(self: Self) usize {
            return self.index;
        }

        pub fn rollback(self: *Self, index: usize) void {
            self.index = index;
        }

        pub fn touched_slice(self: Self) []const T {
            return self.buffer[0..self.touched_index];
        }
    };
}

test "peek" {
    const buffer = "1234";
    const cursor = Cursor(u8).init(buffer);
    try std.testing.expectEqualSlices(u8, "1", try cursor.peek(1));
    try std.testing.expectEqualSlices(u8, "12", try cursor.peek(2));
    try std.testing.expectEqualSlices(u8, "123", try cursor.peek(3));
    try std.testing.expectEqualSlices(u8, "1234", try cursor.peek(4));
    try std.testing.expectError(ReadError.EndOfBuffer, cursor.peek(5));
}

test "consume" {
    const buffer = "12345678";
    var cursor = Cursor(u8).init(buffer);
    try std.testing.expectEqualSlices(u8, "1", try cursor.consume(1));
    try std.testing.expectEqualSlices(u8, "23", try cursor.consume(2));
    try std.testing.expectEqualSlices(u8, "456", try cursor.consume(3));
    try std.testing.expectError(ReadError.EndOfBuffer, cursor.consume(4));
}