summaryrefslogtreecommitdiff
path: root/src/estd/cursor.zig
blob: 904248ad1f2734561fea6f6acaba82006d7cc998 (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));
}