Skip to content

Instantly share code, notes, and snippets.

@slimsag

slimsag/literal.zig

Created Mar 10, 2021
Embed
What would you like to do?
const std = @import("std");
const Allocator = std.mem.Allocator;
const Parser = @import("parser.zig").Parser;
const Error = @import("parser.zig").Error;
pub fn Literal(comptime Reader: type) type {
return struct {
parser: Parser([]u8, Reader) = .{
._parse = parse,
},
want: []const u8,
const Self = @This();
pub fn init(want: []const u8) Self {
return Self{
.want = want
};
}
fn parse(parser: *Parser([]u8, Reader), allocator: *Allocator, src: *Reader) callconv(.Inline) Error!?[]u8 {
const self = @fieldParentPtr(Self, "parser", parser);
const buf = try allocator.alloc(u8, self.want.len);
const read = try src.reader().readAll(buf);
if (read < self.want.len or !std.mem.eql(u8, buf, self.want)) {
try src.seekableStream().seekBy(-@intCast(i64, read));
allocator.free(buf);
return null;
}
return buf;
}
};
}
test "literal" {
const allocator = std.testing.allocator;
var reader = std.io.fixedBufferStream("abcdef");
var want: []const u8 = "abc";
var literal = Literal(@TypeOf(reader)).init(want);
const p = &literal.parser;
var result = try p.parse(allocator, &reader);
std.testing.expectEqualStrings(want, result.?);
if (result) |r| {
allocator.free(r);
}
}
const std = @import("std");
const Allocator = std.mem.Allocator;
pub const Error = error{
EndOfStream,
Utf8InvalidStartByte,
} || std.fs.File.ReadError || std.fs.File.SeekError || std.mem.Allocator.Error;
pub fn Parser(comptime Value: type, comptime Reader: type) type {
return struct {
const Self = @This();
_parse: fn(self: *Self, allocator: *Allocator, src: *Reader) callconv(.Inline) Error!?Value,
pub fn parse(self: *Self, allocator: *Allocator, src: *Reader) callconv(.Inline) Error!?Value {
return self._parse(self, allocator, src);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment