package bin // ВАЖНО! // Игры с битами для int* лучше всего делать в аналогичном uint* типе, а затем в конце // приводить, например int32(uint32). // Битовое представление отрицательного числа - все 0 заменяются на единицы. import ( "bytes" "errors" "fmt" "io" "log" "math" "time" ) // ByteOrder - порядок байт type ByteOrder string const ( maxReadAttempts = 5 // LH - low to high byte order LH ByteOrder = "LH" // HL - high to low byte order HL ByteOrder = "HL" 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'") unknownByteOrder = "bin: unknown byteOrder %q" wrongArraySize = "bin: array size %d is not enough" offsets24HL = []uint{24, 16, 8} offsets24LH = []uint{0, 8, 16} offsets32HL = []uint{24, 16, 8, 0} offsets32LH = []uint{0, 8, 16, 24} offsets48HL = []uint{56, 48, 40, 32, 24, 16} offsets48LH = []uint{0, 8, 16, 24, 32, 40} offsets64HL = []uint{56, 48, 40, 32, 24, 16, 8, 0} offsets64LH = []uint{0, 8, 16, 24, 32, 40, 48, 56} ) func ReadByteAsInt(r io.ByteReader) (i int, err error) { b, err := r.ReadByte() if err != nil { return } return int(b), nil } func ReadUint32AsInt64(r io.ByteReader, byteOrder ByteOrder) (_ int64, err error) { u32, err := ReadUint32(r, byteOrder) if err != nil { return } return int64(u32), nil } // ReadN - безопасно читаем n байт. Обрабатывает все возможные ситуации, в том числе // баги Reader func ReadN(r io.Reader, n int) (_ []byte, err error) { if n == 0 { return } if n < 0 { err = fmt.Errorf("Wrong n=%d", n) } buf := make([]byte, n) var q, total, readAttempts int // Избегаем вечного цикла из-за неправильной реализации ридера for readAttempts < maxReadAttempts { bufsize := n - total q, err = r.Read(buf[total:]) // Если буфер заполнен - успех, возвращаем буфер, err игнорируем if q == bufsize { return buf, 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, err error) { buf, err := ReadN(r, n) if err != nil { return } return string(buf), nil } // GetInt16 - читает из массива arr 2 байта и декодирует их в int16. func GetInt16(arr []byte, byteOrder ByteOrder) (num int16, err error) { if len(arr) < 2 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: num = int16(arr[0]) | (int16(arr[1]) << 8) case HL: num = int16(arr[1]) | (int16(arr[0]) << 8) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // GetInt32 - читает из массива arr 4 байта и декодирует их в int32. func GetInt32(arr []byte, byteOrder ByteOrder) (num int32, err error) { if len(arr) < 4 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: num = int32(arr[0]) | (int32(arr[1]) << 8) | (int32(arr[2]) << 16) | (int32(arr[3]) << 24) case HL: num = int32(arr[3]) | (int32(arr[2]) << 8) | (int32(arr[1]) << 16) | (int32(arr[0]) << 24) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // GetInt64 - читает из массива arr 8 байт и декодирует их в int64. func GetInt64(arr []byte, byteOrder ByteOrder) (num int64, err error) { if len(arr) < 8 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: num = int64(arr[0]) | (int64(arr[1]) << 8) | (int64(arr[2]) << 16) | (int64(arr[3]) << 24) | (int64(arr[4]) << 32) | (int64(arr[5]) << 40) | (int64(arr[6]) << 48) | (int64(arr[7]) << 56) case HL: num = int64(arr[7]) | (int64(arr[6]) << 8) | (int64(arr[5]) << 16) | (int64(arr[4]) << 24) | (int64(arr[3]) << 32) | (int64(arr[2]) << 40) | (int64(arr[1]) << 48) | (int64(arr[0]) << 56) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // GetUint16 - читает из массива arr 2 байта и декодирует их в uint16. func GetUint16(arr []byte, byteOrder ByteOrder) (num uint16, err error) { if len(arr) < 2 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: num = uint16(arr[0]) | (uint16(arr[1]) << 8) case HL: num = uint16(arr[1]) | (uint16(arr[0]) << 8) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // GetUint32 - читает из массива arr 4 байта и декодирует их в uint32. func GetUint32(arr []byte, byteOrder ByteOrder) (num uint32, err error) { if len(arr) < 4 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: num = uint32(arr[0]) | (uint32(arr[1]) << 8) | (uint32(arr[2]) << 16) | (uint32(arr[3]) << 24) case HL: num = uint32(arr[3]) | (uint32(arr[2]) << 8) | (uint32(arr[1]) << 16) | (uint32(arr[0]) << 24) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // GetUint64 - читает из массива arr 8 байт и декодирует их в uint64. func GetUint64(arr []byte, byteOrder ByteOrder) (num uint64, err error) { if len(arr) < 8 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: num = uint64(arr[0]) | (uint64(arr[1]) << 8) | (uint64(arr[2]) << 16) | (uint64(arr[3]) << 24) | (uint64(arr[4]) << 32) | (uint64(arr[5]) << 40) | (uint64(arr[6]) << 48) | (uint64(arr[7]) << 56) case HL: num = uint64(arr[7]) | (uint64(arr[6]) << 8) | (uint64(arr[5]) << 16) | (uint64(arr[4]) << 24) | (uint64(arr[3]) << 32) | (uint64(arr[2]) << 40) | (uint64(arr[1]) << 48) | (uint64(arr[0]) << 56) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // GetFloat32 - записывает 4 байта в массив arr func GetFloat32(arr []byte, byteOrder ByteOrder) (_ float32, err error) { tmp, err := GetUint32(arr, byteOrder) if err != nil { return } return math.Float32frombits(tmp), nil } // GetFloat64 - записывает 4 байта в массив arr func GetFloat64(arr []byte, byteOrder ByteOrder) (_ float64, err error) { tmp, err := GetUint64(arr, byteOrder) if err != nil { return } return math.Float64frombits(tmp), nil } // PutInt16 - записывает 2 байта в массив arr func PutInt16(arr []byte, num int16, byteOrder ByteOrder) (err error) { if len(arr) < 2 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: arr[0] = byte(num) arr[1] = byte(num >> 8) case HL: arr[1] = byte(num) arr[0] = byte(num >> 8) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // PutInt32 - записывает 4 байта в массив arr func PutInt32(arr []byte, num int32, byteOrder ByteOrder) (err error) { if len(arr) < 4 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: arr[0] = byte(num) arr[1] = byte(num >> 8) arr[2] = byte(num >> 16) arr[3] = byte(num >> 24) case HL: arr[3] = byte(num) arr[2] = byte(num >> 8) arr[1] = byte(num >> 16) arr[0] = byte(num >> 24) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // PutInt64 - записывает 8 байт в массив arr func PutInt64(arr []byte, num int64, byteOrder ByteOrder) (err error) { if len(arr) < 8 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: arr[0] = byte(num) arr[1] = byte(num >> 8) arr[2] = byte(num >> 16) arr[3] = byte(num >> 24) arr[4] = byte(num >> 32) arr[5] = byte(num >> 40) arr[6] = byte(num >> 48) arr[7] = byte(num >> 56) case HL: arr[7] = byte(num) arr[6] = byte(num >> 8) arr[5] = byte(num >> 16) arr[4] = byte(num >> 24) arr[3] = byte(num >> 32) arr[2] = byte(num >> 40) arr[1] = byte(num >> 48) arr[0] = byte(num >> 56) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // PutUint16 - записывает 2 байта в массив arr func PutUint16(arr []byte, num uint16, byteOrder ByteOrder) (err error) { if len(arr) < 2 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: arr[0] = byte(num) arr[1] = byte(num >> 8) case HL: arr[1] = byte(num) arr[0] = byte(num >> 8) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // PutUint32 - записывает 4 байта в массив arr func PutUint32(arr []byte, num uint32, byteOrder ByteOrder) (err error) { if len(arr) < 4 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: arr[0] = byte(num) arr[1] = byte(num >> 8) arr[2] = byte(num >> 16) arr[3] = byte(num >> 24) case HL: arr[3] = byte(num) arr[2] = byte(num >> 8) arr[1] = byte(num >> 16) arr[0] = byte(num >> 24) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // PutUint64 - записывает 8 байт в массив arr func PutUint64(arr []byte, num uint64, byteOrder ByteOrder) (err error) { if len(arr) < 8 { err = fmt.Errorf(wrongArraySize, len(arr)) return } switch byteOrder { case LH: arr[0] = byte(num) arr[1] = byte(num >> 8) arr[2] = byte(num >> 16) arr[3] = byte(num >> 24) arr[4] = byte(num >> 32) arr[5] = byte(num >> 40) arr[6] = byte(num >> 48) arr[7] = byte(num >> 56) case HL: arr[7] = byte(num) arr[6] = byte(num >> 8) arr[5] = byte(num >> 16) arr[4] = byte(num >> 24) arr[3] = byte(num >> 32) arr[2] = byte(num >> 40) arr[1] = byte(num >> 48) arr[0] = byte(num >> 56) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // PutFloat32 - записывает 4 байта в массив arr func PutFloat32(arr []byte, num float32, byteOrder ByteOrder) (err error) { return PutUint32(arr, math.Float32bits(num), byteOrder) } // PutFloat64 - записывает 4 байта в массив arr func PutFloat64(arr []byte, num float64, byteOrder ByteOrder) (err error) { return PutUint64(arr, math.Float64bits(num), byteOrder) } /* PutVarUint64 - записывает в Writer от 1 до 9 байт, возвращает количество записанных байт. Порядок байт - от младшего к старшему. В 9м байте все биты значащие. */ func PutVarUint64(arr []byte, num uint64) (_ int, err error) { for i := 0; i < 8; i++ { arr[i] = byte(num & 127) num >>= 7 if num == 0 { arr[i] |= 128 return i + 1, nil } } // в последнем 9м байте все биты значащие arr[8] = byte(num) return 9, nil } // WriteInt16 - записывает в Writer 2 байта func WriteInt16(w io.Writer, num int16, byteOrder ByteOrder) (err error) { switch byteOrder { case LH: _, err = w.Write([]byte{ byte(num), byte(num >> 8), }) case HL: _, err = w.Write([]byte{ byte(num >> 8), byte(num), }) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // WriteInt24 - записывает в Writer 3 байта func WriteInt24(w io.Writer, num int32, byteOrder ByteOrder) (err error) { var sign byte if num < 0 { sign = 128 } switch byteOrder { case LH: _, err = w.Write([]byte{ byte(num), byte(num >> 8), byte((num>>16)&127) | sign, }) case HL: _, err = w.Write([]byte{ byte((num>>16)&127) | sign, byte(num >> 8), byte(num), }) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // WriteInt32 - записывает в Writer 4 байта func WriteInt32(w io.Writer, num int32, byteOrder ByteOrder) (err error) { switch byteOrder { case LH: _, err = w.Write([]byte{ byte(num), byte(num >> 8), byte(num >> 16), byte(num >> 24), }) case HL: _, err = w.Write([]byte{ byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num), }) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // WriteInt48 - записывает в Writer 6 байт func WriteInt48(w io.Writer, num int64, byteOrder ByteOrder) (err error) { var sign byte if num < 0 { sign = 128 } switch byteOrder { case LH: _, err = w.Write([]byte{ byte(num), byte(num >> 8), byte(num >> 16), byte(num >> 24), byte(num >> 32), byte((num>>40)&127) | sign, }) case HL: _, err = w.Write([]byte{ byte((num>>40)&127) | sign, byte(num >> 32), byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num), }) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // WriteInt64 - записывает в Writer 8 байт func WriteInt64(w io.Writer, num int64, byteOrder ByteOrder) (err error) { switch byteOrder { case LH: _, 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), }) case HL: _, err = w.Write([]byte{ byte(num >> 56), byte(num >> 48), byte(num >> 40), byte(num >> 32), byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num), }) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // WriteUint16 - записывает в Writer 2 байта func WriteUint16(w io.Writer, num uint16, byteOrder ByteOrder) (err error) { switch byteOrder { case LH: _, err = w.Write([]byte{ byte(num), byte(num >> 8), }) case HL: _, err = w.Write([]byte{ byte(num >> 8), byte(num), }) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // WriteUint32 - записывает в Writer 4 байта func WriteUint32(w io.Writer, num uint32, byteOrder ByteOrder) (err error) { switch byteOrder { case LH: _, err = w.Write([]byte{ byte(num), byte(num >> 8), byte(num >> 16), byte(num >> 24), }) case HL: _, err = w.Write([]byte{ byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num), }) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // WriteUint64 - записывает в Writer 8 байт func WriteUint64(w io.Writer, num uint64, byteOrder ByteOrder) (err error) { switch byteOrder { case LH: _, 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), }) case HL: _, err = w.Write([]byte{ byte(num >> 56), byte(num >> 48), byte(num >> 40), byte(num >> 32), byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num), }) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // WriteFloat32 - записывает в Writer 4 байта func WriteFloat32(w io.Writer, num float32, byteOrder ByteOrder) (err error) { return WriteUint32(w, math.Float32bits(num), byteOrder) } // WriteFloat64 - записывает в Writer 8 байт func WriteFloat64(w io.Writer, num float64, byteOrder ByteOrder) (err error) { return WriteUint64(w, math.Float64bits(num), byteOrder) } // ReadInt16 - читает из ByteReader arr 2 байта и декодирует их в int16. func ReadInt16(src io.ByteReader, byteOrder ByteOrder) (num int16, err error) { b1, err := src.ReadByte() if err != nil { return } b2, err := src.ReadByte() if err != nil { return } switch byteOrder { case LH: num = int16(b1) | (int16(b2) << 8) case HL: num = int16(b2) | (int16(b1) << 8) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // ReadInt24 - читает из ByteReader arr 3 байта и декодирует их в int32. // Нужно для протокола mbus. func ReadInt24(src io.ByteReader, byteOrder ByteOrder) (i int32, err error) { var ( num uint32 b, high byte ) if byteOrder == LH { for _, offset := range []uint{0, 8} { b, err = src.ReadByte() if err != nil { return } num |= uint32(b) << offset } high, err = src.ReadByte() if err != nil { return } } else { high, err = src.ReadByte() if err != nil { return } for _, offset := range []uint{8, 0} { b, err = src.ReadByte() if err != nil { return } num |= uint32(b) << offset } } num |= uint32(high&127) << 16 if high > 127 { // заглушка num |= 255 << 23 num |= Int32SignBit } return int32(num), nil } // ReadInt32 - читает из ByteReader arr 4 байта и декодирует их в int32. func ReadInt32(src io.ByteReader, byteOrder ByteOrder) (num int32, err error) { var ( b byte offsets []uint ) switch byteOrder { case LH: offsets = offsets32LH case HL: offsets = offsets32HL default: err = fmt.Errorf(unknownByteOrder, byteOrder) return } for _, off := range offsets { b, err = src.ReadByte() if err != nil { return } num |= int32(b) << off } return } // ReadInt48 - читает из ByteReader arr 6 байт и декодирует их в int64. // Нужно для протокола mbus. func ReadInt48(src io.ByteReader, byteOrder ByteOrder) (i int64, err error) { var ( num uint64 b, high byte ) if byteOrder == LH { for _, offset := range []uint{0, 8, 16, 24, 32} { b, err = src.ReadByte() if err != nil { return } num |= uint64(b) << offset } high, err = src.ReadByte() if err != nil { return } } else { high, err = src.ReadByte() if err != nil { return } for _, offset := range []uint{32, 24, 16, 8, 0} { b, err = src.ReadByte() if err != nil { return } num |= uint64(b) << offset } } num |= uint64(high&127) << 40 if high > 127 { // 2 заглушки num |= 255 << 47 num |= 255 << 55 num |= Int64SignBit } return int64(num), nil } // ReadInt64 - читает из ByteReader arr 8 байт и декодирует их в int64. func ReadInt64(src io.ByteReader, byteOrder ByteOrder) (num int64, err error) { var ( b byte offsets []uint ) switch byteOrder { case LH: offsets = offsets64LH case HL: offsets = offsets64HL default: err = fmt.Errorf(unknownByteOrder, byteOrder) return } for _, off := range offsets { b, err = src.ReadByte() if err != nil { return } num |= int64(b) << off } return } // ReadUint16 - читает из ByteReader arr 2 байта и декодирует их в uint16. func ReadUint16(src io.ByteReader, byteOrder ByteOrder) (num uint16, err error) { b1, err := src.ReadByte() if err != nil { return } b2, err := src.ReadByte() if err != nil { return } switch byteOrder { case LH: num = uint16(b1) | (uint16(b2) << 8) case HL: num = uint16(b2) | (uint16(b1) << 8) default: err = fmt.Errorf(unknownByteOrder, byteOrder) } return } // ReadUint32 - читает из ByteReader arr 4 байта и декодирует их в uint32. func ReadUint32(src io.ByteReader, byteOrder ByteOrder) (num uint32, err error) { var ( b byte offsets []uint ) switch byteOrder { case LH: offsets = offsets32LH case HL: offsets = offsets32HL default: err = fmt.Errorf(unknownByteOrder, byteOrder) return } for _, off := range offsets { b, err = src.ReadByte() if err != nil { return } num |= uint32(b) << off } return } // ReadUint64 - читает из ByteReader arr 8 байт и декодирует их в uint64. func ReadUint64(src io.ByteReader, byteOrder ByteOrder) (num uint64, err error) { var ( b byte offsets []uint ) switch byteOrder { case LH: offsets = offsets64LH case HL: offsets = offsets64HL default: err = fmt.Errorf(unknownByteOrder, byteOrder) return } for _, off := range offsets { b, err = src.ReadByte() if err != nil { return } num |= uint64(b) << off } return } // ReadFloat32 - читает из ByteReader arr 4 байта и декодирует их в float32. func ReadFloat32(src io.ByteReader, byteOrder ByteOrder) (_ float32, err error) { tmp, err := ReadUint32(src, byteOrder) if err != nil { return } return math.Float32frombits(tmp), nil } // ReadFloat64 - читает из ByteReader arr 8 байт и декодирует их в float64. func ReadFloat64(src io.ByteReader, byteOrder ByteOrder) (_ float64, err error) { tmp, err := ReadUint64(src, byteOrder) if err != nil { return } return math.Float64frombits(tmp), nil } /////////////////////////////////// VAR /* WriteVarUint32 - записывает в Writer от 1 до 5 байт, возвращает количество записанных байт. Порядок байт - от младшего к старшему. Значение последнего байта всегда >= 128, остальных < 128. */ func WriteVarUint32(w io.Writer, num uint32) (i int) { arr := make([]byte, 5) for ; i < 5; i++ { arr[i] = byte(num & 127) num >>= 7 if num == 0 { break } } arr[i] |= 128 i++ w.Write(arr[:i]) return } /* ReadVarUint32 - читает из ByteReader от 1 до 5 байт, и декодирует их в uint32. */ func ReadVarUint32(src io.ByteReader) (num uint32, err error) { var b byte for i := 0; i < 5; i++ { b, err = src.ReadByte() if err != nil { return } if b >= 128 { num |= uint32(b&127) << uint(i*7) return } num |= uint32(b) << uint(i*7) } err = fmt.Errorf("VarUint32 encoded value not found\n") return } /* WriteVarUint64 - записывает в Writer от 1 до 9 байт, возвращает количество записанных байт. Порядок байт - от младшего к старшему. В 9м байте все биты значащие. */ func WriteVarUint64(w io.Writer, num uint64) (_ int, err error) { arr := make([]byte, 9) for i := 0; i < 8; i++ { arr[i] = byte(num & 127) num >>= 7 if num == 0 { arr[i] |= 128 i++ return w.Write(arr[:i]) } } // в последнем 9м байте все биты значащие arr[8] = byte(num) return w.Write(arr) } /* ReadVarUint64 - читает из ByteReader от 1 до 9 байт, и декодирует их в uint64. */ func ReadVarUint64(src io.ByteReader) (num uint64, err error) { var b byte for i := 0; i < 8; i++ { b, err = src.ReadByte() if err != nil { return } if b >= 128 { num |= uint64(b&127) << uint(i*7) return } num |= uint64(b) << uint(i*7) } b, err = src.ReadByte() if err != nil { return } // в последнем 9м байте все биты значащие num |= uint64(b) << 56 return } func WriteVarSize(w io.Writer, n int) (_ int, err error) { num := uint64(n) arr := make([]byte, 9) for i := 0; i < 8; i++ { arr[i] = byte(num & 127) num >>= 7 if num == 0 { arr[i] |= 128 i++ return w.Write(arr[:i]) } } // в последнем 9м байте все биты значащие arr[8] = byte(num) return w.Write(arr) } func ReadVarSize(src io.ByteReader) (_ int, err error) { var ( b byte num uint64 ) for i := 0; i < 8; i++ { b, err = src.ReadByte() if err != nil { return } if b >= 128 { num |= uint64(b&127) << uint(i*7) return } num |= uint64(b) << uint(i*7) } b, err = src.ReadByte() if err != nil { return } // в последнем 9м байте все биты значащие num |= uint64(b) << 56 return int(num), nil } ///////////////// НУЖНЫ ЛИ ? /* WriteMaxUint64 - кодирует число минимально возможным количеством байт (от 1 до 8). Возвращает количество записанных байт. Порядок байт - от младшего к старшему. */ func WriteMaxUint64(w io.Writer, num uint64) (i int) { arr := make([]byte, 8) for ; i < 8; i++ { arr[i] = byte(num) num >>= 8 if num == 0 { break } } i++ w.Write(arr[:i]) return } /* ReadMaxUint64 - читает из ByteReader число, закодированное методом MaxUint64. */ func ReadMaxUint64(src io.ByteReader, n int) (num uint64, err error) { if n < 1 || n > 8 { log.Fatalf("n=%d, allowed values 1-8\n", n) } var b byte for i := 0; i < n; i++ { b, err = src.ReadByte() if err != nil { return } num |= uint64(b) << uint(i*8) } return } /* func PutVar2b(w io.Writer, num int) int { if num < 128 { w.Write([]byte{byte(num)}) return 1 } w.Write([]byte{ byte(num&127) | 128, byte(num >> 7), }) return 2 } func getVar2b(w io.Writer, num int) int { if num < 128 { w.Write([]byte{byte(num)}) return 1 } w.Write([]byte{ byte(num&127) | 128, byte(num >> 7), }) return 2 } func PutVarInt32(w io.Writer, num int32) (int, error) { //if num > 2147483647 { // return 0, fmt.Errorf("num %d overflows int32", num) //} arr := make([]byte, 5) for i := 0; i < 4; i++ { arr[i] = byte(num & 127) num >>= 7 if num == 0 { arr[i] |= 128 return w.Write(arr[:i+1]) } } // в последнем 9м байте все биты значащие arr[5] = byte(num) return w.Write(arr) } func VarInt32(src io.ByteReader) (num int, err error) { var ( b byte off uint ) for ; off < 28; off += 7 { b, err = src.ReadByte() if err != nil { return } if b < 128 { num |= int(b) << off } else { num |= int(b&127) << off return } } b, err = src.ReadByte() if err != nil { return } // в последнем 9м байте все биты значащие num |= int(b&7) << 28 return } */ /* func PackVarUint32(num int) (err error) { idx := 0 for num > 127 { s.vint[idx] = byte(num & 127) num >>= 7 idx++ } // Даже в последнем байте отсекаем старший бит (знак) s.vint[idx] = byte(num&127) | 128 _, err = s.dst.Write(s.vint[:idx+1]) return } */ var zeroUnixTime = []byte{0, 0, 0, 0, 0, 0} func Read6bDateTime(r io.ByteReader) (_ time.Time, err error) { var arr []byte for i := 0; i < 6; i++ { var b byte b, err = r.ReadByte() if err != nil { return } arr = append(arr, b) } if bytes.Equal(arr, zeroUnixTime) { return time.Unix(0, 0), nil } tm := time.Date( int(arr[0])+2000, time.Month(arr[1]), int(arr[2]), int(arr[3]), int(arr[4]), int(arr[5]), 0, time.UTC, ) return tm, nil } func Write6bDateTime(w io.Writer, tm time.Time) (err error) { var arr []byte // ВАЖНО! tm = tm.In(time.UTC) if tm.Unix() == 0 { arr = zeroUnixTime } else { arr = []byte{ byte(tm.Year() - 2000), byte(tm.Month()), byte(tm.Day()), byte(tm.Hour()), byte(tm.Minute()), byte(tm.Second()), } } //fmt.Printf("TIME: %v / %v\n", tm.Unix(), arr) _, err = w.Write(arr) return } const ( MaxUint8 uint64 = 1<<8 - 1 MaxUint16 uint64 = 1<<16 - 1 MaxUint24 uint64 = 1<<24 - 1 MaxUint32 uint64 = 1<<32 - 1 MaxUint40 uint64 = 1<<40 - 1 MaxUint48 uint64 = 1<<48 - 1 MaxUint56 uint64 = 1<<56 - 1 MaxUint64 uint64 = 18446744073709551615 // MaxSafeInt - максимальное целое, которое можно сохранить в переменной // типа float64 без потери точности MinSafeInt int64 = -(1 << 53) MaxSafeInt int64 = 1<<53 - 1 ) // WriteMaxSafeUint - кодирует 2**53-1 // LH func WriteMaxSafeUint(w io.Writer, num uint64, byteOrder ByteOrder) (n int, err error) { var arr []byte if num <= MaxUint8 { arr = []byte{ byte(num), } } else if num <= MaxUint16 { if byteOrder == LH { arr = []byte{ byte(num), byte(num >> 8), } } else { arr = []byte{ byte(num >> 8), byte(num), } } } else if num <= MaxUint24 { if byteOrder == LH { arr = []byte{ byte(num), byte(num >> 8), byte(num >> 16), } } else { arr = []byte{ byte(num >> 16), byte(num >> 8), byte(num), } } } else if num <= MaxUint32 { if byteOrder == LH { arr = []byte{ byte(num), byte(num >> 8), byte(num >> 16), byte(num >> 24), } } else { arr = []byte{ byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num), } } } else if num <= MaxUint40 { if byteOrder == LH { arr = []byte{ byte(num), byte(num >> 8), byte(num >> 16), byte(num >> 24), byte(num >> 32), } } else { arr = []byte{ byte(num >> 32), byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num), } } } else if num <= MaxUint48 { if byteOrder == LH { arr = []byte{ byte(num), byte(num >> 8), byte(num >> 16), byte(num >> 24), byte(num >> 32), byte(num >> 40), } } else { arr = []byte{ byte(num >> 40), byte(num >> 32), byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num), } } } else if num <= uint64(MaxSafeInt) { if byteOrder == LH { arr = []byte{ byte(num), byte(num >> 8), byte(num >> 16), byte(num >> 24), byte(num >> 32), byte(num >> 40), byte(num >> 48), } } else { arr = []byte{ byte(num >> 48), byte(num >> 40), byte(num >> 32), byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num), } } } else { err = fmt.Errorf("num %d > MaxSafeInt %d", num, MaxSafeInt) return } return w.Write(arr) } type SplittedFloat struct { Int int64 // bin.MaxSafeInt Frac int64 // до 7 разрядов } func (s SplittedFloat) AsFloat64(fracDigits int) float64 { //return float64(s.Int) + float64(s.Frac)/ fracMultipliers[fracDigits] return float64(s.Int) + float64(s.Frac)/math.Pow10(fracDigits) } /* var fracMultipliers = []float64{ 0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, } */ var prec = []float64{ 0.999999999, // 0 0.99999999, // 1 0.9999999, // 2 0.999999, // 3 0.99999, // 4 0.9999, // 5 0.999, // 6 0.99, // 7 //0.99, // 8 } func SplitFloat(num float64, fracDigits int) SplittedFloat { var isNegative bool if num < 0 { isNegative = true } num = math.Abs(num) //if fracDigits >= len(fracMultipliers) { // panic(fmt.Sprintf("max fracDigits is %d, not %d\n", // len(fracMultipliers), fracDigits)) //} i, f := math.Modf(num) poweredFrac := f * math.Pow10(fracDigits) // В этот момент может произойти потеря точности, когда 0.55 превратится // в 0.5499999999 (в меньшую сторону) fracAsInt := int64(poweredFrac) // dif := poweredFrac - float64(fracAsInt) //fmt.Printf("DIF %.10f\n\n", dif) var eps float64 if fracDigits >= len(prec) { eps = 0.99 } else { eps = prec[fracDigits] } if dif > eps { fracAsInt++ } //fmt.Printf("\nSPLIT: %.10f, int = %d, frac = %v, %v, %d\n\n", num, int(i), f, f*fracMultipliers[fracDigits], int(f*fracMultipliers[fracDigits])) if isNegative { i *= -1 } return SplittedFloat{ Int: int64(i), Frac: fracAsInt, } } /* if byteOrder == LH { } else { } */ /* // Round a float to a specific decimal place or precision func Round(input float64, places int) (rounded float64, err error) { // If the float is not a number if math.IsNaN(input) { return math.NaN(), fmt.Errorf("fuck") } // Find out the actual sign and correct the input for later sign := 1.0 if input < 0 { sign = -1 input *= -1 } // Use the places arg to get the amount of precision wanted precision := math.Pow(10, float64(places)) // Find the decimal place we are looking to round digit := input * precision // Get the actual decimal number as a fraction to be compared _, decimal := math.Modf(digit) // If the decimal is less than .5 we round down otherwise up if decimal >= 0.5 { rounded = math.Ceil(digit) } else { rounded = math.Floor(digit) } // Finally we do the math to actually create a rounded number return rounded / precision * sign, nil } */ func UnsetBit(b byte, idx byte) byte { if ((b >> idx) & 1) == 1 { // сбрасываем var mask byte = ^(1 << idx) return b & mask } return b } func SetBit(b byte, idx byte) byte { if ((b >> idx) & 1) == 0 { // устанавливаем return b | (1 << idx) } return b } func Float64AsUint64(f float64) uint64 { arr := make([]byte, 8) PutFloat64(arr, f, LH) u, _ := GetUint64(arr, LH) return u } func Uint64AsFloat64(u uint64) float64 { arr := make([]byte, 8) PutUint64(arr, u, LH) f, _ := GetFloat64(arr, LH) return f } func Int64AsUint64(i int64) uint64 { arr := make([]byte, 8) PutInt64(arr, i, LH) u, _ := GetUint64(arr, LH) return u } func Uint64AsInt64(u uint64) int64 { arr := make([]byte, 8) PutUint64(arr, u, LH) i, _ := GetInt64(arr, LH) return i }