github.com/davecgh/go-xdr@v0.0.0-20161123171359-e6a2ba005892/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  // 	RFC Section 4.1 - Integer
   113  // 	32-bit big-endian signed integer in range [-2147483648, 2147483647]
   114  func (enc *Encoder) EncodeInt(v int32) (err error) {
   115  	b := make([]byte, 4, 4)
   116  	b[0] = byte(v >> 24)
   117  	b[1] = byte(v >> 16)
   118  	b[2] = byte(v >> 8)
   119  	b[3] = byte(v)
   120  
   121  	if len(enc.data) > maxInt-4 {
   122  		err = marshalError("EncodeInt", ErrOverflow, errMaxSlice, b)
   123  		return
   124  	}
   125  
   126  	enc.data = append(enc.data, b...)
   127  	return
   128  }
   129  
   130  // EncodeInt appends the XDR encoded representation of the passed 32-bit
   131  // unsigned integer to the Encoder's data.
   132  //
   133  // A MarshalError is returned if appending the data would overflow the
   134  // internal data slice.
   135  //
   136  // Reference:
   137  // 	RFC Section 4.2 - Unsigned Integer
   138  // 	32-bit big-endian unsigned integer in range [0, 4294967295]
   139  func (enc *Encoder) EncodeUint(v uint32) (err error) {
   140  	b := make([]byte, 4, 4)
   141  	b[0] = byte(v >> 24)
   142  	b[1] = byte(v >> 16)
   143  	b[2] = byte(v >> 8)
   144  	b[3] = byte(v)
   145  
   146  	if len(enc.data) > maxInt-4 {
   147  		err = marshalError("EncodeUint", ErrOverflow, errMaxSlice, b)
   148  		return
   149  	}
   150  
   151  	enc.data = append(enc.data, b...)
   152  	return
   153  }
   154  
   155  // EncodeEnum treats the passed 32-bit signed integer as an enumeration value
   156  // and, if it is in the list of passed valid enumeration values, appends the XDR
   157  // encoded representation of it to the Encoder's data.
   158  //
   159  // A MarshalError is returned if the enumeration value is not one of the provided
   160  // valid values or appending the data would overflow the internal data slice.
   161  //
   162  // Reference:
   163  // 	RFC Section 4.3 - Enumeration
   164  // 	Represented as an XDR encoded signed integer
   165  func (enc *Encoder) EncodeEnum(v int32, validEnums map[int32]bool) (err error) {
   166  	if !validEnums[v] {
   167  		err = marshalError("EncodeEnum", ErrBadEnumValue, "invalid enum", v)
   168  		return
   169  	}
   170  	return enc.EncodeInt(v)
   171  }
   172  
   173  // EncodeInt appends the XDR encoded representation of the passed boolean
   174  // to the Encoder's data.
   175  //
   176  // A MarshalError is returned if appending the data would overflow the
   177  // internal data slice.
   178  //
   179  // Reference:
   180  // 	RFC Section 4.4 - Boolean
   181  // 	Represented as an XDR encoded enumeration where 0 is false and 1 is true
   182  func (enc *Encoder) EncodeBool(v bool) (err error) {
   183  	i := int32(0)
   184  	if v == true {
   185  		i = 1
   186  	}
   187  	return enc.EncodeInt(i)
   188  }
   189  
   190  // EncodeHyper appends the XDR encoded representation of the passed 64-bit
   191  // signed integer to the Encoder's data.
   192  //
   193  // A MarshalError is returned if appending the data would overflow the
   194  // internal data slice.
   195  //
   196  // Reference:
   197  // 	RFC Section 4.5 - Hyper Integer
   198  // 	64-bit big-endian signed integer in range [-9223372036854775808, 9223372036854775807]
   199  func (enc *Encoder) EncodeHyper(v int64) (err error) {
   200  	b := make([]byte, 8, 8)
   201  	b[0] = byte(v >> 56)
   202  	b[1] = byte(v >> 48)
   203  	b[2] = byte(v >> 40)
   204  	b[3] = byte(v >> 32)
   205  	b[4] = byte(v >> 24)
   206  	b[5] = byte(v >> 16)
   207  	b[6] = byte(v >> 8)
   208  	b[7] = byte(v)
   209  
   210  	if len(enc.data) > maxInt-8 {
   211  		err = marshalError("EncodeHyper", ErrOverflow, errMaxSlice, b)
   212  		return
   213  	}
   214  
   215  	enc.data = append(enc.data, b...)
   216  	return
   217  }
   218  
   219  // EncodeUhyper appends the XDR encoded representation of the passed 64-bit
   220  // unsigned integer to the Encoder's data.
   221  //
   222  // A MarshalError is returned if appending the data would overflow the
   223  // internal data slice.
   224  //
   225  // Reference:
   226  // 	RFC Section 4.5 - Unsigned Hyper Integer
   227  // 	64-bit big-endian unsigned integer in range [0, 18446744073709551615]
   228  func (enc *Encoder) EncodeUhyper(v uint64) (err error) {
   229  	b := make([]byte, 8, 8)
   230  	b[0] = byte(v >> 56)
   231  	b[1] = byte(v >> 48)
   232  	b[2] = byte(v >> 40)
   233  	b[3] = byte(v >> 32)
   234  	b[4] = byte(v >> 24)
   235  	b[5] = byte(v >> 16)
   236  	b[6] = byte(v >> 8)
   237  	b[7] = byte(v)
   238  
   239  	if len(enc.data) > maxInt-8 {
   240  		err = marshalError("EncodeUhyper", ErrOverflow, errMaxSlice, b)
   241  		return
   242  	}
   243  
   244  	enc.data = append(enc.data, b...)
   245  	return
   246  }
   247  
   248  // EncodeFloat appends the XDR encoded representation of the passed 32-bit
   249  // (single-precision) floating point to the Encoder's data.
   250  //
   251  // A MarshalError is returned if appending the data would overflow the
   252  // internal data slice.
   253  //
   254  // Reference:
   255  // 	RFC Section 4.6 - Floating Point
   256  // 	32-bit single-precision IEEE 754 floating point
   257  func (enc *Encoder) EncodeFloat(v float32) (err error) {
   258  	ui := math.Float32bits(v)
   259  	return enc.EncodeUint(ui)
   260  }
   261  
   262  // EncodeDouble appends the XDR encoded representation of the passed 64-bit
   263  // (double-precision) floating point to the Encoder's data.
   264  //
   265  // A MarshalError is returned if appending the data would overflow the
   266  // internal data slice.
   267  //
   268  // Reference:
   269  // 	RFC Section 4.7 -  Double-Precision Floating Point
   270  // 	64-bit double-precision IEEE 754 floating point
   271  func (enc *Encoder) EncodeDouble(v float64) (err error) {
   272  	ui := math.Float64bits(v)
   273  	return enc.EncodeUhyper(ui)
   274  }
   275  
   276  // RFC Section 4.8 -  Quadruple-Precision Floating Point
   277  // 128-bit quadruple-precision floating point
   278  // Not Implemented
   279  
   280  // EncodeFixedOpaque treats the passed byte slice as opaque data of a fixed
   281  // size and appends the XDR encoded representation of it to the Encoder's data.
   282  //
   283  // A MarshalError is returned if appending the data would overflow the
   284  // internal data slice.
   285  //
   286  // Reference:
   287  // 	RFC Section 4.9 - Fixed-Length Opaque Data
   288  // 	Fixed-length uninterpreted data zero-padded to a multiple of four
   289  func (enc *Encoder) EncodeFixedOpaque(v []byte) (err error) {
   290  	l := len(v)
   291  	pad := (4 - (l % 4)) % 4
   292  	size := l + pad
   293  
   294  	if len(enc.data) > maxInt-size {
   295  		err = marshalError("EncodeFixedOpaque", ErrOverflow, errMaxSlice, size)
   296  		return
   297  	}
   298  
   299  	enc.data = append(enc.data, v...)
   300  	if pad > 0 {
   301  		b := make([]byte, pad, pad)
   302  		for i := 0; i < pad; i++ {
   303  			b[i] = 0
   304  		}
   305  		enc.data = append(enc.data, b...)
   306  	}
   307  	return
   308  }
   309  
   310  // EncodeOpaque treats the passed byte slice as opaque data of a variable
   311  // size and appends the XDR encoded representation of it to the Encoder's data.
   312  //
   313  // A MarshalError is returned if appending the data would overflow the
   314  // internal data slice or the data in the byte slice is larger than XDR
   315  // supports.
   316  //
   317  // Reference:
   318  // 	RFC Section 4.10 - Variable-Length Opaque Data
   319  // 	Unsigned integer length followed by fixed opaque data of that length
   320  func (enc *Encoder) EncodeOpaque(v []byte) (err error) {
   321  	dataLen := len(v)
   322  	if uint(dataLen) > math.MaxUint32 {
   323  		err = marshalError("EncodeOpaque", ErrOverflow, errMaxXdr, dataLen)
   324  		return
   325  	}
   326  	err = enc.EncodeUint(uint32(dataLen))
   327  	if err != nil {
   328  		return
   329  	}
   330  	err = enc.EncodeFixedOpaque(v)
   331  	return
   332  }
   333  
   334  // EncodeString appends the XDR encoded representation of the passed string
   335  // to the Encoder's data.  Character encoding is assumed to be UTF-8 and
   336  // therefore ASCII compatible.  If the underlying character encoding
   337  // is not compatible with this assumption, the data can instead be written as
   338  // variable-length opaque data (EncodeOpaque) and manually converted as needed.
   339  //
   340  // A MarshalError is returned if appending the data would overflow the
   341  // internal data slice or the length of the string is larger than XDR supports.
   342  //
   343  // Reference:
   344  // 	RFC Section 4.11 - String
   345  // 	Unsigned integer length followed by bytes zero-padded to a multiple of four
   346  func (enc *Encoder) EncodeString(v string) (err error) {
   347  	dataLen := len(v)
   348  	if uint(dataLen) > math.MaxUint32 {
   349  		err = marshalError("EncodeString", ErrOverflow, errMaxXdr, dataLen)
   350  		return
   351  	}
   352  	err = enc.EncodeUint(uint32(dataLen))
   353  	if err != nil {
   354  		return
   355  	}
   356  	err = enc.EncodeFixedOpaque([]byte(v))
   357  	return
   358  }
   359  
   360  // encodeFixedArray appends the XDR encoded representation of each element
   361  // in the passed array represented by the reflection value to the Encoder's
   362  // data.  The ignoreOpaque flag controls whether or not uint8 (byte) elements
   363  // should be encoded individually or as a fixed sequence of opaque data.
   364  //
   365  // A MarshalError is returned if any issues are encountered while encoding
   366  // the array elements.
   367  //
   368  // Reference:
   369  // 	RFC Section 4.12 - Fixed-Length Array
   370  // 	Individually XDR encoded array elements
   371  func (enc *Encoder) encodeFixedArray(v reflect.Value, ignoreOpaque bool) (err error) {
   372  	// Treat [#]byte (byte is alias for uint8) as opaque data unless ignored.
   373  	if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
   374  		// Create a slice of the underlying array for better efficiency when
   375  		// possible.  Can't create a slice of an unaddressable value.
   376  		if v.CanAddr() {
   377  			err = enc.EncodeFixedOpaque(v.Slice(0, v.Len()).Bytes())
   378  			return
   379  		}
   380  
   381  		// When the underlying array isn't addressable fall back to copying the
   382  		// array into a new slice.  This is rather ugly, but the inability to
   383  		// create a constant slice from an unaddressable array seems to be a
   384  		// limitation of Go.
   385  		slice := make([]byte, v.Len(), v.Len())
   386  		reflect.Copy(reflect.ValueOf(slice), v)
   387  		err = enc.EncodeFixedOpaque(slice)
   388  		return
   389  	}
   390  
   391  	// Encode each array element.
   392  	for i := 0; i < v.Len(); i++ {
   393  		err = enc.encode(v.Index(i))
   394  		if err != nil {
   395  			return err
   396  		}
   397  	}
   398  	return
   399  }
   400  
   401  // encodeArray appends an XDR encoded integer representing the number of
   402  // elements in the passed slice represented by the reflection value followed by
   403  // the XDR encoded representation of each element in slice to the Encoder's
   404  // data.  The ignoreOpaque flag controls whether or not uint8 (byte) elements
   405  // should be encoded individually or as a variable sequence of opaque data.
   406  //
   407  // A MarshalError is returned if any issues are encountered while encoding
   408  // the array elements.
   409  //
   410  // Reference:
   411  // 	RFC Section 4.13 - Variable-Length Array
   412  // 	Unsigned integer length followed by individually XDR encoded array elements
   413  func (enc *Encoder) encodeArray(v reflect.Value, ignoreOpaque bool) (err error) {
   414  	numItems := uint32(v.Len())
   415  	err = enc.encode(reflect.ValueOf(numItems))
   416  	if err != nil {
   417  		return err
   418  	}
   419  	err = enc.encodeFixedArray(v, ignoreOpaque)
   420  	return
   421  }
   422  
   423  // encodeStruct appends an XDR encoded representation of each value in the
   424  // exported fields of the struct represented by the passed reflection value to
   425  // the Encoder's data.  Pointers are automatically indirected through arbitrary
   426  // depth to encode the actual value pointed to.
   427  //
   428  // A MarshalError is returned if any issues are encountered while encoding
   429  // the elements.
   430  //
   431  // Reference:
   432  // 	RFC Section 4.14 - Structure
   433  // 	XDR encoded elements in the order of their declaration in the struct
   434  func (enc *Encoder) encodeStruct(v reflect.Value) (err error) {
   435  	vt := v.Type()
   436  	for i := 0; i < v.NumField(); i++ {
   437  		// Skip unexported fields and indirect through pointers.
   438  		vtf := vt.Field(i)
   439  		if vtf.PkgPath != "" {
   440  			continue
   441  		}
   442  		vf := v.Field(i)
   443  		vf = enc.indirect(vf)
   444  
   445  		// Handle non-opaque data to []uint8 and [#]uint8 based on struct tag.
   446  		tag := vtf.Tag.Get("xdropaque")
   447  		if tag == "false" {
   448  			switch vf.Kind() {
   449  			case reflect.Slice:
   450  				err = enc.encodeArray(vf, true)
   451  				if err != nil {
   452  					return
   453  				}
   454  				continue
   455  
   456  			case reflect.Array:
   457  				err = enc.encodeFixedArray(vf, true)
   458  				if err != nil {
   459  					return
   460  				}
   461  				continue
   462  			}
   463  		}
   464  
   465  		// Encode each struct field.
   466  		err = enc.encode(vf)
   467  		if err != nil {
   468  			return err
   469  		}
   470  	}
   471  	return
   472  }
   473  
   474  // RFC Section 4.15 - Discriminated Union
   475  // RFC Section 4.16 - Void
   476  // RFC Section 4.17 - Constant
   477  // RFC Section 4.18 - Typedef
   478  // RFC Section 4.19 - Optional data
   479  // RFC Sections 4.15 though 4.19 only apply to the data specification language
   480  // which is not implemented by this package.  In the case of discriminated
   481  // unions, struct tags are used to perform a similar function.
   482  
   483  // encodeMap treats the map represented by the passed reflection value as a
   484  // variable-length array of 2-element structures whose fields are of the same
   485  // type as the map keys and elements and appends its XDR encoded representation
   486  // to the Encoder's data.
   487  //
   488  // A MarshalError is returned if any issues are encountered while encoding
   489  // the elements.
   490  func (enc *Encoder) encodeMap(v reflect.Value) (err error) {
   491  	dataLen := v.Len()
   492  	if uint(dataLen) > math.MaxUint32 {
   493  		err = marshalError("encodeMap", ErrOverflow, errMaxXdr, dataLen)
   494  		return
   495  	}
   496  	err = enc.EncodeUint(uint32(dataLen))
   497  	if err != nil {
   498  		return
   499  	}
   500  
   501  	// Encode each key and value according to their type.
   502  	for _, key := range v.MapKeys() {
   503  		err = enc.encode(key)
   504  		if err != nil {
   505  			return
   506  		}
   507  
   508  		err = enc.encode(v.MapIndex(key))
   509  		if err != nil {
   510  			return
   511  		}
   512  	}
   513  	return
   514  }
   515  
   516  // encodeInterface examines the interface represented by the passed reflection
   517  // value to detect whether it is an interface that can be encoded if it is,
   518  // extracts the underlying value to pass back into the encode function for
   519  // encoding according to its type.
   520  //
   521  // A MarshalError is returned if any issues are encountered while encoding
   522  // the interface.
   523  func (enc *Encoder) encodeInterface(v reflect.Value) (err error) {
   524  	if v.IsNil() || !v.CanInterface() {
   525  		msg := fmt.Sprintf("can't encode nil interface")
   526  		err = marshalError("encodeInterface", ErrNilInterface, msg, nil)
   527  		return err
   528  	}
   529  
   530  	// Extract underlying value from the interface and indirect through pointers.
   531  	ve := reflect.ValueOf(v.Interface())
   532  	ve = enc.indirect(ve)
   533  	return enc.encode(ve)
   534  }
   535  
   536  // encode is the main workhorse for marshalling via reflection.  It uses
   537  // the passed reflection value to choose the XDR primitives to encode into
   538  // the data field of the Encoder.  It is a recursive function, so cyclic data
   539  // structures are not supported and will result in an infinite loop.
   540  func (enc *Encoder) encode(v reflect.Value) (err error) {
   541  	if !v.IsValid() {
   542  		msg := fmt.Sprintf("type '%s' is not valid", v.Kind().String())
   543  		err = marshalError("encode", ErrUnsupportedType, msg, nil)
   544  		return
   545  	}
   546  
   547  	// Indirect through pointers to get at the concrete value.
   548  	ve := enc.indirect(v)
   549  
   550  	// Handle time.Time values by encoding them as an RFC3339 formatted
   551  	// string with nanosecond precision.  Check the type string before
   552  	// doing a full blown conversion to interface and type assertion since
   553  	// checking a string is much quicker.
   554  	if ve.Type().String() == "time.Time" && ve.CanInterface() {
   555  		viface := ve.Interface()
   556  		if tv, ok := viface.(time.Time); ok {
   557  			err = enc.EncodeString(tv.Format(time.RFC3339Nano))
   558  			return
   559  		}
   560  	}
   561  
   562  	// Handle native Go types.
   563  	switch ve.Kind() {
   564  	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int:
   565  		err = enc.EncodeInt(int32(ve.Int()))
   566  
   567  	case reflect.Int64:
   568  		err = enc.EncodeHyper(ve.Int())
   569  
   570  	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint:
   571  		err = enc.EncodeUint(uint32(ve.Uint()))
   572  
   573  	case reflect.Uint64:
   574  		err = enc.EncodeUhyper(ve.Uint())
   575  
   576  	case reflect.Bool:
   577  		err = enc.EncodeBool(ve.Bool())
   578  
   579  	case reflect.Float32:
   580  		err = enc.EncodeFloat(float32(ve.Float()))
   581  
   582  	case reflect.Float64:
   583  		err = enc.EncodeDouble(ve.Float())
   584  
   585  	case reflect.String:
   586  		err = enc.EncodeString(ve.String())
   587  
   588  	case reflect.Array:
   589  		err = enc.encodeFixedArray(ve, false)
   590  
   591  	case reflect.Slice:
   592  		err = enc.encodeArray(ve, false)
   593  
   594  	case reflect.Struct:
   595  		err = enc.encodeStruct(ve)
   596  
   597  	case reflect.Map:
   598  		err = enc.encodeMap(ve)
   599  
   600  	case reflect.Interface:
   601  		err = enc.encodeInterface(ve)
   602  
   603  	// reflect.Uintptr, reflect.UnsafePointer
   604  	default:
   605  		msg := fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String())
   606  		err = marshalError("encode", ErrUnsupportedType, msg, nil)
   607  	}
   608  
   609  	return
   610  }
   611  
   612  // indirect dereferences pointers until it reaches a non-pointer.  This allows
   613  // transparent encoding through arbitrary levels of indirection.
   614  func (enc *Encoder) indirect(v reflect.Value) (rv reflect.Value) {
   615  	rv = v
   616  	for rv.Kind() == reflect.Ptr {
   617  		rv = rv.Elem()
   618  	}
   619  	return
   620  }
   621  
   622  // Data returns the XDR encoded data stored in the Encoder.
   623  func (enc *Encoder) Data() (rv []byte) {
   624  	return enc.data[:]
   625  }
   626  
   627  // Reset clears the internal XDR encoded data so the Encoder may be reused.
   628  func (enc *Encoder) Reset() {
   629  	enc.data = enc.data[0:0]
   630  }
   631  
   632  // NewEncoder returns an object that can be used to manually build an XDR
   633  // encoded byte slice.  Typically, Marshal should be used instead of manually
   634  // creating an Encoder. An Encoder, along with several of its methods to encode
   635  // XDR primitives, is exposed so it is possible to perform manual encoding of
   636  // data without relying on reflection should it be necessary in complex
   637  // scenarios where automatic reflection-based decoding won't work.
   638  func NewEncoder() *Encoder {
   639  	return &Encoder{}
   640  }