Add rudimentary scalar parsing

This commit is contained in:
jaina heartles 2022-11-27 06:24:41 -08:00
parent 4a98b6a9c4
commit 2f78490545

View file

@ -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;