github.com/stellar/go-xdr@v0.0.0-20231122183749-b53fb00bcac2/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 ( 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. For example, an integer 47 // decoded from XDR that is too large to fit into a target type of int8, 48 // or opaque data that exceeds the max length of a Go slice. 49 ErrOverflow 50 51 // ErrNilInterface indicates an interface with no concrete type 52 // information was encountered. Type information is necessary to 53 // perform mapping between XDR and Go types. 54 ErrNilInterface 55 56 // ErrIO indicates an error was encountered while reading or writing to 57 // an io.Reader or io.Writer, respectively. The actual underlying error 58 // will be available via the Err field of the MarshalError or 59 // UnmarshalError struct. 60 ErrIO 61 62 // ErrParseTime indicates an error was encountered while parsing an 63 // RFC3339 formatted time value. The actual underlying error will be 64 // available via the Err field of the UnmarshalError struct. 65 ErrParseTime 66 ) 67 68 // Map of ErrorCode values back to their constant names for pretty printing. 69 var errorCodeStrings = map[ErrorCode]string{ 70 ErrBadArguments: "ErrBadArguments", 71 ErrUnsupportedType: "ErrUnsupportedType", 72 ErrBadEnumValue: "ErrBadEnumValue", 73 ErrNotSettable: "ErrNotSettable", 74 ErrOverflow: "ErrOverflow", 75 ErrNilInterface: "ErrNilInterface", 76 ErrIO: "ErrIO", 77 ErrParseTime: "ErrParseTime", 78 } 79 80 // String returns the ErrorCode as a human-readable name. 81 func (e ErrorCode) String() string { 82 if s := errorCodeStrings[e]; s != "" { 83 return s 84 } 85 return fmt.Sprintf("Unknown ErrorCode (%d)", e) 86 } 87 88 // UnmarshalError describes a problem encountered while unmarshaling data. 89 // Some potential issues are unsupported Go types, attempting to decode a value 90 // which is too large to fit into a specified Go type, and exceeding max slice 91 // limitations. 92 type UnmarshalError struct { 93 ErrorCode ErrorCode // Describes the kind of error 94 Func string // Function name 95 Value interface{} // Value actually parsed where appropriate 96 Description string // Human readable description of the issue 97 Err error // The underlying error for IO errors 98 } 99 100 // Error satisfies the error interface and prints human-readable errors. 101 func (e *UnmarshalError) Error() string { 102 switch e.ErrorCode { 103 case ErrBadEnumValue, ErrOverflow, ErrIO, ErrParseTime: 104 return fmt.Sprintf("xdr:%s: %s - read: '%v'", e.Func, 105 e.Description, e.Value) 106 } 107 return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description) 108 } 109 110 // unmarshalError creates an error given a set of arguments and will copy byte 111 // slices into the Value field since they might otherwise be changed from from 112 // the original value. 113 func unmarshalError(f string, c ErrorCode, desc string, v interface{}, err error) *UnmarshalError { 114 e := &UnmarshalError{ErrorCode: c, Func: f, Description: desc, Err: err} 115 switch t := v.(type) { 116 case []byte: 117 slice := make([]byte, len(t)) 118 copy(slice, t) 119 e.Value = slice 120 default: 121 e.Value = v 122 } 123 124 return e 125 } 126 127 // MarshalError describes a problem encountered while marshaling data. 128 // Some potential issues are unsupported Go types, attempting to encode more 129 // opaque data than can be represented by a single opaque XDR entry, and 130 // exceeding max slice limitations. 131 type MarshalError struct { 132 ErrorCode ErrorCode // Describes the kind of error 133 Func string // Function name 134 Value interface{} // Value actually parsed where appropriate 135 Description string // Human readable description of the issue 136 Err error // The underlying error for IO errors 137 } 138 139 // Error satisfies the error interface and prints human-readable errors. 140 func (e *MarshalError) Error() string { 141 switch e.ErrorCode { 142 case ErrIO: 143 return fmt.Sprintf("xdr:%s: %s - wrote: '%v'", e.Func, 144 e.Description, e.Value) 145 case ErrBadEnumValue: 146 return fmt.Sprintf("xdr:%s: %s - value: '%v'", e.Func, 147 e.Description, e.Value) 148 } 149 return fmt.Sprintf("xdr:%s: %s", e.Func, e.Description) 150 } 151 152 // marshalError creates an error given a set of arguments and will copy byte 153 // slices into the Value field since they might otherwise be changed from from 154 // the original value. 155 func marshalError(f string, c ErrorCode, desc string, v interface{}, err error) *MarshalError { 156 e := &MarshalError{ErrorCode: c, Func: f, Description: desc, Err: err} 157 switch t := v.(type) { 158 case []byte: 159 slice := make([]byte, len(t)) 160 copy(slice, t) 161 e.Value = slice 162 default: 163 e.Value = v 164 } 165 166 return e 167 }