github.com/ergo-services/ergo@v1.999.224/etf/decode.go (about)

     1  package etf
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"math"
     7  	"math/big"
     8  	"reflect"
     9  
    10  	"github.com/ergo-services/ergo/lib"
    11  )
    12  
    13  // linked list for decoding complex types like list/map/tuple
    14  type stackElement struct {
    15  	parent   *stackElement
    16  	reg      *reflect.Value // used for registered types decoding
    17  	term     Term           //value
    18  	tmp      Term           // temporary value. used as a temporary storage for a key of map
    19  	i        int            // current
    20  	children int
    21  	termType byte
    22  
    23  	regKeyKind   reflect.Kind // we should align key and value types for maps (int*, float*)
    24  	regValueKind reflect.Kind // in case of decoding into value with registered type
    25  
    26  	strict bool // if encoding/decoding registered types must be strict
    27  }
    28  
    29  var (
    30  	biggestInt = big.NewInt(0xfffffffffffffff)
    31  	lowestInt  = big.NewInt(-0xfffffffffffffff)
    32  
    33  	termNil = make(List, 0)
    34  
    35  	errMalformedAtomUTF8      = fmt.Errorf("Malformed ETF. ettAtomUTF8")
    36  	errMalformedSmallAtomUTF8 = fmt.Errorf("Malformed ETF. ettSmallAtomUTF8")
    37  	errMalformedString        = fmt.Errorf("Malformed ETF. ettString")
    38  	errMalformedCacheRef      = fmt.Errorf("Malformed ETF. ettCacheRef")
    39  	errMalformedNewFloat      = fmt.Errorf("Malformed ETF. ettNewFloat")
    40  	errMalformedFloat         = fmt.Errorf("Malformed ETF. ettFloat")
    41  	errMalformedSmallInteger  = fmt.Errorf("Malformed ETF. ettSmallInteger")
    42  	errMalformedInteger       = fmt.Errorf("Malformed ETF. ettInteger")
    43  	errMalformedSmallBig      = fmt.Errorf("Malformed ETF. ettSmallBig")
    44  	errMalformedLargeBig      = fmt.Errorf("Malformed ETF. ettLargeBig")
    45  	errMalformedList          = fmt.Errorf("Malformed ETF. ettList")
    46  	errMalformedSmallTuple    = fmt.Errorf("Malformed ETF. ettSmallTuple")
    47  	errMalformedLargeTuple    = fmt.Errorf("Malformed ETF. ettLargeTuple")
    48  	errMalformedMap           = fmt.Errorf("Malformed ETF. ettMap")
    49  	errMalformedBinary        = fmt.Errorf("Malformed ETF. ettBinary")
    50  	errMalformedBitBinary     = fmt.Errorf("Malformed ETF. ettBitBinary")
    51  	errMalformedPid           = fmt.Errorf("Malformed ETF. ettPid")
    52  	errMalformedNewPid        = fmt.Errorf("Malformed ETF. ettNewPid")
    53  	errMalformedRef           = fmt.Errorf("Malformed ETF. ettNewRef")
    54  	errMalformedNewRef        = fmt.Errorf("Malformed ETF. ettNewerRef")
    55  	errMalformedPort          = fmt.Errorf("Malformed ETF. ettPort")
    56  	errMalformedNewPort       = fmt.Errorf("Malformed ETF. ettNewPort")
    57  	errMalformedFun           = fmt.Errorf("Malformed ETF. ettNewFun")
    58  	errMalformedExport        = fmt.Errorf("Malformed ETF. ettExport")
    59  	errMalformedUnknownType   = fmt.Errorf("Malformed ETF. unknown type")
    60  
    61  	errMalformed = fmt.Errorf("Malformed ETF")
    62  	errInternal  = fmt.Errorf("Internal error")
    63  )
    64  
    65  // DecodeOptions
    66  type DecodeOptions struct {
    67  	AtomMapping   *AtomMapping
    68  	FlagBigPidRef bool
    69  }
    70  
    71  // stackless implementation is speeding up decoding function up to x25 times
    72  
    73  // it might looks hard to understand the logic, but
    74  // there are only two stages
    75  // 1) Stage1: decoding basic types (atoms, strings, numbers...)
    76  // 2) Stage2: decoding list/tuples/maps and complex types like Port/Pid/Ref using linked list named 'stack'
    77  //
    78  // see comments within this function
    79  
    80  // Decode
    81  func Decode(packet []byte, cache []Atom, options DecodeOptions) (retTerm Term, retByte []byte, retErr error) {
    82  	var term Term
    83  	var stack *stackElement
    84  	var child *stackElement
    85  	var t byte
    86  	if lib.CatchPanic() {
    87  		defer func() {
    88  			// We should catch any panic happened during decoding the raw data.
    89  			// Some of the Erlang' types can not be supported in Golang.
    90  			// As an example: Erlang map with tuple as a key cause a panic
    91  			// in Golang runtime with message:
    92  			// 'panic: runtime error: hash of unhashable type etf.Tuple'
    93  			// The problem is in etf.Tuple type - it is interface type. At the same
    94  			// time Golang does support hashable key in map (like struct as a key),
    95  			// but it should be known implicitly. It means we can encode such kind
    96  			// of data, but can not to decode it back.
    97  			if r := recover(); r != nil {
    98  				retTerm = nil
    99  				retByte = nil
   100  				retErr = fmt.Errorf("%v", r)
   101  			}
   102  		}()
   103  	}
   104  
   105  	for {
   106  		child = nil
   107  		if len(packet) == 0 {
   108  			return nil, nil, errMalformed
   109  		}
   110  
   111  		t = packet[0]
   112  		packet = packet[1:]
   113  
   114  		// Stage 1: decoding base type. if have encountered List/Map/Tuple
   115  		// or complex type like Pid/Ref/Port:
   116  		//  save the state in stackElement and push it to the stack (basically,
   117  		//  we just append the new item to the linked list)
   118  		//
   119  
   120  		switch t {
   121  		case ettAtomUTF8, ettAtom:
   122  			if len(packet) < 2 {
   123  				return nil, nil, errMalformedAtomUTF8
   124  			}
   125  
   126  			n := binary.BigEndian.Uint16(packet)
   127  			if len(packet) < int(n+2) {
   128  				return nil, nil, errMalformedAtomUTF8
   129  			}
   130  
   131  			atom := Atom(packet[2 : n+2])
   132  			if len([]rune(atom)) > 255 {
   133  				return nil, nil, errMalformedAtomUTF8
   134  			}
   135  
   136  			// replace atom value if we have mapped value for it
   137  			if options.AtomMapping != nil {
   138  				options.AtomMapping.MutexIn.RLock()
   139  				if mapped, ok := options.AtomMapping.In[atom]; ok {
   140  					atom = mapped
   141  				}
   142  				options.AtomMapping.MutexIn.RUnlock()
   143  			}
   144  
   145  			term = atom
   146  			packet = packet[n+2:]
   147  
   148  		case ettSmallAtomUTF8, ettSmallAtom:
   149  			if len(packet) == 0 {
   150  				return nil, nil, errMalformedSmallAtomUTF8
   151  			}
   152  
   153  			n := int(packet[0])
   154  			if len(packet) < n+1 {
   155  				return nil, nil, errMalformedSmallAtomUTF8
   156  			}
   157  
   158  			switch Atom(packet[1 : n+1]) {
   159  			case "true":
   160  				term = true
   161  			case "false":
   162  				term = false
   163  			default:
   164  				atom := Atom(packet[1 : n+1])
   165  				// replace atom value if we have mapped value for it
   166  				if options.AtomMapping != nil {
   167  					options.AtomMapping.MutexIn.RLock()
   168  					if mapped, ok := options.AtomMapping.In[atom]; ok {
   169  						atom = mapped
   170  					}
   171  					options.AtomMapping.MutexIn.RUnlock()
   172  				}
   173  				term = atom
   174  			}
   175  			packet = packet[n+1:]
   176  
   177  		case ettString:
   178  			if len(packet) < 2 {
   179  				return nil, nil, errMalformedString
   180  			}
   181  
   182  			n := binary.BigEndian.Uint16(packet)
   183  			if len(packet) < int(n+2) {
   184  				return nil, nil, errMalformedString
   185  			}
   186  
   187  			term = string(packet[2 : n+2])
   188  			packet = packet[n+2:]
   189  
   190  		case ettCacheRef:
   191  			if len(packet) == 0 {
   192  				return nil, nil, errMalformedCacheRef
   193  			}
   194  
   195  			switch cache[int(packet[0])] {
   196  			case "true":
   197  				term = true
   198  			case "false":
   199  				term = false
   200  			default:
   201  				atom := cache[int(packet[0])]
   202  				// replace atom value if we have mapped value for it
   203  				if options.AtomMapping != nil {
   204  					options.AtomMapping.MutexIn.RLock()
   205  					if mapped, ok := options.AtomMapping.In[atom]; ok {
   206  						atom = mapped
   207  					}
   208  					options.AtomMapping.MutexIn.RUnlock()
   209  				}
   210  				term = atom
   211  			}
   212  			packet = packet[1:]
   213  
   214  		case ettSmallInteger:
   215  			if len(packet) == 0 {
   216  				return nil, nil, errMalformedSmallInteger
   217  			}
   218  
   219  			i := int(packet[0])
   220  			term = int(i)
   221  			packet = packet[1:]
   222  
   223  			if stack == nil {
   224  				break
   225  			}
   226  
   227  			t := stack.regKeyKind
   228  			if stack.i&0x01 == 1 {
   229  				t = stack.regValueKind
   230  			}
   231  			switch t {
   232  			case reflect.Invalid:
   233  				// not registered type
   234  				break
   235  			case reflect.Int64:
   236  				term = int64(i)
   237  			case reflect.Int:
   238  				term = i
   239  			case reflect.Int8:
   240  				if i > math.MaxInt8 || i < math.MinInt8 {
   241  					panic("overflows int8")
   242  				}
   243  				term = int8(i)
   244  			case reflect.Int16:
   245  				term = int16(i)
   246  			case reflect.Int32:
   247  				term = int32(i)
   248  			case reflect.Uint:
   249  				term = uint(i)
   250  			case reflect.Uint8:
   251  				term = uint8(i)
   252  			case reflect.Uint16:
   253  				term = uint16(i)
   254  			case reflect.Uint32:
   255  				term = uint32(i)
   256  			default:
   257  				panic("destination value is not an int* or overflows")
   258  			}
   259  
   260  		case ettInteger:
   261  			if len(packet) < 4 {
   262  				return nil, nil, errMalformedInteger
   263  			}
   264  
   265  			// negatives are encoded as ettSmallBig so the value shouldn't be
   266  			// greater int32
   267  			i := int32(binary.BigEndian.Uint32(packet[:4]))
   268  			term = int64(i)
   269  			packet = packet[4:]
   270  
   271  			if stack == nil {
   272  				break
   273  			}
   274  
   275  			t := stack.regKeyKind
   276  			if stack.i&0x01 == 1 {
   277  				t = stack.regValueKind
   278  			}
   279  			switch t {
   280  			case reflect.Invalid:
   281  				// not registered type
   282  				break
   283  			case reflect.Int64:
   284  				term = int64(i)
   285  			case reflect.Int:
   286  				term = int(i)
   287  			case reflect.Int8:
   288  				if i > math.MaxInt8 || i < math.MinInt8 {
   289  					panic("overflows int8")
   290  				}
   291  				term = int8(i)
   292  			case reflect.Int16:
   293  				if i > math.MaxInt16 || i < math.MinInt16 {
   294  					panic("overflows int16")
   295  				}
   296  				term = int16(i)
   297  			case reflect.Int32:
   298  				term = i
   299  			case reflect.Uint:
   300  				term = uint(i)
   301  			case reflect.Uint8:
   302  				if i > math.MaxUint8 {
   303  					panic("overflows uint")
   304  				}
   305  				term = uint8(i)
   306  			case reflect.Uint16:
   307  				if i > math.MaxUint16 {
   308  					panic("overflows uint")
   309  				}
   310  				term = uint16(i)
   311  			case reflect.Uint32:
   312  				term = uint32(i)
   313  			default:
   314  				panic("destination value is not an int* or overflows")
   315  			}
   316  
   317  		case ettSmallBig:
   318  			if len(packet) == 0 {
   319  				return nil, nil, errMalformedSmallBig
   320  			}
   321  
   322  			n := packet[0]
   323  			negative := packet[1] == 1 // sign
   324  
   325  			///// this block improves performance at least 4 times
   326  			if n < 9 { // treat as an int64/uint64
   327  				le8 := make([]byte, 8)
   328  				copy(le8, packet[2:n+2])
   329  				smallBig := binary.LittleEndian.Uint64(le8)
   330  				if negative {
   331  					term = int64(-smallBig)
   332  				} else {
   333  					if smallBig > math.MaxInt64 {
   334  						term = uint64(smallBig)
   335  					} else {
   336  						term = int64(smallBig)
   337  					}
   338  				}
   339  				packet = packet[n+2:]
   340  
   341  				if stack == nil {
   342  					break
   343  				}
   344  
   345  				t := stack.regKeyKind
   346  				if stack.i&0x01 == 1 {
   347  					t = stack.regValueKind
   348  				}
   349  				switch t {
   350  				case reflect.Invalid:
   351  					// not registered type
   352  					break
   353  				case reflect.Int64:
   354  					if negative {
   355  						if smallBig > -math.MinInt64 {
   356  							panic("overflows int64")
   357  						}
   358  						term = int64(-smallBig)
   359  					} else {
   360  						if smallBig > math.MaxInt64 {
   361  							panic("overflows int64")
   362  						}
   363  						term = int64(smallBig)
   364  					}
   365  				case reflect.Int:
   366  					if negative {
   367  						if smallBig > -math.MinInt {
   368  							panic("overflows int")
   369  						}
   370  						term = int(-smallBig)
   371  					} else {
   372  						if smallBig > math.MaxInt {
   373  							panic("overflows int")
   374  						}
   375  						term = int(smallBig)
   376  					}
   377  				case reflect.Int8:
   378  					if negative {
   379  						if smallBig > -math.MinInt8 {
   380  							panic("overflows int8")
   381  						}
   382  						term = int8(-smallBig)
   383  					} else {
   384  						if smallBig > math.MaxInt8 {
   385  							panic("overflows int8")
   386  						}
   387  						term = int8(smallBig)
   388  					}
   389  				case reflect.Int16:
   390  					if negative {
   391  						if smallBig > -math.MinInt16 {
   392  							panic("overflows int16")
   393  						}
   394  						term = int16(-smallBig)
   395  					} else {
   396  						if smallBig > math.MaxInt16 {
   397  							panic("overflows int16")
   398  						}
   399  						term = int16(smallBig)
   400  					}
   401  				case reflect.Int32:
   402  					if negative {
   403  						if smallBig > -math.MinInt32 {
   404  							panic("overflows int32")
   405  						}
   406  						term = int32(-smallBig)
   407  					} else {
   408  						if smallBig > math.MaxInt32 {
   409  							panic("overflows int32")
   410  						}
   411  						term = int32(smallBig)
   412  					}
   413  				case reflect.Uint:
   414  					if negative {
   415  						panic("signed integer value")
   416  					}
   417  					if smallBig > math.MaxUint {
   418  						panic("overflows uint")
   419  					}
   420  					term = uint(smallBig)
   421  				case reflect.Uint8:
   422  					if negative {
   423  						panic("signed integer value")
   424  					}
   425  					if smallBig > math.MaxUint8 {
   426  						panic("overflows uint8")
   427  					}
   428  					term = uint8(smallBig)
   429  				case reflect.Uint16:
   430  					if negative {
   431  						panic("signed integer value")
   432  					}
   433  					if smallBig > math.MaxUint16 {
   434  						panic("overflows uint16")
   435  					}
   436  					term = uint16(smallBig)
   437  				case reflect.Uint32:
   438  					if negative {
   439  						panic("signed integer value")
   440  					}
   441  					if smallBig > math.MaxUint32 {
   442  						panic("overflows uint32")
   443  					}
   444  					term = uint32(smallBig)
   445  				default:
   446  					panic("destination value is not an int* or overflows")
   447  				}
   448  
   449  				break
   450  			}
   451  			/////
   452  
   453  			if len(packet) < int(n+2) {
   454  				return nil, nil, errMalformedSmallBig
   455  			}
   456  			bytes := packet[2 : n+2]
   457  
   458  			// encoded as a little endian. convert it to the big endian order
   459  			l := len(bytes)
   460  			for i := 0; i < l/2; i++ {
   461  				bytes[i], bytes[l-1-i] = bytes[l-1-i], bytes[i]
   462  			}
   463  
   464  			bigInt := &big.Int{}
   465  			bigInt.SetBytes(bytes)
   466  			if negative {
   467  				bigInt = bigInt.Neg(bigInt)
   468  			}
   469  
   470  			// try int and int64
   471  			if bigInt.Cmp(biggestInt) < 0 && bigInt.Cmp(lowestInt) > 0 {
   472  				term = bigInt.Int64()
   473  				packet = packet[n+2:]
   474  				break
   475  			}
   476  
   477  			term = bigInt
   478  			packet = packet[n+2:]
   479  
   480  		case ettLargeBig:
   481  			if len(packet) < 256 { // must be longer than ettSmallBig
   482  				return nil, nil, errMalformedLargeBig
   483  			}
   484  
   485  			n := binary.BigEndian.Uint32(packet[:4])
   486  			negative := packet[4] == 1 // sign
   487  
   488  			if len(packet) < int(n+5) {
   489  				return nil, nil, errMalformedLargeBig
   490  			}
   491  			bytes := packet[5 : n+5]
   492  
   493  			// encoded as a little endian. convert it to the big endian order
   494  			l := len(bytes)
   495  			for i := 0; i < l/2; i++ {
   496  				bytes[i], bytes[l-1-i] = bytes[l-1-i], bytes[i]
   497  			}
   498  
   499  			bigInt := &big.Int{}
   500  			bigInt.SetBytes(bytes)
   501  			if negative {
   502  				bigInt = bigInt.Neg(bigInt)
   503  			}
   504  
   505  			term = bigInt
   506  			packet = packet[n+5:]
   507  
   508  		case ettList:
   509  			if len(packet) < 4 {
   510  				return nil, nil, errMalformedList
   511  			}
   512  
   513  			n := binary.BigEndian.Uint32(packet[:4])
   514  			if n == 0 {
   515  				// must be encoded as ettNil
   516  				return nil, nil, errMalformedList
   517  			}
   518  
   519  			term = make(List, n+1)
   520  			packet = packet[4:]
   521  			child = &stackElement{
   522  				parent:   stack,
   523  				termType: ettList,
   524  				term:     term,
   525  				children: int(n + 1),
   526  			}
   527  
   528  		case ettSmallTuple:
   529  			if len(packet) == 0 {
   530  				return nil, nil, errMalformedSmallTuple
   531  			}
   532  
   533  			n := packet[0]
   534  			packet = packet[1:]
   535  			term = make(Tuple, n)
   536  
   537  			if n == 0 {
   538  				break
   539  			}
   540  
   541  			child = &stackElement{
   542  				parent:   stack,
   543  				termType: ettSmallTuple,
   544  				term:     term,
   545  				children: int(n),
   546  			}
   547  
   548  		case ettLargeTuple:
   549  			if len(packet) < 4 {
   550  				return nil, nil, errMalformedLargeTuple
   551  			}
   552  
   553  			n := binary.BigEndian.Uint32(packet[:4])
   554  			packet = packet[4:]
   555  			term = make(Tuple, n)
   556  
   557  			if n == 0 {
   558  				break
   559  			}
   560  
   561  			child = &stackElement{
   562  				parent:   stack,
   563  				termType: ettLargeTuple,
   564  				term:     term,
   565  				children: int(n),
   566  			}
   567  
   568  		case ettMap:
   569  			if len(packet) < 4 {
   570  				return nil, nil, errMalformedMap
   571  			}
   572  
   573  			n := binary.BigEndian.Uint32(packet[:4])
   574  			packet = packet[4:]
   575  			term = make(Map)
   576  
   577  			if n == 0 {
   578  				break
   579  			}
   580  
   581  			child = &stackElement{
   582  				parent:   stack,
   583  				termType: ettMap,
   584  				term:     term,
   585  				children: int(n) * 2,
   586  			}
   587  
   588  		case ettBinary:
   589  			if len(packet) < 4 {
   590  				return nil, nil, errMalformedBinary
   591  			}
   592  
   593  			n := binary.BigEndian.Uint32(packet)
   594  			if len(packet) < int(n+4) {
   595  				return nil, nil, errMalformedBinary
   596  			}
   597  
   598  			b := make([]byte, n)
   599  			copy(b, packet[4:n+4])
   600  
   601  			term = b
   602  			packet = packet[n+4:]
   603  
   604  		case ettNil:
   605  			// for registered types we should use a nil value
   606  			// otherwise - treat it as an empty list
   607  			if stack.reg != nil {
   608  				term = nil
   609  			} else {
   610  				term = termNil
   611  			}
   612  
   613  		case ettPid, ettNewPid:
   614  			child = &stackElement{
   615  				parent:   stack,
   616  				termType: t,
   617  				children: 1,
   618  			}
   619  
   620  		case ettNewRef, ettNewerRef:
   621  			if len(packet) < 2 {
   622  				return nil, nil, errMalformedRef
   623  			}
   624  
   625  			l := binary.BigEndian.Uint16(packet[:2])
   626  			packet = packet[2:]
   627  
   628  			child = &stackElement{
   629  				parent:   stack,
   630  				termType: t,
   631  				children: 1,
   632  				tmp:      l, // save length in temporary place of the stack element
   633  			}
   634  
   635  		case ettExport:
   636  			child = &stackElement{
   637  				parent:   stack,
   638  				termType: t,
   639  				term:     Export{},
   640  				children: 3,
   641  			}
   642  
   643  		case ettNewFun:
   644  			var unique [16]byte
   645  
   646  			if len(packet) < 32 {
   647  				return nil, nil, errMalformedFun
   648  			}
   649  
   650  			copy(unique[:], packet[5:21])
   651  			l := binary.BigEndian.Uint32(packet[25:29])
   652  
   653  			fun := Function{
   654  				Arity:    packet[4],
   655  				Unique:   unique,
   656  				Index:    binary.BigEndian.Uint32(packet[21:25]),
   657  				FreeVars: make([]Term, l),
   658  			}
   659  
   660  			child = &stackElement{
   661  				parent:   stack,
   662  				termType: t,
   663  				term:     fun,
   664  				children: 4 + int(l),
   665  			}
   666  			packet = packet[29:]
   667  
   668  		case ettPort, ettNewPort:
   669  			child = &stackElement{
   670  				parent:   stack,
   671  				termType: t,
   672  				children: 1,
   673  			}
   674  
   675  		case ettBitBinary:
   676  			if len(packet) < 6 {
   677  				return nil, nil, errMalformedBitBinary
   678  			}
   679  
   680  			n := binary.BigEndian.Uint32(packet)
   681  			bits := uint(packet[4])
   682  
   683  			b := make([]byte, n)
   684  			copy(b, packet[5:n+5])
   685  			b[n-1] = b[n-1] >> (8 - bits)
   686  
   687  			term = b
   688  			packet = packet[n+5:]
   689  
   690  		case ettNewFloat:
   691  			if len(packet) < 8 {
   692  				return nil, nil, errMalformedNewFloat
   693  			}
   694  			bits := binary.BigEndian.Uint64(packet[:8])
   695  
   696  			f := math.Float64frombits(bits)
   697  			term = f
   698  			packet = packet[8:]
   699  
   700  			if stack == nil {
   701  				break
   702  			}
   703  
   704  			t := stack.regKeyKind
   705  			if stack.i&0x01 == 1 {
   706  				t = stack.regValueKind
   707  			}
   708  			switch t {
   709  			case reflect.Invalid:
   710  				// not registered type
   711  				break
   712  			case reflect.Float64:
   713  				break
   714  			case reflect.Float32:
   715  				if f > math.MaxFloat32 {
   716  					panic("overflows float32")
   717  				}
   718  				term = float32(f)
   719  			default:
   720  				panic("destination value is not an float* or overflows")
   721  			}
   722  
   723  		case ettFloat:
   724  			if len(packet) < 31 {
   725  				return nil, nil, errMalformedFloat
   726  			}
   727  
   728  			var f float64
   729  			if r, err := fmt.Sscanf(string(packet[:31]), "%f", &f); err != nil || r != 1 {
   730  				return nil, nil, errMalformedFloat
   731  			}
   732  			term = f
   733  			packet = packet[31:]
   734  
   735  			if stack == nil {
   736  				break
   737  			}
   738  
   739  			t := stack.regKeyKind
   740  			if stack.i&0x01 == 1 {
   741  				t = stack.regValueKind
   742  			}
   743  			switch t {
   744  			case reflect.Invalid:
   745  				// not registered type
   746  				break
   747  			case reflect.Float64:
   748  				break
   749  			case reflect.Float32:
   750  				if f > math.MaxFloat32 {
   751  					panic("overflows float32")
   752  				}
   753  				term = float32(f)
   754  			default:
   755  				panic("destination value is not an float* or overflows")
   756  			}
   757  
   758  		default:
   759  			term = nil
   760  			return nil, nil, errMalformedUnknownType
   761  		}
   762  
   763  		// it was a single element
   764  		if stack == nil && child == nil {
   765  			break
   766  		}
   767  
   768  		// decoding child item of List/Map/Tuple/Pid/Ref/Port/... going deeper
   769  		if child != nil {
   770  			stack = child
   771  			continue
   772  		}
   773  
   774  		// Stage 2
   775  	processStack:
   776  		if stack != nil {
   777  			var field reflect.Value
   778  			var set_field bool
   779  
   780  			switch stack.termType {
   781  			case ettList:
   782  				if stack.i == 0 {
   783  					// if the first value is atom, check for the registered type
   784  					if typeName, isAtom := term.(Atom); isAtom == true {
   785  						registered.RLock()
   786  						r, found := registered.typesDec[typeName]
   787  						registered.RUnlock()
   788  						if found == true {
   789  							switch r.rtype.Kind() {
   790  							case reflect.Slice:
   791  								reg := reflect.MakeSlice(r.rtype, stack.children-2, stack.children-1)
   792  								stack.reg = &reg
   793  							case reflect.Array:
   794  								reg := reflect.Indirect(reflect.New(r.rtype))
   795  								stack.reg = &reg
   796  							default:
   797  								if r.strict {
   798  									panic("destination value of registered type is not a slice/array")
   799  								}
   800  							}
   801  							stack.strict = r.strict
   802  							if r.strict == false {
   803  								stack.term.(List)[stack.i] = term
   804  							}
   805  							stack.i++
   806  							break
   807  						}
   808  					}
   809  				}
   810  
   811  				if stack.reg != nil {
   812  					if stack.i+1 == stack.children {
   813  						if t != ettNil {
   814  							x := reflect.Append(*stack.reg, reflect.ValueOf(term))
   815  							stack.reg = &x
   816  						}
   817  					} else {
   818  						set_field = true
   819  						field = stack.reg.Index(stack.i - 1)
   820  					}
   821  
   822  					if stack.strict == true {
   823  						stack.i++
   824  						break
   825  					}
   826  				}
   827  
   828  				stack.term.(List)[stack.i] = term
   829  				stack.i++
   830  				// remove the last element for proper list (its ettNil)
   831  				if stack.i == stack.children && t == ettNil {
   832  					stack.term = stack.term.(List)[:stack.i-1]
   833  				}
   834  
   835  			case ettSmallTuple, ettLargeTuple:
   836  
   837  				if stack.i == 0 {
   838  					// if the first value is atom, check for the registered type
   839  					if typeName, isAtom := term.(Atom); isAtom == true {
   840  						registered.RLock()
   841  						r, found := registered.typesDec[typeName]
   842  						registered.RUnlock()
   843  						if found == true {
   844  							reg := reflect.Indirect(reflect.New(r.rtype))
   845  							stack.reg = &reg
   846  							stack.strict = r.strict
   847  							if r.strict == false {
   848  								stack.term.(Tuple)[stack.i] = term
   849  							}
   850  							stack.i++
   851  							break
   852  						}
   853  					}
   854  				}
   855  
   856  				if stack.reg != nil {
   857  					set_field = true
   858  					field = stack.reg.Field(stack.i - 1)
   859  					if stack.strict == true {
   860  						stack.i++
   861  						break
   862  					}
   863  				}
   864  				stack.term.(Tuple)[stack.i] = term
   865  				stack.i++
   866  
   867  			case ettMap:
   868  				if stack.i == 0 {
   869  					// if the first key is atom, check for the registered type
   870  					if typeName, isAtom := term.(Atom); isAtom == true {
   871  						registered.RLock()
   872  						r, found := registered.typesDec[typeName]
   873  						registered.RUnlock()
   874  						if found == true {
   875  							if r.rtype.Kind() == reflect.Map {
   876  								reg := reflect.MakeMapWithSize(r.rtype, stack.children/2)
   877  								if r.rtype.Key().Kind() != reflect.Interface {
   878  									stack.regKeyKind = r.rtype.Key().Kind()
   879  								}
   880  								if r.rtype.Elem().Kind() != reflect.Interface {
   881  									stack.regValueKind = r.rtype.Elem().Kind()
   882  								}
   883  								stack.reg = &reg
   884  							} else {
   885  								if r.strict {
   886  									panic("destination value of registered type is not a map")
   887  								}
   888  							}
   889  							stack.strict = r.strict
   890  							if r.strict == false {
   891  								if stack.i&0x01 == 0x01 { // a value
   892  									stack.term.(Map)[stack.tmp] = term
   893  								} else {
   894  									stack.tmp = term
   895  								}
   896  							}
   897  							stack.i++
   898  							break
   899  						}
   900  					}
   901  				}
   902  				if stack.i == 1 && stack.reg != nil && stack.strict == true {
   903  					// skip it. the value of the key which is the registered type
   904  					stack.i++
   905  					break
   906  
   907  				}
   908  				if stack.i&0x01 == 0x01 { // a value
   909  					if stack.i > 1 && stack.reg != nil {
   910  						set_field = true
   911  						field = *stack.reg
   912  					}
   913  					// Erlang can use any value as a key in the map.
   914  					// OTP 25 sends a message to the 'global_name_server' process
   915  					// with etf.Tuple as a key in the map, so it caused a panic
   916  					// and this connection is dropping.
   917  					switch stack.tmp.(type) {
   918  					case Tuple:
   919  						lib.Warning("Erlang sent a etf.Tuple as a map key: %#v => %#v. Ignored this item. Ergo doesn't support it.", stack.tmp, term)
   920  					default:
   921  						stack.term.(Map)[stack.tmp] = term
   922  					}
   923  					stack.i++
   924  					break
   925  				}
   926  
   927  				// a key
   928  				stack.tmp = term
   929  				stack.i++
   930  
   931  			case ettPid:
   932  				if len(packet) < 9 {
   933  					return nil, nil, errMalformedPid
   934  				}
   935  
   936  				name, ok := term.(Atom)
   937  				if !ok {
   938  					return nil, nil, errMalformedPid
   939  				}
   940  				pid := Pid{
   941  					Node: name,
   942  					// Same as NEW_PID_EXT except the Creation field is
   943  					// only one byte and only two bits are significant,
   944  					// the rest are to be 0.
   945  					Creation: uint32(packet[8]) & 3,
   946  				}
   947  
   948  				id := uint64(binary.BigEndian.Uint32(packet[:4]))
   949  				serial := uint64(binary.BigEndian.Uint32(packet[4:8]))
   950  				if options.FlagBigPidRef {
   951  					id = id | (serial << 32)
   952  				} else {
   953  					// id 15 bits only 2**15 - 1 = 32767
   954  					// serial 13 bits only 2**13 - 1 = 8191
   955  					id = (id & 32767) | ((serial & 8191) << 15)
   956  				}
   957  				pid.ID = id
   958  
   959  				packet = packet[9:]
   960  				stack.term = pid
   961  				stack.i++
   962  
   963  			case ettNewPid:
   964  				if len(packet) < 12 {
   965  					return nil, nil, errMalformedNewPid
   966  				}
   967  
   968  				name, ok := term.(Atom)
   969  				if !ok {
   970  					return nil, nil, errMalformedPid
   971  				}
   972  
   973  				id := uint64(binary.BigEndian.Uint32(packet[:4]))
   974  				serial := uint64(binary.BigEndian.Uint32(packet[4:8]))
   975  				pid := Pid{
   976  					Node:     name,
   977  					Creation: binary.BigEndian.Uint32(packet[8:12]),
   978  				}
   979  				if options.FlagBigPidRef {
   980  					id = id | (serial << 32)
   981  				} else {
   982  					// id 15 bits only 2**15 - 1 = 32767
   983  					// serial 13 bits only 2**13 - 1 = 8191
   984  					id = (id & 32767) | ((serial & 8191) << 15)
   985  				}
   986  				pid.ID = id
   987  
   988  				packet = packet[12:]
   989  				stack.term = pid
   990  				stack.i++
   991  
   992  			case ettNewRef:
   993  				var id uint32
   994  				name, ok := term.(Atom)
   995  				if !ok {
   996  					return nil, nil, errMalformedRef
   997  				}
   998  
   999  				l := stack.tmp.(uint16)
  1000  				if l > 5 {
  1001  					return nil, nil, errMalformedRef
  1002  				}
  1003  				if l > 3 && !options.FlagBigPidRef {
  1004  					return nil, nil, errMalformedRef
  1005  				}
  1006  				stack.tmp = nil
  1007  				expectedLength := int(1 + l*4)
  1008  
  1009  				if len(packet) < expectedLength {
  1010  					return nil, nil, errMalformedRef
  1011  				}
  1012  
  1013  				ref := Ref{
  1014  					Node:     name,
  1015  					Creation: uint32(packet[0]),
  1016  				}
  1017  				packet = packet[1:]
  1018  
  1019  				for i := 0; i < int(l); i++ {
  1020  					// In the first word (4 bytes) of ID, only 18 bits
  1021  					// are significant, the rest must be 0.
  1022  					if i == 0 {
  1023  						// 2**18 - 1 = 262143
  1024  						id = binary.BigEndian.Uint32(packet[:4]) & 262143
  1025  					} else {
  1026  						id = binary.BigEndian.Uint32(packet[:4])
  1027  					}
  1028  					ref.ID[i] = id
  1029  					packet = packet[4:]
  1030  				}
  1031  
  1032  				stack.term = ref
  1033  				stack.i++
  1034  
  1035  			case ettNewerRef:
  1036  				var id uint32
  1037  				name, ok := term.(Atom)
  1038  				if !ok {
  1039  					return nil, nil, errMalformedRef
  1040  				}
  1041  
  1042  				l := stack.tmp.(uint16)
  1043  				if l > 5 {
  1044  					return nil, nil, errMalformedRef
  1045  				}
  1046  				if l > 3 && !options.FlagBigPidRef {
  1047  					return nil, nil, errMalformedRef
  1048  				}
  1049  				stack.tmp = nil
  1050  				expectedLength := int(4 + l*4)
  1051  
  1052  				if len(packet) < expectedLength {
  1053  					return nil, nil, errMalformedRef
  1054  				}
  1055  
  1056  				ref := Ref{
  1057  					Node:     name,
  1058  					Creation: binary.BigEndian.Uint32(packet[:4]),
  1059  				}
  1060  				packet = packet[4:]
  1061  
  1062  				for i := 0; i < int(l); i++ {
  1063  					// In the first word (4 bytes) of ID, only 18 bits
  1064  					// are significant, the rest must be 0.
  1065  					if i == 0 {
  1066  						// 2**18 - 1 = 262143
  1067  						id = binary.BigEndian.Uint32(packet[:4]) & 262143
  1068  					} else {
  1069  						id = binary.BigEndian.Uint32(packet[:4])
  1070  					}
  1071  					ref.ID[i] = id
  1072  					packet = packet[4:]
  1073  				}
  1074  
  1075  				stack.term = ref
  1076  				stack.i++
  1077  
  1078  			case ettPort:
  1079  				if len(packet) < 5 {
  1080  					return nil, nil, errMalformedPort
  1081  				}
  1082  
  1083  				name, ok := term.(Atom)
  1084  				if !ok {
  1085  					return nil, nil, errMalformedPort
  1086  				}
  1087  
  1088  				port := Port{
  1089  					Node:     name,
  1090  					ID:       binary.BigEndian.Uint32(packet[:4]),
  1091  					Creation: uint32(packet[4]),
  1092  				}
  1093  
  1094  				packet = packet[5:]
  1095  				stack.term = port
  1096  				stack.i++
  1097  
  1098  			case ettNewPort:
  1099  				if len(packet) < 8 {
  1100  					return nil, nil, errMalformedNewPort
  1101  				}
  1102  
  1103  				name, ok := term.(Atom)
  1104  				if !ok {
  1105  					return nil, nil, errMalformedNewPort
  1106  				}
  1107  
  1108  				port := Port{
  1109  					Node:     name,
  1110  					ID:       binary.BigEndian.Uint32(packet[:4]),
  1111  					Creation: binary.BigEndian.Uint32(packet[4:8]),
  1112  				}
  1113  
  1114  				packet = packet[8:]
  1115  				stack.term = port
  1116  				stack.i++
  1117  
  1118  			case ettNewFun:
  1119  				fun := stack.term.(Function)
  1120  				switch stack.i {
  1121  				case 0:
  1122  					// Module
  1123  					module, ok := term.(Atom)
  1124  					if !ok {
  1125  						return nil, nil, errMalformedFun
  1126  					}
  1127  					fun.Module = module
  1128  
  1129  				case 1:
  1130  					// OldIndex
  1131  					oldindex, ok := term.(int)
  1132  					if !ok {
  1133  						return nil, nil, errMalformedFun
  1134  					}
  1135  					fun.OldIndex = uint32(oldindex)
  1136  
  1137  				case 2:
  1138  					// OldUnique
  1139  					olduniq, ok := term.(int64)
  1140  					if !ok {
  1141  						return nil, nil, errMalformedFun
  1142  					}
  1143  					fun.OldUnique = uint32(olduniq)
  1144  
  1145  				case 3:
  1146  					// Pid
  1147  					pid, ok := term.(Pid)
  1148  					if !ok {
  1149  						return nil, nil, errMalformedFun
  1150  					}
  1151  					fun.Pid = pid
  1152  
  1153  				default:
  1154  					if len(fun.FreeVars) < (stack.i-4)+1 {
  1155  						return nil, nil, errMalformedFun
  1156  					}
  1157  					fun.FreeVars[stack.i-4] = term
  1158  				}
  1159  
  1160  				stack.term = fun
  1161  				stack.i++
  1162  
  1163  			case ettExport:
  1164  				exp := stack.term.(Export)
  1165  				switch stack.i {
  1166  				case 0:
  1167  					module, ok := term.(Atom)
  1168  					if !ok {
  1169  						return nil, nil, errMalformedExport
  1170  					}
  1171  					exp.Module = module
  1172  
  1173  				case 1:
  1174  					function, ok := term.(Atom)
  1175  					if !ok {
  1176  						return nil, nil, errMalformedExport
  1177  					}
  1178  					exp.Function = function
  1179  
  1180  				case 2:
  1181  					arity, ok := term.(int)
  1182  					if !ok {
  1183  						return nil, nil, errMalformedExport
  1184  					}
  1185  					exp.Arity = arity
  1186  
  1187  				default:
  1188  					return nil, nil, errMalformedExport
  1189  
  1190  				}
  1191  
  1192  			default:
  1193  				return nil, nil, errInternal
  1194  			}
  1195  
  1196  			if field.Kind() == reflect.Ptr {
  1197  				pfield := reflect.New(field.Type().Elem())
  1198  				field.Set(pfield)
  1199  				field = pfield.Elem()
  1200  			}
  1201  
  1202  			if set_field && term != nil {
  1203  				switch field.Kind() {
  1204  				case reflect.Int8:
  1205  					switch v := term.(type) {
  1206  					case int:
  1207  						if v > math.MaxInt8 || v < math.MinInt8 {
  1208  							// overflows
  1209  							if stack.strict {
  1210  								panic("overflows int8")
  1211  							}
  1212  							stack.reg = nil
  1213  							break
  1214  						}
  1215  						field.SetInt(int64(v))
  1216  					case int64:
  1217  						if v > math.MaxInt8 || v < math.MinInt8 {
  1218  							// overflows
  1219  							if stack.strict {
  1220  								panic("overflows int8")
  1221  							}
  1222  							stack.reg = nil
  1223  							break
  1224  						}
  1225  						field.SetInt(v)
  1226  					case uint64:
  1227  						if v > math.MaxInt8 {
  1228  							// overflows
  1229  							if stack.strict {
  1230  								panic("overflows int8")
  1231  							}
  1232  							stack.reg = nil
  1233  							break
  1234  						}
  1235  						field.SetInt(int64(v))
  1236  					default:
  1237  						if stack.strict {
  1238  							panic("wrong int8 value")
  1239  						}
  1240  						stack.reg = nil
  1241  					}
  1242  
  1243  				case reflect.Int16:
  1244  					switch v := term.(type) {
  1245  					case int:
  1246  						if v > math.MaxInt16 || v < math.MinInt16 {
  1247  							// overflows
  1248  							if stack.strict {
  1249  								panic("overflows int16")
  1250  							}
  1251  							stack.reg = nil
  1252  							break
  1253  						}
  1254  						field.SetInt(int64(v))
  1255  					case int64:
  1256  						if v > math.MaxInt16 || v < math.MinInt16 {
  1257  							// overflows
  1258  							if stack.strict {
  1259  								panic("overflows int16")
  1260  							}
  1261  							stack.reg = nil
  1262  							break
  1263  						}
  1264  						field.SetInt(v)
  1265  					case uint64:
  1266  						if v > math.MaxInt16 {
  1267  							// overflows
  1268  							if stack.strict {
  1269  								panic("overflows int16")
  1270  							}
  1271  							stack.reg = nil
  1272  							break
  1273  						}
  1274  						field.SetInt(int64(v))
  1275  					default:
  1276  						if stack.strict {
  1277  							panic("wrong int16 value")
  1278  						}
  1279  						stack.reg = nil
  1280  					}
  1281  
  1282  				case reflect.Int32:
  1283  					switch v := term.(type) {
  1284  					case int:
  1285  						if v > math.MaxInt32 || v < math.MinInt32 {
  1286  							// overflows
  1287  							if stack.strict {
  1288  								panic("overflows int32")
  1289  							}
  1290  							stack.reg = nil
  1291  							break
  1292  						}
  1293  						field.SetInt(int64(v))
  1294  					case int64:
  1295  						if v > math.MaxInt32 || v < math.MinInt32 {
  1296  							// overflows
  1297  							if stack.strict {
  1298  								panic("overflows int32")
  1299  							}
  1300  							stack.reg = nil
  1301  							break
  1302  						}
  1303  						field.SetInt(v)
  1304  					case uint64:
  1305  						if v > math.MaxInt32 {
  1306  							// overflows
  1307  							if stack.strict {
  1308  								panic("overflows int32")
  1309  							}
  1310  							stack.reg = nil
  1311  							break
  1312  						}
  1313  						field.SetInt(int64(v))
  1314  					default:
  1315  						if stack.strict {
  1316  							panic("wrong int32 value")
  1317  						}
  1318  						stack.reg = nil
  1319  					}
  1320  				case reflect.Int64:
  1321  					switch v := term.(type) {
  1322  					case int:
  1323  						field.SetInt(int64(v))
  1324  					case int64:
  1325  						field.SetInt(v)
  1326  					case uint64:
  1327  						if v > math.MaxInt64 {
  1328  							// overflows
  1329  							if stack.strict {
  1330  								panic("overflows int64")
  1331  							}
  1332  							stack.reg = nil
  1333  							break
  1334  						}
  1335  						field.SetInt(int64(v))
  1336  					default:
  1337  						if stack.strict {
  1338  							panic("wrong int64 value")
  1339  						}
  1340  						stack.reg = nil
  1341  					}
  1342  				case reflect.Int:
  1343  					switch v := term.(type) {
  1344  					case int:
  1345  						field.SetInt(int64(v))
  1346  					case int64:
  1347  						if v > math.MaxInt {
  1348  							// overflows
  1349  							if stack.strict {
  1350  								panic("overflows int")
  1351  							}
  1352  							stack.reg = nil
  1353  							break
  1354  						}
  1355  						field.SetInt(v)
  1356  					case uint64:
  1357  						if v > math.MaxInt {
  1358  							// overflows
  1359  							if stack.strict {
  1360  								panic("overflows int")
  1361  							}
  1362  							stack.reg = nil
  1363  							break
  1364  						}
  1365  						field.SetInt(int64(v))
  1366  					default:
  1367  						if stack.strict {
  1368  							panic("wrong int value")
  1369  						}
  1370  						stack.reg = nil
  1371  					}
  1372  
  1373  				case reflect.Uint8:
  1374  					switch v := term.(type) {
  1375  					case int:
  1376  						if int64(v) > math.MaxUint8 || v < 0 {
  1377  							// overflows
  1378  							if stack.strict {
  1379  								panic("overflows uint8")
  1380  							}
  1381  							stack.reg = nil
  1382  							break
  1383  						}
  1384  						field.SetUint(uint64(v))
  1385  					case int64:
  1386  						if v > math.MaxUint8 || v < 0 {
  1387  							// overflows
  1388  							if stack.strict {
  1389  								panic("overflows uint8")
  1390  							}
  1391  							stack.reg = nil
  1392  							break
  1393  						}
  1394  						field.SetUint(uint64(v))
  1395  					case uint64:
  1396  						if v > math.MaxUint8 {
  1397  							// overflows
  1398  							if stack.strict {
  1399  								panic("overflows uint8")
  1400  							}
  1401  							stack.reg = nil
  1402  							break
  1403  						}
  1404  						field.SetUint(v)
  1405  					default:
  1406  						if stack.strict {
  1407  							panic("wrong uint8 value")
  1408  						}
  1409  						stack.reg = nil
  1410  					}
  1411  
  1412  				case reflect.Uint16:
  1413  					switch v := term.(type) {
  1414  					case int:
  1415  						if int64(v) > math.MaxUint16 || v < 0 {
  1416  							// overflows
  1417  							if stack.strict {
  1418  								panic("overflows uint16")
  1419  							}
  1420  							stack.reg = nil
  1421  							break
  1422  						}
  1423  						field.SetUint(uint64(v))
  1424  					case int64:
  1425  						if v > math.MaxUint16 || v < 0 {
  1426  							// overflows
  1427  							if stack.strict {
  1428  								panic("overflows uint16")
  1429  							}
  1430  							stack.reg = nil
  1431  							break
  1432  						}
  1433  						field.SetUint(uint64(v))
  1434  					case uint64:
  1435  						if v > math.MaxUint16 {
  1436  							// overflows
  1437  							if stack.strict {
  1438  								panic("overflows uint16")
  1439  							}
  1440  							stack.reg = nil
  1441  							break
  1442  						}
  1443  						field.SetUint(v)
  1444  					default:
  1445  						if stack.strict {
  1446  							panic("wrong uint16 value")
  1447  						}
  1448  						stack.reg = nil
  1449  					}
  1450  				case reflect.Uint32:
  1451  					switch v := term.(type) {
  1452  					case int:
  1453  						if int64(v) > math.MaxUint32 || v < 0 {
  1454  							// overflows
  1455  							if stack.strict {
  1456  								panic("overflows uint32")
  1457  							}
  1458  							stack.reg = nil
  1459  							break
  1460  						}
  1461  						field.SetUint(uint64(v))
  1462  					case int64:
  1463  						if v > math.MaxUint32 || v < 0 {
  1464  							// overflows
  1465  							if stack.strict {
  1466  								panic("overflows uint32")
  1467  							}
  1468  							stack.reg = nil
  1469  							break
  1470  						}
  1471  						field.SetUint(uint64(v))
  1472  					case uint64:
  1473  						if v > math.MaxUint32 {
  1474  							// overflows
  1475  							if stack.strict {
  1476  								panic("overflows uint32")
  1477  							}
  1478  							stack.reg = nil
  1479  							break
  1480  						}
  1481  						field.SetUint(v)
  1482  					default:
  1483  						if stack.strict {
  1484  							panic("wrong uint32 value")
  1485  						}
  1486  						stack.reg = nil
  1487  					}
  1488  
  1489  				case reflect.Uint64:
  1490  					switch v := term.(type) {
  1491  					case int:
  1492  						if v < 0 {
  1493  							// overflows
  1494  							if stack.strict {
  1495  								panic("overflows uint64")
  1496  							}
  1497  							stack.reg = nil
  1498  							break
  1499  						}
  1500  						field.SetUint(uint64(v))
  1501  					case int64:
  1502  						if v < 0 {
  1503  							// overflows
  1504  							if stack.strict {
  1505  								panic("overflows uint64")
  1506  							}
  1507  							stack.reg = nil
  1508  							break
  1509  						}
  1510  						field.SetUint(uint64(v))
  1511  					case uint64:
  1512  						field.SetUint(v)
  1513  					default:
  1514  						if stack.strict {
  1515  							panic("wrong uint64 value")
  1516  						}
  1517  						stack.reg = nil
  1518  					}
  1519  
  1520  				case reflect.Uint:
  1521  					switch v := term.(type) {
  1522  					case int:
  1523  						if v < 0 {
  1524  							// overflows
  1525  							if stack.strict {
  1526  								panic("overflows uint")
  1527  							}
  1528  							stack.reg = nil
  1529  							break
  1530  						}
  1531  						field.SetUint(uint64(v))
  1532  					case int64:
  1533  						if v > math.MaxInt || v < 0 {
  1534  							// overflows
  1535  							if stack.strict {
  1536  								panic("overflows uint")
  1537  							}
  1538  							stack.reg = nil
  1539  							break
  1540  						}
  1541  						field.SetUint(uint64(v))
  1542  					case uint64:
  1543  						if v > math.MaxUint {
  1544  							// overflows
  1545  							if stack.strict {
  1546  								panic("overflows uint")
  1547  							}
  1548  							stack.reg = nil
  1549  							break
  1550  						}
  1551  						field.SetUint(v)
  1552  					default:
  1553  						if stack.strict {
  1554  							panic("wrong uint value")
  1555  						}
  1556  						stack.reg = nil
  1557  					}
  1558  				case reflect.Float32:
  1559  					f, ok := term.(float64)
  1560  					if ok == false {
  1561  						if stack.strict {
  1562  							panic("wrong float value")
  1563  						}
  1564  						stack.reg = nil
  1565  						break
  1566  					}
  1567  					field.SetFloat(f)
  1568  
  1569  				case reflect.Float64:
  1570  					f64, ok := term.(float64)
  1571  					if ok == false {
  1572  						if stack.strict {
  1573  							panic("wrong float64")
  1574  						}
  1575  						stack.reg = nil
  1576  						break
  1577  					}
  1578  					field.SetFloat(f64)
  1579  
  1580  				case reflect.String:
  1581  					switch v := term.(type) {
  1582  					case List:
  1583  						s, err := convertCharlistToString(v)
  1584  						if err != nil {
  1585  							if stack.strict {
  1586  								panic("can't convert charlist into string")
  1587  							}
  1588  							stack.reg = nil
  1589  							break
  1590  						}
  1591  						field.SetString(s)
  1592  					case []byte:
  1593  						field.SetString(string(v))
  1594  					case string:
  1595  						field.SetString(v)
  1596  					case Atom:
  1597  						field.SetString(string(v))
  1598  					default:
  1599  						if stack.strict {
  1600  							panic("wrong string value")
  1601  						}
  1602  						stack.reg = nil
  1603  					}
  1604  				case reflect.Bool:
  1605  					b, ok := term.(bool)
  1606  					if !ok {
  1607  						if stack.strict {
  1608  							panic("wrong bool value")
  1609  						}
  1610  						stack.reg = nil
  1611  						break
  1612  					}
  1613  					field.SetBool(b)
  1614  
  1615  				case reflect.Map:
  1616  					if stack.tmp == nil {
  1617  						field.Set(reflect.ValueOf(term))
  1618  						break
  1619  					}
  1620  					destkey := reflect.ValueOf(stack.tmp)
  1621  					destval := reflect.ValueOf(term)
  1622  					stack.reg.SetMapIndex(destkey, destval)
  1623  
  1624  				default:
  1625  					if stack.strict {
  1626  						if field.Type().Name() == "Alias" {
  1627  							term = Alias(term.(Ref))
  1628  						}
  1629  						field.Set(reflect.ValueOf(term))
  1630  					} else {
  1631  						// wrap it to catch the panic
  1632  						setValue := func(f reflect.Value, v interface{}) (ok bool) {
  1633  							if lib.CatchPanic() {
  1634  								defer func() {
  1635  									if r := recover(); r != nil {
  1636  										ok = false
  1637  									}
  1638  								}()
  1639  							}
  1640  							if field.Type().Name() == "Alias" {
  1641  								v = Alias(v.(Ref))
  1642  							}
  1643  							f.Set(reflect.ValueOf(v))
  1644  							return true
  1645  						}
  1646  						if setValue(field, term) == false {
  1647  							stack.reg = nil
  1648  						}
  1649  
  1650  					}
  1651  				}
  1652  
  1653  			}
  1654  
  1655  		}
  1656  
  1657  		// we are still decoding children of Lis/Map/Tuple/...
  1658  		if stack.i < stack.children {
  1659  			continue
  1660  		}
  1661  
  1662  		if stack.reg != nil {
  1663  			term = (*stack.reg).Interface()
  1664  		} else {
  1665  			term = stack.term
  1666  		}
  1667  
  1668  		// this term was the last element of List/Map/Tuple/...
  1669  		// pop from the stack, but if its the root just finish
  1670  		if stack.parent == nil {
  1671  			break
  1672  		}
  1673  
  1674  		stack, stack.parent = stack.parent, nil // nil here is just a little help for GC
  1675  		goto processStack
  1676  
  1677  	}
  1678  
  1679  	return term, packet, nil
  1680  }