Merge remote-tracking branch 'upstream/master'
diff --git a/date_test.go b/date_test.go
index 5e4f789..ed7f96c 100644
--- a/date_test.go
+++ b/date_test.go
@@ -43,7 +43,7 @@
 }
 
 func testDateFramework(t *testing.T, method string, expected time.Time) {
-	r, e := decodeResponse(method)
+	r, e := decodeJavaResponse(method, "")
 	if e != nil {
 		t.Errorf("%s: decode fail with error %+v", method, e)
 		return
diff --git a/decode_test.go b/decode_test.go
index 1993308..8dae2b6 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -55,9 +55,13 @@
 	}
 }
 
-func getReply(method string) []byte {
+func getJavaReply(method, className string) []byte {
 	genHessianJar()
-	cmd := exec.Command("java", "-jar", hessianJar, method)
+	cmdArgs := []string{"-jar", hessianJar, method}
+	if className != "" {
+		cmdArgs = append(cmdArgs, className)
+	}
+	cmd := exec.Command("java", cmdArgs...)
 	out, err := cmd.Output()
 	if err != nil {
 		log.Fatal(err)
@@ -65,8 +69,8 @@
 	return out
 }
 
-func decodeResponse(method string) (interface{}, error) {
-	b := getReply(method)
+func decodeJavaResponse(method, className string) (interface{}, error) {
+	b := getJavaReply(method, className)
 	d := NewDecoder(b)
 	r, e := d.Decode()
 	if e != nil {
@@ -76,7 +80,11 @@
 }
 
 func testDecodeFramework(t *testing.T, method string, expected interface{}) {
-	r, e := decodeResponse(method)
+	testDecodeJavaData(t, method, "", expected)
+}
+
+func testDecodeJavaData(t *testing.T, method, className string, expected interface{}) {
+	r, e := decodeJavaResponse(method, className)
 	if e != nil {
 		t.Errorf("%s: decode fail with error %v", method, e)
 		return
@@ -92,7 +100,7 @@
 }
 
 func testDecodeFrameworkFunc(t *testing.T, method string, expected func(interface{})) {
-	r, e := decodeResponse(method)
+	r, e := decodeJavaResponse(method, "")
 	if e != nil {
 		t.Errorf("%s: decode fail with error %v", method, e)
 		return
diff --git a/double.go b/double.go
index 73abb93..050ee25 100644
--- a/double.go
+++ b/double.go
@@ -47,7 +47,7 @@
 		if iv >= -0x80 && iv < 0x80 {
 			return encByte(b, BC_DOUBLE_BYTE, byte(iv))
 		} else if iv >= -0x8000 && iv < 0x8000 {
-			return encByte(b, BC_DOUBLE_BYTE, byte(iv>>8), byte(iv))
+			return encByte(b, BC_DOUBLE_SHORT, byte(iv>>8), byte(iv))
 		}
 
 		goto END
diff --git a/encode.go b/encode.go
index 7a6b082..30d6364 100644
--- a/encode.go
+++ b/encode.go
@@ -70,8 +70,18 @@
 	case bool:
 		e.buffer = encBool(e.buffer, val)
 
-	case int8, int16, int32:
-		e.buffer = encInt32(e.buffer, v.(int32))
+	case uint8:
+		e.buffer = encInt32(e.buffer, int32(val))
+	case int8:
+		e.buffer = encInt32(e.buffer, int32(val))
+	case int16:
+		e.buffer = encInt32(e.buffer, int32(val))
+	case uint16:
+		e.buffer = encInt32(e.buffer, int32(val))
+	case int32:
+		e.buffer = encInt32(e.buffer, int32(val))
+	case uint32:
+		e.buffer = encInt64(e.buffer, int64(val))
 
 	case int:
 		// if v.(int) >= -2147483648 && v.(int) <= 2147483647 {
@@ -85,6 +95,8 @@
 
 	case int64:
 		e.buffer = encInt64(e.buffer, val)
+	case uint64:
+		e.buffer = encInt64(e.buffer, int64(val))
 
 	case time.Time:
 		e.buffer = encDateInMs(e.buffer, val)
diff --git a/long.go b/long.go
index c482a2f..6fec2fb 100644
--- a/long.go
+++ b/long.go
@@ -41,7 +41,7 @@
 		return encByte(b, byte(int64(BC_LONG_BYTE_ZERO)+(v>>8)), byte(v))
 	} else if int64(LONG_SHORT_MIN) <= v && v <= int64(LONG_SHORT_MAX) {
 		return encByte(b, byte(int64(BC_LONG_SHORT_ZERO)+(v>>16)), byte(v>>8), byte(v))
-	} else if 0x80000000 <= v && v <= 0x7fffffff {
+	} else if -0x80000000 <= v && v <= 0x7fffffff {
 		return encByte(b, BC_LONG_INT, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
 	}
 
diff --git a/object.go b/object.go
index 2a13170..b653f6b 100644
--- a/object.go
+++ b/object.go
@@ -330,15 +330,15 @@
 		fldRawValue := UnpackPtrValue(field)
 
 		kind := fldTyp.Kind()
-		switch {
-		case kind == reflect.String:
+		switch kind {
+		case reflect.String:
 			str, err := d.decString(TAG_READ)
 			if err != nil {
 				return nil, perrors.Wrapf(err, "decInstance->ReadString: %s", fieldName)
 			}
 			fldRawValue.SetString(str)
 
-		case kind == reflect.Int32 || kind == reflect.Int16:
+		case reflect.Int32, reflect.Int16, reflect.Int8:
 			num, err := d.decInt32(TAG_READ)
 			if err != nil {
 				// java enum
@@ -351,13 +351,17 @@
 					enumValue, _ := s.(JavaEnum)
 					num = int32(enumValue)
 				} else {
-					return nil, perrors.Wrapf(err, "decInstance->ParseInt, field name:%s", fieldName)
+					return nil, perrors.Wrapf(err, "decInstance->decInt32, field name:%s", fieldName)
 				}
 			}
-
 			fldRawValue.SetInt(int64(num))
-
-		case kind == reflect.Int || kind == reflect.Int64 || kind == reflect.Uint64:
+		case reflect.Uint16, reflect.Uint8:
+			num, err := d.decInt32(TAG_READ)
+			if err != nil {
+				return nil, perrors.Wrapf(err, "decInstance->decInt32, field name:%s", fieldName)
+			}
+			fldRawValue.SetUint(uint64(num))
+		case reflect.Uint, reflect.Int, reflect.Int64:
 			num, err := d.decInt64(TAG_READ)
 			if err != nil {
 				if fldTyp.Implements(javaEnumType) {
@@ -374,29 +378,34 @@
 			}
 
 			fldRawValue.SetInt(num)
-
-		case kind == reflect.Bool:
+		case reflect.Uint32, reflect.Uint64:
+			num, err := d.decInt64(TAG_READ)
+			if err != nil {
+				return nil, perrors.Wrapf(err, "decInstance->decInt64, field name:%s", fieldName)
+			}
+			fldRawValue.SetUint(uint64(num))
+		case reflect.Bool:
 			b, err := d.Decode()
 			if err != nil {
 				return nil, perrors.Wrapf(err, "decInstance->Decode field name:%s", fieldName)
 			}
 			fldRawValue.SetBool(b.(bool))
 
-		case kind == reflect.Float32 || kind == reflect.Float64:
+		case reflect.Float32, reflect.Float64:
 			num, err := d.decDouble(TAG_READ)
 			if err != nil {
 				return nil, perrors.Wrapf(err, "decInstance->decDouble field name:%s", fieldName)
 			}
 			fldRawValue.SetFloat(num.(float64))
 
-		case kind == reflect.Map:
+		case reflect.Map:
 			// decode map should use the original field value for correct value setting
 			err := d.decMapByValue(field)
 			if err != nil {
 				return nil, perrors.Wrapf(err, "decInstance->decMapByValue field name: %s", fieldName)
 			}
 
-		case kind == reflect.Slice || kind == reflect.Array:
+		case reflect.Slice, reflect.Array:
 			m, err := d.decList(TAG_READ)
 			if err != nil {
 				if err == io.EOF {
@@ -410,7 +419,7 @@
 			if err != nil {
 				return nil, err
 			}
-		case kind == reflect.Struct:
+		case reflect.Struct:
 			var (
 				err error
 				s   interface{}
diff --git a/object_test.go b/object_test.go
index ef6ce95..6c5b44e 100644
--- a/object_test.go
+++ b/object_test.go
@@ -15,6 +15,7 @@
 package hessian
 
 import (
+	"math"
 	"reflect"
 	"testing"
 )
@@ -365,3 +366,100 @@
 	cons.Rest = &cons
 	testDecodeFramework(t, "replyObject_3", &cons)
 }
+
+type Tuple struct {
+	Byte    int8
+	Short   int16
+	Integer int32
+	Long    int64
+	Double  float32
+	B       uint8
+	S       uint16
+	I       uint32
+	L       uint64
+	D       float64
+}
+
+func (t Tuple) JavaClassName() string {
+	return "test.tuple.Tuple"
+}
+
+func TestDecodeJavaTupleObject(t *testing.T) {
+	tuple := &Tuple{
+		Byte:    1,
+		Short:   1,
+		Integer: 1,
+		Long:    1,
+		Double:  1.23,
+		B:       0x01,
+		S:       1,
+		I:       1,
+		L:       1,
+		D:       1.23,
+	}
+
+	RegisterPOJO(tuple)
+
+	testDecodeJavaData(t, "getTheTuple", "test.tuple.TupleProviderImpl", tuple)
+}
+
+func TestEncodeDecodeTuple(t *testing.T) {
+	doTestEncodeDecodeTuple(t, &Tuple{
+		Byte:    1,
+		Short:   1,
+		Integer: 1,
+		Long:    1,
+		Double:  1.23,
+		B:       0x01,
+		S:       1,
+		I:       1,
+		L:       1,
+		D:       1.23,
+	})
+
+	doTestEncodeDecodeTuple(t, &Tuple{
+		Byte:    math.MinInt8,
+		Short:   math.MinInt16,
+		Integer: math.MinInt32,
+		Long:    math.MinInt64,
+		Double:  -99.99,
+		B:       0x00,
+		S:       0,
+		I:       0,
+		L:       0,
+		D:       -9999.9999,
+	})
+
+	doTestEncodeDecodeTuple(t, &Tuple{
+		Byte:    math.MaxInt8,
+		Short:   math.MaxInt16,
+		Integer: math.MaxInt32,
+		Long:    math.MaxInt64,
+		Double:  math.MaxFloat32,
+		B:       0xFF,
+		S:       0xFFFF,
+		I:       0xFFFFFFFF,
+		L:       0xFFFFFFFFFFFFFFFF,
+		D:       math.MaxFloat64,
+	})
+}
+
+func doTestEncodeDecodeTuple(t *testing.T, tuple *Tuple) {
+	e := NewEncoder()
+	err := e.encObject(tuple)
+	if err != nil {
+		t.Error(err)
+		t.FailNow()
+	}
+
+	d := NewDecoder(e.buffer)
+	decObj, err := d.Decode()
+	if err != nil {
+		t.Error(err)
+		t.FailNow()
+	}
+
+	if !reflect.DeepEqual(tuple, decObj) {
+		t.Errorf("expect: %v, but get: %v", tuple, decObj)
+	}
+}
diff --git a/test_hessian/pom.xml b/test_hessian/pom.xml
index 3e2fa8b..031ddd1 100644
--- a/test_hessian/pom.xml
+++ b/test_hessian/pom.xml
@@ -1,15 +1,11 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>test</groupId>
     <artifactId>test_hessian</artifactId>
     <version>1.0.0</version>
 
-    <properties>
-        <maven.compiler.source>1.8</maven.compiler.source>
-        <maven.compiler.target>1.8</maven.compiler.target>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>com.alibaba</groupId>
@@ -34,6 +30,13 @@
     <build>
         <plugins>
             <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-shade-plugin</artifactId>
                 <version>3.1.1</version>
@@ -45,7 +48,8 @@
                         </goals>
                         <configuration>
                             <transformers>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                     <mainClass>test.Hessian</mainClass>
                                 </transformer>
                             </transformers>
diff --git a/test_hessian/src/main/java/test/Hessian.java b/test_hessian/src/main/java/test/Hessian.java
index 4865d3a..5f89645 100644
--- a/test_hessian/src/main/java/test/Hessian.java
+++ b/test_hessian/src/main/java/test/Hessian.java
@@ -23,6 +23,11 @@
 
 public class Hessian {
     public static void main(String[] args) throws Exception {
+        if (args.length > 1) {
+            testCustomClassMethod(args[0], args[1]);
+            return;
+        }
+
         if (args[0].startsWith("reply")) {
             Method method = TestHessian2Servlet.class.getMethod(args[0]);
             TestHessian2Servlet servlet = new TestHessian2Servlet();
@@ -56,4 +61,14 @@
             output.flush();
         }
     }
+
+    private static void testCustomClassMethod(String methodName, String className) throws Exception {
+        Class<?> clazz = Class.forName(className);
+        Method method = clazz.getMethod(methodName);
+        Object target = clazz.newInstance();
+        Object result = method.invoke(target);
+        Hessian2Output output = new Hessian2Output(System.out);
+        output.writeObject(result);
+        output.flush();
+    }
 }
\ No newline at end of file
diff --git a/test_hessian/src/main/java/test/tuple/Tuple.java b/test_hessian/src/main/java/test/tuple/Tuple.java
new file mode 100644
index 0000000..3854a91
--- /dev/null
+++ b/test_hessian/src/main/java/test/tuple/Tuple.java
@@ -0,0 +1,99 @@
+package test.tuple;
+
+import java.io.Serializable;
+
+public class Tuple implements Serializable {
+    private static final long serialVersionUID = -1L;
+
+    Integer Integer;
+    Byte Byte;
+    Short Short;
+    Long Long;
+    Double Double;
+    int i;
+    byte b;
+    short s;
+    long l;
+    double d;
+
+
+    public java.lang.Integer getInteger() {
+        return Integer;
+    }
+
+    public void setInteger(java.lang.Integer integer) {
+        Integer = integer;
+    }
+
+    public java.lang.Byte getByte() {
+        return Byte;
+    }
+
+    public void setByte(java.lang.Byte aByte) {
+        Byte = aByte;
+    }
+
+    public java.lang.Short getShort() {
+        return Short;
+    }
+
+    public void setShort(java.lang.Short aShort) {
+        Short = aShort;
+    }
+
+    public java.lang.Long getLong() {
+        return Long;
+    }
+
+    public void setLong(java.lang.Long aLong) {
+        Long = aLong;
+    }
+
+    public int getI() {
+        return i;
+    }
+
+    public void setI(int i) {
+        this.i = i;
+    }
+
+    public byte getB() {
+        return b;
+    }
+
+    public void setB(byte b) {
+        this.b = b;
+    }
+
+    public short getS() {
+        return s;
+    }
+
+    public void setS(short s) {
+        this.s = s;
+    }
+
+    public long getL() {
+        return l;
+    }
+
+    public void setL(long l) {
+        this.l = l;
+    }
+
+    public java.lang.Double getDouble() {
+        return Double;
+    }
+
+    public void setDouble(java.lang.Double aDouble) {
+        Double = aDouble;
+    }
+
+    public double getD() {
+        return d;
+    }
+
+    public void setD(double d) {
+        this.d = d;
+    }
+}
\ No newline at end of file
diff --git a/test_hessian/src/main/java/test/tuple/TupleProvider.java b/test_hessian/src/main/java/test/tuple/TupleProvider.java
new file mode 100644
index 0000000..075a098
--- /dev/null
+++ b/test_hessian/src/main/java/test/tuple/TupleProvider.java
@@ -0,0 +1,6 @@
+package test.tuple;
+
+public interface TupleProvider {
+
+    Tuple getTheTuple();
+}
diff --git a/test_hessian/src/main/java/test/tuple/TupleProviderImpl.java b/test_hessian/src/main/java/test/tuple/TupleProviderImpl.java
new file mode 100644
index 0000000..5237680
--- /dev/null
+++ b/test_hessian/src/main/java/test/tuple/TupleProviderImpl.java
@@ -0,0 +1,21 @@
+package test.tuple;
+
+public class TupleProviderImpl implements TupleProvider {
+
+    @Override
+    public Tuple getTheTuple() {
+        Tuple result = new Tuple();
+        result.setB((byte) 1);
+        result.setByte(Byte.valueOf("1"));
+        result.setI(1);
+        result.setInteger(Integer.valueOf("1"));
+        result.setL(1L);
+        result.setLong(Long.valueOf("1"));
+        result.setS((short) 1);
+        result.setShort(Short.valueOf("1"));
+        result.setD(1.23);
+        result.setDouble(Double.valueOf("1.23"));
+        return result;
+    }
+
+}