func (d *Decoder) DecodeAmf3ByteArray(r io.Reader, decodeMarker bool) (result []byte, err error) {
	if err = AssertMarker(r, decodeMarker, AMF3_BYTEARRAY_MARKER); err != nil {
		return
	}
	var isRef bool
	var refVal uint32
	isRef, refVal, err = d.decodeReferenceInt(r)
	if err != nil {
		return result, fmt.Errorf("amf3 decode: unable to decode byte array reference and length: %s", err)
	}
	if isRef {
		var ok bool
		result, ok = d.objectRefs[refVal].([]byte)
		if ok != true {
			return result, fmt.Errorf("amf3 decode: unable to convert object ref to bytes")
		}
		return
	}
	result = make([]byte, refVal)
	_, err = r.Read(result)
	if err != nil {
		return result, fmt.Errorf("amf3 decode: unable to read bytearray: %s", err)
	}
	d.objectRefs = append(d.objectRefs, result)
	return
}
marker: 1 byte 0x0c
format:
- u29 reference int. if reference, no more data. if not reference,
length value of bytes to read.
package amf
import (
	"encoding/binary"
	"fmt"
	"io"
	"time"
)
func (d *Decoder) DecodeAmf3(r io.Reader) (interface{}, error) {
	marker, err := ReadMarker(r)
	if err != nil {
		return nil, err
	}
	switch marker {
	case AMF3_UNDEFINED_MARKER:
		return d.DecodeAmf3Undefined(r, false)
	case AMF3_NULL_MARKER:
		return d.DecodeAmf3Null(r, false)
	case AMF3_FALSE_MARKER:
		return d.DecodeAmf3False(r, false)
	case AMF3_TRUE_MARKER:
		return d.DecodeAmf3True(r, false)
	case AMF3_INTEGER_MARKER:
		return d.DecodeAmf3Integer(r, false)
	case AMF3_DOUBLE_MARKER:
		return d.DecodeAmf3Double(r, false)
	case AMF3_STRING_MARKER:
		return d.DecodeAmf3String(r, false)
	case AMF3_XMLDOC_MARKER:
		return d.DecodeAmf3Xml(r, false)
	case AMF3_DATE_MARKER:
		return d.DecodeAmf3Date(r, false)
	case AMF3_ARRAY_MARKER:
		return d.DecodeAmf3Array(r, false)
	case AMF3_OBJECT_MARKER:
		return d.DecodeAmf3Object(r, false)
	case AMF3_XMLSTRING_MARKER:
		return d.DecodeAmf3Xml(r, false)
	case AMF3_BYTEARRAY_MARKER:
		return d.DecodeAmf3ByteArray(r, false)
	}
	return nil, fmt.Errorf("decode amf3: unsupported type %d", marker)
}
func (d *Decoder) DecodeAmf3Undefined(r io.Reader, decodeMarker bool) (result interface{}, err error) {
	err = AssertMarker(r, decodeMarker, AMF3_UNDEFINED_MARKER)
	return
}
func (d *Decoder) DecodeAmf3Null(r io.Reader, decodeMarker bool) (result interface{}, err error) {
	err = AssertMarker(r, decodeMarker, AMF3_NULL_MARKER)
	return
}
func (d *Decoder) DecodeAmf3False(r io.Reader, decodeMarker bool) (result bool, err error) {
	err = AssertMarker(r, decodeMarker, AMF3_FALSE_MARKER)
	result = false
	return
}
func (d *Decoder) DecodeAmf3True(r io.Reader, decodeMarker bool) (result bool, err error) {
	err = AssertMarker(r, decodeMarker, AMF3_TRUE_MARKER)
	result = true
	return
}
func (d *Decoder) DecodeAmf3Integer(r io.Reader, decodeMarker bool) (result int32, err error) {
	if err = AssertMarker(r, decodeMarker, AMF3_INTEGER_MARKER); err != nil {
		return
	}
	var u29 uint32
	u29, err = d.decodeU29(r)
	if err != nil {
		return
	}
	result = int32(u29)
	if result > 0xfffffff {
		result = int32(u29 - 0x20000000)
	}
	return
}
func (d *Decoder) DecodeAmf3Double(r io.Reader, decodeMarker bool) (result float64, err error) {
	if err = AssertMarker(r, decodeMarker, AMF3_DOUBLE_MARKER); err != nil {
		return
	}
	err = binary.Read(r, binary.BigEndian, &result)
	if err != nil {
		return float64(0), fmt.Errorf("amf3 decode: unable to read double: %s", err)
	}
	return
}
func (d *Decoder) DecodeAmf3String(r io.Reader, decodeMarker bool) (result string, err error) {
	if err = AssertMarker(r, decodeMarker, AMF3_STRING_MARKER); err != nil {
		return
	}
	var isRef bool
	var refVal uint32
	isRef, refVal, err = d.decodeReferenceInt(r)
	if err != nil {
		return "", fmt.Errorf("amf3 decode: unable to decode string reference and length: %s", err)
	}
	if isRef {
		result = d.stringRefs[refVal]
		return
	}
	buf := make([]byte, refVal)
	_, err = r.Read(buf)
	if err != nil {
		return "", fmt.Errorf("amf3 decode: unable to read string: %s", err)
	}
	result = string(buf)
	if result != "" {
		d.stringRefs = append(d.stringRefs, result)
	}
	return
}
func (d *Decoder) DecodeAmf3Date(r io.Reader, decodeMarker bool) (result time.Time, err error) {
	if err = AssertMarker(r, decodeMarker, AMF3_DATE_MARKER); err != nil {
		return
	}
	var isRef bool
	var refVal uint32
	isRef, refVal, err = d.decodeReferenceInt(r)
	if err != nil {
		return result, fmt.Errorf("amf3 decode: unable to decode date reference and length: %s", err)
	}
	if isRef {
		res, ok := d.objectRefs[refVal].(time.Time)
		if ok != true {
			return result, fmt.Errorf("amf3 decode: unable to extract time from date object references")
		}
		return res, err
	}
	var u64 float64
	err = binary.Read(r, binary.BigEndian, &u64)
	if err != nil {
		return result, fmt.Errorf("amf3 decode: unable to read double: %s", err)
	}
	result = time.Unix(int64(u64/1000), 0).UTC()
	d.objectRefs = append(d.objectRefs, result)
	return
}
func (d *Decoder) DecodeAmf3Array(r io.Reader, decodeMarker bool) (result Array, err error) {
	if err = AssertMarker(r, decodeMarker, AMF3_ARRAY_MARKER); err != nil {
		return
	}
	var isRef bool
	var refVal uint32
	isRef, refVal, err = d.decodeReferenceInt(r)
	if err != nil {
		return result, fmt.Errorf("amf3 decode: unable to decode array reference and length: %s", err)
	}
	if isRef {
		objRefId := refVal >> 1
		res, ok := d.objectRefs[objRefId].(Array)
		if ok != true {
			return result, fmt.Errorf("amf3 decode: unable to extract array from object references")
		}
		return res, err
	}
	var key string
	key, err = d.DecodeAmf3String(r, false)
	if err != nil {
		return result, fmt.Errorf("amf3 decode: unable to read key for array: %s", err)
	}
	if key != "" {
		return result, fmt.Errorf("amf3 decode: array key is not empty, can't handle associative array")
	}
	for i := uint32(0); i < refVal; i++ {
		tmp, err := d.DecodeAmf3(r)
		if err != nil {
			return result, fmt.Errorf("amf3 decode: array element could not be decoded: %s", err)
		}
		result = append(result, tmp)
	}
	d.objectRefs = append(d.objectRefs, result)
	return
}
func (d *Decoder) DecodeAmf3Object(r io.Reader, decodeMarker bool) (result interface{}, err error) {
	if err = AssertMarker(r, decodeMarker, AMF3_OBJECT_MARKER); err != nil {
		return nil, err
	}
	isRef, refVal, err := d.decodeReferenceInt(r)
	if err != nil {
		return nil, fmt.Errorf("amf3 decode: unable to decode object reference and length: %s", err)
	}
	if isRef {
		objRefId := refVal >> 1
		return d.objectRefs[objRefId], nil
	}
	var trait Trait
	traitIsRef := (refVal & 0x01) == 0
	if traitIsRef {
		traitRef := refVal >> 1
		trait = d.traitRefs[traitRef]
	} else {
		trait = *NewTrait()
		trait.Externalizable = (refVal & 0x02) != 0
		trait.Dynamic = (refVal & 0x04) != 0
		var cls string
		cls, err = d.DecodeAmf3String(r, false)
		if err != nil {
			return result, fmt.Errorf("amf3 decode: unable to read trait type for object: %s", err)
		}
		trait.Type = cls
		propLength := refVal >> 3
		for i := uint32(0); i < propLength; i++ {
			tmp, err := d.DecodeAmf3String(r, false)
			if err != nil {
				return result, fmt.Errorf("amf3 decode: unable to read trait property for object: %s", err)
			}
			trait.Properties = append(trait.Properties, tmp)
		}
		d.traitRefs = append(d.traitRefs, trait)
	}
	d.objectRefs = append(d.objectRefs, result)
	if trait.Externalizable {
		switch trait.Type {
		case "DSA":  
			result, err = d.decodeAsyncMessageExt(r)
			if err != nil {
				return result, fmt.Errorf("amf3 decode: unable to decode dsa: %s", err)
			}
		case "DSK":  
			result, err = d.decodeAcknowledgeMessageExt(r)
			if err != nil {
				return result, fmt.Errorf("amf3 decode: unable to decode dsk: %s", err)
			}
		case "flex.messaging.io.ArrayCollection":
			result, err = d.decodeArrayCollection(r)
			if err != nil {
				return result, fmt.Errorf("amf3 decode: unable to decode ac: %s", err)
			}
			d.objectRefs = append(d.objectRefs, result)
		default:
			fn, ok := d.externalHandlers[trait.Type]
			if ok {
				result, err = fn(d, r)
				if err != nil {
					return result, fmt.Errorf("amf3 decode: unable to call external decoder for type %s: %s", trait.Type, err)
				}
			} else {
				return result, fmt.Errorf("amf3 decode: unable to decode external type %s, no handler", trait.Type)
			}
		}
		return result, err
	}
	var key string
	var val interface{}
	var obj Object
	obj = make(Object)
	for _, key = range trait.Properties {
		val, err = d.DecodeAmf3(r)
		if err != nil {
			return result, fmt.Errorf("amf3 decode: unable to decode object property: %s", err)
		}
		obj[key] = val
	}
	if trait.Dynamic {
		for {
			key, err = d.DecodeAmf3String(r, false)
			if err != nil {
				return result, fmt.Errorf("amf3 decode: unable to decode dynamic key: %s", err)
			}
			if key == "" {
				break
			}
			val, err = d.DecodeAmf3(r)
			if err != nil {
				return result, fmt.Errorf("amf3 decode: unable to decode dynamic value: %s", err)
			}
			obj[key] = val
		}
	}
	result = obj
	return
}
func (d *Decoder) DecodeAmf3Xml(r io.Reader, decodeMarker bool) (result string, err error) {
	if decodeMarker {
		var marker byte
		marker, err = ReadMarker(r)
		if err != nil {
			return "", err
		}
		if (marker != AMF3_XMLDOC_MARKER) && (marker != AMF3_XMLSTRING_MARKER) {
			return "", fmt.Errorf("decode assert marker failed: expected %v or %v, got %v", AMF3_XMLDOC_MARKER, AMF3_XMLSTRING_MARKER, marker)
		}
	}
	var isRef bool
	var refVal uint32
	isRef, refVal, err = d.decodeReferenceInt(r)
	if err != nil {
		return "", fmt.Errorf("amf3 decode: unable to decode xml reference and length: %s", err)
	}
	if isRef {
		var ok bool
		buf := d.objectRefs[refVal]
		result, ok = buf.(string)
		if ok != true {
			return "", fmt.Errorf("amf3 decode: cannot coerce object reference into xml string")
		}
		return
	}
	buf := make([]byte, refVal)
	_, err = r.Read(buf)
	if err != nil {
		return "", fmt.Errorf("amf3 decode: unable to read xml string: %s", err)
	}
	result = string(buf)
	if result != "" {
		d.objectRefs = append(d.objectRefs, result)
	}
	return
}