From: Joe Tsai Date: Wed, 13 Apr 2022 20:21:30 +0000 (-0700) Subject: encoding/binary: add AppendVarint AppendUvarint X-Git-Tag: go1.19beta1~659 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=35a92f92bd0ce15c658dd6794238ca90b71e4422;p=gostls13.git encoding/binary: add AppendVarint AppendUvarint This adds a straight-forward implementation of the functionality. A more performant version could be added that unrolls the loop as is done in google.golang.org/protobuf/encoding/protowire, but usages that demand high performance can use that package instead. Fixes #51644 Change-Id: I9d3b615a60cdff47e5200e7e5d2276adf4c93783 Reviewed-on: https://go-review.googlesource.com/c/go/+/400176 Reviewed-by: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov Run-TryBot: Joseph Tsai TryBot-Result: Gopher Robot --- diff --git a/api/next/51644.txt b/api/next/51644.txt new file mode 100644 index 0000000000..d93dbbf184 --- /dev/null +++ b/api/next/51644.txt @@ -0,0 +1,2 @@ +pkg encoding/binary, func AppendUvarint([]uint8, uint64) []uint8 #51644 +pkg encoding/binary, func AppendVarint([]uint8, int64) []uint8 #51644 diff --git a/src/encoding/binary/varint.go b/src/encoding/binary/varint.go index 1b07e2541d..c807d15f44 100644 --- a/src/encoding/binary/varint.go +++ b/src/encoding/binary/varint.go @@ -36,6 +36,16 @@ const ( MaxVarintLen64 = 10 ) +// AppendUvarint appends the varint-encoded form of x, +// as generated by PutUvarint, to buf and returns the extended buffer. +func AppendUvarint(buf []byte, x uint64) []byte { + for x >= 0x80 { + buf = append(buf, byte(x)|0x80) + x >>= 7 + } + return append(buf, byte(x)) +} + // PutUvarint encodes a uint64 into buf and returns the number of bytes written. // If the buffer is too small, PutUvarint will panic. func PutUvarint(buf []byte, x uint64) int { @@ -77,6 +87,16 @@ func Uvarint(buf []byte) (uint64, int) { return 0, 0 } +// AppendVarint appends the varint-encoded form of x, +// as generated by PutVarint, to buf and returns the extended buffer. +func AppendVarint(buf []byte, x int64) []byte { + ux := uint64(x) << 1 + if x < 0 { + ux = ^ux + } + return AppendUvarint(buf, ux) +} + // PutVarint encodes an int64 into buf and returns the number of bytes written. // If the buffer is too small, PutVarint will panic. func PutVarint(buf []byte, x int64) int { diff --git a/src/encoding/binary/varint_test.go b/src/encoding/binary/varint_test.go index d025a67538..080a2148f0 100644 --- a/src/encoding/binary/varint_test.go +++ b/src/encoding/binary/varint_test.go @@ -36,6 +36,12 @@ func testVarint(t *testing.T, x int64) { t.Errorf("Varint(%d): got n = %d; want %d", x, m, n) } + buf2 := []byte("prefix") + buf2 = AppendVarint(buf2, x) + if string(buf2) != "prefix"+string(buf[:n]) { + t.Errorf("AppendVarint(%d): got %q, want %q", x, buf2, "prefix"+string(buf[:n])) + } + y, err := ReadVarint(bytes.NewReader(buf)) if err != nil { t.Errorf("ReadVarint(%d): %s", x, err) @@ -56,6 +62,12 @@ func testUvarint(t *testing.T, x uint64) { t.Errorf("Uvarint(%d): got n = %d; want %d", x, m, n) } + buf2 := []byte("prefix") + buf2 = AppendUvarint(buf2, x) + if string(buf2) != "prefix"+string(buf[:n]) { + t.Errorf("AppendUvarint(%d): got %q, want %q", x, buf2, "prefix"+string(buf[:n])) + } + y, err := ReadUvarint(bytes.NewReader(buf)) if err != nil { t.Errorf("ReadUvarint(%d): %s", x, err)