Fix parsing for enum and boolean values
This commit is contained in:
parent
29a38240d9
commit
d0e08e4b04
1 changed files with 13 additions and 14 deletions
|
@ -66,10 +66,6 @@ const QueryIter = @import("util").QueryIter;
|
|||
/// Would be used to parse a query string like
|
||||
/// `?foo.baz=12345`
|
||||
///
|
||||
/// Compound types cannot currently be nullable, and must be structs.
|
||||
///
|
||||
/// TODO: values are currently case-sensitive, and are not url-decoded properly.
|
||||
/// This should be fixed.
|
||||
pub fn parseQuery(alloc: std.mem.Allocator, comptime T: type, query: []const u8) !T {
|
||||
if (comptime !std.meta.trait.isContainer(T)) @compileError("T must be a struct");
|
||||
var iter = QueryIter.from(query);
|
||||
|
@ -88,7 +84,7 @@ pub fn parseQuery(alloc: std.mem.Allocator, comptime T: type, query: []const u8)
|
|||
return (try parse(alloc, T, "", "", fields)) orelse error.NoQuery;
|
||||
}
|
||||
|
||||
fn decodeString(alloc: std.mem.Allocator, val: []const u8) ![]const u8 {
|
||||
fn decodeString(alloc: std.mem.Allocator, val: []const u8) ![]u8 {
|
||||
var list = try std.ArrayList(u8).initCapacity(alloc, val.len);
|
||||
errdefer list.deinit();
|
||||
|
||||
|
@ -266,20 +262,23 @@ fn parseQueryValueNotNull(alloc: std.mem.Allocator, comptime T: type, value: []c
|
|||
|
||||
if (comptime std.meta.trait.isZigString(T)) return decoded;
|
||||
|
||||
defer alloc.free(decoded);
|
||||
|
||||
const result = if (comptime std.meta.trait.isIntegral(T))
|
||||
try std.fmt.parseInt(T, decoded, 0)
|
||||
else if (comptime std.meta.trait.isFloat(T))
|
||||
try std.fmt.parseFloat(T, decoded)
|
||||
else if (comptime std.meta.trait.is(.Enum)(T))
|
||||
std.meta.stringToEnum(T, decoded) orelse return error.InvalidEnumValue
|
||||
else if (T == bool)
|
||||
bool_map.get(value) orelse return error.InvalidBool
|
||||
else if (comptime std.meta.trait.hasFn("parse")(T))
|
||||
else if (comptime std.meta.trait.is(.Enum)(T)) blk: {
|
||||
_ = std.ascii.lowerString(decoded, decoded);
|
||||
break :blk std.meta.stringToEnum(T, decoded) orelse return error.InvalidEnumValue;
|
||||
} else if (T == bool) blk: {
|
||||
_ = std.ascii.lowerString(decoded, decoded);
|
||||
break :blk bool_map.get(decoded) orelse return error.InvalidBool;
|
||||
} else if (comptime std.meta.trait.hasFn("parse")(T))
|
||||
try T.parse(value)
|
||||
else
|
||||
@compileError("Invalid type " ++ @typeName(T));
|
||||
|
||||
alloc.free(decoded);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -359,7 +358,7 @@ fn format(comptime prefix: []const u8, comptime name: []const u8, params: anytyp
|
|||
}
|
||||
}
|
||||
|
||||
test {
|
||||
test "parseQuery" {
|
||||
const TestQuery = struct {
|
||||
int: usize = 3,
|
||||
boolean: bool = false,
|
||||
|
@ -370,11 +369,11 @@ test {
|
|||
.int = 3,
|
||||
.boolean = false,
|
||||
.str_enum = null,
|
||||
}, try parseQuery(TestQuery, ""));
|
||||
}, try parseQuery(std.testing.allocator, TestQuery, ""));
|
||||
|
||||
try std.testing.expectEqual(TestQuery{
|
||||
.int = 5,
|
||||
.boolean = true,
|
||||
.str_enum = .foo,
|
||||
}, try parseQuery(TestQuery, "?int=5&boolean=yes&str_enum=foo"));
|
||||
}, try parseQuery(std.testing.allocator, TestQuery, "?int=5&boolean=yes&str_enum=foo"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue