Skip to content

Commit 525bb89

Browse files
authored
Merge pull request #12 from loopholelabs/staging
Release v0.5.0
2 parents fc850a7 + 838a3a0 commit 525bb89

File tree

7 files changed

+166
-55
lines changed

7 files changed

+166
-55
lines changed

.github/workflows/version.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: publish
33
on:
44
push:
55
branches:
6-
- main
6+
- staging
77

88
jobs:
99
build:

buffer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,5 +431,5 @@ func TestLen(t *testing.T) {
431431
p := NewBuffer()
432432
Encoder(p).String("Hello World")
433433

434-
assert.Equal(t, 17, p.Len())
434+
assert.Equal(t, 14, p.Len())
435435
}

decode.go

Lines changed: 95 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ import (
2222
)
2323

2424
const (
25-
emptyString = ""
25+
emptyString = ""
26+
VarIntLen16 = 3
27+
VarIntLen32 = 5
28+
VarIntLen64 = 10
29+
continuation = 0x80
2630
)
2731

2832
var (
@@ -162,48 +166,121 @@ func decodeUint8(b []byte) ([]byte, uint8, error) {
162166
return b, 0, InvalidUint8
163167
}
164168

169+
// Variable integer encoding with the same format as binary.varint
170+
//(https://developers.google.com/protocol-buffers/docs/encoding#varints)
165171
func decodeUint16(b []byte) ([]byte, uint16, error) {
166-
if len(b) > 2 {
167-
if b[0] == Uint16Kind[0] {
168-
return b[3:], uint16(b[2]) | uint16(b[1])<<8, nil
172+
if len(b) > 1 && b[0] == Uint16Kind[0] {
173+
var x uint16
174+
var s uint
175+
for i := 1; i < VarIntLen16+1; i++ {
176+
cb := b[i]
177+
// Check if msb is set signifying a continuation byte
178+
if cb < continuation {
179+
if i > VarIntLen16 && cb > 1 {
180+
return b, 0, InvalidUint32
181+
}
182+
// End of varint, add the last bits and advance the buffer
183+
return b[i+1:], x | uint16(cb)<<s, nil
184+
}
185+
x |= uint16(cb&(continuation-1)) << s
186+
s += 7
169187
}
170188
}
171189
return b, 0, InvalidUint16
172190
}
173191

174192
func decodeUint32(b []byte) ([]byte, uint32, error) {
175-
if len(b) > 4 {
176-
if b[0] == Uint32Kind[0] {
177-
return b[5:], uint32(b[4]) | uint32(b[3])<<8 | uint32(b[2])<<16 | uint32(b[1])<<24, nil
193+
if len(b) > 1 && b[0] == Uint32Kind[0] {
194+
var x uint32
195+
var s uint
196+
for i := 1; i < VarIntLen32+1; i++ {
197+
cb := b[i]
198+
// Check if msb is set signifying a continuation byte
199+
if cb < continuation {
200+
if i > VarIntLen32 && cb > 1 {
201+
return b, 0, InvalidUint32
202+
}
203+
// End of varint, add the last bits and advance the buffer
204+
return b[i+1:], x | uint32(cb)<<s, nil
205+
}
206+
// Add the lower 7 bits to the result and continue to the next byte
207+
x |= uint32(cb&(continuation-1)) << s
208+
s += 7
178209
}
179210
}
180211
return b, 0, InvalidUint32
181212
}
182213

183214
func decodeUint64(b []byte) ([]byte, uint64, error) {
184-
if len(b) > 8 {
185-
if b[0] == Uint64Kind[0] {
186-
return b[9:], uint64(b[8]) | uint64(b[7])<<8 | uint64(b[6])<<16 | uint64(b[5])<<24 |
187-
uint64(b[4])<<32 | uint64(b[3])<<40 | uint64(b[2])<<48 | uint64(b[1])<<56, nil
215+
if len(b) > 1 && b[0] == Uint64Kind[0] {
216+
var x uint64
217+
var s uint
218+
for i := 1; i < VarIntLen64+1; i++ {
219+
cb := b[i]
220+
// Check if msb is set signifying a continuation byte
221+
if cb < continuation {
222+
// Check for overflow
223+
if i > VarIntLen64 && cb > 1 {
224+
return b, 0, InvalidUint64
225+
}
226+
// End of varint, add the last bits and advance the buffer
227+
return b[i+1:], x | uint64(cb)<<s, nil
228+
}
229+
// Add the lower 7 bits to the result and continue to the next byte
230+
x |= uint64(cb&(continuation-1)) << s
231+
s += 7
188232
}
189233
}
190234
return b, 0, InvalidUint64
191235
}
192236

193237
func decodeInt32(b []byte) ([]byte, int32, error) {
194-
if len(b) > 4 {
195-
if b[0] == Int32Kind[0] {
196-
return b[5:], int32(uint32(b[4]) | uint32(b[3])<<8 | uint32(b[2])<<16 | uint32(b[1])<<24), nil
238+
if len(b) > 1 && b[0] == Int32Kind[0] {
239+
var ux uint32
240+
var s uint
241+
for i := 1; i < VarIntLen32+1; i++ {
242+
cb := b[i]
243+
// Check if msb is set signifying a continuation byte
244+
if cb < continuation {
245+
if i > VarIntLen32 && cb > 1 {
246+
return b, 0, InvalidInt32
247+
}
248+
// End of varint, add the last bits and cast to signed integer
249+
x := int32((ux | uint32(cb)<<s) >> 1)
250+
// Flip the bits if the sign bit is set
251+
if ux&1 != 0 {
252+
x = ^x
253+
}
254+
return b[i+1:], x, nil
255+
}
256+
ux |= uint32(cb&(continuation-1)) << s
257+
s += 7
197258
}
198259
}
199260
return b, 0, InvalidInt32
200261
}
201262

202263
func decodeInt64(b []byte) ([]byte, int64, error) {
203-
if len(b) > 8 {
204-
if b[0] == Int64Kind[0] {
205-
return b[9:], int64(uint64(b[8]) | uint64(b[7])<<8 | uint64(b[6])<<16 | uint64(b[5])<<24 |
206-
uint64(b[4])<<32 | uint64(b[3])<<40 | uint64(b[2])<<48 | uint64(b[1])<<56), nil
264+
if len(b) > 1 && b[0] == Int64Kind[0] {
265+
var ux uint64
266+
var s uint
267+
for i := 1; i < VarIntLen64+1; i++ {
268+
cb := b[i]
269+
// Check if msb is set signifying a continuation byte
270+
if cb < continuation {
271+
if i > VarIntLen64 && cb > 1 {
272+
return b, 0, InvalidInt64
273+
}
274+
// End of varint, add the last bits and cast to signed integer
275+
x := int64((ux | uint64(cb)<<s) >> 1)
276+
// Flip the bits if the sign bit is set
277+
if ux&1 != 0 {
278+
x = ^x
279+
}
280+
return b[i+1:], x, nil
281+
}
282+
ux |= uint64(cb&(continuation-1)) << s
283+
s += 7
207284
}
208285
}
209286
return b, 0, InvalidInt64

encode.go

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,31 +114,66 @@ func encodeUint8(b *Buffer, value uint8) {
114114
*b = append(*b, value)
115115
}
116116

117+
// Variable integer encoding with the same format as binary.varint
118+
//(https://developers.google.com/protocol-buffers/docs/encoding#varints)
117119
func encodeUint16(b *Buffer, value uint16) {
118120
b.Write(Uint16Kind)
119-
*b = append(*b, byte(value>>8), byte(value))
121+
for value >= continuation {
122+
// Append the lower 7 bits of the value, then shift the value to the right by 7 bits.
123+
*b = append(*b, byte(value)|continuation)
124+
value >>= 7
125+
}
126+
*b = append(*b, byte(value))
120127
}
121128

122129
func encodeUint32(b *Buffer, value uint32) {
123130
b.Write(Uint32Kind)
124-
*b = append(*b, byte(value>>24), byte(value>>16), byte(value>>8), byte(value))
131+
for value >= continuation {
132+
// Append the lower 7 bits of the value, then shift the value to the right by 7 bits.
133+
*b = append(*b, byte(value)|continuation)
134+
value >>= 7
135+
}
136+
*b = append(*b, byte(value))
125137
}
126138

127139
func encodeUint64(b *Buffer, value uint64) {
128140
b.Write(Uint64Kind)
129-
*b = append(*b, byte(value>>56), byte(value>>48), byte(value>>40), byte(value>>32), byte(value>>24), byte(value>>16), byte(value>>8), byte(value))
141+
for value >= continuation {
142+
// Append the lower 7 bits of the value, then shift the value to the right by 7 bits.
143+
*b = append(*b, byte(value)|continuation)
144+
value >>= 7
145+
}
146+
*b = append(*b, byte(value))
130147
}
131148

132149
func encodeInt32(b *Buffer, value int32) {
133150
b.Write(Int32Kind)
134-
castValue := uint32(value)
135-
*b = append(*b, byte(castValue>>24), byte(castValue>>16), byte(castValue>>8), byte(castValue))
151+
// Shift the value to the left by 1 bit, then flip the bits if the value is negative.
152+
castValue := uint32(value) << 1
153+
if value < 0 {
154+
castValue = ^castValue
155+
}
156+
for castValue >= continuation {
157+
// Append the lower 7 bits of the value, then shift the value to the right by 7 bits.
158+
*b = append(*b, byte(castValue)|continuation)
159+
castValue >>= 7
160+
}
161+
*b = append(*b, byte(castValue))
136162
}
137163

138164
func encodeInt64(b *Buffer, value int64) {
139165
b.Write(Int64Kind)
140-
castValue := uint64(value)
141-
*b = append(*b, byte(castValue>>56), byte(castValue>>48), byte(castValue>>40), byte(castValue>>32), byte(castValue>>24), byte(castValue>>16), byte(castValue>>8), byte(castValue))
166+
// Shift the value to the left by 1 bit, then flip the bits if the value is negative.
167+
castValue := uint64(value) << 1
168+
if value < 0 {
169+
castValue = ^castValue
170+
}
171+
for castValue >= continuation {
172+
// Append the lower 7 bits of the value, then shift the value to the right by 7 bits.
173+
*b = append(*b, byte(castValue)|continuation)
174+
castValue >>= 7
175+
}
176+
*b = append(*b, byte(castValue))
142177
}
143178

144179
func encodeFloat32(b *Buffer, value float32) {

encode_test.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func TestEncodeMap(t *testing.T) {
4545
p := NewBuffer()
4646
encodeMap(p, 32, StringKind, Uint32Kind)
4747

48-
assert.Equal(t, 1+1+1+1+4, len(p.Bytes()))
48+
assert.Equal(t, 1+1+1+1+1, len(p.Bytes()))
4949
assert.Equal(t, MapKind, Kind((p.Bytes())[0:1]))
5050
assert.Equal(t, StringKind, Kind((p.Bytes())[1:2]))
5151
assert.Equal(t, Uint32Kind, Kind((p.Bytes())[2:3]))
@@ -64,7 +64,7 @@ func TestEncodeSlice(t *testing.T) {
6464
p := NewBuffer()
6565
encodeSlice(p, 32, StringKind)
6666

67-
assert.Equal(t, 1+1+1+4, len(p.Bytes()))
67+
assert.Equal(t, 1+1+1+1, len(p.Bytes()))
6868
assert.Equal(t, SliceKind, Kind((p.Bytes())[0:1]))
6969
assert.Equal(t, StringKind, Kind((p.Bytes())[1:2]))
7070
assert.Equal(t, Uint32Kind, Kind((p.Bytes())[2:3]))
@@ -84,8 +84,8 @@ func TestEncodeBytes(t *testing.T) {
8484

8585
encodeBytes(p, v)
8686

87-
assert.Equal(t, 1+1+4+len(v), len(p.Bytes()))
88-
assert.Equal(t, v, (p.Bytes())[1+1+4:])
87+
assert.Equal(t, 1+1+1+len(v), len(p.Bytes()))
88+
assert.Equal(t, v, (p.Bytes())[1+1+1:])
8989

9090
p.Reset()
9191
n := testing.AllocsPerRun(100, func() {
@@ -104,8 +104,8 @@ func TestEncodeString(t *testing.T) {
104104

105105
encodeString(p, v)
106106

107-
assert.Equal(t, 1+1+4+len(e), len(p.Bytes()))
108-
assert.Equal(t, e, (p.Bytes())[1+1+4:])
107+
assert.Equal(t, 1+1+1+len(e), len(p.Bytes()))
108+
assert.Equal(t, e, (p.Bytes())[1+1+1:])
109109

110110
p.Reset()
111111
n := testing.AllocsPerRun(100, func() {
@@ -124,8 +124,8 @@ func TestEncodeError(t *testing.T) {
124124

125125
encodeError(p, v)
126126

127-
assert.Equal(t, 1+1+1+4+len(e), len(p.Bytes()))
128-
assert.Equal(t, e, (p.Bytes())[1+1+1+4:])
127+
assert.Equal(t, 1+1+1+1+len(e), len(p.Bytes()))
128+
assert.Equal(t, e, (p.Bytes())[1+1+1+1:])
129129

130130
p.Reset()
131131
n := testing.AllocsPerRun(100, func() {
@@ -179,7 +179,7 @@ func TestEncodeUint16(t *testing.T) {
179179

180180
p := NewBuffer()
181181
v := uint16(1024)
182-
e := []byte{byte(v >> 8), byte(v)}
182+
e := []byte{128, 8}
183183

184184
encodeUint16(p, v)
185185

@@ -199,7 +199,7 @@ func TestEncodeUint32(t *testing.T) {
199199

200200
p := NewBuffer()
201201
v := uint32(4294967290)
202-
e := []byte{byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}
202+
e := []byte{250, 255, 255, 255, 15}
203203

204204
encodeUint32(p, v)
205205

@@ -219,11 +219,10 @@ func TestEncodeUint64(t *testing.T) {
219219

220220
p := NewBuffer()
221221
v := uint64(18446744073709551610)
222-
e := []byte{byte(v >> 56), byte(v >> 48), byte(v >> 40), byte(v >> 32), byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}
222+
e := []byte{250, 255, 255, 255, 255, 255, 255, 255, 255, 1}
223223

224224
encodeUint64(p, v)
225225

226-
assert.Equal(t, 1+len(e), len(p.Bytes()))
227226
assert.Equal(t, e, (p.Bytes())[1:])
228227

229228
p.Reset()
@@ -239,7 +238,7 @@ func TestEncodeInt32(t *testing.T) {
239238

240239
p := NewBuffer()
241240
v := int32(-2147483648)
242-
e := []byte{byte(uint32(v) >> 24), byte(uint32(v) >> 16), byte(uint32(v) >> 8), byte(uint32(v))}
241+
e := []byte{255, 255, 255, 255, 15}
243242

244243
encodeInt32(p, v)
245244

@@ -259,7 +258,7 @@ func TestEncodeInt64(t *testing.T) {
259258

260259
p := NewBuffer()
261260
v := int64(-9223372036854775808)
262-
e := []byte{byte(uint64(v) >> 56), byte(uint64(v) >> 48), byte(uint64(v) >> 40), byte(uint64(v) >> 32), byte(uint64(v) >> 24), byte(uint64(v) >> 16), byte(uint64(v) >> 8), byte(uint64(v))}
261+
e := []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 1}
263262

264263
encodeInt64(p, v)
265264

0 commit comments

Comments
 (0)