Files
dolt/go/perf/encode-perf-rig/binary-varint-encoder.go

93 lines
2.1 KiB
Go

// Copyright 2016 Attic Labs, Inc. All rights reserved.
// Licensed under the Apache License, version 2.0:
// http://www.apache.org/licenses/LICENSE-2.0
package main
import (
"encoding/binary"
"io"
"math/big"
)
type BinaryVarintEncoderDecoder struct {
tmp *big.Float
}
func NewBinaryVarintEncoderDecoder() BinaryVarintEncoderDecoder {
bed := BinaryVarintEncoderDecoder{}
bed.tmp = new(big.Float)
bed.tmp.SetPrec(ENCODER_DECODER_PREC)
return bed
}
func (bed BinaryVarintEncoderDecoder) Encode(w io.Writer, n *big.Float) error {
if n.IsInt() {
x, _ := n.Int64()
// TODO - if accuracy is not Exact, then use the other path
buf := make([]byte, binary.MaxVarintLen64)
nBytes := binary.PutVarint(buf, x)
if _, err := w.Write([]byte{byte(0)}); err != nil {
return err
}
_, err := w.Write(buf[0:nBytes])
return err
} else {
if err := binary.Write(w, binary.BigEndian, int8(1)); err != nil {
return err
}
exponent := n.MantExp(bed.tmp)
f, _ := bed.tmp.Float64()
if err := binary.Write(w, binary.BigEndian, f); err != nil {
return err
}
return binary.Write(w, binary.BigEndian, int32(exponent))
}
}
func (bed BinaryVarintEncoderDecoder) Decode(r io.Reader, n *big.Float) error {
var isInteger int8
var f float64
var exponent int32
n.SetUint64(0)
if err := binary.Read(r, binary.BigEndian, &isInteger); err != nil {
return err
}
if isInteger <= 0 {
var x int64
var err error
if x, err = binary.ReadVarint(miniByteReader{r}); err != nil {
return err
}
n.SetInt64(x)
n.SetPrec(ENCODER_DECODER_PREC)
return nil
} else {
if err := binary.Read(r, binary.BigEndian, &f); err != nil {
return err
}
if err := binary.Read(r, binary.BigEndian, &exponent); err != nil {
return err
}
bed.tmp.SetFloat64(f)
bed.tmp.SetPrec(ENCODER_DECODER_PREC)
n.SetMantExp(bed.tmp, int(exponent))
return nil
}
}
type miniByteReader struct {
r io.Reader
}
func (r miniByteReader) ReadByte() (byte, error) {
p := []byte{byte(0)}
// io.Reader.Read(p []byte) (n int, err error)
// io.ByteReader.ReadByte() (c byte, err error)
_, err := r.r.Read(p)
return p[0], err
}