wip varint

This commit is contained in:
Motiejus Jakštys 2022-02-23 06:47:56 +02:00 committed by Motiejus Jakštys
parent b58063ef63
commit d555994960
2 changed files with 91 additions and 0 deletions

View File

@ -5,4 +5,5 @@ test "turbonss test suite" {
_ = @import("user.zig");
_ = @import("group.zig");
_ = @import("padding.zig");
_ = @import("varint.zig");
}

90
src/varint.zig Normal file
View File

@ -0,0 +1,90 @@
//
// varint64 []const u8 variants
//
// Thanks to https://github.com/gsquire/zig-snappy/blob/master/snappy.zig and golang's
// varint implementation.
const std = @import("std");
// Represents a variable length integer that we read from a byte stream along
// with how many bytes were read to decode it.
pub const Varint = struct {
value: u64,
bytesRead: usize,
};
const MaxVarintLen64 = 10;
// https://golang.org/pkg/encoding/binary/#Uvarint
pub fn uvarint(buf: []const u8) error{Overflow}!Varint {
var x: u64 = 0;
var s: u6 = 0;
for (buf) |b, i| {
if (i == MaxVarintLen64) {
// Catch byte reads past MaxVarintLen64.
// See issue https://golang.org/issues/41185
return error.Overflow;
}
if (b < 0x80) {
if (i == MaxVarintLen64 - 1 and b > 1) {
return error.Overflow;
}
return Varint{ .value = x | (@as(u64, b) << s), .bytesRead = i + 1 };
}
x |= (@as(u64, b & 0x7f) << s);
s += 7;
}
return Varint{
.value = 0,
.bytesRead = 0,
};
}
// https://golang.org/pkg/encoding/binary/#PutUvarint
pub fn putUvarint(buf: []u8, x: u64) usize {
var i: usize = 0;
var mutX = x;
while (mutX >= 0x80) {
buf[i] = @truncate(u8, mutX) | 0x80;
mutX >>= 7;
i += 1;
}
buf[i] = @truncate(u8, mutX);
return i + 1;
}
const testing = std.testing;
const tests = [_]u64{
0,
1,
2,
10,
20,
63,
64,
65,
127,
128,
129,
255,
256,
257,
1 << 63 - 1,
};
test "uvarint" {
for (tests) |x| {
var buf: [MaxVarintLen64]u8 = undefined;
const n = putUvarint(buf[0..], x);
const got = try uvarint(buf[0..n]);
try testing.expectEqual(x, got.value);
try testing.expectEqual(n, got.bytesRead);
}
}