2025-08-16 19:31:11 +00:00
|
|
|
|
package little
|
|
|
|
|
|
|
|
|
|
|
|
// LOW TO HIGHT
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"errors"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"io"
|
|
|
|
|
|
"math"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
|
maxReadAttempts = 5
|
|
|
|
|
|
|
2025-08-16 21:11:17 +00:00
|
|
|
|
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
|
|
|
|
|
|
|
2025-08-16 19:31:11 +00:00
|
|
|
|
//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") // слишком длинная строка или массив байт
|
2025-08-16 21:11:17 +00:00
|
|
|
|
ErrRange = errors.New("bin: out of range")
|
2025-08-16 19:31:11 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
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 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) {
|
2025-08-16 21:11:17 +00:00
|
|
|
|
if num < MinInt24 || num > MaxInt24 {
|
|
|
|
|
|
return ErrRange
|
|
|
|
|
|
}
|
2025-08-16 19:31:11 +00:00
|
|
|
|
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) {
|
2025-08-16 21:11:17 +00:00
|
|
|
|
if num < MinInt48 || num > MaxInt48 {
|
|
|
|
|
|
return ErrRange
|
|
|
|
|
|
}
|
2025-08-16 19:31:11 +00:00
|
|
|
|
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) {
|
2025-08-16 21:11:17 +00:00
|
|
|
|
if num > MaxUint24 {
|
|
|
|
|
|
return ErrRange
|
|
|
|
|
|
}
|
2025-08-16 19:31:11 +00:00
|
|
|
|
_, 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) {
|
2025-08-16 21:11:17 +00:00
|
|
|
|
if num > MaxUint48 {
|
|
|
|
|
|
return ErrRange
|
|
|
|
|
|
}
|
2025-08-16 19:31:11 +00:00
|
|
|
|
_, 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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-16 21:11:17 +00:00
|
|
|
|
// для записи timestamp-ов
|
2025-08-16 21:13:23 +00:00
|
|
|
|
func WriteInt64AsUint32(w io.Writer, num int64) error {
|
2025-08-16 21:11:17 +00:00
|
|
|
|
if num < 0 || num > 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 || num > math.MaxUint32 {
|
|
|
|
|
|
return ErrRange
|
|
|
|
|
|
}
|
|
|
|
|
|
return WriteUint32(w, uint32(num))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-16 19:31:11 +00:00
|
|
|
|
// 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 {
|
2025-08-16 21:11:17 +00:00
|
|
|
|
if num < MinInt24 || num > MaxInt24 {
|
|
|
|
|
|
return ErrRange
|
|
|
|
|
|
}
|
2025-08-16 19:31:11 +00:00
|
|
|
|
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 {
|
2025-08-16 21:11:17 +00:00
|
|
|
|
if num < MinInt48 || num > MaxInt48 {
|
|
|
|
|
|
return ErrRange
|
|
|
|
|
|
}
|
2025-08-16 19:31:11 +00:00
|
|
|
|
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 {
|
2025-08-16 21:11:17 +00:00
|
|
|
|
if num > MaxUint24 {
|
|
|
|
|
|
return ErrRange
|
|
|
|
|
|
}
|
2025-08-16 19:31:11 +00:00
|
|
|
|
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 {
|
2025-08-16 21:11:17 +00:00
|
|
|
|
if num > MaxUint48 {
|
|
|
|
|
|
return ErrRange
|
|
|
|
|
|
}
|
2025-08-16 19:31:11 +00:00
|
|
|
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// VAR
|
|
|
|
|
|
|
|
|
|
|
|
// 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 := 0; i < 5; i++ {
|
|
|
|
|
|
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 := 0; i < 8; i++ {
|
|
|
|
|
|
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 := 0; i < 8; i++ {
|
|
|
|
|
|
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 WriteVarSize(w io.Writer, n int) (int, error) {
|
|
|
|
|
|
num := uint64(n)
|
|
|
|
|
|
a := make([]byte, 9)
|
|
|
|
|
|
for i := 0; i < 8; i++ {
|
|
|
|
|
|
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 := 0; i < 8; i++ {
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|