Last active
May 1, 2020 15:54
-
-
Save DutchGhost/4d7bd8a818c27fbef2f56b2a02d7738b to your computer and use it in GitHub Desktop.
zig build test fails on this
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const testing = std.testing; | |
const meta = std.meta; | |
pub const Type = union(enum) { | |
Character, | |
}; | |
pub const Ammount = union(enum) { | |
Infinite, | |
Ammount: usize, | |
}; | |
const Any = struct {}; | |
fn starts_with(comptime T: type, slice: []const T, pattern: []const T) bool { | |
if (slice.len < pattern.len) return false; | |
return std.mem.eql(T, slice[0..pattern.len], pattern); | |
} | |
const ParseError = error{Invalid}; | |
pub fn parsing(comptime T: type, comptime Desc: var) type { | |
return struct { | |
pub fn parse(s: []const u8) ParseError!T { | |
var slice = s; | |
var r: T = undefined; | |
inline for (meta.fields(@TypeOf(Desc))) |field| { | |
// Does the name begin with `skip`, | |
comptime var is_skip = starts_with(u8, field.name, "skip"); | |
switch (@field(Desc, field.name).kind) { | |
.Character => { | |
// Grab out the filter clause | |
const filter = @field(Desc, field.name).filter; | |
// If we put in a literal character | |
// as the filter clause, then try match | |
// against that | |
if (@TypeOf(filter) == comptime_int) { | |
const c = slice[0]; | |
if (c == filter) { | |
// Skip assigning a found clause | |
// if its a skipper | |
if (comptime !is_skip) { | |
@field(r, field.name) = c; | |
} | |
slice = slice[1..]; | |
} else { | |
return ParseError.Invalid; | |
} | |
} | |
// If we don't care what character, | |
// `Any` matches anything | |
if (@TypeOf(filter) == Any) { | |
if (comptime !is_skip) { | |
@field(r, field.name) = s[0]; | |
} | |
slice = slice[1..]; | |
} | |
}, | |
else => unreachable, | |
} | |
} | |
return r; | |
} | |
}; | |
} | |
fn isWhitespace(c: *const u8) bool { | |
return c.* == ' '; | |
} | |
test "basic add functionality" { | |
const x = struct { | |
c: u8, | |
pub usingnamespace parsing(@This(), .{ | |
.skip = .{ | |
.kind = .Character, | |
.filter = ' ', | |
}, | |
.skip1 = .{ | |
.kind = .Character, | |
.filter = ' ', | |
}, | |
.c = .{ | |
.kind = .Character, | |
.filter = '1', | |
}, | |
}); | |
}; | |
var parsed = try x.parse(" 1"); | |
std.debug.assert(parsed.c == '1'); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const testing = std.testing; | |
const meta = std.meta; | |
pub const Type = union(enum) { | |
Character, | |
}; | |
const Any = struct {}; | |
fn starts_with(comptime T: type, slice: []const T, pattern: []const T) bool { | |
if (slice.len < pattern.len) return false; | |
return std.mem.eql(T, slice[0..pattern.len], pattern); | |
} | |
const ParseError = error{Invalid}; | |
pub fn parsing(comptime T: type, comptime Description: var) type { | |
return struct { | |
fn parseCharacter(comptime fieldName: []const u8, result: *T, s: []const u8) ParseError!usize { | |
comptime var is_skip = starts_with(u8, fieldName, "skip"); | |
const filter = @field(Description, fieldName).filter; | |
const matches = switch (@TypeOf(filter)) { | |
Any => true, | |
comptime_int => filter == s[0], | |
fn (*const u8) bool => filter(&s[0]), | |
else => @compileError("Type `" ++ @typeName(filter) ++ "` is not handled."), | |
}; | |
if (matches) { | |
if (!is_skip) { | |
@field(result, fieldName) = s[0]; | |
} | |
return 1; | |
} else { | |
return ParseError.Invalid; | |
} | |
} | |
pub fn parse(s: []const u8) ParseError!T { | |
var slice = s; | |
var r: T = undefined; | |
comptime var slice_idx = @as(usize, 0); | |
inline for (meta.fields(@TypeOf(Description))) |field| { | |
switch (@field(Description, field.name).kind) { | |
.Character => { | |
var ammount = try parseCharacter(field.name, &r, slice); | |
slice = slice[ammount..]; | |
}, | |
else => unreachable, | |
} | |
} | |
return r; | |
} | |
}; | |
} | |
fn isWhitespace(c: *const u8) bool { | |
return c.* == ' '; | |
} | |
test "basic character parse" { | |
const x = struct { | |
c: u8, | |
pub usingnamespace parsing(@This(), .{ | |
.skip = .{ | |
.kind = .Character, | |
.filter = isWhitespace, | |
}, | |
.skip1 = .{ | |
.kind = .Character, | |
.filter = Any{}, | |
}, | |
.c = .{ | |
.kind = .Character, | |
.filter = Any{}, | |
}, | |
}); | |
}; | |
var parsed = try x.parse(" a2"); | |
std.debug.assert(parsed.c == '2'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment