github.com/stellar/go-xdr@v0.0.0-20231122183749-b53fb00bcac2/xdr/encode.go (about)

     1  /*
     2   * Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
     3   *
     4   * Permission to use, copy, modify, and distribute this software for any
     5   * purpose with or without fee is hereby granted, provided that the above
     6   * copyright notice and this permission notice appear in all copies.
     7   *
     8   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     9   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    10   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    11   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    12   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    13   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    14   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    15   */
    16  
    17  package xdr
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  	"reflect"
    23  	"time"
    24  )
    25  
    26  var errMaxXdr = "data exceeds max xdr size limit"
    27  
    28  /*
    29  Marshal returns the XDR encoding of v.  It traverses v recursively and
    30  automatically indirects pointers through arbitrary depth to encode the actual
    31  value pointed to.
    32  
    33  Marshal uses reflection to determine the type of the concrete value contained
    34  by v and performs a mapping of Go types to the underlying XDR types as follows:
    35  
    36  	Go Type -> XDR Type
    37  	--------------------
    38  	int8, int16, int32, int -> XDR Integer
    39  	uint8, uint16, uint32, uint -> XDR Unsigned Integer
    40  	int64 -> XDR Hyper Integer
    41  	uint64 -> XDR Unsigned Hyper Integer
    42  	bool -> XDR Boolean
    43  	float32 -> XDR Floating-Point
    44  	float64 -> XDR Double-Precision Floating-Point
    45  	string -> XDR String
    46  	byte -> XDR Integer
    47  	[]byte -> XDR Variable-Length Opaque Data
    48  	[#]byte -> XDR Fixed-Length Opaque Data
    49  	[]<type> -> XDR Variable-Length Array
    50  	[#]<type> -> XDR Fixed-Length Array
    51  	struct -> XDR Structure
    52  	map -> XDR Variable-Length Array of two-element XDR Structures
    53  	time.Time -> XDR String encoded with RFC3339 nanosecond precision
    54  
    55  Notes and Limitations:
    56  
    57    - Automatic marshalling of variable and fixed-length arrays of uint8s
    58      requires a special struct tag `xdropaque:"false"` since byte slices and
    59      byte arrays are assumed to be opaque data and byte is a Go alias for uint8
    60      thus indistinguishable under reflection
    61    - Channel, complex, and function types cannot be encoded
    62    - Interfaces without a concrete value cannot be encoded
    63    - Cyclic data structures are not supported and will result in infinite loops
    64    - Strings are marshalled with UTF-8 character encoding which differs from
    65      the XDR specification of ASCII, however UTF-8 is backwards compatible with
    66      ASCII so this should rarely cause issues
    67  
    68  If any issues are encountered during the marshalling process, a MarshalError is
    69  returned with a human readable description as well as an ErrorCode value for
    70  further inspection from sophisticated callers.  Some potential issues are
    71  unsupported Go types, attempting to encode more opaque data than can be
    72  represented by a single opaque XDR entry, and exceeding max slice limitations.
    73  */
    74  func Marshal(v interface{}) (rv []byte, err error) {
    75  	if v == nil {
    76  		msg := "can't marshal nil interface"
    77  		err = marshalError("Marshal", ErrNilInterface, msg, nil)
    78  		return nil, err
    79  	}
    80  
    81  	vv := reflect.ValueOf(v)
    82  	vve := vv
    83  	for vve.Kind() == reflect.Ptr {
    84  		if vve.IsNil() {
    85  			msg := fmt.Sprintf("can't marshal nil pointer '%v'",
    86  				vv.Type().String())
    87  			err = marshalError("Marshal", ErrBadArguments, msg, nil)
    88  			return nil, err
    89  		}
    90  		vve = vve.Elem()
    91  	}
    92  
    93  	enc := Encoder{}
    94  	err = enc.encode(vve)
    95  	return enc.data, err
    96  }
    97  
    98  // An Encoder contains information about the state of an encode operation
    99  // from an interface value into an XDR-encoded byte slice.  See NewEncoder.
   100  type Encoder struct {
   101  	data []byte
   102  	off  int
   103  }
   104  
   105  // EncodeInt appends the XDR encoded representation of the passed 32-bit signed
   106  // integer to the Encoder's data.
   107  //
   108  // A MarshalError is returned if appending the data would overflow the
   109  // internal data slice.
   110  //
   111  // Reference:
   112  //
   113  //	RFC Section 4.1 - Integer
   114  //	32-bit big-endian signed integer in range [-2147483648, 2147483647]
   115  func (enc *Encoder) EncodeInt(v int32) (err error) {
   116  	b := make([]byte, 4, 4)
   117  	b[0] = byte(v >> 24)
   118  	b[1] = byte(v >> 16)
   119  	b[2] = byte(v >> 8)
   120  	b[3] = byte(v)
   121  
   122  	if len(enc.data) > maxInt-4 {
   123  		err = marshalError("EncodeInt", ErrOverflow, errMaxSlice, b)
   124  		return
   125  	}
   126  
   127  	enc.data = append(enc.data, b...)
   128  	return
   129  }
   130  
   131  // EncodeUint appends the XDR encoded representation of the passed 32-bit
   132  // unsigned integer to the Encoder's data.
   133  //
   134  // A MarshalError is returned if appending the data would overflow the
   135  // internal data slice.
   136  //
   137  // Reference:
   138  //
   139  //	RFC Section 4.2 - Unsigned Integer
   140  //	32-bit big-endian unsigned integer in range [0, 4294967295]
   141  func (enc *Encoder) EncodeUint(v uint32) (err error) {
   142  	b := make([]byte, 4, 4)
   143  	b[0] = byte(v >> 24)
   144  	b[1] = byte(v >> 16)
   145  	b[2] = byte(v >> 8)
   146  	b[3] = byte(v)
   147  
   148  	if len(enc.data) > maxInt-4 {
   149  		err = marshalError("EncodeUint", ErrOverflow, errMaxSlice, b)
   150  		return
   151  	}
   152  
   153  	enc.data = append(enc.data, b...)
   154  	return
   155  }
   156  
   157  // EncodeEnum treats the passed 32-bit signed integer as an enumeration value
   158  // and, if it is in the list of passed valid enumeration values, appends the XDR
   159  // encoded representation of it to the Encoder's data.
   160  //
   161  // A MarshalError is returned if the enumeration value is not one of the provided
   162  // valid values or appending the data would overflow the internal data slice.
   163  //
   164  // Reference:
   165  //
   166  //	RFC Section 4.3 - Enumeration
   167  //	Represented as an XDR encoded signed integer
   168  func (enc *Encoder) EncodeEnum(v int32, validEnums map[int32]bool) (err error) {
   169  	if !validEnums[v] {
   170  		err = marshalError("EncodeEnum", ErrBadEnumValue, "invalid enum", v)
   171  		return
   172  	}
   173  	return enc.EncodeInt(v)
   174  }
   175  
   176  // EncodeBool appends the XDR encoded representation of the passed boolean
   177  // to the Encoder's data.
   178  //
   179  // A MarshalError is returned if appending the data would overflow the
   180  // internal data slice.
   181  //
   182  // Reference:
   183  //
   184  //	RFC Section 4.4 - Boolean
   185  //	Represented as an XDR encoded enumeration where 0 is false and 1 is true
   186  func (enc *Encoder) EncodeBool(v bool) (err error) {
   187  	i := int32(0)
   188  	if v == true {
   189  		i = 1
   190  	}
   191  	return enc.EncodeInt(i)
   192  }
   193  
   194  // EncodeHyper appends the XDR encoded representation of the passed 64-bit
   195  // signed integer to the Encoder's data.
   196  //
   197  // A MarshalError is returned if appending the data would overflow the
   198  // internal data slice.
   199  //
   200  // Reference:
   201  //
   202  //	RFC Section 4.5 - Hyper Integer
   203  //	64-bit big-endian signed integer in range [-9223372036854775808, 9223372036854775807]
   204  func (enc *Encoder) EncodeHyper(v int64) (err error) {
   205  	b := make([]byte, 8, 8)
   206  	b[0] = byte(v >> 56)
   207  	b[1] = byte(v >> 48)
   208  	b[2] = byte(v >> 40)
   209  	b[3] = byte(v >> 32)
   210  	b[4] = byte(v >> 24)
   211  	b[5] = byte(v >> 16)
   212  	b[6] = byte(v >> 8)
   213  	b[7] = byte(v)
   214  
   215  	if len(enc.data) > maxInt-8 {
   216  		err = marshalError("EncodeHyper", ErrOverflow, errMaxSlice, b)
   217  		return
   218  	}
   219  
   220  	enc.data = append(enc.data, b...)
   221  	return
   222  }
   223  
   224  // EncodeUhyper appends the XDR encoded representation of the passed 64-bit
   225  // unsigned integer to the Encoder's data.
   226  //
   227  // A MarshalError is returned if appending the data would overflow the
   228  // internal data slice.
   229  //
   230  // Reference:
   231  //
   232  //	RFC Section 4.5 - Unsigned Hyper Integer
   233  //	64-bit big-endian unsigned integer in range [0, 18446744073709551615]
   234  func (enc *Encoder) EncodeUhyper(v uint64) (err error) {
   235  	b := make([]byte, 8, 8)
   236  	b[0] = byte(v >> 56)
   237  	b[1] = byte(v >> 48)
   238  	b[2] = byte(v >> 40)
   239  	b[3] = byte(v >> 32)
   240  	b[4] = byte(v >> 24)
   241  	b[5] = byte(v >> 16)
   242  	b[6] = byte(v >> 8)
   243  	b[7] = byte(v)
   244  
   245  	if len(enc.data) > maxInt-8 {
   246  		err = marshalError("EncodeUhyper", ErrOverflow, errMaxSlice, b)
   247  		return
   248  	}
   249  
   250  	enc.data = append(enc.data, b...)
   251  	return
   252  }
   253  
   254  // EncodeFloat appends the XDR encoded representation of the passed 32-bit
   255  // (single-precision) floating point to the Encoder's data.
   256  //
   257  // A MarshalError is returned if appending the data would overflow the
   258  // internal data slice.
   259  //
   260  // Reference:
   261  //
   262  //	RFC Section 4.6 - Floating Point
   263  //	32-bit single-precision IEEE 754 floating point
   264  func (enc *Encoder) EncodeFloat(v float32) (err error) {
   265  	ui := math.Float32bits(v)
   266  	return enc.EncodeUint(ui)
   267  }
   268  
   269  // EncodeDouble appends the XDR encoded representation of the passed 64-bit
   270  // (double-precision) floating point to the Encoder's data.
   271  //
   272  // A MarshalError is returned if appending the data would overflow the
   273  // internal data slice.
   274  //
   275  // Reference:
   276  //
   277  //	RFC Section 4.7 -  Double-Precision Floating Point
   278  //	64-bit double-precision IEEE 754 floating point
   279  func (enc *Encoder) EncodeDouble(v float64) (err error) {
   280  	ui := math.Float64bits(v)
   281  	return enc.EncodeUhyper(ui)
   282  }
   283  
   284  // RFC Section 4.8 -  Quadruple-Precision Floating Point
   285  // 128-bit quadruple-precision floating point
   286  // Not Implemented
   287  
   288  // EncodeFixedOpaque treats the passed byte slice as opaque data of a fixed
   289  // size and appends the XDR encoded representation of it to the Encoder's data.
   290  //
   291  // A MarshalError is returned if appending the data would overflow the
   292  // internal data slice.
   293  //
   294  // Reference:
   295  //
   296  //	RFC Section 4.9 - Fixed-Length Opaque Data
   297  //	Fixed-length uninterpreted data zero-padded to a multiple of four
   298  func (enc *Encoder) EncodeFixedOpaque(v []byte) (err error) {
   299  	l := len(v)
   300  	pad := (4 - (l % 4)) % 4
   301  	size := l + pad
   302  
   303  	if len(enc.data) > maxInt-size {
   304  		err = marshalError("EncodeFixedOpaque", ErrOverflow, errMaxSlice, size)
   305  		return
   306  	}
   307  
   308  	enc.data = append(enc.data, v...)
   309  	if pad > 0 {
   310  		b := make([]byte, pad, pad)
   311  		for i := 0; i < pad; i++ {
   312  			b[i] = 0
   313  		}
   314  		enc.data = append(enc.data, b...)
   315  	}
   316  	return
   317  }
   318  
   319  // EncodeOpaque treats the passed byte slice as opaque data of a variable
   320  // size and appends the XDR encoded representation of it to the Encoder's data.
   321  //
   322  // A MarshalError is returned if appending the data would overflow the
   323  // internal data slice or the data in the byte slice is larger than XDR
   324  // supports.
   325  //
   326  // Reference:
   327  //
   328  //	RFC Section 4.10 - Variable-Length Opaque Data
   329  //	Unsigned integer length followed by fixed opaque data of that length
   330  func (enc *Encoder) EncodeOpaque(v []byte) (err error) {
   331  	dataLen := len(v)
   332  	if uint(dataLen) > math.MaxUint32 {
   333  		err = marshalError("EncodeOpaque", ErrOverflow, errMaxXdr, dataLen)
   334  		return
   335  	}
   336  	err = enc.EncodeUint(uint32(dataLen))
   337  	if err != nil {
   338  		return
   339  	}
   340  	err = enc.EncodeFixedOpaque(v)
   341  	return
   342  }
   343  
   344  // EncodeString appends the XDR encoded representation of the passed string
   345  // to the Encoder's data.  Character encoding is assumed to be UTF-8 and
   346  // therefore ASCII compatible.  If the underlying character encoding
   347  // is not compatible with this assumption, the data can instead be written as
   348  // variable-length opaque data (EncodeOpaque) and manually converted as needed.
   349  //
   350  // A MarshalError is returned if appending the data would overflow the
   351  // internal data slice or the length of the string is larger than XDR supports.
   352  //
   353  // Reference:
   354  //
   355  //	RFC Section 4.11 - String
   356  //	Unsigned integer length followed by bytes zero-padded to a multiple of four
   357  func (enc *Encoder) EncodeString(v string) (err error) {
   358  	dataLen := len(v)
   359  	if uint(dataLen) > math.MaxUint32 {
   360  		err = marshalError("EncodeString", ErrOverflow, errMaxXdr, dataLen)
   361  		return
   362  	}
   363  	err = enc.EncodeUint(uint32(dataLen))
   364  	if err != nil {
   365  		return
   366  	}
   367  	err = enc.EncodeFixedOpaque([]byte(v))
   368  	return
   369  }
   370  
   371  // encodeFixedArray appends the XDR encoded representation of each element
   372  // in the passed array represented by the reflection value to the Encoder's
   373  // data.  The ignoreOpaque flag controls whether or not uint8 (byte) elements
   374  // should be encoded individually or as a fixed sequence of opaque data.
   375  //
   376  // A MarshalError is returned if any issues are encountered while encoding
   377  // the array elements.
   378  //
   379  // Reference:
   380  //
   381  //	RFC Section 4.12 - Fixed-Length Array
   382  //	Individually XDR encoded array elements
   383  func (enc *Encoder) encodeFixedArray(v reflect.Value, ignoreOpaque bool) (err error) {
   384  	// Treat [#]byte (byte is alias for uint8) as opaque data unless ignored.
   385  	if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
   386  		// Create a slice of the underlying array for better efficiency when
   387  		// possible.  Can't create a slice of an unaddressable value.
   388  		if v.CanAddr() {
   389  			err = enc.EncodeFixedOpaque(v.Slice(0, v.Len()).Bytes())
   390  			return
   391  		}
   392  
   393  		// When the underlying array isn't addressable fall back to copying the
   394  		// array into a new slice.  This is rather ugly, but the inability to
   395  		// create a constant slice from an unaddressable array seems to be a
   396  		// limitation of Go.
   397  		slice := make([]byte, v.Len(), v.Len())
   398  		reflect.Copy(reflect.ValueOf(slice), v)
   399  		err = enc.EncodeFixedOpaque(slice)
   400  		return
   401  	}
   402  
   403  	// Encode each array element.
   404  	for i := 0; i < v.Len(); i++ {
   405  		err = enc.encode(v.Index(i))
   406  		if err != nil {
   407  			return err
   408  		}
   409  	}
   410  	return
   411  }
   412  
   413  // encodeArray appends an XDR encoded integer representing the number of
   414  // elements in the passed slice represented by the reflection value followed by
   415  // the XDR encoded representation of each element in slice to the Encoder's
   416  // data.  The ignoreOpaque flag controls whether or not uint8 (byte) elements
   417  // should be encoded individually or as a variable sequence of opaque data.
   418  //
   419  // A MarshalError is returned if any issues are encountered while encoding
   420  // the array elements.
   421  //
   422  // Reference:
   423  //
   424  //	RFC Section 4.13 - Variable-Length Array
   425  //	Unsigned integer length followed by individually XDR encoded array elements
   426  func (enc *Encoder) encodeArray(v reflect.Value, ignoreOpaque bool) (err error) {
   427  	numItems := uint32(v.Len())
   428  	err = enc.encode(reflect.ValueOf(numItems))
   429  	if err != nil {
   430  		return err
   431  	}
   432  	err = enc.encodeFixedArray(v, ignoreOpaque)
   433  	return
   434  }
   435  
   436  // encodeStruct appends an XDR encoded representation of each value in the
   437  // exported fields of the struct represented by the passed reflection value to
   438  // the Encoder's data.  Pointers are automatically indirected through arbitrary
   439  // depth to encode the actual value pointed to.
   440  //
   441  // A MarshalError is returned if any issues are encountered while encoding
   442  // the elements.
   443  //
   444  // Reference:
   445  //
   446  //	RFC Section 4.14 - Structure
   447  //	XDR encoded elements in the order of their declaration in the struct
   448  func (enc *Encoder) encodeStruct(v reflect.Value) (err error) {
   449  	vt := v.Type()
   450  	for i := 0; i < v.NumField(); i++ {
   451  		// Skip unexported fields and indirect through pointers.
   452  		vtf := vt.Field(i)
   453  		if vtf.PkgPath != "" {
   454  			continue
   455  		}
   456  		vf := v.Field(i)
   457  		vf = enc.indirect(vf)
   458  
   459  		// Handle non-opaque data to []uint8 and [#]uint8 based on struct tag.
   460  		tag := vtf.Tag.Get("xdropaque")
   461  		if tag == "false" {
   462  			switch vf.Kind() {
   463  			case reflect.Slice:
   464  				err = enc.encodeArray(vf, true)
   465  				if err != nil {
   466  					return
   467  				}
   468  				continue
   469  
   470  			case reflect.Array:
   471  				err = enc.encodeFixedArray(vf, true)
   472  				if err != nil {
   473  					return
   474  				}
   475  				continue
   476  			}
   477  		}
   478  
   479  		// Encode each struct field.
   480  		err = enc.encode(vf)
   481  		if err != nil {
   482  			return err
   483  		}
   484  	}
   485  	return
   486  }
   487  
   488  // RFC Section 4.15 - Discriminated Union
   489  // RFC Section 4.16 - Void
   490  // RFC Section 4.17 - Constant
   491  // RFC Section 4.18 - Typedef
   492  // RFC Section 4.19 - Optional data
   493  // RFC Sections 4.15 though 4.19 only apply to the data specification language
   494  // which is not implemented by this package.  In the case of discriminated
   495  // unions, struct tags are used to perform a similar function.
   496  
   497  // encodeMap treats the map represented by the passed reflection value as a
   498  // variable-length array of 2-element structures whose fields are of the same
   499  // type as the map keys and elements and appends its XDR encoded representation
   500  // to the Encoder's data.
   501  //
   502  // A MarshalError is returned if any issues are encountered while encoding
   503  // the elements.
   504  func (enc *Encoder) encodeMap(v reflect.Value) (err error) {
   505  	dataLen := v.Len()
   506  	if uint(dataLen) > math.MaxUint32 {
   507  		err = marshalError("encodeMap", ErrOverflow, errMaxXdr, dataLen)
   508  		return
   509  	}
   510  	err = enc.EncodeUint(uint32(dataLen))
   511  	if err != nil {
   512  		return
   513  	}
   514  
   515  	// Encode each key and value according to their type.
   516  	for _, key := range v.MapKeys() {
   517  		err = enc.encode(key)
   518  		if err != nil {
   519  			return
   520  		}
   521  
   522  		err = enc.encode(v.MapIndex(key))
   523  		if err != nil {
   524  			return
   525  		}
   526  	}
   527  	return
   528  }
   529  
   530  // encodeInterface examines the interface represented by the passed reflection
   531  // value to detect whether it is an interface that can be encoded if it is,
   532  // extracts the underlying value to pass back into the encode function for
   533  // encoding according to its type.
   534  //
   535  // A MarshalError is returned if any issues are encountered while encoding
   536  // the interface.
   537  func (enc *Encoder) encodeInterface(v reflect.Value) (err error) {
   538  	if v.IsNil() || !v.CanInterface() {
   539  		msg := fmt.Sprintf("can't encode nil interface")
   540  		err = marshalError("encodeInterface", ErrNilInterface, msg, nil)
   541  		return err
   542  	}
   543  
   544  	// Extract underlying value from the interface and indirect through pointers.
   545  	ve := reflect.ValueOf(v.Interface())
   546  	ve = enc.indirect(ve)
   547  	return enc.encode(ve)
   548  }
   549  
   550  // encode is the main workhorse for marshalling via reflection.  It uses
   551  // the passed reflection value to choose the XDR primitives to encode into
   552  // the data field of the Encoder.  It is a recursive function, so cyclic data
   553  // structures are not supported and will result in an infinite loop.
   554  func (enc *Encoder) encode(v reflect.Value) (err error) {
   555  	if !v.IsValid() {
   556  		msg := fmt.Sprintf("type '%s' is not valid", v.Kind().String())
   557  		err = marshalError("encode", ErrUnsupportedType, msg, nil)
   558  		return
   559  	}
   560  
   561  	// Indirect through pointers to get at the concrete value.
   562  	ve := enc.indirect(v)
   563  
   564  	// Handle time.Time values by encoding them as an RFC3339 formatted
   565  	// string with nanosecond precision.  Check the type string before
   566  	// doing a full blown conversion to interface and type assertion since
   567  	// checking a string is much quicker.
   568  	if ve.Type().String() == "time.Time" && ve.CanInterface() {
   569  		viface := ve.Interface()
   570  		if tv, ok := viface.(time.Time); ok {
   571  			err = enc.EncodeString(tv.Format(time.RFC3339Nano))
   572  			return
   573  		}
   574  	}
   575  
   576  	// Handle native Go types.
   577  	switch ve.Kind() {
   578  	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int:
   579  		err = enc.EncodeInt(int32(ve.Int()))
   580  
   581  	case reflect.Int64:
   582  		err = enc.EncodeHyper(ve.Int())
   583  
   584  	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint:
   585  		err = enc.EncodeUint(uint32(ve.Uint()))
   586  
   587  	case reflect.Uint64:
   588  		err = enc.EncodeUhyper(ve.Uint())
   589  
   590  	case reflect.Bool:
   591  		err = enc.EncodeBool(ve.Bool())
   592  
   593  	case reflect.Float32:
   594  		err = enc.EncodeFloat(float32(ve.Float()))
   595  
   596  	case reflect.Float64:
   597  		err = enc.EncodeDouble(ve.Float())
   598  
   599  	case reflect.String:
   600  		err = enc.EncodeString(ve.String())
   601  
   602  	case reflect.Array:
   603  		err = enc.encodeFixedArray(ve, false)
   604  
   605  	case reflect.Slice:
   606  		err = enc.encodeArray(ve, false)
   607  
   608  	case reflect.Struct:
   609  		err = enc.encodeStruct(ve)
   610  
   611  	case reflect.Map:
   612  		err = enc.encodeMap(ve)
   613  
   614  	case reflect.Interface:
   615  		err = enc.encodeInterface(ve)
   616  
   617  	// reflect.Uintptr, reflect.UnsafePointer
   618  	default:
   619  		msg := fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String())
   620  		err = marshalError("encode", ErrUnsupportedType, msg, nil)
   621  	}
   622  
   623  	return
   624  }
   625  
   626  // indirect dereferences pointers until it reaches a non-pointer.  This allows
   627  // transparent encoding through arbitrary levels of indirection.
   628  func (enc *Encoder) indirect(v reflect.Value) (rv reflect.Value) {
   629  	rv = v
   630  	for rv.Kind() == reflect.Ptr {
   631  		rv = rv.Elem()
   632  	}
   633  	return
   634  }
   635  
   636  // Data returns the XDR encoded data stored in the Encoder.
   637  func (enc *Encoder) Data() (rv []byte) {
   638  	return enc.data[:]
   639  }
   640  
   641  // Reset clears the internal XDR encoded data so the Encoder may be reused.
   642  func (enc *Encoder) Reset() {
   643  	enc.data = enc.data[0:0]
   644  }
   645  
   646  // NewEncoder returns an object that can be used to manually build an XDR
   647  // encoded byte slice.  Typically, Marshal should be used instead of manually
   648  // creating an Encoder. An Encoder, along with several of its methods to encode
   649  // XDR primitives, is exposed so it is possible to perform manual encoding of
   650  // data without relying on reflection should it be necessary in complex
   651  // scenarios where automatic reflection-based decoding won't work.
   652  func NewEncoder() *Encoder {
   653  	return &Encoder{}
   654  }