summaryrefslogtreecommitdiff
path: root/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2021-03-25 10:50:01 -0700
committerGitHub <noreply@github.com>2021-03-25 10:50:01 -0700
commitdb356748738762c31a036c179d23488d7978dabf (patch)
treea01d257cba3349b47ff743b11eaa7f496bac991b /vendor/github.com/digitalocean/go-libvirt/internal/go-xdr
parent24581d8760691af1657c4f890d42ebd76f5e85c4 (diff)
parent4ab8a6f67eb9de0de40d478cb0cbec05b1b725c0 (diff)
downloadpodman-db356748738762c31a036c179d23488d7978dabf.tar.gz
podman-db356748738762c31a036c179d23488d7978dabf.tar.bz2
podman-db356748738762c31a036c179d23488d7978dabf.zip
Merge pull request #9781 from baude/addqemu
introduce podman machine
Diffstat (limited to 'vendor/github.com/digitalocean/go-libvirt/internal/go-xdr')
-rw-r--r--vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/LICENSE13
-rw-r--r--vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/decode.go896
-rw-r--r--vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/doc.go171
-rw-r--r--vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/encode.go669
-rw-r--r--vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/error.go177
5 files changed, 1926 insertions, 0 deletions
diff --git a/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/LICENSE b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/LICENSE
new file mode 100644
index 000000000..0cc3543ce
--- /dev/null
+++ b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file
diff --git a/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/decode.go b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/decode.go
new file mode 100644
index 000000000..7f33f7d32
--- /dev/null
+++ b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/decode.go
@@ -0,0 +1,896 @@
+/*
+ * Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package xdr
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "time"
+)
+
+var (
+ errMaxSlice = "data exceeds max slice limit"
+ errIODecode = "%s while decoding %d bytes"
+)
+
+/*
+Unmarshal parses XDR-encoded data into the value pointed to by v reading from
+reader r and returning the total number of bytes read. An addressable pointer
+must be provided since Unmarshal needs to both store the result of the decode as
+well as obtain target type information. Unmarhsal traverses v recursively and
+automatically indirects pointers through arbitrary depth, allocating them as
+necessary, to decode the data into the underlying value pointed to.
+
+Unmarshal uses reflection to determine the type of the concrete value contained
+by v and performs a mapping of underlying XDR types to Go types as follows:
+
+ Go Type <- XDR Type
+ --------------------
+ int8, int16, int32, int <- XDR Integer
+ uint8, uint16, uint32, uint <- XDR Unsigned Integer
+ int64 <- XDR Hyper Integer
+ uint64 <- XDR Unsigned Hyper Integer
+ bool <- XDR Boolean
+ float32 <- XDR Floating-Point
+ float64 <- XDR Double-Precision Floating-Point
+ string <- XDR String
+ byte <- XDR Integer
+ []byte <- XDR Variable-Length Opaque Data
+ [#]byte <- XDR Fixed-Length Opaque Data
+ []<type> <- XDR Variable-Length Array
+ [#]<type> <- XDR Fixed-Length Array
+ struct <- XDR Structure
+ map <- XDR Variable-Length Array of two-element XDR Structures
+ time.Time <- XDR String encoded with RFC3339 nanosecond precision
+
+Notes and Limitations:
+
+ * Automatic unmarshalling of variable and fixed-length arrays of uint8s
+ requires a special struct tag `xdropaque:"false"` since byte slices
+ and byte arrays are assumed to be opaque data and byte is a Go alias
+ for uint8 thus indistinguishable under reflection
+ * Cyclic data structures are not supported and will result in infinite
+ loops
+
+If any issues are encountered during the unmarshalling process, an
+UnmarshalError is returned with a human readable description as well as
+an ErrorCode value for further inspection from sophisticated callers. Some
+potential issues are unsupported Go types, attempting to decode a value which is
+too large to fit into a specified Go type, and exceeding max slice limitations.
+*/
+func Unmarshal(r io.Reader, v interface{}) (int, error) {
+ d := Decoder{r: r}
+ return d.Decode(v)
+}
+
+// UnmarshalLimited is identical to Unmarshal but it sets maxReadSize in order
+// to cap reads.
+func UnmarshalLimited(r io.Reader, v interface{}, maxSize uint) (int, error) {
+ d := Decoder{r: r, maxReadSize: maxSize}
+ return d.Decode(v)
+}
+
+// TypeDecoder lets a caller provide a custom decode routine for a custom type.
+type TypeDecoder interface {
+ Decode(*Decoder, reflect.Value) (int, error)
+}
+
+// A Decoder wraps an io.Reader that is expected to provide an XDR-encoded byte
+// stream and provides several exposed methods to manually decode various XDR
+// primitives without relying on reflection. The NewDecoder function can be
+// used to get a new Decoder directly.
+//
+// Typically, Unmarshal should be used instead of manual decoding. A Decoder
+// is exposed so it is possible to perform manual decoding should it be
+// necessary in complex scenarios where automatic reflection-based decoding
+// won't work.
+type Decoder struct {
+ r io.Reader
+
+ // maxReadSize is the default maximum bytes an element can contain. 0
+ // is unlimited and provides backwards compatability. Setting it to a
+ // non-zero value caps reads.
+ maxReadSize uint
+
+ // customTypes is a map allowing the caller to provide decoder routines for
+ // custom types known only to itself.
+ customTypes map[string]TypeDecoder
+}
+
+// DecodeInt treats the next 4 bytes as an XDR encoded integer and returns the
+// result as an int32 along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.1 - Integer
+// 32-bit big-endian signed integer in range [-2147483648, 2147483647]
+func (d *Decoder) DecodeInt() (int32, int, error) {
+ var buf [4]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 4)
+ err := unmarshalError("DecodeInt", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ rv := int32(buf[3]) | int32(buf[2])<<8 |
+ int32(buf[1])<<16 | int32(buf[0])<<24
+ return rv, n, nil
+}
+
+// DecodeUint treats the next 4 bytes as an XDR encoded unsigned integer and
+// returns the result as a uint32 along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.2 - Unsigned Integer
+// 32-bit big-endian unsigned integer in range [0, 4294967295]
+func (d *Decoder) DecodeUint() (uint32, int, error) {
+ var buf [4]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 4)
+ err := unmarshalError("DecodeUint", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ rv := uint32(buf[3]) | uint32(buf[2])<<8 |
+ uint32(buf[1])<<16 | uint32(buf[0])<<24
+ return rv, n, nil
+}
+
+// DecodeEnum treats the next 4 bytes as an XDR encoded enumeration value and
+// returns the result as an int32 after verifying that the value is in the
+// provided map of valid values. It also returns the number of bytes actually
+// read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining or
+// the parsed enumeration value is not one of the provided valid values.
+//
+// Reference:
+// RFC Section 4.3 - Enumeration
+// Represented as an XDR encoded signed integer
+func (d *Decoder) DecodeEnum(validEnums map[int32]bool) (int32, int, error) {
+ val, n, err := d.DecodeInt()
+ if err != nil {
+ return 0, n, err
+ }
+
+ if !validEnums[val] {
+ err := unmarshalError("DecodeEnum", ErrBadEnumValue,
+ "invalid enum", val, nil)
+ return 0, n, err
+ }
+ return val, n, nil
+}
+
+// DecodeBool treats the next 4 bytes as an XDR encoded boolean value and
+// returns the result as a bool along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining or
+// the parsed value is not a 0 or 1.
+//
+// Reference:
+// RFC Section 4.4 - Boolean
+// Represented as an XDR encoded enumeration where 0 is false and 1 is true
+func (d *Decoder) DecodeBool() (bool, int, error) {
+ val, n, err := d.DecodeInt()
+ if err != nil {
+ return false, n, err
+ }
+ switch val {
+ case 0:
+ return false, n, nil
+ case 1:
+ return true, n, nil
+ }
+
+ err = unmarshalError("DecodeBool", ErrBadEnumValue, "bool not 0 or 1",
+ val, nil)
+ return false, n, err
+}
+
+// DecodeHyper treats the next 8 bytes as an XDR encoded hyper value and
+// returns the result as an int64 along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.5 - Hyper Integer
+// 64-bit big-endian signed integer in range [-9223372036854775808, 9223372036854775807]
+func (d *Decoder) DecodeHyper() (int64, int, error) {
+ var buf [8]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 8)
+ err := unmarshalError("DecodeHyper", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ rv := int64(buf[7]) | int64(buf[6])<<8 |
+ int64(buf[5])<<16 | int64(buf[4])<<24 |
+ int64(buf[3])<<32 | int64(buf[2])<<40 |
+ int64(buf[1])<<48 | int64(buf[0])<<56
+ return rv, n, err
+}
+
+// DecodeUhyper treats the next 8 bytes as an XDR encoded unsigned hyper value
+// and returns the result as a uint64 along with the number of bytes actually
+// read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.5 - Unsigned Hyper Integer
+// 64-bit big-endian unsigned integer in range [0, 18446744073709551615]
+func (d *Decoder) DecodeUhyper() (uint64, int, error) {
+ var buf [8]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 8)
+ err := unmarshalError("DecodeUhyper", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ rv := uint64(buf[7]) | uint64(buf[6])<<8 |
+ uint64(buf[5])<<16 | uint64(buf[4])<<24 |
+ uint64(buf[3])<<32 | uint64(buf[2])<<40 |
+ uint64(buf[1])<<48 | uint64(buf[0])<<56
+ return rv, n, nil
+}
+
+// DecodeFloat treats the next 4 bytes as an XDR encoded floating point and
+// returns the result as a float32 along with the number of bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.6 - Floating Point
+// 32-bit single-precision IEEE 754 floating point
+func (d *Decoder) DecodeFloat() (float32, int, error) {
+ var buf [4]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 4)
+ err := unmarshalError("DecodeFloat", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ val := uint32(buf[3]) | uint32(buf[2])<<8 |
+ uint32(buf[1])<<16 | uint32(buf[0])<<24
+ return math.Float32frombits(val), n, nil
+}
+
+// DecodeDouble treats the next 8 bytes as an XDR encoded double-precision
+// floating point and returns the result as a float64 along with the number of
+// bytes actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining.
+//
+// Reference:
+// RFC Section 4.7 - Double-Precision Floating Point
+// 64-bit double-precision IEEE 754 floating point
+func (d *Decoder) DecodeDouble() (float64, int, error) {
+ var buf [8]byte
+ n, err := io.ReadFull(d.r, buf[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), 8)
+ err := unmarshalError("DecodeDouble", ErrIO, msg, buf[:n], err)
+ return 0, n, err
+ }
+
+ val := uint64(buf[7]) | uint64(buf[6])<<8 |
+ uint64(buf[5])<<16 | uint64(buf[4])<<24 |
+ uint64(buf[3])<<32 | uint64(buf[2])<<40 |
+ uint64(buf[1])<<48 | uint64(buf[0])<<56
+ return math.Float64frombits(val), n, nil
+}
+
+// RFC Section 4.8 - Quadruple-Precision Floating Point
+// 128-bit quadruple-precision floating point
+// Not Implemented
+
+// DecodeFixedOpaque treats the next 'size' bytes as XDR encoded opaque data and
+// returns the result as a byte slice along with the number of bytes actually
+// read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining to
+// satisfy the passed size, including the necessary padding to make it a
+// multiple of 4.
+//
+// Reference:
+// RFC Section 4.9 - Fixed-Length Opaque Data
+// Fixed-length uninterpreted data zero-padded to a multiple of four
+func (d *Decoder) DecodeFixedOpaque(size int32) ([]byte, int, error) {
+ // Nothing to do if size is 0.
+ if size == 0 {
+ return nil, 0, nil
+ }
+
+ pad := (4 - (size % 4)) % 4
+ paddedSize := size + pad
+ if uint(paddedSize) > uint(math.MaxInt32) {
+ err := unmarshalError("DecodeFixedOpaque", ErrOverflow,
+ errMaxSlice, paddedSize, nil)
+ return nil, 0, err
+ }
+
+ buf := make([]byte, paddedSize)
+ n, err := io.ReadFull(d.r, buf)
+ if err != nil {
+ msg := fmt.Sprintf(errIODecode, err.Error(), paddedSize)
+ err := unmarshalError("DecodeFixedOpaque", ErrIO, msg, buf[:n],
+ err)
+ return nil, n, err
+ }
+ return buf[0:size], n, nil
+}
+
+// DecodeOpaque treats the next bytes as variable length XDR encoded opaque
+// data and returns the result as a byte slice along with the number of bytes
+// actually read.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining or
+// the opaque data is larger than the max length of a Go slice.
+//
+// Reference:
+// RFC Section 4.10 - Variable-Length Opaque Data
+// Unsigned integer length followed by fixed opaque data of that length
+func (d *Decoder) DecodeOpaque() ([]byte, int, error) {
+ dataLen, n, err := d.DecodeUint()
+ if err != nil {
+ return nil, n, err
+ }
+ if uint(dataLen) > uint(math.MaxInt32) ||
+ (d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
+ err := unmarshalError("DecodeOpaque", ErrOverflow, errMaxSlice,
+ dataLen, nil)
+ return nil, n, err
+ }
+
+ rv, n2, err := d.DecodeFixedOpaque(int32(dataLen))
+ n += n2
+ if err != nil {
+ return nil, n, err
+ }
+ return rv, n, nil
+}
+
+// DecodeString treats the next bytes as a variable length XDR encoded string
+// and returns the result as a string along with the number of bytes actually
+// read. Character encoding is assumed to be UTF-8 and therefore ASCII
+// compatible. If the underlying character encoding is not compatibile with
+// this assumption, the data can instead be read as variable-length opaque data
+// (DecodeOpaque) and manually converted as needed.
+//
+// An UnmarshalError is returned if there are insufficient bytes remaining or
+// the string data is larger than the max length of a Go slice.
+//
+// Reference:
+// RFC Section 4.11 - String
+// Unsigned integer length followed by bytes zero-padded to a multiple of
+// four
+func (d *Decoder) DecodeString() (string, int, error) {
+ dataLen, n, err := d.DecodeUint()
+ if err != nil {
+ return "", n, err
+ }
+ if uint(dataLen) > uint(math.MaxInt32) ||
+ (d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
+ err = unmarshalError("DecodeString", ErrOverflow, errMaxSlice,
+ dataLen, nil)
+ return "", n, err
+ }
+
+ opaque, n2, err := d.DecodeFixedOpaque(int32(dataLen))
+ n += n2
+ if err != nil {
+ return "", n, err
+ }
+ return string(opaque), n, nil
+}
+
+// decodeFixedArray treats the next bytes as a series of XDR encoded elements
+// of the same type as the array represented by the reflection value and decodes
+// each element into the passed array. The ignoreOpaque flag controls whether
+// or not uint8 (byte) elements should be decoded individually or as a fixed
+// sequence of opaque data. It returns the the number of bytes actually read.
+//
+// An UnmarshalError is returned if any issues are encountered while decoding
+// the array elements.
+//
+// Reference:
+// RFC Section 4.12 - Fixed-Length Array
+// Individually XDR encoded array elements
+func (d *Decoder) decodeFixedArray(v reflect.Value, ignoreOpaque bool) (int, error) {
+ // Treat [#]byte (byte is alias for uint8) as opaque data unless
+ // ignored.
+ if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
+ data, n, err := d.DecodeFixedOpaque(int32(v.Len()))
+ if err != nil {
+ return n, err
+ }
+ reflect.Copy(v, reflect.ValueOf(data))
+ return n, nil
+ }
+
+ // Decode each array element.
+ var n int
+ for i := 0; i < v.Len(); i++ {
+ n2, err := d.decode(v.Index(i))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+}
+
+// decodeArray treats the next bytes as a variable length series of XDR encoded
+// elements of the same type as the array represented by the reflection value.
+// The number of elements is obtained by first decoding the unsigned integer
+// element count. Then each element is decoded into the passed array. The
+// ignoreOpaque flag controls whether or not uint8 (byte) elements should be
+// decoded individually or as a variable sequence of opaque data. It returns
+// the number of bytes actually read.
+//
+// An UnmarshalError is returned if any issues are encountered while decoding
+// the array elements.
+//
+// Reference:
+// RFC Section 4.13 - Variable-Length Array
+// Unsigned integer length followed by individually XDR encoded array
+// elements
+func (d *Decoder) decodeArray(v reflect.Value, ignoreOpaque bool) (int, error) {
+ dataLen, n, err := d.DecodeUint()
+ if err != nil {
+ return n, err
+ }
+ if uint(dataLen) > uint(math.MaxInt32) ||
+ (d.maxReadSize != 0 && uint(dataLen) > d.maxReadSize) {
+ err := unmarshalError("decodeArray", ErrOverflow, errMaxSlice,
+ dataLen, nil)
+ return n, err
+ }
+
+ // Allocate storage for the slice elements (the underlying array) if
+ // existing slice does not have enough capacity.
+ sliceLen := int(dataLen)
+ if v.Cap() < sliceLen {
+ v.Set(reflect.MakeSlice(v.Type(), sliceLen, sliceLen))
+ }
+ if v.Len() < sliceLen {
+ v.SetLen(sliceLen)
+ }
+
+ // Treat []byte (byte is alias for uint8) as opaque data unless ignored.
+ if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
+ data, n2, err := d.DecodeFixedOpaque(int32(sliceLen))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ v.SetBytes(data)
+ return n, nil
+ }
+
+ // Decode each slice element.
+ for i := 0; i < sliceLen; i++ {
+ n2, err := d.decode(v.Index(i))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+}
+
+// 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. It returns the the number of bytes actually read.
+//
+// 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
+func (d *Decoder) decodeStruct(v reflect.Value) (int, error) {
+ var n int
+ 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 n, err
+ }
+ if !vf.CanSet() {
+ msg := fmt.Sprintf("can't decode to unsettable '%v'",
+ vf.Type().String())
+ err := unmarshalError("decodeStruct", ErrNotSettable,
+ msg, nil, nil)
+ return n, 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:
+ n2, err := d.decodeArray(vf, true)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ continue
+
+ case reflect.Array:
+ n2, err := d.decodeFixedArray(vf, true)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ continue
+ }
+ }
+
+ // Decode each struct field.
+ n2, err := d.decode(vf)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+
+ return n, nil
+}
+
+// RFC Section 4.15 - Discriminated Union
+// RFC Section 4.16 - Void
+// RFC Section 4.17 - Constant
+// RFC Section 4.18 - Typedef
+// RFC Section 4.19 - Optional data
+// RFC Sections 4.15 though 4.19 only apply to the data specification language
+// which is not implemented by this package. In the case of discriminated
+// unions, struct tags are used to perform a similar function.
+
+// decodeMap treats the next bytes as an XDR encoded variable array of 2-element
+// structures whose fields are of the same type as the map keys and elements
+// represented by the passed reflection value. Pointers are automatically
+// indirected and allocated as necessary. It returns the the number of bytes
+// actually read.
+//
+// An UnmarshalError is returned if any issues are encountered while decoding
+// the elements.
+func (d *Decoder) decodeMap(v reflect.Value) (int, error) {
+ dataLen, n, err := d.DecodeUint()
+ if err != nil {
+ return n, err
+ }
+
+ // Allocate storage for the underlying map if needed.
+ vt := v.Type()
+ if v.IsNil() {
+ v.Set(reflect.MakeMap(vt))
+ }
+
+ // Decode each key and value according to their type.
+ keyType := vt.Key()
+ elemType := vt.Elem()
+ for i := uint32(0); i < dataLen; i++ {
+ key := reflect.New(keyType).Elem()
+ n2, err := d.decode(key)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+
+ val := reflect.New(elemType).Elem()
+ n2, err = d.decode(val)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ v.SetMapIndex(key, val)
+ }
+ return n, nil
+}
+
+// decodeInterface examines the interface represented by the passed reflection
+// value to detect whether it is an interface that can be decoded into and
+// if it is, extracts the underlying value to pass back into the decode function
+// for decoding according to its type. It returns the the number of bytes
+// actually read.
+//
+// An UnmarshalError is returned if any issues are encountered while decoding
+// the interface.
+func (d *Decoder) decodeInterface(v reflect.Value) (int, error) {
+ if v.IsNil() || !v.CanInterface() {
+ msg := fmt.Sprintf("can't decode to nil interface")
+ err := unmarshalError("decodeInterface", ErrNilInterface, msg,
+ nil, nil)
+ return 0, err
+ }
+
+ // Extract underlying value from the interface and indirect through
+ // pointers allocating them as needed.
+ ve := reflect.ValueOf(v.Interface())
+ ve, err := d.indirect(ve)
+ if err != nil {
+ return 0, err
+ }
+ if !ve.CanSet() {
+ msg := fmt.Sprintf("can't decode to unsettable '%v'",
+ ve.Type().String())
+ err := unmarshalError("decodeInterface", ErrNotSettable, msg,
+ nil, nil)
+ return 0, err
+ }
+ return d.decode(ve)
+}
+
+// decode is the main workhorse for unmarshalling via reflection. It uses
+// the passed reflection value to choose the XDR primitives to decode from
+// the encapsulated reader. It is a recursive function,
+// so cyclic data structures are not supported and will result in an infinite
+// loop. It returns the the number of bytes actually read.
+func (d *Decoder) decode(v reflect.Value) (int, error) {
+ if !v.IsValid() {
+ msg := fmt.Sprintf("type '%s' is not valid", v.Kind().String())
+ err := unmarshalError("decode", ErrUnsupportedType, msg, nil, nil)
+ return 0, err
+ }
+
+ // Indirect through pointers allocating them as needed.
+ ve, err := d.indirect(v)
+ if err != nil {
+ return 0, err
+ }
+
+ // Handle time.Time values by decoding them as an RFC3339 formatted
+ // string with nanosecond precision. Check the type string rather
+ // than doing a full blown conversion to interface and type assertion
+ // since checking a string is much quicker.
+ switch ve.Type().String() {
+ case "time.Time":
+ // Read the value as a string and parse it.
+ timeString, n, err := d.DecodeString()
+ if err != nil {
+ return n, err
+ }
+ ttv, err := time.Parse(time.RFC3339, timeString)
+ if err != nil {
+ err := unmarshalError("decode", ErrParseTime,
+ err.Error(), timeString, err)
+ return n, err
+ }
+ ve.Set(reflect.ValueOf(ttv))
+ return n, nil
+ }
+ // If this type is in our custom types map, call the decode routine set up
+ // for it.
+ if dt, ok := d.customTypes[ve.Type().String()]; ok {
+ return dt.Decode(d, v)
+ }
+
+ // Handle native Go types.
+ switch ve.Kind() {
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int:
+ i, n, err := d.DecodeInt()
+ if err != nil {
+ return n, err
+ }
+ if ve.OverflowInt(int64(i)) {
+ msg := fmt.Sprintf("signed integer too large to fit '%s'",
+ ve.Kind().String())
+ err = unmarshalError("decode", ErrOverflow, msg, i, nil)
+ return n, err
+ }
+ ve.SetInt(int64(i))
+ return n, nil
+
+ case reflect.Int64:
+ i, n, err := d.DecodeHyper()
+ if err != nil {
+ return n, err
+ }
+ ve.SetInt(i)
+ return n, nil
+
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint:
+ ui, n, err := d.DecodeUint()
+ if err != nil {
+ return n, err
+ }
+ if ve.OverflowUint(uint64(ui)) {
+ msg := fmt.Sprintf("unsigned integer too large to fit '%s'",
+ ve.Kind().String())
+ err = unmarshalError("decode", ErrOverflow, msg, ui, nil)
+ return n, err
+ }
+ ve.SetUint(uint64(ui))
+ return n, nil
+
+ case reflect.Uint64:
+ ui, n, err := d.DecodeUhyper()
+ if err != nil {
+ return n, err
+ }
+ ve.SetUint(ui)
+ return n, nil
+
+ case reflect.Bool:
+ b, n, err := d.DecodeBool()
+ if err != nil {
+ return n, err
+ }
+ ve.SetBool(b)
+ return n, nil
+
+ case reflect.Float32:
+ f, n, err := d.DecodeFloat()
+ if err != nil {
+ return n, err
+ }
+ ve.SetFloat(float64(f))
+ return n, nil
+
+ case reflect.Float64:
+ f, n, err := d.DecodeDouble()
+ if err != nil {
+ return n, err
+ }
+ ve.SetFloat(f)
+ return n, nil
+
+ case reflect.String:
+ s, n, err := d.DecodeString()
+ if err != nil {
+ return n, err
+ }
+ ve.SetString(s)
+ return n, nil
+
+ case reflect.Array:
+ n, err := d.decodeFixedArray(ve, false)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+
+ case reflect.Slice:
+ n, err := d.decodeArray(ve, false)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+
+ case reflect.Struct:
+ n, err := d.decodeStruct(ve)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+
+ case reflect.Map:
+ n, err := d.decodeMap(ve)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+
+ case reflect.Interface:
+ n, err := d.decodeInterface(ve)
+ if err != nil {
+ return n, err
+ }
+ return n, nil
+ }
+
+ // The only unhandled types left are unsupported. At the time of this
+ // writing the only remaining unsupported types that exist are
+ // reflect.Uintptr and reflect.UnsafePointer.
+ msg := fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String())
+ err = unmarshalError("decode", ErrUnsupportedType, msg, nil, nil)
+ return 0, err
+}
+
+// indirect dereferences pointers allocating them as needed until it reaches
+// a non-pointer. This allows transparent decoding through arbitrary levels
+// of indirection.
+func (d *Decoder) indirect(v reflect.Value) (reflect.Value, error) {
+ rv := v
+ for rv.Kind() == reflect.Ptr {
+ // Allocate pointer if needed.
+ isNil := rv.IsNil()
+ if isNil && !rv.CanSet() {
+ msg := fmt.Sprintf("unable to allocate pointer for '%v'",
+ rv.Type().String())
+ err := unmarshalError("indirect", ErrNotSettable, msg,
+ nil, nil)
+ return rv, err
+ }
+ if isNil {
+ rv.Set(reflect.New(rv.Type().Elem()))
+ }
+ rv = rv.Elem()
+ }
+ return rv, nil
+}
+
+// Decode operates identically to the Unmarshal function with the exception of
+// using the reader associated with the Decoder as the source of XDR-encoded
+// data instead of a user-supplied reader. See the Unmarhsal documentation for
+// specifics.
+func (d *Decoder) Decode(v interface{}) (int, error) {
+ if v == nil {
+ msg := "can't unmarshal to nil interface"
+ return 0, unmarshalError("Unmarshal", ErrNilInterface, msg, nil,
+ nil)
+ }
+
+ vv := reflect.ValueOf(v)
+ if vv.Kind() != reflect.Ptr {
+ msg := fmt.Sprintf("can't unmarshal to non-pointer '%v' - use "+
+ "& operator", vv.Type().String())
+ err := unmarshalError("Unmarshal", ErrBadArguments, msg, nil, nil)
+ return 0, err
+ }
+ if vv.IsNil() && !vv.CanSet() {
+ msg := fmt.Sprintf("can't unmarshal to unsettable '%v' - use "+
+ "& operator", vv.Type().String())
+ err := unmarshalError("Unmarshal", ErrNotSettable, msg, nil, nil)
+ return 0, err
+ }
+
+ return d.decode(vv)
+}
+
+// NewDecoder returns a Decoder that can be used to manually decode XDR data
+// from a provided reader. Typically, Unmarshal should be used instead of
+// manually creating a Decoder.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{r: r}
+}
+
+// NewDecoderLimited is identical to NewDecoder but it sets maxReadSize in
+// order to cap reads.
+func NewDecoderLimited(r io.Reader, maxSize uint) *Decoder {
+ return &Decoder{r: r, maxReadSize: maxSize}
+}
+
+// NewDecoderCustomTypes returns a decoder with support for custom types known
+// to the caller. The second parameter is a map of the type name to the decoder
+// routine. When the decoder finds a type matching one of the entries in the map
+// it will call the custom routine for that type.
+func NewDecoderCustomTypes(r io.Reader, maxSize uint, ct map[string]TypeDecoder) *Decoder {
+ return &Decoder{r: r, maxReadSize: maxSize, customTypes: ct}
+}
diff --git a/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/doc.go b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/doc.go
new file mode 100644
index 000000000..8823d62f3
--- /dev/null
+++ b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/doc.go
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+Package xdr implements the data representation portion of the External Data
+Representation (XDR) standard protocol as specified in RFC 4506 (obsoletes
+RFC 1832 and RFC 1014).
+
+The XDR RFC defines both a data specification language and a data
+representation standard. This package implements methods to encode and decode
+XDR data per the data representation standard with the exception of 128-bit
+quadruple-precision floating points. It does not currently implement parsing of
+the data specification language. In other words, the ability to automatically
+generate Go code by parsing an XDR data specification file (typically .x
+extension) is not supported. In practice, this limitation of the package is
+fairly minor since it is largely unnecessary due to the reflection capabilities
+of Go as described below.
+
+This package provides two approaches for encoding and decoding XDR data:
+
+ 1) Marshal/Unmarshal functions which automatically map between XDR and Go types
+ 2) Individual Encoder/Decoder objects to manually work with XDR primitives
+
+For the Marshal/Unmarshal functions, Go reflection capabilities are used to
+choose the type of the underlying XDR data based upon the Go type to encode or
+the target Go type to decode into. A description of how each type is mapped is
+provided below, however one important type worth reviewing is Go structs. In
+the case of structs, each exported field (first letter capitalized) is reflected
+and mapped in order. As a result, this means a Go struct with exported fields
+of the appropriate types listed in the expected order can be used to
+automatically encode / decode the XDR data thereby eliminating the need to write
+a lot of boilerplate code to encode/decode and error check each piece of XDR
+data as is typically required with C based XDR libraries.
+
+Go Type to XDR Type Mappings
+
+The following chart shows an overview of how Go types are mapped to XDR types
+for automatic marshalling and unmarshalling. The documentation for the Marshal
+and Unmarshal functions has specific details of how the mapping proceeds.
+
+ Go Type <-> XDR Type
+ --------------------
+ int8, int16, int32, int <-> XDR Integer
+ uint8, uint16, uint32, uint <-> XDR Unsigned Integer
+ int64 <-> XDR Hyper Integer
+ uint64 <-> XDR Unsigned Hyper Integer
+ bool <-> XDR Boolean
+ float32 <-> XDR Floating-Point
+ float64 <-> XDR Double-Precision Floating-Point
+ string <-> XDR String
+ byte <-> XDR Integer
+ []byte <-> XDR Variable-Length Opaque Data
+ [#]byte <-> XDR Fixed-Length Opaque Data
+ []<type> <-> XDR Variable-Length Array
+ [#]<type> <-> XDR Fixed-Length Array
+ struct <-> XDR Structure
+ map <-> XDR Variable-Length Array of two-element XDR Structures
+ time.Time <-> XDR String encoded with RFC3339 nanosecond precision
+
+Notes and Limitations:
+
+ * Automatic marshalling and unmarshalling of variable and fixed-length
+ arrays of uint8s require a special struct tag `xdropaque:"false"`
+ since byte slices and byte arrays are assumed to be opaque data and
+ byte is a Go alias for uint8 thus indistinguishable under reflection
+ * Channel, complex, and function types cannot be encoded
+ * Interfaces without a concrete value cannot be encoded
+ * Cyclic data structures are not supported and will result in infinite
+ loops
+ * Strings are marshalled and unmarshalled with UTF-8 character encoding
+ which differs from the XDR specification of ASCII, however UTF-8 is
+ backwards compatible with ASCII so this should rarely cause issues
+
+
+Encoding
+
+To encode XDR data, use the Marshal function.
+ func Marshal(w io.Writer, v interface{}) (int, error)
+
+For example, given the following code snippet:
+
+ type ImageHeader struct {
+ Signature [3]byte
+ Version uint32
+ IsGrayscale bool
+ NumSections uint32
+ }
+ h := ImageHeader{[3]byte{0xAB, 0xCD, 0xEF}, 2, true, 10}
+
+ var w bytes.Buffer
+ bytesWritten, err := xdr.Marshal(&w, &h)
+ // Error check elided
+
+The result, encodedData, will then contain the following XDR encoded byte
+sequence:
+
+ 0xAB, 0xCD, 0xEF, 0x00,
+ 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x0A
+
+
+In addition, while the automatic marshalling discussed above will work for the
+vast majority of cases, an Encoder object is provided that can be used to
+manually encode XDR primitives for complex scenarios where automatic
+reflection-based encoding won't work. The included examples provide a sample of
+manual usage via an Encoder.
+
+
+Decoding
+
+To decode XDR data, use the Unmarshal function.
+ func Unmarshal(r io.Reader, v interface{}) (int, error)
+
+For example, given the following code snippet:
+
+ type ImageHeader struct {
+ Signature [3]byte
+ Version uint32
+ IsGrayscale bool
+ NumSections uint32
+ }
+
+ // Using output from the Encoding section above.
+ encodedData := []byte{
+ 0xAB, 0xCD, 0xEF, 0x00,
+ 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x0A,
+ }
+
+ var h ImageHeader
+ bytesRead, err := xdr.Unmarshal(bytes.NewReader(encodedData), &h)
+ // Error check elided
+
+The struct instance, h, will then contain the following values:
+
+ h.Signature = [3]byte{0xAB, 0xCD, 0xEF}
+ h.Version = 2
+ h.IsGrayscale = true
+ h.NumSections = 10
+
+In addition, while the automatic unmarshalling discussed above will work for the
+vast majority of cases, a Decoder object is provided that can be used to
+manually decode XDR primitives for complex scenarios where automatic
+reflection-based decoding won't work. The included examples provide a sample of
+manual usage via a Decoder.
+
+Errors
+
+All errors are either of type UnmarshalError or MarshalError. Both provide
+human-readable output as well as an ErrorCode field which can be inspected by
+sophisticated callers if necessary.
+
+See the documentation of UnmarshalError, MarshalError, and ErrorCode for further
+details.
+*/
+package xdr
diff --git a/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/encode.go b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/encode.go
new file mode 100644
index 000000000..7bac2681d
--- /dev/null
+++ b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/encode.go
@@ -0,0 +1,669 @@
+/*
+ * Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package xdr
+
+import (
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "time"
+)
+
+var errIOEncode = "%s while encoding %d bytes"
+
+/*
+Marshal writes the XDR encoding of v to writer w and returns the number of bytes
+written. It traverses v recursively and automatically indirects pointers
+through arbitrary depth to encode the actual value pointed to.
+
+Marshal uses reflection to determine the type of the concrete value contained by
+v and performs a mapping of Go types to the underlying XDR types as follows:
+
+ Go Type -> XDR Type
+ --------------------
+ int8, int16, int32, int -> XDR Integer
+ uint8, uint16, uint32, uint -> XDR Unsigned Integer
+ int64 -> XDR Hyper Integer
+ uint64 -> XDR Unsigned Hyper Integer
+ bool -> XDR Boolean
+ float32 -> XDR Floating-Point
+ float64 -> XDR Double-Precision Floating-Point
+ string -> XDR String
+ byte -> XDR Integer
+ []byte -> XDR Variable-Length Opaque Data
+ [#]byte -> XDR Fixed-Length Opaque Data
+ []<type> -> XDR Variable-Length Array
+ [#]<type> -> XDR Fixed-Length Array
+ struct -> XDR Structure
+ map -> XDR Variable-Length Array of two-element XDR Structures
+ time.Time -> XDR String encoded with RFC3339 nanosecond precision
+
+Notes and Limitations:
+
+ * Automatic marshalling of variable and fixed-length arrays of uint8s
+ requires a special struct tag `xdropaque:"false"` since byte slices and
+ byte arrays are assumed to be opaque data and byte is a Go alias for uint8
+ thus indistinguishable under reflection
+ * Channel, complex, and function types cannot be encoded
+ * Interfaces without a concrete value cannot be encoded
+ * Cyclic data structures are not supported and will result in infinite loops
+ * Strings are marshalled with UTF-8 character encoding which differs from
+ the XDR specification of ASCII, however UTF-8 is backwards compatible with
+ ASCII so this should rarely cause issues
+
+If any issues are encountered during the marshalling process, a MarshalError is
+returned with a human readable description as well as an ErrorCode value for
+further inspection from sophisticated callers. Some potential issues are
+unsupported Go types, attempting to encode more opaque data than can be
+represented by a single opaque XDR entry, and exceeding max slice limitations.
+*/
+func Marshal(w io.Writer, v interface{}) (int, error) {
+ enc := Encoder{w: w}
+ return enc.Encode(v)
+}
+
+// An Encoder wraps an io.Writer that will receive the XDR encoded byte stream.
+// See NewEncoder.
+type Encoder struct {
+ w io.Writer
+}
+
+// EncodeInt writes the XDR encoded representation of the passed 32-bit signed
+// integer to the encapsulated writer and returns the number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.1 - Integer
+// 32-bit big-endian signed integer in range [-2147483648, 2147483647]
+func (enc *Encoder) EncodeInt(v int32) (int, error) {
+ var b [4]byte
+ b[0] = byte(v >> 24)
+ b[1] = byte(v >> 16)
+ b[2] = byte(v >> 8)
+ b[3] = byte(v)
+
+ n, err := enc.w.Write(b[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
+ err := marshalError("EncodeInt", ErrIO, msg, b[:n], err)
+ return n, err
+ }
+
+ return n, nil
+}
+
+// EncodeUint writes the XDR encoded representation of the passed 32-bit
+// unsigned integer to the encapsulated writer and returns the number of bytes
+// written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.2 - Unsigned Integer
+// 32-bit big-endian unsigned integer in range [0, 4294967295]
+func (enc *Encoder) EncodeUint(v uint32) (int, error) {
+ var b [4]byte
+ b[0] = byte(v >> 24)
+ b[1] = byte(v >> 16)
+ b[2] = byte(v >> 8)
+ b[3] = byte(v)
+
+ n, err := enc.w.Write(b[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), 4)
+ err := marshalError("EncodeUint", ErrIO, msg, b[:n], err)
+ return n, err
+ }
+
+ return n, nil
+}
+
+// EncodeEnum treats the passed 32-bit signed integer as an enumeration value
+// and, if it is in the list of passed valid enumeration values, writes the XDR
+// encoded representation of it to the encapsulated writer. It returns the
+// number of bytes written.
+//
+// A MarshalError is returned if the enumeration value is not one of the
+// provided valid values or if writing the data fails.
+//
+// Reference:
+// RFC Section 4.3 - Enumeration
+// Represented as an XDR encoded signed integer
+func (enc *Encoder) EncodeEnum(v int32, validEnums map[int32]bool) (int, error) {
+ if !validEnums[v] {
+ err := marshalError("EncodeEnum", ErrBadEnumValue,
+ "invalid enum", v, nil)
+ return 0, err
+ }
+ return enc.EncodeInt(v)
+}
+
+// EncodeBool writes the XDR encoded representation of the passed boolean to the
+// encapsulated writer and returns the number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.4 - Boolean
+// Represented as an XDR encoded enumeration where 0 is false and 1 is true
+func (enc *Encoder) EncodeBool(v bool) (int, error) {
+ i := int32(0)
+ if v == true {
+ i = 1
+ }
+ return enc.EncodeInt(i)
+}
+
+// EncodeHyper writes the XDR encoded representation of the passed 64-bit
+// signed integer to the encapsulated writer and returns the number of bytes
+// written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.5 - Hyper Integer
+// 64-bit big-endian signed integer in range [-9223372036854775808, 9223372036854775807]
+func (enc *Encoder) EncodeHyper(v int64) (int, error) {
+ var b [8]byte
+ b[0] = byte(v >> 56)
+ b[1] = byte(v >> 48)
+ b[2] = byte(v >> 40)
+ b[3] = byte(v >> 32)
+ b[4] = byte(v >> 24)
+ b[5] = byte(v >> 16)
+ b[6] = byte(v >> 8)
+ b[7] = byte(v)
+
+ n, err := enc.w.Write(b[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
+ err := marshalError("EncodeHyper", ErrIO, msg, b[:n], err)
+ return n, err
+ }
+
+ return n, nil
+}
+
+// EncodeUhyper writes the XDR encoded representation of the passed 64-bit
+// unsigned integer to the encapsulated writer and returns the number of bytes
+// written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.5 - Unsigned Hyper Integer
+// 64-bit big-endian unsigned integer in range [0, 18446744073709551615]
+func (enc *Encoder) EncodeUhyper(v uint64) (int, error) {
+ var b [8]byte
+ b[0] = byte(v >> 56)
+ b[1] = byte(v >> 48)
+ b[2] = byte(v >> 40)
+ b[3] = byte(v >> 32)
+ b[4] = byte(v >> 24)
+ b[5] = byte(v >> 16)
+ b[6] = byte(v >> 8)
+ b[7] = byte(v)
+
+ n, err := enc.w.Write(b[:])
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), 8)
+ err := marshalError("EncodeUhyper", ErrIO, msg, b[:n], err)
+ return n, err
+ }
+
+ return n, nil
+}
+
+// EncodeFloat writes the XDR encoded representation of the passed 32-bit
+// (single-precision) floating point to the encapsulated writer and returns the
+// number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.6 - Floating Point
+// 32-bit single-precision IEEE 754 floating point
+func (enc *Encoder) EncodeFloat(v float32) (int, error) {
+ ui := math.Float32bits(v)
+ return enc.EncodeUint(ui)
+}
+
+// EncodeDouble writes the XDR encoded representation of the passed 64-bit
+// (double-precision) floating point to the encapsulated writer and returns the
+// number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.7 - Double-Precision Floating Point
+// 64-bit double-precision IEEE 754 floating point
+func (enc *Encoder) EncodeDouble(v float64) (int, error) {
+ ui := math.Float64bits(v)
+ return enc.EncodeUhyper(ui)
+}
+
+// RFC Section 4.8 - Quadruple-Precision Floating Point
+// 128-bit quadruple-precision floating point
+// Not Implemented
+
+// EncodeFixedOpaque treats the passed byte slice as opaque data of a fixed
+// size and writes the XDR encoded representation of it to the encapsulated
+// writer. It returns the number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.9 - Fixed-Length Opaque Data
+// Fixed-length uninterpreted data zero-padded to a multiple of four
+func (enc *Encoder) EncodeFixedOpaque(v []byte) (int, error) {
+ l := len(v)
+ pad := (4 - (l % 4)) % 4
+
+ // Write the actual bytes.
+ n, err := enc.w.Write(v)
+ if err != nil {
+ msg := fmt.Sprintf(errIOEncode, err.Error(), len(v))
+ err := marshalError("EncodeFixedOpaque", ErrIO, msg, v[:n], err)
+ return n, err
+ }
+
+ // Write any padding if needed.
+ if pad > 0 {
+ b := make([]byte, pad)
+ n2, err := enc.w.Write(b)
+ n += n2
+ if err != nil {
+ written := make([]byte, l+n2)
+ copy(written, v)
+ copy(written[l:], b[:n2])
+ msg := fmt.Sprintf(errIOEncode, err.Error(), l+pad)
+ err := marshalError("EncodeFixedOpaque", ErrIO, msg,
+ written, err)
+ return n, err
+ }
+ }
+
+ return n, nil
+}
+
+// EncodeOpaque treats the passed byte slice as opaque data of a variable
+// size and writes the XDR encoded representation of it to the encapsulated
+// writer. It returns the number of bytes written.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.10 - Variable-Length Opaque Data
+// Unsigned integer length followed by fixed opaque data of that length
+func (enc *Encoder) EncodeOpaque(v []byte) (int, error) {
+ // Length of opaque data.
+ n, err := enc.EncodeUint(uint32(len(v)))
+ if err != nil {
+ return n, err
+ }
+
+ n2, err := enc.EncodeFixedOpaque(v)
+ n += n2
+ return n, err
+}
+
+// EncodeString writes the XDR encoded representation of the passed string
+// to the encapsulated writer and returns the number of bytes written.
+// Character encoding is assumed to be UTF-8 and therefore ASCII compatible. If
+// the underlying character encoding is not compatible with this assumption, the
+// data can instead be written as variable-length opaque data (EncodeOpaque) and
+// manually converted as needed.
+//
+// A MarshalError with an error code of ErrIO is returned if writing the data
+// fails.
+//
+// Reference:
+// RFC Section 4.11 - String
+// Unsigned integer length followed by bytes zero-padded to a multiple of four
+func (enc *Encoder) EncodeString(v string) (int, error) {
+ // Length of string.
+ n, err := enc.EncodeUint(uint32(len(v)))
+ if err != nil {
+ return n, err
+ }
+
+ n2, err := enc.EncodeFixedOpaque([]byte(v))
+ n += n2
+ return n, err
+}
+
+// encodeFixedArray writes the XDR encoded representation of each element
+// in the passed array represented by the reflection value to the encapsulated
+// writer and returns the number of bytes written. The ignoreOpaque flag
+// controls whether or not uint8 (byte) elements should be encoded individually
+// or as a fixed sequence of opaque data.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the array elements.
+//
+// Reference:
+// RFC Section 4.12 - Fixed-Length Array
+// Individually XDR encoded array elements
+func (enc *Encoder) encodeFixedArray(v reflect.Value, ignoreOpaque bool) (int, error) {
+ // Treat [#]byte (byte is alias for uint8) as opaque data unless ignored.
+ if !ignoreOpaque && v.Type().Elem().Kind() == reflect.Uint8 {
+ // Create a slice of the underlying array for better efficiency
+ // when possible. Can't create a slice of an unaddressable
+ // value.
+ if v.CanAddr() {
+ return enc.EncodeFixedOpaque(v.Slice(0, v.Len()).Bytes())
+ }
+
+ // When the underlying array isn't addressable fall back to
+ // copying the array into a new slice. This is rather ugly, but
+ // the inability to create a constant slice from an
+ // unaddressable array is a limitation of Go.
+ slice := make([]byte, v.Len(), v.Len())
+ reflect.Copy(reflect.ValueOf(slice), v)
+ return enc.EncodeFixedOpaque(slice)
+ }
+
+ // Encode each array element.
+ var n int
+ for i := 0; i < v.Len(); i++ {
+ n2, err := enc.encode(v.Index(i))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+
+ return n, nil
+}
+
+// encodeArray writes an XDR encoded integer representing the number of
+// elements in the passed slice represented by the reflection value followed by
+// the XDR encoded representation of each element in slice to the encapsulated
+// writer and returns the number of bytes written. The ignoreOpaque flag
+// controls whether or not uint8 (byte) elements should be encoded individually
+// or as a variable sequence of opaque data.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the array elements.
+//
+// Reference:
+// RFC Section 4.13 - Variable-Length Array
+// Unsigned integer length followed by individually XDR encoded array elements
+func (enc *Encoder) encodeArray(v reflect.Value, ignoreOpaque bool) (int, error) {
+ numItems := uint32(v.Len())
+ n, err := enc.EncodeUint(numItems)
+ if err != nil {
+ return n, err
+ }
+
+ n2, err := enc.encodeFixedArray(v, ignoreOpaque)
+ n += n2
+ return n, err
+}
+
+// encodeStruct writes an XDR encoded representation of each value in the
+// exported fields of the struct represented by the passed reflection value to
+// the encapsulated writer and returns the number of bytes written. Pointers
+// are automatically indirected through arbitrary depth to encode the actual
+// value pointed to.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the elements.
+//
+// Reference:
+// RFC Section 4.14 - Structure
+// XDR encoded elements in the order of their declaration in the struct
+func (enc *Encoder) encodeStruct(v reflect.Value) (int, error) {
+ var n int
+ vt := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ // Skip unexported fields and indirect through pointers.
+ vtf := vt.Field(i)
+ if vtf.PkgPath != "" {
+ continue
+ }
+ vf := v.Field(i)
+ vf = enc.indirect(vf)
+
+ // 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:
+ n2, err := enc.encodeArray(vf, true)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ continue
+
+ case reflect.Array:
+ n2, err := enc.encodeFixedArray(vf, true)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ continue
+ }
+ }
+
+ // Encode each struct field.
+ n2, err := enc.encode(vf)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+
+ return n, nil
+}
+
+// RFC Section 4.15 - Discriminated Union
+// RFC Section 4.16 - Void
+// RFC Section 4.17 - Constant
+// RFC Section 4.18 - Typedef
+// RFC Section 4.19 - Optional data
+// RFC Sections 4.15 though 4.19 only apply to the data specification language
+// which is not implemented by this package. In the case of discriminated
+// unions, struct tags are used to perform a similar function.
+
+// encodeMap treats the map represented by the passed reflection value as a
+// variable-length array of 2-element structures whose fields are of the same
+// type as the map keys and elements and writes its XDR encoded representation
+// to the encapsulated writer. It returns the number of bytes written.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the elements.
+func (enc *Encoder) encodeMap(v reflect.Value) (int, error) {
+ // Number of elements.
+ n, err := enc.EncodeUint(uint32(v.Len()))
+ if err != nil {
+ return n, err
+ }
+
+ // Encode each key and value according to their type.
+ for _, key := range v.MapKeys() {
+ n2, err := enc.encode(key)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+
+ n2, err = enc.encode(v.MapIndex(key))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+
+ return n, nil
+}
+
+// encodeInterface examines the interface represented by the passed reflection
+// value to detect whether it is an interface that can be encoded if it is,
+// extracts the underlying value to pass back into the encode function for
+// encoding according to its type.
+//
+// A MarshalError is returned if any issues are encountered while encoding
+// the interface.
+func (enc *Encoder) encodeInterface(v reflect.Value) (int, error) {
+ if v.IsNil() || !v.CanInterface() {
+ msg := fmt.Sprintf("can't encode nil interface")
+ err := marshalError("encodeInterface", ErrNilInterface, msg,
+ nil, nil)
+ return 0, err
+ }
+
+ // Extract underlying value from the interface and indirect through pointers.
+ ve := reflect.ValueOf(v.Interface())
+ ve = enc.indirect(ve)
+ return enc.encode(ve)
+}
+
+// encode is the main workhorse for marshalling via reflection. It uses
+// the passed reflection value to choose the XDR primitives to encode into
+// the encapsulated writer and returns the number of bytes written. It is a
+// recursive function, so cyclic data structures are not supported and will
+// result in an infinite loop.
+func (enc *Encoder) encode(v reflect.Value) (int, error) {
+ if !v.IsValid() {
+ msg := fmt.Sprintf("type '%s' is not valid", v.Kind().String())
+ err := marshalError("encode", ErrUnsupportedType, msg, nil, nil)
+ return 0, err
+ }
+
+ // Indirect through pointers to get at the concrete value.
+ ve := enc.indirect(v)
+
+ // Handle time.Time values by encoding them as an RFC3339 formatted
+ // string with nanosecond precision. Check the type string before
+ // doing a full blown conversion to interface and type assertion since
+ // checking a string is much quicker.
+ if ve.Type().String() == "time.Time" && ve.CanInterface() {
+ viface := ve.Interface()
+ if tv, ok := viface.(time.Time); ok {
+ return enc.EncodeString(tv.Format(time.RFC3339Nano))
+ }
+ }
+
+ // Handle native Go types.
+ switch ve.Kind() {
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int:
+ return enc.EncodeInt(int32(ve.Int()))
+
+ case reflect.Int64:
+ return enc.EncodeHyper(ve.Int())
+
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint:
+ return enc.EncodeUint(uint32(ve.Uint()))
+
+ case reflect.Uint64:
+ return enc.EncodeUhyper(ve.Uint())
+
+ case reflect.Bool:
+ return enc.EncodeBool(ve.Bool())
+
+ case reflect.Float32:
+ return enc.EncodeFloat(float32(ve.Float()))
+
+ case reflect.Float64:
+ return enc.EncodeDouble(ve.Float())
+
+ case reflect.String:
+ return enc.EncodeString(ve.String())
+
+ case reflect.Array:
+ return enc.encodeFixedArray(ve, false)
+
+ case reflect.Slice:
+ return enc.encodeArray(ve, false)
+
+ case reflect.Struct:
+ return enc.encodeStruct(ve)
+
+ case reflect.Map:
+ return enc.encodeMap(ve)
+
+ case reflect.Interface:
+ return enc.encodeInterface(ve)
+ }
+
+ // The only unhandled types left are unsupported. At the time of this
+ // writing the only remaining unsupported types that exist are
+ // reflect.Uintptr and reflect.UnsafePointer.
+ msg := fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String())
+ err := marshalError("encode", ErrUnsupportedType, msg, nil, nil)
+ return 0, err
+}
+
+// indirect dereferences pointers until it reaches a non-pointer. This allows
+// transparent encoding through arbitrary levels of indirection.
+func (enc *Encoder) indirect(v reflect.Value) reflect.Value {
+ rv := v
+ for rv.Kind() == reflect.Ptr {
+ rv = rv.Elem()
+ }
+ return rv
+}
+
+// Encode operates identically to the Marshal function with the exception of
+// using the writer associated with the Encoder for the destination of the
+// XDR-encoded data instead of a user-supplied writer. See the Marshal
+// documentation for specifics.
+func (enc *Encoder) Encode(v interface{}) (int, error) {
+ if v == nil {
+ msg := "can't marshal nil interface"
+ err := marshalError("Marshal", ErrNilInterface, msg, nil, nil)
+ return 0, err
+ }
+
+ vv := reflect.ValueOf(v)
+ vve := vv
+ for vve.Kind() == reflect.Ptr {
+ if vve.IsNil() {
+ msg := fmt.Sprintf("can't marshal nil pointer '%v'",
+ vv.Type().String())
+ err := marshalError("Marshal", ErrBadArguments, msg,
+ nil, nil)
+ return 0, err
+ }
+ vve = vve.Elem()
+ }
+
+ return enc.encode(vve)
+}
+
+// NewEncoder returns an object that can be used to manually choose fields to
+// XDR encode to the passed writer w. Typically, Marshal should be used instead
+// of manually creating an Encoder. An Encoder, along with several of its
+// methods to encode XDR primitives, is exposed so it is possible to perform
+// manual encoding of data without relying on reflection should it be necessary
+// in complex scenarios where automatic reflection-based encoding won't work.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{w: w}
+}
diff --git a/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/error.go b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/error.go
new file mode 100644
index 000000000..42079ad35
--- /dev/null
+++ b/vendor/github.com/digitalocean/go-libvirt/internal/go-xdr/xdr2/error.go
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2012-2014 Dave Collins <dave@davec.name>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package xdr
+
+import "fmt"
+
+// ErrorCode identifies a kind of error.
+type ErrorCode int
+
+const (
+ // ErrBadArguments indicates arguments passed to the function are not
+ // what was expected.
+ ErrBadArguments ErrorCode = iota
+
+ // ErrUnsupportedType indicates the Go type is not a supported type for
+ // marshalling and unmarshalling XDR data.
+ ErrUnsupportedType
+
+ // ErrBadEnumValue indicates an enumeration value is not in the list of
+ // valid values.
+ ErrBadEnumValue
+
+ // ErrNotSettable indicates an interface value cannot be written to.
+ // This usually means the interface value was not passed with the &
+ // operator, but it can also happen if automatic pointer allocation
+ // fails.
+ ErrNotSettable
+
+ // ErrOverflow indicates that the data in question is too large to fit
+ // into the corresponding Go or XDR data type. For example, an integer
+ // decoded from XDR that is too large to fit into a target type of int8,
+ // or opaque data that exceeds the max length of a Go slice.
+ ErrOverflow
+
+ // ErrNilInterface indicates an interface with no concrete type
+ // information was encountered. Type information is necessary to
+ // perform mapping between XDR and Go types.
+ ErrNilInterface
+
+ // ErrIO indicates an error was encountered while reading or writing to
+ // an io.Reader or io.Writer, respectively. The actual underlying error
+ // will be available via the Err field of the MarshalError or
+ // UnmarshalError struct.
+ ErrIO
+
+ // ErrParseTime indicates an error was encountered while parsing an
+ // RFC3339 formatted time value. The actual underlying error will be
+ // available via the Err field of the UnmarshalError struct.
+ ErrParseTime
+)
+
+// Map of ErrorCode values back to their constant names for pretty printing.
+var errorCodeStrings = map[ErrorCode]string{
+ ErrBadArguments: "ErrBadArguments",
+ ErrUnsupportedType: "ErrUnsupportedType",
+ ErrBadEnumValue: "ErrBadEnumValue",
+ ErrNotSettable: "ErrNotSettable",
+ ErrOverflow: "ErrOverflow",
+ ErrNilInterface: "ErrNilInterface",
+ ErrIO: "ErrIO",
+ ErrParseTime: "ErrParseTime",
+}
+
+// String returns the ErrorCode as a human-readable name.
+func (e ErrorCode) String() string {
+ if s := errorCodeStrings[e]; s != "" {
+ return s
+ }
+ return fmt.Sprintf("Unknown ErrorCode (%d)", e)
+}
+
+// UnmarshalError describes a problem encountered while unmarshaling data.
+// Some potential issues are unsupported Go types, attempting to decode a value
+// which is too large to fit into a specified Go type, and exceeding max slice
+// limitations.
+type UnmarshalError struct {
+ ErrorCode ErrorCode // Describes the kind of error
+ Func string // Function name
+ Value interface{} // Value actually parsed where appropriate
+ Description string // Human readable description of the issue
+ Err error // The underlying error for IO errors
+}
+
+// Error satisfies the error interface and prints human-readable errors.
+func (e *UnmarshalError) Error() string {
+ switch e.ErrorCode {
+ case ErrBadEnumValue, ErrOverflow, ErrIO, ErrParseTime:
+ return fmt.Sprintf("xdr:%s: %s - read: '%v'", e.Func,
+ e.Description, e.Value)
+ }
+ return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description)
+}
+
+// unmarshalError creates an error given a set of arguments and will copy byte
+// slices into the Value field since they might otherwise be changed from from
+// the original value.
+func unmarshalError(f string, c ErrorCode, desc string, v interface{}, err error) *UnmarshalError {
+ e := &UnmarshalError{ErrorCode: c, Func: f, Description: desc, Err: err}
+ switch t := v.(type) {
+ case []byte:
+ slice := make([]byte, len(t))
+ copy(slice, t)
+ e.Value = slice
+ default:
+ e.Value = v
+ }
+
+ return e
+}
+
+// IsIO returns a boolean indicating whether the error is known to report that
+// the underlying reader or writer encountered an ErrIO.
+func IsIO(err error) bool {
+ switch e := err.(type) {
+ case *UnmarshalError:
+ return e.ErrorCode == ErrIO
+ case *MarshalError:
+ return e.ErrorCode == ErrIO
+ }
+ return false
+}
+
+// MarshalError describes a problem encountered while marshaling data.
+// Some potential issues are unsupported Go types, attempting to encode more
+// opaque data than can be represented by a single opaque XDR entry, and
+// exceeding max slice limitations.
+type MarshalError struct {
+ ErrorCode ErrorCode // Describes the kind of error
+ Func string // Function name
+ Value interface{} // Value actually parsed where appropriate
+ Description string // Human readable description of the issue
+ Err error // The underlying error for IO errors
+}
+
+// Error satisfies the error interface and prints human-readable errors.
+func (e *MarshalError) Error() string {
+ switch e.ErrorCode {
+ case ErrIO:
+ return fmt.Sprintf("xdr:%s: %s - wrote: '%v'", e.Func,
+ e.Description, e.Value)
+ case ErrBadEnumValue:
+ return fmt.Sprintf("xdr:%s: %s - value: '%v'", e.Func,
+ e.Description, e.Value)
+ }
+ return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description)
+}
+
+// marshalError creates an error given a set of arguments and will copy byte
+// slices into the Value field since they might otherwise be changed from from
+// the original value.
+func marshalError(f string, c ErrorCode, desc string, v interface{}, err error) *MarshalError {
+ e := &MarshalError{ErrorCode: c, Func: f, Description: desc, Err: err}
+ switch t := v.(type) {
+ case []byte:
+ slice := make([]byte, len(t))
+ copy(slice, t)
+ e.Value = slice
+ default:
+ e.Value = v
+ }
+
+ return e
+}