Skip to content

Commit 939fcce

Browse files
authored
std.mem.readVarInt: fix for 8-bits and below (Reloaded) (#20513)
1 parent 08e83fe commit 939fcce

File tree

1 file changed

+30
-4
lines changed

1 file changed

+30
-4
lines changed

lib/std/mem.zig

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,21 +1594,47 @@ test containsAtLeast {
15941594
/// T specifies the return type, which must be large enough to store
15951595
/// the result.
15961596
pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: Endian) ReturnType {
1597-
var result: ReturnType = 0;
1597+
const bits = @typeInfo(ReturnType).Int.bits;
1598+
const signedness = @typeInfo(ReturnType).Int.signedness;
1599+
const WorkType = std.meta.Int(signedness, @max(16, bits));
1600+
var result: WorkType = 0;
15981601
switch (endian) {
15991602
.big => {
16001603
for (bytes) |b| {
16011604
result = (result << 8) | b;
16021605
}
16031606
},
16041607
.little => {
1605-
const ShiftType = math.Log2Int(ReturnType);
1608+
const ShiftType = math.Log2Int(WorkType);
16061609
for (bytes, 0..) |b, index| {
1607-
result = result | (@as(ReturnType, b) << @as(ShiftType, @intCast(index * 8)));
1610+
result = result | (@as(WorkType, b) << @as(ShiftType, @intCast(index * 8)));
16081611
}
16091612
},
16101613
}
1611-
return result;
1614+
return @as(ReturnType, @truncate(result));
1615+
}
1616+
1617+
test readVarInt {
1618+
try testing.expect(readVarInt(u0, &[_]u8{}, .big) == 0x0);
1619+
try testing.expect(readVarInt(u0, &[_]u8{}, .little) == 0x0);
1620+
try testing.expect(readVarInt(u8, &[_]u8{0x12}, .big) == 0x12);
1621+
try testing.expect(readVarInt(u8, &[_]u8{0xde}, .little) == 0xde);
1622+
try testing.expect(readVarInt(u16, &[_]u8{ 0x12, 0x34 }, .big) == 0x1234);
1623+
try testing.expect(readVarInt(u16, &[_]u8{ 0x12, 0x34 }, .little) == 0x3412);
1624+
1625+
try testing.expect(readVarInt(i8, &[_]u8{0xff}, .big) == -1);
1626+
try testing.expect(readVarInt(i8, &[_]u8{0xfe}, .little) == -2);
1627+
try testing.expect(readVarInt(i16, &[_]u8{ 0xff, 0xfd }, .big) == -3);
1628+
try testing.expect(readVarInt(i16, &[_]u8{ 0xfc, 0xff }, .little) == -4);
1629+
1630+
// Return type can be oversized (bytes.len * 8 < @typeInfo(ReturnType).Int.bits)
1631+
try testing.expect(readVarInt(u9, &[_]u8{0x12}, .little) == 0x12);
1632+
try testing.expect(readVarInt(u9, &[_]u8{0xde}, .big) == 0xde);
1633+
try testing.expect(readVarInt(u80, &[_]u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }, .big) == 0x123456789abcdef024);
1634+
try testing.expect(readVarInt(u80, &[_]u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }, .little) == 0xfedcba9876543210ec);
1635+
1636+
try testing.expect(readVarInt(i9, &[_]u8{0xff}, .big) == 0xff);
1637+
try testing.expect(readVarInt(i9, &[_]u8{0xfe}, .little) == 0xfe);
16121638
}
16131639

16141640
/// Loads an integer from packed memory with provided bit_count, bit_offset, and signedness.

0 commit comments

Comments
 (0)