github.com/davecgh/go-xdr@v0.0.0-20161123171359-e6a2ba005892/xdr2/error.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 "fmt" 20 21 // ErrorCode identifies a kind of error. 22 type ErrorCode int 23 24 const ( 25 // ErrBadArguments indicates arguments passed to the function are not 26 // what was expected. 27 ErrBadArguments ErrorCode = iota 28 29 // ErrUnsupportedType indicates the Go type is not a supported type for 30 // marshalling and unmarshalling XDR data. 31 ErrUnsupportedType 32 33 // ErrBadEnumValue indicates an enumeration value is not in the list of 34 // valid values. 35 ErrBadEnumValue 36 37 // ErrNotSettable indicates an interface value cannot be written to. 38 // This usually means the interface value was not passed with the & 39 // operator, but it can also happen if automatic pointer allocation 40 // fails. 41 ErrNotSettable 42 43 // ErrOverflow indicates that the data in question is too large to fit 44 // into the corresponding Go or XDR data type. For example, an integer 45 // decoded from XDR that is too large to fit into a target type of int8, 46 // or opaque data that exceeds the max length of a Go slice. 47 ErrOverflow 48 49 // ErrNilInterface indicates an interface with no concrete type 50 // information was encountered. Type information is necessary to 51 // perform mapping between XDR and Go types. 52 ErrNilInterface 53 54 // ErrIO indicates an error was encountered while reading or writing to 55 // an io.Reader or io.Writer, respectively. The actual underlying error 56 // will be available via the Err field of the MarshalError or 57 // UnmarshalError struct. 58 ErrIO 59 60 // ErrParseTime indicates an error was encountered while parsing an 61 // RFC3339 formatted time value. The actual underlying error will be 62 // available via the Err field of the UnmarshalError struct. 63 ErrParseTime 64 ) 65 66 // Map of ErrorCode values back to their constant names for pretty printing. 67 var errorCodeStrings = map[ErrorCode]string{ 68 ErrBadArguments: "ErrBadArguments", 69 ErrUnsupportedType: "ErrUnsupportedType", 70 ErrBadEnumValue: "ErrBadEnumValue", 71 ErrNotSettable: "ErrNotSettable", 72 ErrOverflow: "ErrOverflow", 73 ErrNilInterface: "ErrNilInterface", 74 ErrIO: "ErrIO", 75 ErrParseTime: "ErrParseTime", 76 } 77 78 // String returns the ErrorCode as a human-readable name. 79 func (e ErrorCode) String() string { 80 if s := errorCodeStrings[e]; s != "" { 81 return s 82 } 83 return fmt.Sprintf("Unknown ErrorCode (%d)", e) 84 } 85 86 // UnmarshalError describes a problem encountered while unmarshaling data. 87 // Some potential issues are unsupported Go types, attempting to decode a value 88 // which is too large to fit into a specified Go type, and exceeding max slice 89 // limitations. 90 type UnmarshalError struct { 91 ErrorCode ErrorCode // Describes the kind of error 92 Func string // Function name 93 Value interface{} // Value actually parsed where appropriate 94 Description string // Human readable description of the issue 95 Err error // The underlying error for IO errors 96 } 97 98 // Error satisfies the error interface and prints human-readable errors. 99 func (e *UnmarshalError) Error() string { 100 switch e.ErrorCode { 101 case ErrBadEnumValue, ErrOverflow, ErrIO, ErrParseTime: 102 return fmt.Sprintf("xdr:%s: %s - read: '%v'", e.Func, 103 e.Description, e.Value) 104 } 105 return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description) 106 } 107 108 // unmarshalError creates an error given a set of arguments and will copy byte 109 // slices into the Value field since they might otherwise be changed from from 110 // the original value. 111 func unmarshalError(f string, c ErrorCode, desc string, v interface{}, err error) *UnmarshalError { 112 e := &UnmarshalError{ErrorCode: c, Func: f, Description: desc, Err: err} 113 switch t := v.(type) { 114 case []byte: 115 slice := make([]byte, len(t)) 116 copy(slice, t) 117 e.Value = slice 118 default: 119 e.Value = v 120 } 121 122 return e 123 } 124 125 // IsIO returns a boolean indicating whether the error is known to report that 126 // the underlying reader or writer encountered an ErrIO. 127 func IsIO(err error) bool { 128 switch e := err.(type) { 129 case *UnmarshalError: 130 return e.ErrorCode == ErrIO 131 case *MarshalError: 132 return e.ErrorCode == ErrIO 133 } 134 return false 135 } 136 137 // MarshalError describes a problem encountered while marshaling data. 138 // Some potential issues are unsupported Go types, attempting to encode more 139 // opaque data than can be represented by a single opaque XDR entry, and 140 // exceeding max slice limitations. 141 type MarshalError struct { 142 ErrorCode ErrorCode // Describes the kind of error 143 Func string // Function name 144 Value interface{} // Value actually parsed where appropriate 145 Description string // Human readable description of the issue 146 Err error // The underlying error for IO errors 147 } 148 149 // Error satisfies the error interface and prints human-readable errors. 150 func (e *MarshalError) Error() string { 151 switch e.ErrorCode { 152 case ErrIO: 153 return fmt.Sprintf("xdr:%s: %s - wrote: '%v'", e.Func, 154 e.Description, e.Value) 155 case ErrBadEnumValue: 156 return fmt.Sprintf("xdr:%s: %s - value: '%v'", e.Func, 157 e.Description, e.Value) 158 } 159 return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description) 160 } 161 162 // marshalError creates an error given a set of arguments and will copy byte 163 // slices into the Value field since they might otherwise be changed from from 164 // the original value. 165 func marshalError(f string, c ErrorCode, desc string, v interface{}, err error) *MarshalError { 166 e := &MarshalError{ErrorCode: c, Func: f, Description: desc, Err: err} 167 switch t := v.(type) { 168 case []byte: 169 slice := make([]byte, len(t)) 170 copy(slice, t) 171 e.Value = slice 172 default: 173 e.Value = v 174 } 175 176 return e 177 }