-
-
Notifications
You must be signed in to change notification settings - Fork 655
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #322 from mattetti/ma-variable-length-quantity
new exercise to encode/decode variable length quantity
- Loading branch information
Showing
3 changed files
with
94 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package variablelengthquantity | ||
|
||
// EncodeVarint returns the varint encoding of x. | ||
func EncodeVarint(x uint32) []byte { | ||
if x>>7 == 0 { | ||
return []byte{ | ||
byte(x), | ||
} | ||
} | ||
|
||
if x>>14 == 0 { | ||
return []byte{ | ||
byte(0x80 | x>>7), | ||
byte(127 & x), | ||
} | ||
} | ||
|
||
if x>>21 == 0 { | ||
return []byte{ | ||
byte(0x80 | x>>14), | ||
byte(0x80 | x>>7), | ||
byte(127 & x), | ||
} | ||
} | ||
|
||
return []byte{ | ||
byte(0x80 | x>>21), | ||
byte(0x80 | x>>14), | ||
byte(0x80 | x>>7), | ||
byte(127 & x), | ||
} | ||
} | ||
|
||
// DecodeVarint reads a varint-encoded integer from the slice. | ||
// It returns the integer and the number of bytes consumed, or | ||
// zero if there is not enough. | ||
func DecodeVarint(buf []byte) (x uint32, n int) { | ||
if len(buf) < 1 { | ||
return 0, 0 | ||
} | ||
|
||
if buf[0] <= 0x80 { | ||
return uint32(buf[0]), 1 | ||
} | ||
|
||
var b byte | ||
for n, b = range buf { | ||
x = x << 7 | ||
x |= uint32(b) & 0x7F | ||
if (b & 0x80) == 0 { | ||
return x, n | ||
} | ||
} | ||
|
||
return x, n | ||
} |
36 changes: 36 additions & 0 deletions
36
exercises/variable-length-quantity/variable_length_quantity_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package variablelengthquantity | ||
|
||
import ( | ||
"bytes" | ||
"testing" | ||
) | ||
|
||
func TestEncodeDecodeVarint(t *testing.T) { | ||
testCases := []struct { | ||
input []byte | ||
output uint32 | ||
}{ | ||
0: {[]byte{0x7F}, 127}, | ||
1: {[]byte{0x81, 0x00}, 128}, | ||
2: {[]byte{0xC0, 0x00}, 8192}, | ||
3: {[]byte{0xFF, 0x7F}, 16383}, | ||
4: {[]byte{0x81, 0x80, 0x00}, 16384}, | ||
5: {[]byte{0xFF, 0xFF, 0x7F}, 2097151}, | ||
6: {[]byte{0x81, 0x80, 0x80, 0x00}, 2097152}, | ||
7: {[]byte{0xC0, 0x80, 0x80, 0x00}, 134217728}, | ||
8: {[]byte{0xFF, 0xFF, 0xFF, 0x7F}, 268435455}, | ||
|
||
9: {[]byte{0x82, 0x00}, 256}, | ||
10: {[]byte{0x81, 0x10}, 144}, | ||
} | ||
|
||
for i, tc := range testCases { | ||
t.Logf("test case %d - %#v\n", i, tc.input) | ||
if o, _ := DecodeVarint(tc.input); o != tc.output { | ||
t.Fatalf("expected %d\ngot\n%d\n", tc.output, o) | ||
} | ||
if encoded := EncodeVarint(tc.output); bytes.Compare(encoded, tc.input) != 0 { | ||
t.Fatalf("%d - expected %#v\ngot\n%#v\n", tc.output, tc.input, encoded) | ||
} | ||
} | ||
} |