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  }