blob: 3c75387f779b78e9da697a6cc01434c9b73b24d0 [file] [log] [blame]
William Kurkianea869482019-04-09 15:16:11 -04001package sarama
2
3import (
4 "encoding/binary"
5
6 "github.com/rcrowley/go-metrics"
7)
8
9type realEncoder struct {
10 raw []byte
11 off int
12 stack []pushEncoder
13 registry metrics.Registry
14}
15
16// primitives
17
18func (re *realEncoder) putInt8(in int8) {
19 re.raw[re.off] = byte(in)
20 re.off++
21}
22
23func (re *realEncoder) putInt16(in int16) {
24 binary.BigEndian.PutUint16(re.raw[re.off:], uint16(in))
25 re.off += 2
26}
27
28func (re *realEncoder) putInt32(in int32) {
29 binary.BigEndian.PutUint32(re.raw[re.off:], uint32(in))
30 re.off += 4
31}
32
33func (re *realEncoder) putInt64(in int64) {
34 binary.BigEndian.PutUint64(re.raw[re.off:], uint64(in))
35 re.off += 8
36}
37
38func (re *realEncoder) putVarint(in int64) {
39 re.off += binary.PutVarint(re.raw[re.off:], in)
40}
41
42func (re *realEncoder) putArrayLength(in int) error {
43 re.putInt32(int32(in))
44 return nil
45}
46
47func (re *realEncoder) putBool(in bool) {
48 if in {
49 re.putInt8(1)
50 return
51 }
52 re.putInt8(0)
53}
54
55// collection
56
57func (re *realEncoder) putRawBytes(in []byte) error {
58 copy(re.raw[re.off:], in)
59 re.off += len(in)
60 return nil
61}
62
63func (re *realEncoder) putBytes(in []byte) error {
64 if in == nil {
65 re.putInt32(-1)
66 return nil
67 }
68 re.putInt32(int32(len(in)))
69 return re.putRawBytes(in)
70}
71
72func (re *realEncoder) putVarintBytes(in []byte) error {
73 if in == nil {
74 re.putVarint(-1)
75 return nil
76 }
77 re.putVarint(int64(len(in)))
78 return re.putRawBytes(in)
79}
80
81func (re *realEncoder) putString(in string) error {
82 re.putInt16(int16(len(in)))
83 copy(re.raw[re.off:], in)
84 re.off += len(in)
85 return nil
86}
87
88func (re *realEncoder) putNullableString(in *string) error {
89 if in == nil {
90 re.putInt16(-1)
91 return nil
92 }
93 return re.putString(*in)
94}
95
96func (re *realEncoder) putStringArray(in []string) error {
97 err := re.putArrayLength(len(in))
98 if err != nil {
99 return err
100 }
101
102 for _, val := range in {
103 if err := re.putString(val); err != nil {
104 return err
105 }
106 }
107
108 return nil
109}
110
111func (re *realEncoder) putInt32Array(in []int32) error {
112 err := re.putArrayLength(len(in))
113 if err != nil {
114 return err
115 }
116 for _, val := range in {
117 re.putInt32(val)
118 }
119 return nil
120}
121
122func (re *realEncoder) putInt64Array(in []int64) error {
123 err := re.putArrayLength(len(in))
124 if err != nil {
125 return err
126 }
127 for _, val := range in {
128 re.putInt64(val)
129 }
130 return nil
131}
132
133func (re *realEncoder) offset() int {
134 return re.off
135}
136
137// stacks
138
139func (re *realEncoder) push(in pushEncoder) {
140 in.saveOffset(re.off)
141 re.off += in.reserveLength()
142 re.stack = append(re.stack, in)
143}
144
145func (re *realEncoder) pop() error {
146 // this is go's ugly pop pattern (the inverse of append)
147 in := re.stack[len(re.stack)-1]
148 re.stack = re.stack[:len(re.stack)-1]
149
150 return in.run(re.off, re.raw)
151}
152
153// we do record metrics during the real encoder pass
154func (re *realEncoder) metricRegistry() metrics.Registry {
155 return re.registry
156}