From e98ba5fc4044cd84ab88b10cb8c88d765884462f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 13 Dec 2018 06:38:14 -0500 Subject: [PATCH] add mem.readVarInt, fix InStream.readVarInt, fix stack traces fixes a regression from b883bc8 --- std/debug/index.zig | 2 +- std/io.zig | 11 ++++++----- std/mem.zig | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/std/debug/index.zig b/std/debug/index.zig index 3967e5a8be..73c6ea7b56 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -1200,7 +1200,7 @@ const Constant = struct { fn asUnsignedLe(self: *const Constant) !u64 { if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; if (self.signed) return error.InvalidDebugInfo; - return mem.readIntSliceLittle(u64, self.payload); + return mem.readVarInt(u64, self.payload, builtin.Endian.Little); } }; diff --git a/std/io.zig b/std/io.zig index 8d33dfc5ea..c40ededc00 100644 --- a/std/io.zig +++ b/std/io.zig @@ -183,11 +183,12 @@ pub fn InStream(comptime ReadError: type) type { return mem.readIntSlice(T, bytes, endian); } - pub fn readVarInt(self: *Self, comptime T: type, endian: builtin.Endian, size: usize) !T { - assert(size <= @sizeOf(T)); - var bytes: [@sizeOf(T)]u8 = undefined; - try self.readNoEof(bytes[0..size]); - return mem.readIntSlice(T, bytes, endian); + pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType { + assert(size <= @sizeOf(ReturnType)); + var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined; + const bytes = bytes_buf[0..size]; + try self.readNoEof(bytes); + return mem.readVarInt(ReturnType, bytes, endian); } pub fn skipBytes(self: *Self, num_bytes: usize) !void { diff --git a/std/mem.zig b/std/mem.zig index 97dc46a80f..393033f22a 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -407,6 +407,27 @@ test "mem.indexOf" { assert(lastIndexOfScalar(u8, "boo", 'o').? == 2); } +/// Reads an integer from memory with size equal to bytes.len. +/// T specifies the return type, which must be large enough to store +/// the result. +pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType { + var result: ReturnType = 0; + switch (endian) { + builtin.Endian.Big => { + for (bytes) |b| { + result = (result << 8) | b; + } + }, + builtin.Endian.Little => { + const ShiftType = math.Log2Int(ReturnType); + for (bytes) |b, index| { + result = result | (ReturnType(b) << @intCast(ShiftType, index * 8)); + } + }, + } + return result; +} + /// Reads an integer from memory with bit count specified by T. /// The bit count of T must be evenly divisible by 8. /// This function cannot fail and cannot cause undefined behavior.