|
- package iohelper
-
- import (
- "bytes"
- "encoding/binary"
- "io"
-
- "github.com/juju/errors"
- )
-
- var (
- cachedItob [][]byte
- )
-
- func init() {
- cachedItob = make([][]byte, 1024)
- for i := 0; i < len(cachedItob); i++ {
- var b bytes.Buffer
- writeVLong(&b, int64(i))
- cachedItob[i] = b.Bytes()
- }
- }
-
- func itob(i int) ([]byte, error) {
- if i >= 0 && i < len(cachedItob) {
- return cachedItob[i], nil
- }
-
- var b bytes.Buffer
- err := binary.Write(&b, binary.BigEndian, i)
- if err != nil {
- return nil, errors.Trace(err)
- }
- return b.Bytes(), nil
- }
-
- func decodeVIntSize(value byte) int32 {
- if int32(value) >= -112 {
- return int32(1)
- }
-
- if int32(value) < -120 {
- return -119 - int32(value)
- }
-
- return -111 - int32(value)
- }
-
- func isNegativeVInt(value byte) bool {
- return int32(value) < -120 || int32(value) >= -112 && int32(value) < 0
- }
-
- func readVLong(r io.Reader) (int64, error) {
- var firstByte byte
- err := binary.Read(r, binary.BigEndian, &firstByte)
- if err != nil {
- return 0, errors.Trace(err)
- }
-
- l := decodeVIntSize(firstByte)
- if l == 1 {
- return int64(firstByte), nil
- }
-
- var (
- i int64
- idx int32
- )
-
- for idx = 0; idx < l-1; idx++ {
- var b byte
- err = binary.Read(r, binary.BigEndian, &b)
- if err != nil {
- return 0, errors.Trace(err)
- }
-
- i <<= 8
- i |= int64(b & 255)
- }
-
- if isNegativeVInt(firstByte) {
- return ^i, nil
- }
-
- return i, nil
- }
-
- func writeVLong(w io.Writer, i int64) error {
- var err error
- if i >= -112 && i <= 127 {
- err = binary.Write(w, binary.BigEndian, byte(i))
- if err != nil {
- return errors.Trace(err)
- }
- } else {
- var l int32 = -112
- if i < 0 {
- i = ^i
- l = -120
- }
- var tmp int64
- for tmp = i; tmp != 0; l-- {
- tmp >>= 8
- }
-
- err = binary.Write(w, binary.BigEndian, byte(l))
- if err != nil {
- return errors.Trace(err)
- }
-
- if l < -120 {
- l = -(l + 120)
- } else {
- l = -(l + 112)
- }
-
- for idx := l; idx != 0; idx-- {
- var mask int64
- shiftbits := uint((idx - 1) * 8)
- mask = int64(255) << shiftbits
- err = binary.Write(w, binary.BigEndian, byte((i&mask)>>shiftbits))
- if err != nil {
- return errors.Trace(err)
- }
- }
- }
-
- return nil
- }
-
- func ReadVarBytes(r ByteMultiReader) ([]byte, error) {
- sz, err := readVLong(r)
- if err != nil {
- return nil, errors.Trace(err)
- }
-
- b := make([]byte, sz)
- _, err = r.Read(b)
- if err != nil {
- return nil, errors.Trace(err)
- }
-
- return b, nil
- }
-
- func WriteVarBytes(w io.Writer, b []byte) error {
- lenb, err := itob(len(b))
- if err != nil {
- return errors.Trace(err)
- }
-
- _, err = w.Write(lenb)
- if err != nil {
- return errors.Trace(err)
- }
-
- _, err = w.Write(b)
- return errors.Trace(err)
- }
-
- func ReadInt32(r io.Reader) (int32, error) {
- var n int32
- err := binary.Read(r, binary.BigEndian, &n)
- return n, errors.Trace(err)
- }
-
- func ReadN(r io.Reader, n int32) ([]byte, error) {
- b := make([]byte, n)
- _, err := io.ReadFull(r, b)
- return b, errors.Trace(err)
- }
-
- func ReadUint64(r io.Reader) (uint64, error) {
- var n uint64
- err := binary.Read(r, binary.BigEndian, &n)
- return n, errors.Trace(err)
- }
|