@@ 6,6 6,7 @@ const mem = std.mem;
const meta = std.meta;
pub const DecodeError = error{
+ DuplicateKey,
Overflow,
InvalidBool,
InvalidUnion,
@@ 194,7 195,13 @@ pub fn Decoder(comptime ReaderType: type) type {
for (0..i) |_| {
const key = try self.decode(K);
const val = try self.decode(V);
- _ = map.putAssumeCapacity(key, val);
+
+ const res = map.getOrPutAssumeCapacity(key);
+
+ if (res.found_existing)
+ return DecodeError.DuplicateKey;
+
+ res.value_ptr.* = val;
}
return map;
@@ 146,3 146,89 @@ test "unmarshal slice" {
try expectEqual(@as(usize, 0x33), val[2]);
try expectEqual(@as(usize, 0x44), val[3]);
}
+
+test "unmarshal map" {
+ {
+ const payload = &[_]u8{
+ 0x03,
+ 0x01,
+ 0x11,
+ 0x02,
+ 0x22,
+ 0x03,
+ 0x33,
+ };
+ var fbs = io.fixedBufferStream(payload);
+ const reader = fbs.reader();
+ var d = decoder(testing.allocator, reader);
+ defer d.deinit();
+ const val = try d.decode(std.AutoHashMap(u8, u8));
+ try expectEqual(@as(usize, 3), val.count());
+ try expectEqual(@as(?u8, 0x11), val.get(0x01));
+ try expectEqual(@as(?u8, 0x22), val.get(0x02));
+ try expectEqual(@as(?u8, 0x33), val.get(0x03));
+ }
+
+ // rejects duplicate keys
+ {
+ const payload = &[_]u8{
+ 0x02,
+ 0x01,
+ 0x13,
+ 0x01,
+ 0x37,
+ };
+ var fbs = io.fixedBufferStream(payload);
+ const reader = fbs.reader();
+ var d = decoder(testing.allocator, reader);
+ defer d.deinit();
+ const val = d.decode(std.AutoHashMap(u8, u8));
+ try expectError(error.DuplicateKey, val);
+ }
+
+ // respects size limits
+ {
+ // TODO: we don't have such limits.
+ }
+}
+
+test "unmarshal union" {
+ const NameAge = union(enum) {
+ name: []const u8,
+ age: isize,
+ };
+
+ {
+ const payload = &[_]u8{ 0x00, 0x04, 0x4d, 0x61, 0x72, 0x79 };
+ var fbs = io.fixedBufferStream(payload);
+ const reader = fbs.reader();
+ var d = decoder(testing.allocator, reader);
+ defer d.deinit();
+ const val = try d.decode(NameAge);
+ try expectEqualSlices(u8, (NameAge{ .name = "Mary" }).name, val.name);
+ }
+
+ {
+ const payload = &[_]u8{ 0x01, 0x30 };
+ var fbs = io.fixedBufferStream(payload);
+ const reader = fbs.reader();
+ var d = decoder(testing.allocator, reader);
+ defer d.deinit();
+ const val = try d.decode(NameAge);
+ try expectEqual((NameAge{ .age = 24 }).age, val.age);
+ }
+
+ {
+ const payload = &[_]u8{ 0x13, 0x37 };
+ var fbs = io.fixedBufferStream(payload);
+ const reader = fbs.reader();
+ var d = decoder(testing.allocator, reader);
+ defer d.deinit();
+ const val = d.decode(NameAge);
+ try expectError(error.InvalidUnion, val);
+ }
+}
+
+test "unmarshal custom" {
+ // TODO: we should allow custom decode methods.
+}