const std = @import("std"); const root = @import("root.zig"); const Result = root.Result; pub fn Parser(T: type) type { const R = Result(T); return struct { parse: *const fn ([]const u8) anyerror!R, pub fn parseAll(self: *const @This(), buffer: []const u8) !T { const value, const next = try self.parse(buffer); if (next.len > 0) { return error.NotExhaustive; } return value; } pub fn fromType(P: type) @This() { return .{ .parse = P.parse }; } pub fn variants(V: type) @This() { if (@typeInfo(T) != .@"union") { @compileError("variants is only allowed with an union as result type"); } return .{ .parse = struct { fn parse(buffer: []const u8) !R { inline for (std.meta.fields(T)) |field| { if (@field(V, field.name).parse(buffer)) |result| { const value, const next = result; return .{ @unionInit(T, field.name, value), next, }; } else |_| {} } return error.Variants; } }.parse, }; } pub fn any(P: type, comptime parsers: []const struct { Parser(P), T }) @This() { return .{ .parse = struct { fn parse(buffer: []const u8) !R { inline for (parsers) |pair| { const parser, const value = pair; if (parser.parse(buffer)) |result| { _, const next = result; return .{ value, next }; } else |_| {} } return error.Any; } }.parse, }; } }; }