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