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
|
/// Would be used to parse a query string like
|
||||||
/// `?foo.baz=12345`
|
/// `?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 {
|
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");
|
if (comptime !std.meta.trait.isContainer(T)) @compileError("T must be a struct");
|
||||||
var iter = QueryIter.from(query);
|
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;
|
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);
|
var list = try std.ArrayList(u8).initCapacity(alloc, val.len);
|
||||||
errdefer list.deinit();
|
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;
|
if (comptime std.meta.trait.isZigString(T)) return decoded;
|
||||||
|
|
||||||
|
defer alloc.free(decoded);
|
||||||
|
|
||||||
const result = if (comptime std.meta.trait.isIntegral(T))
|
const result = if (comptime std.meta.trait.isIntegral(T))
|
||||||
try std.fmt.parseInt(T, decoded, 0)
|
try std.fmt.parseInt(T, decoded, 0)
|
||||||
else if (comptime std.meta.trait.isFloat(T))
|
else if (comptime std.meta.trait.isFloat(T))
|
||||||
try std.fmt.parseFloat(T, decoded)
|
try std.fmt.parseFloat(T, decoded)
|
||||||
else if (comptime std.meta.trait.is(.Enum)(T))
|
else if (comptime std.meta.trait.is(.Enum)(T)) blk: {
|
||||||
std.meta.stringToEnum(T, decoded) orelse return error.InvalidEnumValue
|
_ = std.ascii.lowerString(decoded, decoded);
|
||||||
else if (T == bool)
|
break :blk std.meta.stringToEnum(T, decoded) orelse return error.InvalidEnumValue;
|
||||||
bool_map.get(value) orelse return error.InvalidBool
|
} else if (T == bool) blk: {
|
||||||
else if (comptime std.meta.trait.hasFn("parse")(T))
|
_ = 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)
|
try T.parse(value)
|
||||||
else
|
else
|
||||||
@compileError("Invalid type " ++ @typeName(T));
|
@compileError("Invalid type " ++ @typeName(T));
|
||||||
|
|
||||||
alloc.free(decoded);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,7 +358,7 @@ fn format(comptime prefix: []const u8, comptime name: []const u8, params: anytyp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test "parseQuery" {
|
||||||
const TestQuery = struct {
|
const TestQuery = struct {
|
||||||
int: usize = 3,
|
int: usize = 3,
|
||||||
boolean: bool = false,
|
boolean: bool = false,
|
||||||
|
@ -370,11 +369,11 @@ test {
|
||||||
.int = 3,
|
.int = 3,
|
||||||
.boolean = false,
|
.boolean = false,
|
||||||
.str_enum = null,
|
.str_enum = null,
|
||||||
}, try parseQuery(TestQuery, ""));
|
}, try parseQuery(std.testing.allocator, TestQuery, ""));
|
||||||
|
|
||||||
try std.testing.expectEqual(TestQuery{
|
try std.testing.expectEqual(TestQuery{
|
||||||
.int = 5,
|
.int = 5,
|
||||||
.boolean = true,
|
.boolean = true,
|
||||||
.str_enum = .foo,
|
.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