Merge pull request #261 from wongoo/fix-259

Fix map decode error issue #259
diff --git a/decode.go b/decode.go
index b916703..00b8461 100644
--- a/decode.go
+++ b/decode.go
@@ -33,7 +33,6 @@
 	reader *bufio.Reader
 	refs   []interface{}
 	// record type refs, both list and map need it
-	// todo: map
 	typeRefs      *TypeRefs
 	classInfoList []*classInfo
 	isSkip        bool
@@ -162,36 +161,52 @@
 }
 
 // read the type of data, used to decode list or map
-func (d *Decoder) decType() (string, error) {
+func (d *Decoder) decMapType() (reflect.Type, error) {
 	var (
-		err error
-		arr [1]byte
-		buf []byte
-		tag byte
-		idx int32
-		typ reflect.Type
+		err     error
+		arr     [1]byte
+		buf     []byte
+		tag     byte
+		idx     int32
+		typ     reflect.Type
+		typName string
 	)
 
 	buf = arr[:1]
 	if _, err = io.ReadFull(d.reader, buf); err != nil {
-		return "", perrors.WithStack(err)
+		return nil, perrors.WithStack(err)
 	}
 	tag = buf[0]
 	if (tag >= BC_STRING_DIRECT && tag <= STRING_DIRECT_MAX) ||
 		(tag >= 0x30 && tag <= 0x33) || (tag == BC_STRING) || (tag == BC_STRING_CHUNK) {
-		return d.decString(int32(tag))
+		typName, err = d.decString(int32(tag))
+		if err != nil {
+			return nil, perrors.WithStack(err)
+		}
+
+		info, ok := getStructInfo(typName)
+		if ok {
+			typ = info.typ
+		} else {
+			typ = reflect.TypeOf(map[interface{}]interface{}{})
+		}
+
+		// add to type map
+		d.typeRefs.appendTypeRefs(typName, typ)
+
+		return typ, nil
 	}
 
 	if idx, err = d.decInt32(int32(tag)); err != nil {
-		return "", perrors.WithStack(err)
+		return nil, perrors.WithStack(err)
 	}
 
-	typ, _, err = d.getStructDefByIndex(int(idx))
-	if err == nil {
-		return typ.String(), nil
+	typ = d.typeRefs.Get(int(idx))
+	if typ == nil {
+		return nil, perrors.Errorf("the type ref index %d is out of range", idx)
 	}
 
-	return "", err
+	return typ, err
 }
 
 // Decode parse hessian data, and ensure the reflection value unpacked
diff --git a/decode_test.go b/decode_test.go
index 3c4dd95..0e57f45 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -110,7 +110,7 @@
 func testDecodeJavaData(t *testing.T, method, className string, skip bool, expected interface{}) {
 	r, e := decodeJavaResponse(method, className, skip)
 	if e != nil {
-		t.Errorf("%s: decode fail with error %v", method, e)
+		t.Errorf("%s: decode fail with error: %v", method, e)
 		return
 	}
 
diff --git a/map.go b/map.go
index 0d83d4e..d43b915 100644
--- a/map.go
+++ b/map.go
@@ -217,13 +217,12 @@
 	return nil
 }
 
-// TODO to decode ref object in map
+// decode map object
 func (d *Decoder) decMap(flag int32) (interface{}, error) {
 	var (
 		err        error
 		tag        byte
 		ok         bool
-		t          string
 		m          map[interface{}]interface{}
 		k          interface{}
 		v          interface{}
@@ -231,6 +230,7 @@
 		instValue  reflect.Value
 		fieldName  string
 		fieldValue reflect.Value
+		typ        reflect.Type
 	)
 
 	if flag != TAG_READ {
@@ -245,67 +245,48 @@
 	case tag == BC_REF:
 		return d.decRef(int32(tag))
 	case tag == BC_MAP:
-		if t, err = d.decType(); err != nil {
+		if typ, err = d.decMapType(); err != nil {
 			return nil, err
 		}
 
-		_, ok = checkPOJORegistry(t)
-		if ok {
-			inst = createInstance(t)
-			instValue = reflect.ValueOf(inst)
-			d.appendRefs(inst)
-			for d.peekByte() != BC_END {
-				k, err = d.Decode()
-				if err != nil {
-					return nil, err
-				}
-				v, err = d.Decode()
-				if err != nil {
-					return nil, err
-				}
+		if typ.Kind() == reflect.Map {
+			instValue = reflect.MakeMap(typ)
+		} else {
+			instValue = reflect.New(typ).Elem()
+		}
 
+		inst = instValue.Interface()
+
+		d.appendRefs(inst)
+
+		for d.peekByte() != BC_END {
+			k, err = d.Decode()
+			if err != nil {
+				return nil, err
+			}
+			v, err = d.Decode()
+			if err != nil {
+				return nil, err
+			}
+
+			if typ.Kind() == reflect.Map {
+				instValue.SetMapIndex(reflect.ValueOf(k), EnsureRawValue(v))
+			} else {
 				fieldName, ok = k.(string)
 				if !ok {
 					return nil, perrors.Errorf("the type of map key must be string, but get %v", k)
 				}
-				if instValue.Kind() == reflect.Map {
-					instValue.SetMapIndex(reflect.ValueOf(k), EnsureRawValue(v))
-				} else {
-					fieldValue = instValue.FieldByName(fieldName)
-					if fieldValue.IsValid() {
-						fieldValue.Set(EnsureRawValue(v))
-					}
+				fieldValue = instValue.FieldByName(fieldName)
+				if fieldValue.IsValid() {
+					fieldValue.Set(EnsureRawValue(v))
 				}
 			}
-			_, err = d.ReadByte()
-			if err != nil {
-				return nil, perrors.WithStack(err)
-			}
-			return inst, nil
-		} else {
-			m = make(map[interface{}]interface{})
-			classIndex := RegisterPOJOMapping(t, m)
-			d.appendClsDef(pojoRegistry.classInfoList[classIndex])
-
-			d.appendRefs(m)
-			for d.peekByte() != BC_END {
-				k, err = d.Decode()
-				if err != nil {
-					return nil, err
-				}
-				v, err = d.Decode()
-				if err != nil {
-					return nil, err
-				}
-				m[k] = v
-			}
-			_, err = d.ReadByte()
-			if err != nil {
-				return nil, perrors.WithStack(err)
-			}
-			return m, nil
 		}
-
+		_, err = d.ReadByte()
+		if err != nil {
+			return nil, perrors.WithStack(err)
+		}
+		return inst, nil
 	case tag == BC_MAP_UNTYPED:
 		m = make(map[interface{}]interface{})
 		d.appendRefs(m)
diff --git a/map_test.go b/map_test.go
index 3a84aef..e80fbe6 100644
--- a/map_test.go
+++ b/map_test.go
@@ -21,6 +21,10 @@
 	"testing"
 )
 
+import (
+	big "github.com/dubbogo/gost/math/big"
+)
+
 func TestEncUntypedMap(t *testing.T) {
 	var (
 		m   map[interface{}]interface{}
@@ -106,4 +110,20 @@
 	}
 	testDecodeFramework(t, "customReplyMapInMap", mapInMap)
 	testDecodeFramework(t, "customReplyMapInMapJsonObject", mapInMap)
+
+	b3 := &big.Decimal{}
+	_ = b3.FromString("33.33")
+	b3.Value = "33.33"
+
+	b5 := &big.Decimal{}
+	_ = b5.FromString("55.55")
+	b5.Value = "55.55"
+
+	multipleTypeMap := map[interface{}]interface{}{
+		"m1": map[interface{}]interface{}{"a": int32(1), "b": int32(2)},
+		"m2": map[interface{}]interface{}{int64(3): "c", int64(4): "d"},
+		"m3": map[interface{}]interface{}{int32(3): b3, int32(5): b5},
+	}
+
+	testDecodeFramework(t, "customReplyMultipleTypeMap", multipleTypeMap)
 }
diff --git a/serialize_test.go b/serialize_test.go
index 4d602c5..4ba4148 100644
--- a/serialize_test.go
+++ b/serialize_test.go
@@ -165,6 +165,23 @@
 	}
 }
 
+func TestCustomReplyObjectJsonObjectBigDecimalDecode(t *testing.T) {
+	decimal := &big.Decimal{}
+	_ = decimal.FromString("100")
+
+	out, err := decodeJavaResponse(`customReplyObjectJsonObjectBigDecimal`, ``, false)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	res := out.(map[interface{}]interface{})
+	assert.Equal(t, 1, len(res))
+
+	dec := res["test_BigDecimal"].(*big.Decimal)
+	assert.Equal(t, decimal.String(), dec.String())
+}
+
 func TestObjectListGoDecode(t *testing.T) {
 	data := []string{
 		"1234",
diff --git a/test_hessian/src/main/java/test/TestCustomReply.java b/test_hessian/src/main/java/test/TestCustomReply.java
index be212ac..1f99785 100644
--- a/test_hessian/src/main/java/test/TestCustomReply.java
+++ b/test_hessian/src/main/java/test/TestCustomReply.java
@@ -419,6 +419,14 @@
         output.flush();
     }
 
+    public void customReplyObjectJsonObjectBigDecimal() throws Exception {
+        JSONObject t = new JSONObject();
+        BigDecimal decimal = new BigDecimal("100");
+        t.put("test_BigDecimal",decimal);
+        output.writeObject(t);
+        output.flush();
+    }
+
     public void customReplyTypedFixedDateNull() throws Exception {
         DateDemo demo = new DateDemo("zhangshan", null, null);
         output.writeObject(demo);
@@ -492,6 +500,25 @@
         output.flush();
     }
 
+    public void customReplyMultipleTypeMap() throws Exception {
+        Map<String, Integer> map1 = new HashMap<String, Integer>(4);
+        map1.put("a", 1);
+        map1.put("b", 2);
+        Map<Long, String> map2 = new HashMap<Long, String>(4);
+        map2.put(3L, "c");
+        map2.put(4L, "d");
+        Map<Integer, BigDecimal> map3 = new HashMap<Integer, BigDecimal>(4);
+        map3.put(5,new BigDecimal("55.55"));
+        map3.put(3,new BigDecimal("33.33"));
+        Map<String, Object> map = new HashMap<String, Object>(4);
+        map.put("m1", map1);
+        map.put("m2", map2);
+        map.put("m3", map3);
+
+        output.writeObject(map);
+        output.flush();
+    }
+
     public Map<String, Object> mapInMap() throws Exception {
         Map<String, Object> map1 = new HashMap<String, Object>();
         map1.put("a", 1);
@@ -567,3 +594,4 @@
     public String name;
     public Integer age;
 }
+