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

     1  package etf
     2  
     3  import (
     4  	"fmt"
     5  	"hash/crc32"
     6  	"reflect"
     7  	"strings"
     8  	"sync"
     9  
    10  	"github.com/ergo-services/ergo/lib"
    11  )
    12  
    13  var (
    14  	registered = registeredTypes{
    15  		typesEnc: make(map[Atom]*registerType),
    16  		typesDec: make(map[Atom]*registerType),
    17  	}
    18  )
    19  
    20  // Erlang external term tags.
    21  const (
    22  	ettAtom          = byte(100) //deprecated
    23  	ettAtomUTF8      = byte(118)
    24  	ettSmallAtom     = byte(115) //deprecated
    25  	ettSmallAtomUTF8 = byte(119)
    26  	ettString        = byte(107)
    27  
    28  	ettCacheRef = byte(82)
    29  
    30  	ettNewFloat = byte(70)
    31  
    32  	ettSmallInteger = byte(97)
    33  	ettInteger      = byte(98)
    34  	ettLargeBig     = byte(111)
    35  	ettSmallBig     = byte(110)
    36  
    37  	ettList         = byte(108)
    38  	ettListImproper = byte(18) // to be able to encode improper lists like [a|b].
    39  	ettSmallTuple   = byte(104)
    40  	ettLargeTuple   = byte(105)
    41  
    42  	ettMap = byte(116)
    43  
    44  	ettBinary    = byte(109)
    45  	ettBitBinary = byte(77)
    46  
    47  	ettNil = byte(106)
    48  
    49  	ettPid      = byte(103)
    50  	ettNewPid   = byte(88) // since OTP 23, only when BIG_CREATION flag is set
    51  	ettNewRef   = byte(114)
    52  	ettNewerRef = byte(90) // since OTP 21, only when BIG_CREATION flag is set
    53  
    54  	ettExport = byte(113)
    55  	ettFun    = byte(117) // legacy, wont support it here
    56  	ettNewFun = byte(112)
    57  
    58  	ettPort    = byte(102)
    59  	ettNewPort = byte(89) // since OTP 23, only when BIG_CREATION flag is set
    60  
    61  	// ettRef        = byte(101) deprecated
    62  
    63  	ettFloat = byte(99) // legacy
    64  )
    65  
    66  type registeredTypes struct {
    67  	sync.RWMutex
    68  	typesEnc map[Atom]*registerType
    69  	typesDec map[Atom]*registerType
    70  }
    71  type registerType struct {
    72  	rtype  reflect.Type
    73  	name   Atom
    74  	origin Atom
    75  	strict bool
    76  }
    77  
    78  // Term
    79  type Term interface{}
    80  
    81  // Tuple
    82  type Tuple []Term
    83  
    84  // List
    85  type List []Term
    86  
    87  // Alias
    88  type Alias Ref
    89  
    90  // ListImproper as a workaround for the Erlang's improper list [a|b]. Intended to be used to interact with Erlang.
    91  type ListImproper []Term
    92  
    93  // Atom
    94  type Atom string
    95  
    96  // Map
    97  type Map map[Term]Term
    98  
    99  // String this type is intended to be used to interact with Erlang. String value encodes as a binary (Erlang type: <<...>>)
   100  type String string
   101  
   102  // Charlist this type is intended to be used to interact with Erlang. Charlist value encodes as a list of int32 numbers in order to support Erlang string with UTF-8 symbols on an Erlang side (Erlang type: [...])
   103  type Charlist string
   104  
   105  // Pid
   106  type Pid struct {
   107  	Node     Atom
   108  	ID       uint64
   109  	Creation uint32
   110  }
   111  
   112  // Port
   113  type Port struct {
   114  	Node     Atom
   115  	ID       uint32
   116  	Creation uint32
   117  }
   118  
   119  // Ref
   120  type Ref struct {
   121  	Node     Atom
   122  	Creation uint32
   123  	ID       [5]uint32
   124  }
   125  
   126  // Marshaler interface implemented by types that can marshal themselves into valid ETF binary
   127  // Interface implementation must be over the object e.g. (MyObject) UnmarshalETF:
   128  //
   129  //		type MyObject struct{}
   130  //
   131  //		func (m MyObject) MarshalETF() ([]byte, error) {
   132  //			var encoded []byte
   133  //			... encoding routine ...
   134  //			return encoded, nil
   135  //	}
   136  type Marshaler interface {
   137  	MarshalETF() ([]byte, error)
   138  }
   139  
   140  // Unmarshaler interface implemented by types that can unmarshal an ETF binary of themselves.
   141  // Returns error ErrEmpty for []byte{}.
   142  // Interface implementation must be over pointer to the object e.g. (*MyObject) UnmarshalETF:
   143  //
   144  //	type MyObject struct{}
   145  //
   146  //	func (m *MyObject) UnmarshalETF(b []byte) error {
   147  //		var err error
   148  //		... decoding routine ...
   149  //		return err
   150  //	}
   151  type Unmarshaler interface {
   152  	UnmarshalETF([]byte) error
   153  }
   154  
   155  // Function
   156  type Function struct {
   157  	Arity  byte
   158  	Unique [16]byte
   159  	Index  uint32
   160  	//	Free      uint32
   161  	Module    Atom
   162  	OldIndex  uint32
   163  	OldUnique uint32
   164  	Pid       Pid
   165  	FreeVars  []Term
   166  }
   167  
   168  // Export
   169  type Export struct {
   170  	Module   Atom
   171  	Function Atom
   172  	Arity    int
   173  }
   174  
   175  // Element
   176  func (m Map) Element(k Term) Term {
   177  	return m[k]
   178  }
   179  
   180  // Element
   181  func (l List) Element(i int) Term {
   182  	return l[i-1]
   183  }
   184  
   185  // Element
   186  func (t Tuple) Element(i int) Term {
   187  	return t[i-1]
   188  }
   189  
   190  // String
   191  func (p Pid) String() string {
   192  	empty := Pid{}
   193  	if p == empty {
   194  		return "<0.0.0>"
   195  	}
   196  
   197  	n := uint32(0)
   198  	if p.Node != "" {
   199  		n = crc32.Checksum([]byte(p.Node), lib.CRC32Q)
   200  	}
   201  	return fmt.Sprintf("<%08X.%d.%d>", n, int32(p.ID>>32), int32(p.ID))
   202  }
   203  
   204  // String
   205  func (r Ref) String() string {
   206  	n := uint32(0)
   207  	if r.Node != "" {
   208  		n = crc32.Checksum([]byte(r.Node), lib.CRC32Q)
   209  	}
   210  	return fmt.Sprintf("Ref#<%08X.%d.%d.%d>", n, r.ID[0], r.ID[1], r.ID[2])
   211  }
   212  
   213  // String
   214  func (a Alias) String() string {
   215  	n := uint32(0)
   216  	if a.Node != "" {
   217  		n = crc32.Checksum([]byte(a.Node), lib.CRC32Q)
   218  	}
   219  	return fmt.Sprintf("Ref#<%08X.%d.%d.%d>", n, a.ID[0], a.ID[1], a.ID[2])
   220  }
   221  
   222  // ProplistElement
   223  type ProplistElement struct {
   224  	Name  Atom
   225  	Value Term
   226  }
   227  
   228  // TermToString transforms given term (Atom, []byte, List) to the string
   229  func TermToString(t Term) (s string, ok bool) {
   230  	ok = true
   231  	switch x := t.(type) {
   232  	case Atom:
   233  		s = string(x)
   234  	case string:
   235  		s = x
   236  	case []byte:
   237  		s = string(x)
   238  	case List:
   239  		str, err := convertCharlistToString(x)
   240  		if err != nil {
   241  			ok = false
   242  			return
   243  		}
   244  		s = str
   245  	default:
   246  		ok = false
   247  	}
   248  	return
   249  }
   250  
   251  // TermProplistIntoStruct transorms given term into the provided struct 'dest'.
   252  // Proplist is the list of Tuple values with two items { Name , Value },
   253  // where Name can be string or Atom and Value must be the same type as
   254  // it has the field of 'dest' struct with the equivalent name. Its also
   255  // accepts []ProplistElement as a 'term' value
   256  func TermProplistIntoStruct(term Term, dest interface{}) (err error) {
   257  	defer func() {
   258  		if r := recover(); r != nil {
   259  			err = fmt.Errorf("%v", r)
   260  		}
   261  	}()
   262  	v := reflect.Indirect(reflect.ValueOf(dest))
   263  	return setProplist(term, v)
   264  }
   265  
   266  // TermIntoStruct transforms 'term' (etf.Term, etf.List, etf.Tuple, etf.Map) into the
   267  // given 'dest' (could be a struct, map, slice or array). Its a pretty
   268  // expencive operation in terms of CPU usage so you shouldn't use it
   269  // on highload parts of your code. Use manual type casting instead.
   270  func TermIntoStruct(term Term, dest interface{}) (err error) {
   271  	defer func() {
   272  		if r := recover(); r != nil {
   273  			err = fmt.Errorf("%v", r)
   274  		}
   275  	}()
   276  	v := reflect.Indirect(reflect.ValueOf(dest))
   277  	err = termIntoStruct(term, v)
   278  	return
   279  }
   280  
   281  func termIntoStruct(term Term, dest reflect.Value) error {
   282  
   283  	if term == nil {
   284  		return nil
   285  	}
   286  
   287  	if dest.Type().NumMethod() > 0 && dest.CanInterface() {
   288  		v := dest
   289  		if v.Kind() != reflect.Ptr && v.CanAddr() {
   290  			v = v.Addr()
   291  
   292  			if u, ok := v.Interface().(Unmarshaler); ok {
   293  				b, is_binary := term.([]byte)
   294  				if !is_binary {
   295  					return fmt.Errorf("can't unmarshal value, wront type %s", term)
   296  				}
   297  				return u.UnmarshalETF(b)
   298  			}
   299  		}
   300  	}
   301  
   302  	switch dest.Kind() {
   303  	case reflect.Ptr:
   304  		pdest := reflect.New(dest.Type().Elem())
   305  		dest.Set(pdest)
   306  		dest = pdest.Elem()
   307  		return termIntoStruct(term, dest)
   308  
   309  	case reflect.Array, reflect.Slice:
   310  		t := dest.Type()
   311  		byte_slice, ok := term.([]byte)
   312  		if t == reflect.SliceOf(reflect.TypeOf(byte(1))) && ok {
   313  			dest.Set(reflect.ValueOf(byte_slice))
   314  			return nil
   315  
   316  		}
   317  		if _, ok := term.(List); !ok {
   318  			// in case if term is the golang native type
   319  			dest.Set(reflect.ValueOf(term))
   320  			return nil
   321  		}
   322  		return setListField(term.(List), dest)
   323  
   324  	case reflect.Struct:
   325  		switch s := term.(type) {
   326  		case Map:
   327  			return setMapStructField(s, dest)
   328  		case Tuple:
   329  			return setStructField(s, dest)
   330  		case Ref:
   331  			dest.Set(reflect.ValueOf(s))
   332  			return nil
   333  		case Pid:
   334  			dest.Set(reflect.ValueOf(s))
   335  			return nil
   336  		}
   337  		return fmt.Errorf("can't convert %#v to struct", term)
   338  
   339  	case reflect.Map:
   340  		if _, ok := term.(Map); !ok {
   341  			// in case if term is the golang native type
   342  			dest.Set(reflect.ValueOf(term))
   343  			return nil
   344  		}
   345  		return setMapField(term.(Map), dest)
   346  
   347  	case reflect.Bool:
   348  		b, ok := term.(bool)
   349  		if !ok {
   350  			return fmt.Errorf("can't convert %#v to bool", term)
   351  		}
   352  		dest.SetBool(b)
   353  		return nil
   354  
   355  	case reflect.Float32, reflect.Float64:
   356  		f, ok := term.(float64)
   357  		if !ok {
   358  			return fmt.Errorf("can't convert %#v to float64", term)
   359  		}
   360  		dest.SetFloat(f)
   361  		return nil
   362  
   363  	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
   364  		i := int64(0)
   365  		switch v := term.(type) {
   366  		case int64:
   367  			i = v
   368  		case int32:
   369  			i = int64(v)
   370  		case int16:
   371  			i = int64(v)
   372  		case int8:
   373  			i = int64(v)
   374  		case int:
   375  			i = int64(v)
   376  		case uint64:
   377  			i = int64(v)
   378  		case uint32:
   379  			i = int64(v)
   380  		case uint16:
   381  			i = int64(v)
   382  		case uint8:
   383  			i = int64(v)
   384  		case uint:
   385  			i = int64(v)
   386  		default:
   387  			return fmt.Errorf("can't convert %#v to int64", term)
   388  		}
   389  		dest.SetInt(i)
   390  		return nil
   391  
   392  	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
   393  		u := uint64(0)
   394  		switch v := term.(type) {
   395  		case uint64:
   396  			u = v
   397  		case uint32:
   398  			u = uint64(v)
   399  		case uint16:
   400  			u = uint64(v)
   401  		case uint8:
   402  			u = uint64(v)
   403  		case uint:
   404  			u = uint64(v)
   405  		case int64:
   406  			u = uint64(v)
   407  		case int32:
   408  			u = uint64(v)
   409  		case int16:
   410  			u = uint64(v)
   411  		case int8:
   412  			u = uint64(v)
   413  		case int:
   414  			u = uint64(v)
   415  
   416  		default:
   417  			return fmt.Errorf("can't convert %#v to uint64", term)
   418  		}
   419  		dest.SetUint(u)
   420  		return nil
   421  
   422  	case reflect.String:
   423  		switch v := term.(type) {
   424  		case List:
   425  			s, err := convertCharlistToString(v)
   426  			if err != nil {
   427  				return err
   428  			}
   429  			dest.SetString(s)
   430  			return nil
   431  		case []byte:
   432  			dest.SetString(string(v))
   433  			return nil
   434  		case string:
   435  			dest.SetString(v)
   436  			return nil
   437  		case Atom:
   438  			dest.SetString(string(v))
   439  			return nil
   440  		}
   441  
   442  	default:
   443  		dest.Set(reflect.ValueOf(term))
   444  		return nil
   445  	}
   446  
   447  	return nil
   448  }
   449  
   450  func setListField(term List, dest reflect.Value) error {
   451  	var value reflect.Value
   452  	if dest.Kind() == reflect.Ptr {
   453  		pdest := reflect.New(dest.Type().Elem())
   454  		dest.Set(pdest)
   455  		dest = pdest.Elem()
   456  	}
   457  	t := dest.Type()
   458  	switch t.Kind() {
   459  	case reflect.Slice:
   460  		value = reflect.MakeSlice(t, len(term), len(term))
   461  	case reflect.Array:
   462  		if t.Len() != len(term) {
   463  			return NewInvalidTypesError(t, term)
   464  		}
   465  		value = dest
   466  	default:
   467  		return NewInvalidTypesError(t, term)
   468  	}
   469  
   470  	for i, elem := range term {
   471  		if err := termIntoStruct(elem, value.Index(i)); err != nil {
   472  			return err
   473  		}
   474  	}
   475  
   476  	if t.Kind() == reflect.Slice {
   477  		dest.Set(value)
   478  	}
   479  
   480  	return nil
   481  }
   482  
   483  func setProplist(term Term, dest reflect.Value) error {
   484  	switch v := term.(type) {
   485  	case []ProplistElement:
   486  		return setProplistElementField(v, dest)
   487  	case List:
   488  		return setProplistField(v, dest)
   489  	default:
   490  		return NewInvalidTypesError(dest.Type(), term)
   491  	}
   492  
   493  }
   494  
   495  func setProplistField(list List, dest reflect.Value) error {
   496  	t := dest.Type()
   497  	numField := t.NumField()
   498  	fields := make([]reflect.StructField, numField)
   499  	for i := range fields {
   500  		fields[i] = t.Field(i)
   501  	}
   502  
   503  	for _, elem := range list {
   504  		if len(elem.(Tuple)) != 2 {
   505  			return &InvalidStructKeyError{Term: elem}
   506  		}
   507  
   508  		key := elem.(Tuple)[0]
   509  		val := elem.(Tuple)[1]
   510  		fName, ok := TermToString(key)
   511  		if !ok {
   512  			return &InvalidStructKeyError{Term: key}
   513  		}
   514  		index := findStructField(fields, fName)
   515  		if index == -1 {
   516  			continue
   517  		}
   518  
   519  		err := termIntoStruct(val, dest.Field(index))
   520  		if err != nil {
   521  			return err
   522  		}
   523  	}
   524  
   525  	return nil
   526  }
   527  
   528  func setProplistElementField(proplist []ProplistElement, dest reflect.Value) error {
   529  	t := dest.Type()
   530  	numField := t.NumField()
   531  	fields := make([]reflect.StructField, numField)
   532  	for i := range fields {
   533  		fields[i] = t.Field(i)
   534  	}
   535  
   536  	for _, elem := range proplist {
   537  		fName, ok := TermToString(elem.Name)
   538  		if !ok {
   539  			return &InvalidStructKeyError{Term: elem.Name}
   540  		}
   541  		index := findStructField(fields, fName)
   542  		if index == -1 {
   543  			continue
   544  		}
   545  
   546  		err := termIntoStruct(elem.Value, dest.Field(index))
   547  		if err != nil {
   548  			return err
   549  		}
   550  	}
   551  
   552  	return nil
   553  }
   554  func setMapField(term Map, dest reflect.Value) error {
   555  	switch dest.Type().Kind() {
   556  	case reflect.Map:
   557  		return setMapMapField(term, dest)
   558  	case reflect.Struct:
   559  		return setMapStructField(term, dest)
   560  	case reflect.Interface:
   561  		dest.Set(reflect.ValueOf(term))
   562  		return nil
   563  	}
   564  
   565  	return NewInvalidTypesError(dest.Type(), term)
   566  }
   567  
   568  func setStructField(term Tuple, dest reflect.Value) error {
   569  	if dest.Kind() == reflect.Ptr {
   570  		pdest := reflect.New(dest.Type().Elem())
   571  		dest.Set(pdest)
   572  		dest = pdest.Elem()
   573  	}
   574  	for i, elem := range term {
   575  		// let it panic if number of term elements is bigger than
   576  		// number of struct fields
   577  		if err := termIntoStruct(elem, dest.Field(i)); err != nil {
   578  			return err
   579  		}
   580  	}
   581  
   582  	return nil
   583  
   584  }
   585  
   586  func setMapStructField(term Map, dest reflect.Value) error {
   587  	t := dest.Type()
   588  	numField := t.NumField()
   589  	fields := make([]reflect.StructField, numField)
   590  	for i := range fields {
   591  		fields[i] = t.Field(i)
   592  	}
   593  
   594  	for key, val := range term {
   595  		fName, ok := TermToString(key)
   596  		if !ok {
   597  			return &InvalidStructKeyError{Term: key}
   598  		}
   599  		index := findStructField(fields, fName)
   600  		if index == -1 {
   601  			continue
   602  		}
   603  
   604  		err := termIntoStruct(val, dest.Field(index))
   605  		if err != nil {
   606  			return err
   607  		}
   608  	}
   609  
   610  	return nil
   611  }
   612  
   613  func findStructField(term []reflect.StructField, key string) (index int) {
   614  	var fieldName string
   615  	index = -1
   616  	for i, f := range term {
   617  		fieldName = f.Name
   618  
   619  		if tag := f.Tag.Get("etf"); tag != "" {
   620  			fieldName = tag
   621  		}
   622  
   623  		if fieldName == key {
   624  			index = i
   625  			return
   626  		} else {
   627  			if strings.EqualFold(f.Name, key) {
   628  				index = i
   629  			}
   630  		}
   631  	}
   632  
   633  	return
   634  }
   635  
   636  func setMapMapField(term Map, dest reflect.Value) error {
   637  	t := dest.Type()
   638  	if dest.IsNil() {
   639  		dest.Set(reflect.MakeMapWithSize(t, len(term)))
   640  	}
   641  	tkey := t.Key()
   642  	tval := t.Elem()
   643  	for key, val := range term {
   644  		destkey := reflect.Indirect(reflect.New(tkey))
   645  		if err := termIntoStruct(key, destkey); err != nil {
   646  			return err
   647  		}
   648  		destval := reflect.Indirect(reflect.New(tval))
   649  		if err := termIntoStruct(val, destval); err != nil {
   650  			return err
   651  		}
   652  		dest.SetMapIndex(destkey, destval)
   653  	}
   654  	return nil
   655  }
   656  
   657  // RegisterTypeOptins defines custom name for the registering type.
   658  // Leaving the Name option empty makes the name automatically generated.
   659  // Strict option defines whether the decoding process causes panic
   660  // if the decoding value doesn't fit the destination object.
   661  type RegisterTypeOptions struct {
   662  	Name   Atom
   663  	Strict bool
   664  }
   665  
   666  // RegisterType registers new type with the given options. It returns a Name
   667  // of the registered type, which can be used in the UnregisterType function
   668  // for unregistering this type. Supported types: struct, slice, array, map.
   669  // Returns an error if this type can not be registered.
   670  func RegisterType(t interface{}, options RegisterTypeOptions) (Atom, error) {
   671  	switch t.(type) {
   672  	case Pid, Ref, Alias:
   673  		return "", fmt.Errorf("types Pid, Ref, Alias can not be registered")
   674  	}
   675  	tt := reflect.TypeOf(t)
   676  	ttk := tt.Kind()
   677  
   678  	name := options.Name
   679  	origin := regTypeName(tt)
   680  	if name == "" {
   681  		name = origin
   682  	}
   683  	lname := len([]rune(name))
   684  	if lname > 255 {
   685  		return name, fmt.Errorf("type name %q is too long. characters number %d (limit: 255)", name, lname)
   686  	}
   687  
   688  	switch ttk {
   689  	case reflect.Struct, reflect.Slice, reflect.Array:
   690  	case reflect.Map:
   691  		// Using pointers for the network messaging is meaningless.
   692  		// Supporting this feature in the maps is getting the decoding process a bit overloaded.
   693  		// But they still can be used for the other types, even being meaningless.
   694  		if tt.Key().Kind() == reflect.Ptr {
   695  			return name, fmt.Errorf("pointer as a key for the map is not supported")
   696  		}
   697  		if tt.Elem().Kind() == reflect.Ptr {
   698  			return name, fmt.Errorf("pointer as a value for the map is not supported")
   699  		}
   700  		// supported types
   701  	default:
   702  		return name, fmt.Errorf("type %q is not supported", regTypeName(tt))
   703  	}
   704  
   705  	registered.Lock()
   706  	defer registered.Unlock()
   707  
   708  	_, taken := registered.typesDec[name]
   709  	if taken {
   710  		return name, lib.ErrTaken
   711  	}
   712  
   713  	r, taken := registered.typesEnc[origin]
   714  	if taken {
   715  		return name, fmt.Errorf("type is already registered as %q", r.name)
   716  	}
   717  
   718  	checkIsRegistered := func(name Atom, rt reflect.Kind) error {
   719  		switch rt {
   720  		case reflect.Struct, reflect.Array, reflect.Slice, reflect.Map:
   721  			// check if this type is registered
   722  			_, taken := registered.typesEnc[name]
   723  			if taken == false {
   724  				return fmt.Errorf("type %q must be registered first", name)
   725  			}
   726  		case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Complex64, reflect.Complex128:
   727  			return fmt.Errorf("type %q is not supported", rt)
   728  		}
   729  		return nil
   730  	}
   731  
   732  	switch ttk {
   733  	case reflect.Struct:
   734  		// check for unexported fields
   735  		tv := reflect.ValueOf(t)
   736  		for i := 0; i < tv.NumField(); i++ {
   737  			f := tv.Field(i)
   738  			if f.CanInterface() == false {
   739  				return name, fmt.Errorf("struct has unexported field(s)")
   740  			}
   741  
   742  			switch f.Interface().(type) {
   743  			case Pid, Ref, Alias:
   744  				// ignore this types
   745  				continue
   746  			}
   747  
   748  			if f.Type().Kind() == reflect.Slice && f.Type().Elem().Kind() == reflect.Uint8 {
   749  				// []byte
   750  				continue
   751  			}
   752  
   753  			orig := regTypeName(f.Type())
   754  			if err := checkIsRegistered(orig, f.Kind()); err != nil {
   755  				return name, err
   756  			}
   757  		}
   758  	case reflect.Array, reflect.Slice, reflect.Map:
   759  		elem := tt.Elem()
   760  		orig := regTypeName(elem)
   761  		if err := checkIsRegistered(orig, elem.Kind()); err != nil {
   762  			return name, err
   763  		}
   764  	}
   765  
   766  	rt := &registerType{
   767  		rtype:  reflect.TypeOf(t),
   768  		name:   name,
   769  		origin: origin,
   770  		strict: options.Strict,
   771  	}
   772  	registered.typesEnc[origin] = rt
   773  	registered.typesDec[name] = rt
   774  	return name, nil
   775  }
   776  
   777  // UnregisterType unregisters type with a given name.
   778  func UnregisterType(name Atom) error {
   779  	registered.Lock()
   780  	defer registered.Unlock()
   781  	r, found := registered.typesDec[name]
   782  	if found == false {
   783  		return lib.ErrUnknown
   784  	}
   785  	delete(registered.typesDec, name)
   786  	delete(registered.typesEnc, r.origin)
   787  	return nil
   788  }
   789  
   790  type StructPopulatorError struct {
   791  	Type reflect.Type
   792  	Term Term
   793  }
   794  
   795  func (s *StructPopulatorError) Error() string {
   796  	return fmt.Sprintf("Cannot put %#v into go value of type %s", s.Term, s.Type.Kind().String())
   797  }
   798  
   799  func NewInvalidTypesError(t reflect.Type, term Term) error {
   800  	return &StructPopulatorError{
   801  		Type: t,
   802  		Term: term,
   803  	}
   804  }
   805  
   806  type InvalidStructKeyError struct {
   807  	Term Term
   808  }
   809  
   810  func (s *InvalidStructKeyError) Error() string {
   811  	return fmt.Sprintf("Cannot use %s as struct field name", reflect.TypeOf(s.Term).Name())
   812  }
   813  
   814  func convertCharlistToString(l List) (string, error) {
   815  	runes := make([]rune, len(l))
   816  	for i := range l {
   817  		switch x := l[i].(type) {
   818  		case int64:
   819  			runes[i] = int32(x)
   820  		case int32:
   821  			runes[i] = int32(x)
   822  		case int16:
   823  			runes[i] = int32(x)
   824  		case int8:
   825  			runes[i] = int32(x)
   826  		case int:
   827  			runes[i] = int32(x)
   828  		default:
   829  			return "", fmt.Errorf("wrong rune %#v", l[i])
   830  		}
   831  	}
   832  	return string(runes), nil
   833  }
   834  
   835  func regTypeName(t reflect.Type) Atom {
   836  	return Atom("#" + t.PkgPath() + "/" + t.Name())
   837  }