code: func (d *Decoder) decodeStruct(v reflect.Value) (err error) {
  	vt := v.Type()
  	for i := 0; i < v.NumField(); i++ {
  		// Skip unexported fields.
  		vtf := vt.Field(i)
  		if vtf.PkgPath != "" {
  			continue
  		}
  
  		// Indirect through pointers allocating them as needed and ensure
  		// the field is settable.
  		vf := v.Field(i)
  		vf, err = d.indirect(vf)
  		if err != nil {
  			return err
  		}
  		if !vf.CanSet() {
  			msg := fmt.Sprintf("can't decode to unsettable '%v'",
  				vf.Type().String())
  			err = unmarshalError("decodeStruct", ErrNotSettable, msg, nil)
  			return err
  		}
  
  		// Handle non-opaque data to []uint8 and [#]uint8 based on struct tag.
  		tag := vtf.Tag.Get("xdropaque")
  		if tag == "false" {
  			switch vf.Kind() {
  			case reflect.Slice:
  				err = d.decodeArray(vf, true)
  				if err != nil {
  					return
  				}
  				continue
  
  			case reflect.Array:
  				err = d.decodeFixedArray(vf, true)
  				if err != nil {
  					return
  				}
  				continue
  			}
  		}
  
  		// Decode each struct field.
  		err = d.decode(vf)
  		if err != nil {
  			return err
  		}
  	}
  	return
  }
docs: // decodeStruct treats the next bytes as a series of XDR encoded elements
  // of the same type as the exported fields of the struct represented by the
  // passed reflection value.  Pointers are automatically indirected and
  // allocated as necessary.
  //
  // An UnmarshalError is returned if any issues are encountered while decoding
  // the elements.
  //
  // Reference:
  // 	RFC Section 4.14 - Structure
  // 	XDR encoded elements in the order of their declaration in the struct