Add tests for deserialization
This commit is contained in:
parent
aa632ace8b
commit
c7dcded04a
1 changed files with 95 additions and 72 deletions
|
@ -207,7 +207,7 @@ fn DeserializerContext(comptime Result: type, comptime From: type, comptime Cont
|
|||
}
|
||||
|
||||
pub fn finish(self: *@This()) !Result {
|
||||
return (try self.deserialize(Result, &.{})).?;
|
||||
return (try self.deserialize(Result, &.{})) orelse error.MissingField;
|
||||
}
|
||||
|
||||
fn getSerializedField(self: *@This(), comptime field_ref: FieldRef) ?From {
|
||||
|
@ -233,7 +233,7 @@ fn DeserializerContext(comptime Result: type, comptime From: type, comptime Cont
|
|||
const maybe_value = try self.deserialize(F, new_field_ref);
|
||||
if (maybe_value) |value| {
|
||||
// TODO: errdefer cleanup
|
||||
if (result != null) return error.DuplicateUnionField;
|
||||
if (result != null) return error.DuplicateUnionMember;
|
||||
result = @unionInit(T, field.name, value);
|
||||
}
|
||||
}
|
||||
|
@ -258,12 +258,10 @@ fn DeserializerContext(comptime Result: type, comptime From: type, comptime Cont
|
|||
}
|
||||
} else {
|
||||
any_missing = true;
|
||||
std.debug.print("\nMissing field {s}\n", .{util.comptimeJoin(".", new_field_ref)});
|
||||
//return error.MissingStructField;
|
||||
}
|
||||
}
|
||||
if (any_missing) {
|
||||
return if (any_explicit) error.MissingStructField else null;
|
||||
return if (any_explicit) error.MissingField else null;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -292,85 +290,110 @@ const bool_map = std.ComptimeStringMap(bool, .{
|
|||
.{ "0", false },
|
||||
});
|
||||
|
||||
test {
|
||||
const T = struct {
|
||||
foo: usize,
|
||||
bar: bool,
|
||||
};
|
||||
|
||||
const TDefault = struct {
|
||||
foo: usize = 0,
|
||||
bar: bool = false,
|
||||
};
|
||||
_ = TDefault;
|
||||
test "Deserializer" {
|
||||
|
||||
// Happy case - simple
|
||||
{
|
||||
const T = struct { foo: usize, bar: bool };
|
||||
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try ds.setSerializedField("foo", "123");
|
||||
try ds.setSerializedField("bar", "true");
|
||||
try std.testing.expectEqual(T{ .foo = 123, .bar = true }, try ds.finish());
|
||||
}
|
||||
|
||||
// Returns error if nonexistent field set
|
||||
{
|
||||
const T = struct { foo: usize, bar: bool };
|
||||
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try ds.setSerializedField("foo", "123");
|
||||
try std.testing.expectError(error.MissingStructField, ds.finish());
|
||||
try std.testing.expectError(error.UnknownField, ds.setSerializedField("baz", "123"));
|
||||
}
|
||||
|
||||
//const int = Intermediary(T, QueryStringOptions){
|
||||
//.age = "123",
|
||||
//.@"sub_struct.foo" = "abc",
|
||||
//.@"sub_struct.bar" = "abc",
|
||||
//.@"foo_union" = "abc",
|
||||
//};
|
||||
//std.debug.print("{any}\n", .{int});
|
||||
//std.debug.print("{any}\n", .{deserialize(T, QueryStringOptions, &.{}, int)});
|
||||
// Substruct dereferencing
|
||||
{
|
||||
const T = struct {
|
||||
foo: struct { bar: bool, baz: bool },
|
||||
};
|
||||
|
||||
//const int2 = Intermediary(T, FormDataOptions){
|
||||
//.age = .{ .value = "123" },
|
||||
//.@"sub_struct.foo" = .{ .value = "123" },
|
||||
//.@"sub_struct.bar" = .{ .value = "123" },
|
||||
////.@"foo_union" = .{
|
||||
//.value = "abc",
|
||||
//},
|
||||
//};
|
||||
//std.debug.print("{any}\n", .{int2});
|
||||
//
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try ds.setSerializedField("foo.bar", "true");
|
||||
try ds.setSerializedField("foo.baz", "true");
|
||||
try std.testing.expectEqual(T{ .foo = .{ .bar = true, .baz = true } }, try ds.finish());
|
||||
}
|
||||
|
||||
// const T = struct {
|
||||
// age: usize,
|
||||
// sub_struct: ?struct {
|
||||
// x: union(enum) {
|
||||
// foo: []const u8,
|
||||
// bar: []const u8,
|
||||
// },
|
||||
// },
|
||||
// sub_union: union(enum) {
|
||||
// foo_union: []const u8,
|
||||
// bar_union: []const u8,
|
||||
// },
|
||||
// time: ?@import("./DateTime.zig"),
|
||||
// };
|
||||
// inline for (comptime getRecursiveFieldList(T, &.{}, .{})) |list| {
|
||||
// std.debug.print("{s}\n", .{util.comptimeJoin(".", list)});
|
||||
// }
|
||||
// // var ds = Deserializer(struct {
|
||||
// age: usize,
|
||||
// sub_struct: ?struct {
|
||||
// x: union(enum) {
|
||||
// foo: []const u8,
|
||||
// bar: []const u8,
|
||||
// },
|
||||
// },
|
||||
// sub_union: union(enum) {
|
||||
// foo_union: []const u8,
|
||||
// bar_union: []const u8,
|
||||
// },
|
||||
// time: ?@import("./DateTime.zig"),
|
||||
// }, []const u8){ .context = .{} };
|
||||
//try ds.setSerializedField("age", "123");
|
||||
//try ds.setSerializedField("foo_union", "123");
|
||||
//try ds.setSerializedField("sub_struct.foo", "123");
|
||||
//try ds.setSerializedField("sub_struct.bar", "123");
|
||||
// Union embedding
|
||||
{
|
||||
const T = struct {
|
||||
foo: union(enum) { bar: bool, baz: bool },
|
||||
};
|
||||
|
||||
//std.debug.print("{any}\n", .{try ds.finish()});
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try ds.setSerializedField("bar", "true");
|
||||
try std.testing.expectEqual(T{ .foo = .{ .bar = true } }, try ds.finish());
|
||||
}
|
||||
|
||||
// Returns error if multiple union fields specified
|
||||
{
|
||||
const T = struct {
|
||||
foo: union(enum) { bar: bool, baz: bool },
|
||||
};
|
||||
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try ds.setSerializedField("bar", "true");
|
||||
try ds.setSerializedField("baz", "true");
|
||||
try std.testing.expectError(error.DuplicateUnionMember, ds.finish());
|
||||
}
|
||||
|
||||
// Uses default values if fields aren't provided
|
||||
{
|
||||
const T = struct { foo: usize = 123, bar: bool = true };
|
||||
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try std.testing.expectEqual(T{ .foo = 123, .bar = true }, try ds.finish());
|
||||
}
|
||||
|
||||
// Returns an error if fields aren't provided and no default exists
|
||||
{
|
||||
const T = struct { foo: usize, bar: bool };
|
||||
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try ds.setSerializedField("foo", "123");
|
||||
try std.testing.expectError(error.MissingField, ds.finish());
|
||||
}
|
||||
|
||||
// Handles optional containers
|
||||
{
|
||||
const T = struct {
|
||||
foo: ?struct { bar: usize = 3, baz: usize } = null,
|
||||
qux: ?union(enum) { quux: usize } = null,
|
||||
};
|
||||
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try std.testing.expectEqual(T{ .foo = null, .qux = null }, try ds.finish());
|
||||
}
|
||||
|
||||
{
|
||||
const T = struct {
|
||||
foo: ?struct { bar: usize = 3, baz: usize } = null,
|
||||
qux: ?union(enum) { quux: usize } = null,
|
||||
};
|
||||
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try ds.setSerializedField("foo.baz", "3");
|
||||
try ds.setSerializedField("quux", "3");
|
||||
try std.testing.expectEqual(T{ .foo = .{ .bar = 3, .baz = 3 }, .qux = .{ .quux = 3 } }, try ds.finish());
|
||||
}
|
||||
|
||||
{
|
||||
const T = struct {
|
||||
foo: ?struct { bar: usize = 3, baz: usize } = null,
|
||||
qux: ?union(enum) { quux: usize } = null,
|
||||
};
|
||||
|
||||
var ds = Deserializer(T, []const u8){};
|
||||
try ds.setSerializedField("foo.bar", "3");
|
||||
try ds.setSerializedField("quux", "3");
|
||||
try std.testing.expectError(error.MissingField, ds.finish());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue