Browse Source

big uint64 unmarshalling fix

nikandfor 9 years ago
parent
commit
60015fde6e
3 changed files with 73 additions and 2 deletions
  1. 2 1
      AUTHORS
  2. 13 1
      marshal.go
  3. 58 0
      marshal_test.go

+ 2 - 1
AUTHORS

@@ -62,4 +62,5 @@ Adriano Orioli <orioli.adriano@gmail.com>
 Claudiu Raveica <claudiu.raveica@gmail.com>
 Artem Chernyshev <artem.0xD2@gmail.com>
 Ference Fu <fym201@msn.com>
-LOVOO <opensource@lovoo.com>
+LOVOO <opensource@lovoo.com>
+nikandfor <nikandfor@gmail.com>

+ 13 - 1
marshal.go

@@ -401,6 +401,13 @@ func bytesToInt64(data []byte) (ret int64) {
 	return ret
 }
 
+func bytesToUint64(data []byte) (ret uint64) {
+	for i := range data {
+		ret |= uint64(data[i]) << (8 * uint(len(data)-i-1))
+	}
+	return ret
+}
+
 func unmarshalBigInt(info TypeInfo, data []byte, value interface{}) error {
 	return unmarshalIntlike(info, decBigInt(data), data, value)
 }
@@ -410,9 +417,14 @@ func unmarshalInt(info TypeInfo, data []byte, value interface{}) error {
 }
 
 func unmarshalVarint(info TypeInfo, data []byte, value interface{}) error {
-	switch value.(type) {
+	switch v := value.(type) {
 	case *big.Int:
 		return unmarshalIntlike(info, 0, data, value)
+	case *uint64:
+		if len(data) == 9 && data[0] == 0 {
+			*v = bytesToUint64(data[1:])
+			return nil
+		}
 	}
 
 	if len(data) > 8 {

+ 58 - 0
marshal_test.go

@@ -675,6 +675,64 @@ func TestMarshalVarint(t *testing.T) {
 			t.Errorf("unmarshaled varint mismatch: expected %v, got %v (test #%d)", test.Unmarshaled, binder, i)
 		}
 	}
+
+	varintUint64Tests := []struct {
+		Value       interface{}
+		Marshaled   []byte
+		Unmarshaled uint64
+	}{
+		{
+			Value:       int8(0),
+			Marshaled:   []byte("\x00"),
+			Unmarshaled: 0,
+		},
+		{
+			Value:       uint8(255),
+			Marshaled:   []byte("\x00\xFF"),
+			Unmarshaled: 255,
+		},
+		{
+			Value:       big.NewInt(math.MaxInt32),
+			Marshaled:   []byte("\x7F\xFF\xFF\xFF"),
+			Unmarshaled: uint64(math.MaxInt32),
+		},
+		{
+			Value:       big.NewInt(int64(math.MaxInt32) + 1),
+			Marshaled:   []byte("\x00\x80\x00\x00\x00"),
+			Unmarshaled: uint64(int64(math.MaxInt32) + 1),
+		},
+		{
+			Value:       uint64(math.MaxInt64) + 1,
+			Marshaled:   []byte("\x00\x80\x00\x00\x00\x00\x00\x00\x00"),
+			Unmarshaled: 9223372036854775808,
+		},
+		{
+			Value:       math.MaxUint64,
+			Marshaled:   []byte("\x00\x80\x00\x00\x00\x00\x00\x00\x00"),
+			Unmarshaled: math.MaxUint64,
+		},
+	}
+
+	for i, test := range varintTests {
+		data, err := Marshal(NativeType{proto: 2, typ: TypeVarint}, test.Value)
+		if err != nil {
+			t.Errorf("error marshaling varint: %v (test #%d)", err, i)
+		}
+
+		if !bytes.Equal(test.Marshaled, data) {
+			t.Errorf("marshaled varint mismatch: expected %v, got %v (test #%d)", test.Marshaled, data, i)
+		}
+
+		binder := new(uint64)
+		err = Unmarshal(NativeType{proto: 2, typ: TypeVarint}, test.Marshaled, binder)
+		if err != nil {
+			t.Errorf("error unmarshaling varint: %v (test #%d)", err, i)
+		}
+
+		if test.Unmarshaled != binder {
+			t.Errorf("unmarshaled varint mismatch: expected %v, got %v (test #%d)", test.Unmarshaled, binder, i)
+		}
+	}
 }
 
 func equalStringSlice(leftList, rightList []string) bool {