Files
bin/little/little.go

1373 lines
30 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package little
// LOW TO HIGHT
import (
"errors"
"fmt"
"io"
"math"
)
const (
maxReadAttempts = 5
MinInt24 = -1 << 23 // -8388608
MaxInt24 = 1<<23 - 1 // 8388607
MinInt48 = -1 << 47 // -140737488355328
MaxInt48 = 1<<47 - 1 // 140737488355327
MaxUint24 = 1<<24 - 1 // 16777215
MaxUint48 = 1<<48 - 1 // 281474976710655
//Int32SignBit uint32 = 1 << 31
//Int64SignBit uint64 = 1 << 63
)
var (
// ErrReadOverflow shows 100% bug in the source reader
ErrReadOverflow = errors.New("bin: reader returned 'n' > bufsize")
// ErrNegativeReadCount shows 100% bug in the source reader
ErrNegativeReadCount = errors.New("bin: reader returned negative 'n'")
ErrNoSpace = errors.New("bin: no space")
ErrTooLong = errors.New("bin: too long") // слишком длинная строка или массив байт
ErrRange = errors.New("bin: out of range")
ErrNegativeSize = errors.New("bin: negative size")
)
func ReadByteAsInt(r io.Reader) (i int, err error) {
a, err := ReadN(r, 1)
if err != nil {
return
}
return int(a[0]), nil
}
func ReadUint16AsInt(r io.Reader) (_ int, err error) {
u16, err := ReadUint16(r)
if err != nil {
return
}
return int(u16), nil
}
func ReadUint32AsInt(r io.Reader) (_ int, err error) {
u32, err := ReadUint32(r)
if err != nil {
return
}
return int(u32), nil
}
func ReadUint32AsInt64(r io.Reader) (_ int64, err error) {
u32, err := ReadUint32(r)
if err != nil {
return
}
return int64(u32), nil
}
func ReadByte(r io.Reader) (byte, error) {
buf := make([]byte, 1)
if err := ReadNInto(r, buf); err != nil {
return 0, err
}
return buf[0], nil
}
// ReadN - безопасно читаем n байт. Обрабатывает все возможные ситуации, в том числе
// баги Reader
func ReadN(r io.Reader, n int) (_ []byte, err error) {
if n < 0 {
err = fmt.Errorf("wrong n=%d", n)
return
}
buf := make([]byte, n)
err = ReadNInto(r, buf)
if err != nil {
return
}
return buf, nil
}
func ReadNInto(r io.Reader, buf []byte) (err error) {
if len(buf) == 0 {
return
}
var q, total, readAttempts int
// Избегаем вечного цикла из-за неправильной реализации ридера
for readAttempts < maxReadAttempts {
bufsize := len(buf) - total
q, err = r.Read(buf[total:])
// Если буфер заполнен - успех, err игнорируем
if q == bufsize {
return nil
}
// Если ошибка - выходим с ошибкой
if err != nil {
return
}
// Если прочитали больше чем размер буфера. Баг в Reader
if q > bufsize {
err = ErrReadOverflow
return
}
// Если прочитали < 0. Баг в Reader
if q < 0 {
err = ErrNegativeReadCount
return
}
// Если ошибки нет, а прочитали 0 байт - чтобы не войти в бесконечный цикл
// увеличиваем readAttempts
if q == 0 {
readAttempts++
} else {
// Что-то прочитали, но меньше чем нужно - увеличиваем счетчик
// суммарно прочитанного
total += q
}
}
err = io.ErrNoProgress
return
}
func ReadString(r io.Reader, n int) (string, error) {
buf, err := ReadN(r, n)
if err != nil {
return "", nil
}
return string(buf), nil
}
// ReadInt16 - читает из io.Reader 2 байта и декодирует их в int16.
func ReadInt16(src io.Reader) (int16, error) {
a, err := ReadN(src, 2)
if err != nil {
return 0, err
}
num := int16(a[0])
num |= int16(a[1]) << 8
return num, nil
}
// ReadInt24 - читает из io.Reader 3 байта и декодирует их в int32.
// Нужно для протокола mbus.
func ReadInt24(src io.Reader) (int32, error) {
a, err := ReadN(src, 3)
if err != nil {
return 0, err
}
tmp := uint32(a[0])
tmp |= uint32(a[1]) << 8
tmp |= uint32(a[2]&127) << 16
if a[2] > 127 {
// для отрицательного числа старшие 9 бит выставляю в единицы
tmp |= (1<<9 - 1) << 23
}
return int32(tmp), nil
}
// ReadInt32 - читает из io.Reader 4 байта и декодирует их в int32.
func ReadInt32(src io.Reader) (int32, error) {
a, err := ReadN(src, 4)
if err != nil {
return 0, err
}
num := int32(a[0])
num |= int32(a[1]) << 8
num |= int32(a[2]) << 16
num |= int32(a[3]) << 24
return num, nil
}
// ReadInt48 - читает из io.Reader 6 байт и декодирует их в int64.
func ReadInt48(src io.Reader) (int64, error) {
a, err := ReadN(src, 6)
if err != nil {
return 0, err
}
tmp := uint64(a[0])
tmp |= uint64(a[1]) << 8
tmp |= uint64(a[2]) << 16
tmp |= uint64(a[3]) << 24
tmp |= uint64(a[4]) << 32
tmp |= uint64(a[5]&127) << 40
if a[5] > 127 {
// для отрицательного числа старшие 17 бит выставляю в единицы
tmp |= (1<<17 - 1) << 47
}
return int64(tmp), nil
}
// ReadInt64 - читает из io.Reader 8 байт и декодирует их в int64.
func ReadInt64(src io.Reader) (int64, error) {
a, err := ReadN(src, 8)
if err != nil {
return 0, err
}
num := int64(a[0])
num |= int64(a[1]) << 8
num |= int64(a[2]) << 16
num |= int64(a[3]) << 24
num |= int64(a[4]) << 32
num |= int64(a[5]) << 40
num |= int64(a[6]) << 48
num |= int64(a[7]) << 56
return num, nil
}
// ReadUint16 - читает из io.Reader 2 байта и декодирует их в uint16.
func ReadUint16(src io.Reader) (uint16, error) {
a, err := ReadN(src, 2)
if err != nil {
return 0, err
}
num := uint16(a[0])
num |= uint16(a[1]) << 8
return num, nil
}
// ReadUint24 - читает из io.Reader 3 байта и декодирует их в uint32.
func ReadUint24(src io.Reader) (uint32, error) {
a, err := ReadN(src, 3)
if err != nil {
return 0, err
}
num := uint32(a[0])
num |= uint32(a[1]) << 8
num |= uint32(a[2]) << 16
return num, nil
}
// ReadUint32 - читает из io.Reader 4 байта и декодирует их в uint32.
func ReadUint32(src io.Reader) (uint32, error) {
a, err := ReadN(src, 4)
if err != nil {
return 0, err
}
num := uint32(a[0])
num |= uint32(a[1]) << 8
num |= uint32(a[2]) << 16
num |= uint32(a[3]) << 24
return num, nil
}
// ReadUint48 - читает из io.Reader 6 байт и декодирует их в uint64.
func ReadUint48(src io.Reader) (uint64, error) {
a, err := ReadN(src, 6)
if err != nil {
return 0, err
}
num := uint64(a[0])
num |= uint64(a[1]) << 8
num |= uint64(a[2]) << 16
num |= uint64(a[3]) << 24
num |= uint64(a[4]) << 32
num |= uint64(a[5]) << 40
return num, nil
}
// ReadUint64 - читает из io.Reader 8 байт и декодирует их в uint64.
func ReadUint64(src io.Reader) (uint64, error) {
a, err := ReadN(src, 8)
if err != nil {
return 0, err
}
num := uint64(a[0])
num |= uint64(a[1]) << 8
num |= uint64(a[2]) << 16
num |= uint64(a[3]) << 24
num |= uint64(a[4]) << 32
num |= uint64(a[5]) << 40
num |= uint64(a[6]) << 48
num |= uint64(a[7]) << 56
return num, nil
}
// ReadFloat32 - читает из io.Reader 4 байта и декодирует их в float32.
func ReadFloat32(src io.Reader) (float32, error) {
tmp, err := ReadUint32(src)
if err != nil {
return 0, err
}
return math.Float32frombits(tmp), nil
}
// ReadFloat64 - читает из io.Reader 8 байт и декодирует их в float64.
func ReadFloat64(src io.Reader) (_ float64, err error) {
tmp, err := ReadUint64(src)
if err != nil {
return
}
return math.Float64frombits(tmp), nil
}
func ReadString8(src io.Reader) (string, error) {
length, err := ReadByteAsInt(src)
if err != nil {
return "", io.ErrUnexpectedEOF
}
return ReadString(src, length)
}
func ReadString16(src io.Reader) (string, error) {
length, err := ReadUint16AsInt(src)
if err != nil {
return "", err
}
return ReadString(src, length)
}
// WRITE
// WriteInt16 - записывает в io.Writer 2 байта
func WriteInt16(w io.Writer, num int16) (err error) {
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
})
return
}
// WriteInt24 - записывает в io.Writer 3 байта
func WriteInt24(w io.Writer, num int32) (err error) {
if num < MinInt24 || num > MaxInt24 {
return ErrRange
}
var sign byte
if num < 0 {
sign = 128
}
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte((num>>16)&127) | sign,
})
return
}
// WriteInt32 - записывает в io.Writer 4 байта
func WriteInt32(w io.Writer, num int32) (err error) {
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
})
return
}
// WriteInt48 - записывает в io.Writer 6 байт
func WriteInt48(w io.Writer, num int64) (err error) {
if num < MinInt48 || num > MaxInt48 {
return ErrRange
}
var sign byte
if num < 0 {
sign = 128
}
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
byte((num>>40)&127) | sign,
})
return
}
// WriteInt64 - записывает в io.Writer 8 байт
func WriteInt64(w io.Writer, num int64) (err error) {
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
byte(num >> 40),
byte(num >> 48),
byte(num >> 56),
})
return
}
// WriteUint16 - записывает в io.Writer 2 байта
func WriteUint16(w io.Writer, num uint16) (err error) {
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
})
return
}
// WriteUint24 - записывает в io.Writer 3 байта
func WriteUint24(w io.Writer, num uint32) (err error) {
if num > MaxUint24 {
return ErrRange
}
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
})
return
}
// WriteUint32 - записывает в io.Writer 4 байта
func WriteUint32(w io.Writer, num uint32) (err error) {
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
})
return
}
// WriteUint48 - записывает в io.Writer 6 байт
func WriteUint48(w io.Writer, num uint64) (err error) {
if num > MaxUint48 {
return ErrRange
}
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
byte(num >> 40),
})
return
}
// WriteUint64 - записывает в io.Writer 8 байт
func WriteUint64(w io.Writer, num uint64) (err error) {
_, err = w.Write([]byte{
byte(num),
byte(num >> 8),
byte(num >> 16),
byte(num >> 24),
byte(num >> 32),
byte(num >> 40),
byte(num >> 48),
byte(num >> 56),
})
return
}
// WriteFloat32 - записывает 4 байта в io.Writer
func WriteFloat32(w io.Writer, num float32) error {
return WriteUint32(w, math.Float32bits(num))
}
// WriteFloat64 - записывает 8 байт в io.Writer
func WriteFloat64(w io.Writer, num float64) error {
return WriteUint64(w, math.Float64bits(num))
}
func WriteString8(w io.Writer, str string) error {
if len(str) > 255 {
return ErrTooLong
}
tmp := make([]byte, 1+len(str))
PutString8(tmp, str)
_, err := w.Write(tmp)
return err
}
func WriteString16(w io.Writer, str string) error {
if len(str) > math.MaxUint16 {
return ErrTooLong
}
tmp := make([]byte, 2+len(str))
PutString16(tmp, str)
_, err := w.Write(tmp)
return err
}
// для записи timestamp-ов
func WriteInt64AsUint32(w io.Writer, num int64) error {
if num < 0 || num > int64(math.MaxUint32) {
return ErrRange
}
return WriteUint32(w, uint32(num))
}
// удобное кодирования длины
func WriteIntAsByte(w io.Writer, num int) error {
if num < 0 || num > math.MaxUint8 {
return ErrRange
}
_, err := w.Write([]byte{
byte(num),
})
return err
}
// удобное кодирования длины
func WriteIntAsUint16(w io.Writer, num int) error {
if num < 0 || num > math.MaxUint16 {
return ErrRange
}
return WriteUint16(w, uint16(num))
}
// удобное кодирования длины
func WriteIntAsUint24(w io.Writer, num int) error {
if num < 0 || num > MaxUint24 {
return ErrRange
}
return WriteUint24(w, uint32(num))
}
// удобное кодирования длины
func WriteIntAsUint32(w io.Writer, num int) error {
if num < 0 || int64(num) > int64(math.MaxUint32) {
return ErrRange
}
return WriteUint32(w, uint32(num))
}
// PUT
func PutInt16(a []byte, num int16) error {
if len(a) < 2 {
return ErrNoSpace
}
a[0] = byte(num)
a[1] = byte(num >> 8)
return nil
}
func PutInt24(a []byte, num int32) error {
if num < MinInt24 || num > MaxInt24 {
return ErrRange
}
if len(a) < 3 {
return ErrNoSpace
}
var sign byte
if num < 0 {
sign = 128
}
a[0] = byte(num)
a[1] = byte(num >> 8)
a[2] = byte((num>>16)&127) | sign
return nil
}
func PutInt32(a []byte, num int32) error {
if len(a) < 4 {
return ErrNoSpace
}
a[0] = byte(num)
a[1] = byte(num >> 8)
a[2] = byte(num >> 16)
a[3] = byte(num >> 24)
return nil
}
func PutInt48(a []byte, num int64) error {
if num < MinInt48 || num > MaxInt48 {
return ErrRange
}
if len(a) < 6 {
return ErrNoSpace
}
var sign byte
if num < 0 {
sign = 128
}
a[0] = byte(num)
a[1] = byte(num >> 8)
a[2] = byte(num >> 16)
a[3] = byte(num >> 24)
a[4] = byte(num >> 32)
a[5] = byte((num>>40)&127) | sign
return nil
}
func PutInt64(a []byte, num int64) error {
if len(a) < 8 {
return ErrNoSpace
}
a[0] = byte(num)
a[1] = byte(num >> 8)
a[2] = byte(num >> 16)
a[3] = byte(num >> 24)
a[4] = byte(num >> 32)
a[5] = byte(num >> 40)
a[6] = byte(num >> 48)
a[7] = byte(num >> 56)
return nil
}
func PutUint16(a []byte, num uint16) error {
if len(a) < 2 {
return ErrNoSpace
}
a[0] = byte(num)
a[1] = byte(num >> 8)
return nil
}
func PutUint24(a []byte, num uint32) error {
if num > MaxUint24 {
return ErrRange
}
if len(a) < 3 {
return ErrNoSpace
}
a[0] = byte(num)
a[1] = byte(num >> 8)
a[2] = byte(num >> 16)
return nil
}
func PutUint32(a []byte, num uint32) error {
if len(a) < 4 {
return ErrNoSpace
}
a[0] = byte(num)
a[1] = byte(num >> 8)
a[2] = byte(num >> 16)
a[3] = byte(num >> 24)
return nil
}
func PutUint48(a []byte, num uint64) error {
if num > MaxUint48 {
return ErrRange
}
if len(a) < 6 {
return ErrNoSpace
}
a[0] = byte(num)
a[1] = byte(num >> 8)
a[2] = byte(num >> 16)
a[3] = byte(num >> 24)
a[4] = byte(num >> 32)
a[5] = byte(num >> 40)
return nil
}
func PutUint64(a []byte, num uint64) error {
if len(a) < 8 {
return ErrNoSpace
}
a[0] = byte(num)
a[1] = byte(num >> 8)
a[2] = byte(num >> 16)
a[3] = byte(num >> 24)
a[4] = byte(num >> 32)
a[5] = byte(num >> 40)
a[6] = byte(num >> 48)
a[7] = byte(num >> 56)
return nil
}
// PutFloat32 - записывает 4 байта в массив
func PutFloat32(a []byte, num float32) error {
return PutUint32(a, math.Float32bits(num))
}
// PutFloat64 - записывает 8 байт в массив
func PutFloat64(a []byte, num float64) error {
return PutUint64(a, math.Float64bits(num))
}
// PutInt64AsUint32 - записывает 4 байта в массив (для unix timestamp)
func PutInt64AsUint32(a []byte, num int64) error {
return PutUint32(a, uint32(num))
}
// PutIntAsUint16 - записывает 2 байта в массив
func PutIntAsUint16(a []byte, num int) error {
return PutUint16(a, uint16(num))
}
func PutString8(a []byte, str string) error {
if len(str) > 255 {
return ErrTooLong
}
if len(a) < (1 + len(str)) {
return ErrNoSpace
}
a[0] = byte(len(str))
copy(a[1:], str)
return nil
}
func PutString16(a []byte, str string) error {
if len(str) > math.MaxUint16 {
return ErrTooLong
}
if len(a) < (2 + len(str)) {
return ErrNoSpace
}
PutUint16(a, uint16(len(str)))
copy(a[2:], str)
return nil
}
func PutBool(a []byte, flag bool) error {
if len(a) == 0 {
return ErrNoSpace
}
if flag {
a[0] = 1
} else {
a[0] = 0
}
return nil
}
// GET
// GetInt16 - читает из массива 2 байта и декодирует их в int16.
func GetInt16(a []byte) (num int16, err error) {
if len(a) < 2 {
return 0, io.ErrUnexpectedEOF
}
num = int16(a[0])
num |= int16(a[1]) << 8
return
}
// GetInt24 - читает из массива 3 байта и декодирует их в int32.
func GetInt24(a []byte) (num int32, err error) {
if len(a) < 3 {
return 0, io.ErrUnexpectedEOF
}
tmp := uint32(a[0])
tmp |= uint32(a[1]) << 8
tmp |= uint32(a[2]&127) << 16
if a[2] > 127 {
// для отрицательного числа старшие 9 бит выставляю в единицы
tmp |= (1<<9 - 1) << 23
}
return int32(tmp), nil
}
// GetInt32 - читает из массива 4 байта и декодирует их в int32.
func GetInt32(a []byte) (num int32, err error) {
if len(a) < 4 {
return 0, io.ErrUnexpectedEOF
}
num = int32(a[0])
num |= int32(a[1]) << 8
num |= int32(a[2]) << 16
num |= int32(a[3]) << 24
return
}
// GetInt48 - читает из массива 6 байт и декодирует их в int64.
func GetInt48(a []byte) (int64, error) {
if len(a) < 6 {
return 0, io.ErrUnexpectedEOF
}
tmp := uint64(a[0])
tmp |= uint64(a[1]) << 8
tmp |= uint64(a[2]) << 16
tmp |= uint64(a[3]) << 24
tmp |= uint64(a[4]) << 32
tmp |= uint64(a[5]&127) << 40
if a[5] > 127 {
// для отрицательного числа старшие 17 бит выставляю в единицы
tmp |= (1<<17 - 1) << 47
}
return int64(tmp), nil
}
// GetInt64 - читает из массива 8 байт и декодирует их в int64.
func GetInt64(a []byte) (num int64, err error) {
if len(a) < 8 {
return 0, io.ErrUnexpectedEOF
}
num = int64(a[0])
num |= int64(a[1]) << 8
num |= int64(a[2]) << 16
num |= int64(a[3]) << 24
num |= int64(a[4]) << 32
num |= int64(a[5]) << 40
num |= int64(a[6]) << 48
num |= int64(a[7]) << 56
return
}
// GetUint16 - читает из массива 2 байта и декодирует их в uint16.
func GetUint16(a []byte) (num uint16, err error) {
if len(a) < 2 {
return 0, io.ErrUnexpectedEOF
}
num = uint16(a[0])
num |= uint16(a[1]) << 8
return
}
// GetUint24 - читает из массива 3 байта и декодирует их в uint32.
func GetUint24(a []byte) (num uint32, err error) {
if len(a) < 3 {
return 0, io.ErrUnexpectedEOF
}
num = uint32(a[0])
num |= uint32(a[1]) << 8
num |= uint32(a[2]) << 16
return
}
// GetUint32 - читает из массива 4 байта и декодирует их в uint32.
func GetUint32(a []byte) (num uint32, err error) {
if len(a) < 4 {
return 0, io.ErrUnexpectedEOF
}
num = uint32(a[0])
num |= uint32(a[1]) << 8
num |= uint32(a[2]) << 16
num |= uint32(a[3]) << 24
return
}
// GetUint48 - читает из массива 6 байт и декодирует их в uint64.
func GetUint48(a []byte) (num uint64, err error) {
if len(a) < 6 {
return 0, io.ErrUnexpectedEOF
}
num = uint64(a[0])
num |= uint64(a[1]) << 8
num |= uint64(a[2]) << 16
num |= uint64(a[3]) << 24
num |= uint64(a[4]) << 32
num |= uint64(a[5]) << 40
return
}
// GetUint64 - читает из массива 8 байт и декодирует их в uint64.
func GetUint64(a []byte) (num uint64, err error) {
if len(a) < 8 {
return 0, io.ErrUnexpectedEOF
}
num = uint64(a[0])
num |= uint64(a[1]) << 8
num |= uint64(a[2]) << 16
num |= uint64(a[3]) << 24
num |= uint64(a[4]) << 32
num |= uint64(a[5]) << 40
num |= uint64(a[6]) << 48
num |= uint64(a[7]) << 56
return
}
// GetFloat32 - читает из массива 4 байта и декодирует их в float32.
func GetFloat32(a []byte) (float32, error) {
tmp, err := GetUint32(a)
if err != nil {
return 0, err
}
return math.Float32frombits(tmp), nil
}
// GetFloat64 - читает из массива 8 байт и декодирует их в float64.
func GetFloat64(a []byte) (float64, error) {
tmp, err := GetUint64(a)
if err != nil {
return 0, err
}
return math.Float64frombits(tmp), nil
}
func GetString8(a []byte) (string, error) {
pSize := 1
if len(a) < pSize {
return "", io.ErrUnexpectedEOF
}
length := int(a[0])
end := pSize + length
if len(a) < end {
return "", io.ErrUnexpectedEOF
}
return string(a[pSize:end]), nil
}
func GetString16(a []byte) (string, error) {
pSize := 2
if len(a) < pSize {
return "", io.ErrUnexpectedEOF
}
length, err := GetUint16(a)
if err != nil {
return "", err
}
end := pSize + int(length)
if len(a) < end {
return "", io.ErrUnexpectedEOF
}
return string(a[pSize:end]), nil
}
func GetBool(a []byte) (bool, error) {
if len(a) == 0 {
return false, io.ErrUnexpectedEOF
}
if a[0] == 1 {
return true, nil
} else {
return false, nil
}
}
func WriteBool(w io.Writer, flag bool) (err error) {
var b byte
if flag {
b = 1
}
_, err = w.Write([]byte{b})
return
}
func ReadBool(src io.Reader) (bool, error) {
b, err := ReadByte(src)
if err != nil {
return false, err
}
return b == 1, nil
}
// WRITE & READ VAR INT/UINT
// WriteVarUint32 - записывает в Writer от 1 до 5 байт, возвращает количество
// записанных байт. Порядок байт - от младшего к старшему. Значение последнего
// байта всегда >= 128, остальных < 128.
func WriteVarUint32(w io.Writer, num uint32) (i int) {
a := make([]byte, 5)
for ; i < 5; i++ {
a[i] = byte(num & 127)
num >>= 7
if num == 0 {
break
}
}
a[i] |= 128
i++
w.Write(a[:i])
return
}
// ReadVarUint32 - читает из io.Reader от 1 до 5 байт, и декодирует их в uint32.
func ReadVarUint32(src io.Reader) (num uint32, err error) {
var b byte
for i := range 5 {
b, err = ReadByte(src)
if err != nil {
return
}
if b >= 128 {
num |= uint32(b&127) << uint(i*7)
return
}
num |= uint32(b) << uint(i*7)
}
err = fmt.Errorf("value encoded as VarUint32 not found")
return
}
// WriteVarUint64 - записывает в Writer от 1 до 9 байт, возвращает количество
// записанных байт. Порядок байт - от младшего к старшему. В 9м байте все биты
// значащие.
func WriteVarUint64(w io.Writer, num uint64) (int, error) {
a := make([]byte, 9)
for i := range 8 {
a[i] = byte(num & 127)
num >>= 7
if num == 0 {
a[i] |= 128
i++
return w.Write(a[:i])
}
}
// в последнем 9м байте все биты значащие
a[8] = byte(num)
return w.Write(a)
}
// ReadVarUint64 - читает из io.Reader от 1 до 9 байт, и декодирует их в uint64.
func ReadVarUint64(src io.Reader) (num uint64, err error) {
var b byte
for i := range 8 {
b, err = ReadByte(src)
if err != nil {
return
}
if b >= 128 {
num |= uint64(b&127) << uint(i*7)
return
}
num |= uint64(b) << uint(i*7)
}
b, err = ReadByte(src)
if err != nil {
return
}
// в последнем 9м байте все биты значащие
num |= uint64(b) << 56
return
}
func WriteVarInt64(w io.Writer, num int64) (int, error) {
return WriteVarUint64(w, EncodeZigZag(num))
}
func ReadVarInt64(r io.Reader) (int64, error) {
u64, err := ReadVarUint64(r)
if err != nil {
return 0, err
}
return DecodeZigZag(u64), nil
}
// READ/WRITE VAR SIZE
func WriteVarSize(w io.Writer, n int) (int, error) {
if n < 0 {
return 0, ErrNegativeSize
}
var (
num = uint64(n)
a = make([]byte, 9)
)
for i := range 8 {
a[i] = byte(num & 127)
num >>= 7
if num == 0 {
a[i] |= 128
i++
return w.Write(a[:i])
}
}
// в последнем 9м байте все биты значащие
a[8] = byte(num)
return w.Write(a)
}
func ReadVarSize(src io.Reader) (_ int, err error) {
var (
b byte
num uint64
)
for i := range 8 {
b, err = ReadByte(src)
if err != nil {
return
}
if b >= 128 {
num |= uint64(b&127) << uint(i*7)
return int(num), nil
}
num |= uint64(b) << uint(i*7)
}
b, err = ReadByte(src)
if err != nil {
return
}
// в последнем 9м байте все биты значащие
num |= uint64(b) << 56
return int(num), nil
}
var varUint32Cutoffs = []uint32{
1 << 7,
1 << 14,
1 << 21,
1 << 28,
}
func CountVarUint32(n uint32) int {
for i, cutoff := range varUint32Cutoffs {
if n < cutoff {
return i + 1
}
}
return 5
}
var varUint64Cutoffs = []uint64{
1 << 7,
1 << 14,
1 << 21,
1 << 28,
1 << 35,
1 << 42,
1 << 49,
1 << 56,
}
func CountVarUint64(n uint64) int {
for i, cutoff := range varUint64Cutoffs {
if n < cutoff {
return i + 1
}
}
return 9
}
var varInt64PlusCutoffs = []int64{
1 << 6,
1 << 13,
1 << 20,
1 << 27,
1 << 34,
1 << 41,
1 << 48,
1 << 55,
}
var varInt64MinusCutoffs = []int64{
-1 << 6,
-1 << 13,
-1 << 20,
-1 << 27,
-1 << 34,
-1 << 41,
-1 << 48,
-1 << 55,
}
func CountVarInt64(n int64) int {
if n >= 0 {
for i, cutoff := range varInt64PlusCutoffs {
if n < cutoff {
return i + 1
}
}
} else {
for i, cutoff := range varInt64MinusCutoffs {
if n >= cutoff {
return i + 1
}
}
}
return 9
}
func CountVarSize(n int) int {
u64 := uint64(n)
for i, cutoff := range varUint64Cutoffs {
if u64 < cutoff {
return i + 1
}
}
return 9
}
// PUT/GET VAR SIZE
func PutVarUint64(a []byte, num uint64) (int, error) {
var tmp [9]byte
for i := range 8 {
if i < len(a) {
if num < 128 {
tmp[i] = byte(num) | 128
q := i + 1
copy(a, tmp[:q])
return q, nil
}
tmp[i] = byte(num & 127)
num >>= 7
} else {
return 0, ErrNoSpace
}
}
if len(a) < 9 {
return 0, ErrNoSpace
}
tmp[8] = byte(num)
copy(a, tmp[:])
return 9, nil
}
func GetVarUint64(a []byte) (uint64, int, error) {
var num uint64
for i := range 8 {
if i < len(a) {
b := a[i]
num |= uint64(b&127) << uint(i*7)
if b >= 128 {
return num, i + 1, nil
}
} else {
return 0, 0, ErrNoSpace
}
}
if len(a) < 9 {
return 0, 0, ErrNoSpace
}
num |= uint64(a[8]) << 56
return num, 9, nil
}
func PutVarSize(arr []byte, n int) (int, error) {
if n < 0 {
return 0, ErrNegativeSize
}
return PutVarUint64(arr, uint64(n))
}
func GetVarSize(arr []byte) (int, error) {
num, _, err := GetVarUint64(arr)
if err != nil {
return 0, err
}
return int(num), nil
}
func PutVarInt64(arr []byte, num int64) (int, error) {
return PutVarUint64(arr, EncodeZigZag(num))
}
func GetVarInt64(arr []byte) (int64, int, error) {
u64, n, err := GetVarUint64(arr)
if err != nil {
return 0, 0, err
}
return DecodeZigZag(u64), n, nil
}
// REVERSE
// func reverseCopy(dst []byte, src []byte) error {
// if len(dst) >= len(src) {
// i := len(dst) - 1
// for _, b := range src {
// dst[i] = b
// i--
// }
// return nil
// }
// return ErrNoSpace
// }
func copyReversed(dst []byte, src []byte) error {
if len(dst) >= len(src) {
j := 0
for i := len(src) - 1; i >= 0; i-- {
dst[j] = src[i]
j++
}
return nil
}
return ErrNoSpace
}
// ReversePutVarUint64 - записує закодоване значення як PutVarUint64, але із оберненим
// порядком байт. Прочитати значення можна функцією ReverseGetVarUint64, вказавши правильне
// початкове зміщення справа.
func ReversePutVarUint64(arr []byte, num uint64) (int, error) {
var tmp [9]byte
for i := range 8 {
tmp[i] = byte(num & 127)
num >>= 7
if num == 0 {
tmp[i] |= 128
n := i + 1
err := copyReversed(arr, tmp[:n])
if err != nil {
return 0, err
}
return n, nil
}
}
tmp[8] = byte(num)
err := copyReversed(arr, tmp[:])
if err != nil {
return 0, err
}
return 9, nil
}
// ReverseGetVarUint64 - читає значення, закодоване функцією ReversePutVarUint64.
// Останній байт arr - це молодший байт закодованного значення.
func ReverseGetVarUint64(arr []byte) (uint64, int, error) {
var (
num uint64
j = len(arr) - 1
)
for i := range 8 {
if j >= 0 {
b := arr[j]
num |= uint64(b&127) << uint(i*7)
if b >= 128 {
return num, i + 1, nil
}
j--
} else {
return 0, 0, io.EOF
}
}
if j >= 0 {
num |= uint64(arr[j]) << 56
return num, 9, nil
}
return 0, 0, io.EOF
}
// ReversePutVarInt64 - записує закодоване значення як PutVarInt64, але із оберненим
// порядком байт. Прочитати значення можна функцією ReverseGetVarInt64, вказавши правильне
// початкове зміщення справа.
func ReversePutVarInt64(arr []byte, num int64) (int, error) {
return ReversePutVarUint64(arr, EncodeZigZag(num))
}
// ReverseGetVarInt64 - читає значення, закодоване функцією ReversePutVarInt64.
// Останній байт arr - це молодший байт закодованного значення.
func ReverseGetVarInt64(arr []byte) (int64, int, error) {
u64, n, err := ReverseGetVarUint64(arr)
if err != nil {
return 0, 0, err
}
return DecodeZigZag(u64), n, nil
}
// TailPutVarUint64 - записує закодоване значення в кінці arr.
// Прочитати значення можна функцією GetVarUint64, вказавши правильне
// початкове зміщення зліва.
func TailPutVarUint64(arr []byte, num uint64) (int, error) {
var tmp [9]byte
for i := range 8 {
tmp[i] = byte(num & 127)
num >>= 7
if num == 0 {
tmp[i] |= 128
n := i + 1
if len(arr) < n {
return 0, ErrNoSpace
}
copy(arr[len(arr)-n:], tmp[:n])
return n, nil
}
}
tmp[8] = byte(num)
if len(arr) < 9 {
return 0, ErrNoSpace
}
copy(arr[len(arr)-9:], tmp[:])
return 9, nil
}
// TailPutVarInt64 - записує закодоване значення в кінці arr.
// Прочитати значення можна функцією GetVarInt64, вказавши правильне
// початкове зміщення зліва.
func TailPutVarInt64(arr []byte, num int64) (int, error) {
return TailPutVarUint64(arr, EncodeZigZag(num))
}
// ZigZag encoding: int64 -> uint64
func EncodeZigZag(x int64) uint64 {
return uint64(x<<1) ^ uint64(x>>63)
}
// ZigZag decoding: uint64 -> int64
func DecodeZigZag(u uint64) int64 {
return int64(u>>1) ^ -(int64(u & 1))
}