podman
177 строк · 6.2 Кб
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
17package xdr
18
19import "fmt"
20
21// ErrorCode identifies a kind of error.
22type ErrorCode int
23
24const (
25// ErrBadArguments indicates arguments passed to the function are not
26// what was expected.
27ErrBadArguments ErrorCode = iota
28
29// ErrUnsupportedType indicates the Go type is not a supported type for
30// marshalling and unmarshalling XDR data.
31ErrUnsupportedType
32
33// ErrBadEnumValue indicates an enumeration value is not in the list of
34// valid values.
35ErrBadEnumValue
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.
41ErrNotSettable
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.
47ErrOverflow
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.
52ErrNilInterface
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.
58ErrIO
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.
63ErrParseTime
64)
65
66// Map of ErrorCode values back to their constant names for pretty printing.
67var errorCodeStrings = map[ErrorCode]string{
68ErrBadArguments: "ErrBadArguments",
69ErrUnsupportedType: "ErrUnsupportedType",
70ErrBadEnumValue: "ErrBadEnumValue",
71ErrNotSettable: "ErrNotSettable",
72ErrOverflow: "ErrOverflow",
73ErrNilInterface: "ErrNilInterface",
74ErrIO: "ErrIO",
75ErrParseTime: "ErrParseTime",
76}
77
78// String returns the ErrorCode as a human-readable name.
79func (e ErrorCode) String() string {
80if s := errorCodeStrings[e]; s != "" {
81return s
82}
83return 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.
90type UnmarshalError struct {
91ErrorCode ErrorCode // Describes the kind of error
92Func string // Function name
93Value interface{} // Value actually parsed where appropriate
94Description string // Human readable description of the issue
95Err error // The underlying error for IO errors
96}
97
98// Error satisfies the error interface and prints human-readable errors.
99func (e *UnmarshalError) Error() string {
100switch e.ErrorCode {
101case ErrBadEnumValue, ErrOverflow, ErrIO, ErrParseTime:
102return fmt.Sprintf("xdr:%s: %s - read: '%v'", e.Func,
103e.Description, e.Value)
104}
105return 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.
111func unmarshalError(f string, c ErrorCode, desc string, v interface{}, err error) *UnmarshalError {
112e := &UnmarshalError{ErrorCode: c, Func: f, Description: desc, Err: err}
113switch t := v.(type) {
114case []byte:
115slice := make([]byte, len(t))
116copy(slice, t)
117e.Value = slice
118default:
119e.Value = v
120}
121
122return 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.
127func IsIO(err error) bool {
128switch e := err.(type) {
129case *UnmarshalError:
130return e.ErrorCode == ErrIO
131case *MarshalError:
132return e.ErrorCode == ErrIO
133}
134return 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.
141type MarshalError struct {
142ErrorCode ErrorCode // Describes the kind of error
143Func string // Function name
144Value interface{} // Value actually parsed where appropriate
145Description string // Human readable description of the issue
146Err error // The underlying error for IO errors
147}
148
149// Error satisfies the error interface and prints human-readable errors.
150func (e *MarshalError) Error() string {
151switch e.ErrorCode {
152case ErrIO:
153return fmt.Sprintf("xdr:%s: %s - wrote: '%v'", e.Func,
154e.Description, e.Value)
155case ErrBadEnumValue:
156return fmt.Sprintf("xdr:%s: %s - value: '%v'", e.Func,
157e.Description, e.Value)
158}
159return 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.
165func marshalError(f string, c ErrorCode, desc string, v interface{}, err error) *MarshalError {
166e := &MarshalError{ErrorCode: c, Func: f, Description: desc, Err: err}
167switch t := v.(type) {
168case []byte:
169slice := make([]byte, len(t))
170copy(slice, t)
171e.Value = slice
172default:
173e.Value = v
174}
175
176return e
177}
178