github.com/wrgl/wrgl@v0.14.0/pkg/objects/float_list.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright © 2022 Wrangle Ltd 3 4 package objects 5 6 import ( 7 "encoding/binary" 8 "io" 9 "math" 10 ) 11 12 // FloatListEncoder encodes string slice. Max bytes size for each string is 65536 bytes 13 type FloatListEncoder struct { 14 buf []byte 15 } 16 17 func NewFloatListEncoder() *FloatListEncoder { 18 return &FloatListEncoder{ 19 buf: make([]byte, 0, 256), 20 } 21 } 22 23 func (e *FloatListEncoder) Encode(sl []float64) []byte { 24 l := uint32(len(sl)) 25 bufLen := 8*int(l) + 4 26 if bufLen > cap(e.buf) { 27 e.buf = make([]byte, bufLen) 28 } else { 29 e.buf = e.buf[:bufLen] 30 } 31 binary.BigEndian.PutUint32(e.buf, l) 32 for i, f := range sl { 33 bits := math.Float64bits(f) 34 binary.BigEndian.PutUint64(e.buf[4+i*8:], bits) 35 } 36 return e.buf 37 } 38 39 // FloatListDecoder decodes string slice. 40 type FloatListDecoder struct { 41 sl []float64 42 buf []byte 43 pos int64 44 } 45 46 func NewFloatListDecoder(reuseRecords bool) *FloatListDecoder { 47 d := &FloatListDecoder{ 48 buf: make([]byte, 8), 49 } 50 if reuseRecords { 51 d.sl = make([]float64, 0, 256) 52 } 53 return d 54 } 55 56 func (d *FloatListDecoder) makeFloatSlice(n uint32) []float64 { 57 if d.sl == nil { 58 return make([]float64, 0, n) 59 } 60 if n > uint32(cap(d.sl)) { 61 d.sl = make([]float64, n) 62 } 63 return d.sl[:0] 64 } 65 66 func (d *FloatListDecoder) Decode(b []byte) []float64 { 67 n := binary.BigEndian.Uint32(b) 68 sl := d.makeFloatSlice(n) 69 var i uint32 70 for i = 0; i < n; i++ { 71 bits := binary.BigEndian.Uint64(b[4+8*i:]) 72 sl = append(sl, math.Float64frombits(bits)) 73 } 74 return sl 75 } 76 77 func (d *FloatListDecoder) readUint32(r io.Reader) (uint32, error) { 78 n, err := r.Read(d.buf[:4]) 79 if err != nil { 80 return 0, err 81 } 82 d.pos += int64(n) 83 return binary.BigEndian.Uint32(d.buf), nil 84 } 85 86 func (d *FloatListDecoder) readFloat64(r io.Reader) (float64, error) { 87 n, err := r.Read(d.buf) 88 if err != nil { 89 return 0, err 90 } 91 d.pos += int64(n) 92 bits := binary.BigEndian.Uint64(d.buf) 93 return math.Float64frombits(bits), nil 94 } 95 96 func (d *FloatListDecoder) Read(r io.Reader) (int64, []float64, error) { 97 d.pos = 0 98 n, err := d.readUint32(r) 99 if err != nil { 100 return d.pos, nil, err 101 } 102 sl := d.makeFloatSlice(n) 103 var i uint32 104 for i = 0; i < n; i++ { 105 f, err := d.readFloat64(r) 106 if err != nil { 107 return d.pos, nil, err 108 } 109 sl = append(sl, f) 110 } 111 return d.pos, sl, nil 112 }