Skip to content

Commit 65cefed

Browse files
committed
add protocol support for float64s
1 parent 05dd93c commit 65cefed

File tree

5 files changed

+110
-4
lines changed

5 files changed

+110
-4
lines changed

protocol/alterclientquotas/alterclientquotas.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type Request struct {
1212
_ struct{} `kafka:"min=v2,max=v2,tag"`
1313

1414
Entries []Entry `kafka:"min=v0,max=v1"`
15-
ValidateOnly boolean `kafka:"min=v0,max=v1"`
15+
ValidateOnly bool `kafka:"min=v0,max=v1"`
1616
}
1717

1818
func (r *Request) ApiKey() protocol.ApiKey { return protocol.AlterClientQuotas }
@@ -26,15 +26,22 @@ type Entry struct {
2626
Ops []Ops `kafka:"min=v0,max=v1"`
2727
}
2828

29+
type EntityType string
30+
31+
const (
32+
ClientID EntityType = "client-id"
33+
User EntityType = "user"
34+
)
35+
2936
type Entity struct {
30-
EntityType string `kafka:"min=v0,max=v1"`
31-
EntityName string `kafka:"min=v0,max=v1,nullable"`
37+
EntityType EntityType `kafka:"min=v0,max=v1"`
38+
EntityName string `kafka:"min=v0,max=v1,nullable"`
3239
}
3340

3441
type Ops struct {
3542
Key string `kafka:"min=v0,max=v1"`
3643
Value float64 `kafka:"min=v0,max=v1"`
37-
Remove boolean `kafka:"min=v0,max=v1"`
44+
Remove bool `kafka:"min=v0,max=v1"`
3845
}
3946

4047
type Response struct {

protocol/decode.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"hash/crc32"
88
"io"
99
"io/ioutil"
10+
"math"
1011
"reflect"
1112
"sync"
1213
"sync/atomic"
@@ -85,6 +86,10 @@ func (d *decoder) decodeInt64(v value) {
8586
v.setInt64(d.readInt64())
8687
}
8788

89+
func (d *decoder) decodeFloat64(v value) {
90+
v.setFloat64(d.readFloat64())
91+
}
92+
8893
func (d *decoder) decodeString(v value) {
8994
v.setString(d.readString())
9095
}
@@ -216,6 +221,13 @@ func (d *decoder) readInt64() int64 {
216221
return 0
217222
}
218223

224+
func (d *decoder) readFloat64() float64 {
225+
if d.readFull(d.buffer[:8]) {
226+
return readFloat64(d.buffer[:8])
227+
}
228+
return 0
229+
}
230+
219231
func (d *decoder) readString() string {
220232
if n := d.readInt16(); n < 0 {
221233
return ""
@@ -342,6 +354,8 @@ func decodeFuncOf(typ reflect.Type, version int16, flexible bool, tag structTag)
342354
return (*decoder).decodeInt32
343355
case reflect.Int64:
344356
return (*decoder).decodeInt64
357+
case reflect.Float64:
358+
return (*decoder).decodeFloat64
345359
case reflect.String:
346360
return stringDecodeFuncOf(flexible, tag)
347361
case reflect.Struct:
@@ -469,6 +483,10 @@ func readInt64(b []byte) int64 {
469483
return int64(binary.BigEndian.Uint64(b))
470484
}
471485

486+
func readFloat64(b []byte) float64 {
487+
return math.Float64frombits(binary.BigEndian.Uint64(b))
488+
}
489+
472490
func Unmarshal(data []byte, version int16, value interface{}) error {
473491
typ := elemTypeOf(value)
474492
cache, _ := unmarshalers.Load().(map[versionedType]decodeFunc)

protocol/encode.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"hash/crc32"
88
"io"
9+
"math"
910
"reflect"
1011
"sync"
1112
"sync/atomic"
@@ -129,6 +130,10 @@ func (e *encoder) encodeInt64(v value) {
129130
e.writeInt64(v.int64())
130131
}
131132

133+
func (e *encoder) encodeFloat64(v value) {
134+
e.writeFloat64(v.float64())
135+
}
136+
132137
func (e *encoder) encodeString(v value) {
133138
e.writeString(v.string())
134139
}
@@ -230,6 +235,11 @@ func (e *encoder) writeInt64(i int64) {
230235
e.Write(e.buffer[:8])
231236
}
232237

238+
func (e *encoder) writeFloat64(f float64) {
239+
writeFloat64(e.buffer[:8], f)
240+
e.Write(e.buffer[:8])
241+
}
242+
233243
func (e *encoder) writeString(s string) {
234244
e.writeInt16(int16(len(s)))
235245
e.WriteString(s)
@@ -378,6 +388,8 @@ func encodeFuncOf(typ reflect.Type, version int16, flexible bool, tag structTag)
378388
return (*encoder).encodeInt32
379389
case reflect.Int64:
380390
return (*encoder).encodeInt64
391+
case reflect.Float64:
392+
return (*encoder).encodeFloat64
381393
case reflect.String:
382394
return stringEncodeFuncOf(flexible, tag)
383395
case reflect.Struct:
@@ -530,6 +542,10 @@ func writeInt64(b []byte, i int64) {
530542
binary.BigEndian.PutUint64(b, uint64(i))
531543
}
532544

545+
func writeFloat64(b []byte, f float64) {
546+
binary.BigEndian.PutUint64(b, math.Float64bits(f))
547+
}
548+
533549
func Marshal(version int16, value interface{}) ([]byte, error) {
534550
typ := typeOf(value)
535551
cache, _ := marshalers.Load().(map[versionedType]encodeFunc)

protocol/protocol_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package protocol
22

33
import (
44
"bytes"
5+
"math"
56
"reflect"
67
"testing"
78
)
@@ -279,3 +280,63 @@ func TestVarInts(t *testing.T) {
279280

280281
}
281282
}
283+
284+
func TestFloat64(t *testing.T) {
285+
type tc struct {
286+
input float64
287+
expected []byte
288+
}
289+
290+
tcs := []tc{
291+
{
292+
input: 0.0,
293+
expected: []byte{0, 0, 0, 0, 0, 0, 0, 0},
294+
},
295+
{
296+
input: math.MaxFloat64,
297+
expected: []byte{127, 239, 255, 255, 255, 255, 255, 255},
298+
},
299+
{
300+
input: -math.MaxFloat64,
301+
expected: []byte{255, 239, 255, 255, 255, 255, 255, 255},
302+
},
303+
{
304+
input: math.SmallestNonzeroFloat64,
305+
expected: []byte{0, 0, 0, 0, 0, 0, 0, 1},
306+
},
307+
{
308+
input: -math.SmallestNonzeroFloat64,
309+
expected: []byte{128, 0, 0, 0, 0, 0, 0, 1},
310+
},
311+
}
312+
313+
for _, tc := range tcs {
314+
b := &bytes.Buffer{}
315+
e := &encoder{writer: b}
316+
e.writeFloat64(tc.input)
317+
if e.err != nil {
318+
t.Errorf(
319+
"Unexpected error encoding %f as float64: %+v",
320+
tc.input,
321+
e.err,
322+
)
323+
}
324+
if !reflect.DeepEqual(b.Bytes(), tc.expected) {
325+
t.Error(
326+
"Wrong output encoding value", tc.input, "as float64",
327+
"expected", tc.expected,
328+
"got", b.Bytes(),
329+
)
330+
}
331+
332+
d := &decoder{reader: b, remain: len(b.Bytes())}
333+
v := d.readFloat64()
334+
if v != tc.input {
335+
t.Error(
336+
"Decoded float64 value does not equal encoded one",
337+
"expected", tc.input,
338+
"got", v,
339+
)
340+
}
341+
}
342+
}

protocol/reflect.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ func (v value) int32() int32 { return int32(v.int64()) }
4545

4646
func (v value) int64() int64 { return v.val.Int() }
4747

48+
func (v value) float64() float64 { return v.val.Float() }
49+
4850
func (v value) string() string { return v.val.String() }
4951

5052
func (v value) bytes() []byte { return v.val.Bytes() }
@@ -63,6 +65,8 @@ func (v value) setInt32(i int32) { v.setInt64(int64(i)) }
6365

6466
func (v value) setInt64(i int64) { v.val.SetInt(i) }
6567

68+
func (v value) setFloat64(f float64) { v.val.SetFloat(f) }
69+
6670
func (v value) setString(s string) { v.val.SetString(s) }
6771

6872
func (v value) setBytes(b []byte) { v.val.SetBytes(b) }

0 commit comments

Comments
 (0)