Add rudimentary scalar parsing
This commit is contained in:
parent
4a98b6a9c4
commit
2f78490545
1 changed files with 73 additions and 0 deletions
|
@ -9,6 +9,11 @@ const FormFieldResult = struct {
|
|||
more: bool,
|
||||
};
|
||||
|
||||
const FormField = struct {
|
||||
value: []const u8,
|
||||
params: FormDataParams,
|
||||
};
|
||||
|
||||
const ParamIter = struct {
|
||||
str: []const u8,
|
||||
index: usize = 0,
|
||||
|
@ -163,6 +168,74 @@ pub fn parseFormData(boundary: []const u8, reader: anytype, alloc: std.mem.Alloc
|
|||
if (!field.more) return;
|
||||
}
|
||||
}
|
||||
|
||||
const FormFile = struct {
|
||||
filename: ?[]const u8,
|
||||
data: []const u8,
|
||||
};
|
||||
|
||||
fn parseFormValue(alloc: std.mem.Allocator, comptime T: type, field: FormField) !T {
|
||||
const is_optional = std.meta.trait.is(.Optional)(T);
|
||||
if ((comptime is_optional) and field.value.len == 0) return null;
|
||||
|
||||
if (comptime std.meta.trait.isZigString(T)) return field.value;
|
||||
|
||||
if (T == FormFile) {
|
||||
return FormFile{
|
||||
.filename = field.filename,
|
||||
.data = field.value,
|
||||
};
|
||||
}
|
||||
|
||||
const result = if (comptime std.meta.trait.isIntegral(T))
|
||||
try std.fmt.parseInt(T, field.value, 0)
|
||||
else if (comptime std.meta.trait.isFloat(T))
|
||||
try std.fmt.parseFloat(T, field.value)
|
||||
else if (comptime std.meta.trait.is(.Enum)(T)) blk: {
|
||||
const val = std.ascii.lowerStringAlloc(alloc, field.value);
|
||||
defer alloc.free(val);
|
||||
break :blk std.meta.stringToEnum(T, val) orelse return error.InvalidEnumValue;
|
||||
} else if (T == bool) blk: {
|
||||
const val = std.ascii.lowerStringAlloc(alloc, field.value);
|
||||
defer alloc.free(val);
|
||||
break :blk bool_map.get(val) orelse return error.InvalidBool;
|
||||
} else if (comptime std.meta.trait.hasFn("parse")(T))
|
||||
try T.parse(field.value)
|
||||
else
|
||||
@compileError("Invalid type " ++ @typeName(T));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const bool_map = std.ComptimeStringMap(bool, .{
|
||||
.{ "true", true },
|
||||
.{ "t", true },
|
||||
.{ "yes", true },
|
||||
.{ "y", true },
|
||||
.{ "1", true },
|
||||
|
||||
.{ "false", false },
|
||||
.{ "f", false },
|
||||
.{ "no", false },
|
||||
.{ "n", false },
|
||||
.{ "0", false },
|
||||
});
|
||||
|
||||
fn isScalar(comptime T: type) bool {
|
||||
if (comptime std.meta.trait.isZigString(T)) return true;
|
||||
if (comptime std.meta.trait.isIntegral(T)) return true;
|
||||
if (comptime std.meta.trait.isFloat(T)) return true;
|
||||
if (comptime std.meta.trait.is(.Enum)(T)) return true;
|
||||
if (comptime std.meta.trait.is(.EnumLiteral)(T)) return true;
|
||||
if (T == bool) return true;
|
||||
if (T == FormFile) return true;
|
||||
if (comptime std.meta.trait.hasFn("parse")(T)) return true;
|
||||
|
||||
if (comptime std.meta.trait.is(.Optional)(T) and isScalar(std.meta.Child(T))) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fn toCrlf(comptime str: []const u8) []const u8 {
|
||||
comptime {
|
||||
var buf: [str.len * 2]u8 = undefined;
|
||||
|
|
Loading…
Reference in a new issue