rvarint

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 4, 2024 License: BSD-3-Clause Imports: 1 Imported by: 0

README

rvarint

Package rvarint implements reverse varint encoding and decoding.

The encoding is similar to varint, but the bytes are written in reverse order.

Go Reference

Usage

This allows you to read varints from the end of a buffer, which can be useful when reading from a buffer that is being filled from the end.

See GoDoc for examples.

The main difference to enconding/binary is that Uvarint and Varint will read from the end of the buffer.

This also means that appending several values will result in the values being read back in reverse order.

Documentation

Overview

Package rvarint implements reverse varint encoding and decoding.

The encoding is similar to varint, but the bytes are written in reverse order.

This means that reading will read from the end of the buffer, and the encoded values will be read in reverse order.

Index

Examples

Constants

View Source
const (
	MaxVarintLen16 = 3
	MaxVarintLen32 = 5
	MaxVarintLen64 = 10
)

MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.

Variables

This section is empty.

Functions

func AppendUvarint

func AppendUvarint(buf []byte, x uint64) []byte

AppendUvarint appends the reverse varint-encoded form of x to buf and returns the extended buffer.

Example
package main

import (
	"encoding/hex"
	"fmt"

	"github.com/klauspost/rvarint"
)

func main() {
	// Add some existing content to the buffer
	buf := []byte("prefix")

	// values to encode
	values := []uint64{1, 2, 127, 128, 255, 256}
	for _, x := range values {
		buf = rvarint.AppendUvarint(buf, x)
	}
	fmt.Printf("encoded: %s\n", hex.EncodeToString(buf))

	// When we read back we get the values in *reverse* order.
	for range values {
		y, n := rvarint.Uvarint(buf)
		if n <= 0 {
			fmt.Println("unable to read value")
			break
		}
		fmt.Println(y)
		buf = buf[:len(buf)-n]
	}
	fmt.Println("remaining buffer:", string(buf))
}
Output:

encoded: 70726566697801027f018001ff0280
256
255
128
127
2
1
remaining buffer: prefix

func AppendVarint

func AppendVarint(buf []byte, x int64) []byte

AppendVarint appends the varint-encoded form of x, as generated by PutVarint, to buf and returns the extended buffer.

Example
package main

import (
	"encoding/hex"
	"fmt"

	"github.com/klauspost/rvarint"
)

func main() {
	// Add some existing content to the buffer
	buf := []byte("prefix")

	// values to encode
	values := []int64{-65, -64, -2, -1, 0, 1, 2, 63, 64}
	for _, x := range values {
		buf = rvarint.AppendVarint(buf, x)
	}
	fmt.Printf("encoded: %s\n", hex.EncodeToString(buf))

	// When we read back we get the values in *reverse* order.
	for range values {
		y, n := rvarint.Varint(buf)
		if n <= 0 {
			fmt.Println("unable to read value")
			break
		}
		fmt.Println(y)
		buf = buf[:len(buf)-n]
	}
	fmt.Println("remaining buffer:", string(buf))
}
Output:

encoded: 70726566697801817f03010002047e0180
64
63
2
1
0
-1
-2
-64
-65
remaining buffer: prefix

func PutUvarint

func PutUvarint(buf []byte, x uint64) int

PutUvarint encodes a uint64 into buf and returns the number of bytes written. If the buffer is too small, PutUvarint will panic.

Example
package main

import (
	"fmt"

	"github.com/klauspost/rvarint"
)

func main() {
	buf := make([]byte, rvarint.MaxVarintLen64)

	for _, x := range []uint64{1, 2, 127, 128, 255, 256} {
		n := rvarint.PutUvarint(buf, x)
		fmt.Printf("%x\n", buf[:n])
	}
}
Output:

01
02
7f
0180
01ff
0280

func PutVarint

func PutVarint(buf []byte, x int64) int

PutVarint encodes an int64 into buf and returns the number of bytes written. If the buffer is too small, PutVarint will panic.

Example
package main

import (
	"fmt"

	"github.com/klauspost/rvarint"
)

func main() {
	buf := make([]byte, rvarint.MaxVarintLen64)

	for _, x := range []int64{-65, -64, -2, -1, 0, 1, 2, 63, 64} {
		n := rvarint.PutVarint(buf, x)
		fmt.Printf("%x\n", buf[:n])
	}
}
Output:

0181
7f
03
01
00
02
04
7e
0180

func Uvarint

func Uvarint(buf []byte) (uint64, int)

Uvarint decodes a uint64 from the end of buf and returns that value and the number of bytes read (> 0). If an error occurred, the value is 0 and the number of bytes n is <= 0 meaning:

n == 0: buf too small
n  < 0: value larger than 64 bits (overflow)
        and -n is the number of bytes read

On success, the buffer can be truncated using buf = buf[:len(buf)-n]

Example
package main

import (
	"fmt"

	"github.com/klauspost/rvarint"
)

func main() {
	inputs := [][]byte{
		{0x01},
		{0x02},
		{0x7f},
		{0x01, 0x80},
		{0x01, 0xff},
		{0x02, 0x80},
	}
	for _, b := range inputs {
		x, n := rvarint.Uvarint(b)
		if n != len(b) {
			fmt.Println("Uvarint did not consume all of in")
		}
		fmt.Println(x)
	}
}
Output:

1
2
127
128
255
256

func Varint

func Varint(buf []byte) (int64, int)

Varint decodes an int64 from the end of buf and returns that value and the number of bytes read (> 0). If an error occurred, the value is 0 and the number of bytes n is <= 0 with the following meaning:

n == 0: buf too small
n  < 0: value larger than 64 bits (overflow)
        and -n is the number of bytes read

On success, the buffer can be truncated using buf = buf[:len(buf)-n]

Example
package main

import (
	"fmt"

	"github.com/klauspost/rvarint"
)

func main() {
	inputs := [][]byte{
		{0x01, 0x81},
		{0x7f},
		{0x03},
		{0x01},
		{0x00},
		{0x02},
		{0x04},
		{0x7e},
		{0x01, 0x80},
	}
	for _, b := range inputs {
		x, n := rvarint.Varint(b)
		if n != len(b) {
			fmt.Println("Varint did not consume all of in", len(b)-n, "left")
		}
		fmt.Println(x)
	}
}
Output:

-65
-64
-2
-1
0
1
2
63
64

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL