149 lines
4.5 KiB
Go
149 lines
4.5 KiB
Go
// Copyright 2016-2017, Pulumi Corporation. All rights reserved.
|
|
|
|
package mapper
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
// MappingError represents a collection of decoding errors, defined below.
|
|
type MappingError interface {
|
|
error
|
|
Failures() []error // the full set of errors (each of one of the below types).
|
|
AddFailure(err error) // registers a new failure.
|
|
}
|
|
|
|
// mappingError is a concrete implementation of MappingError; it is private, and we prefer to use the above interface
|
|
// type, to avoid tricky non-nil nils in common usage patterns (see https://golang.org/doc/faq#nil_error).
|
|
type mappingError struct {
|
|
failures []error
|
|
}
|
|
|
|
var _ error = (*mappingError)(nil) // ensure this implements the error interface.
|
|
|
|
func NewMappingError(errs []error) MappingError {
|
|
return &mappingError{failures: errs}
|
|
}
|
|
|
|
func (e *mappingError) Failures() []error { return e.failures }
|
|
|
|
func (e *mappingError) AddFailure(err error) {
|
|
e.failures = append(e.failures, err)
|
|
}
|
|
|
|
func (e *mappingError) Error() string {
|
|
str := fmt.Sprintf("%d failures decoding:", len(e.failures))
|
|
for _, failure := range e.failures {
|
|
switch f := failure.(type) {
|
|
case FieldError:
|
|
str += fmt.Sprintf("\n\t%v: %v", f.Field(), f.Reason())
|
|
default:
|
|
str += fmt.Sprintf("\n\t%v", f)
|
|
}
|
|
}
|
|
return str
|
|
}
|
|
|
|
// FieldError represents a failure during decoding of a specific field.
|
|
type FieldError interface {
|
|
error
|
|
Field() string // returns the name of the field with a problem.
|
|
Reason() string // returns a full diagnostic string about the error.
|
|
}
|
|
|
|
// fieldError is used when a general purpose error occurs decoding a field.
|
|
type fieldError struct {
|
|
Type string
|
|
Fld string
|
|
Message string
|
|
}
|
|
|
|
var _ error = (*fieldError)(nil) // ensure this implements the error interface.
|
|
var _ FieldError = (*fieldError)(nil) // ensure this implements the fieldError interface.
|
|
|
|
func NewFieldError(ty string, fld string, err error) FieldError {
|
|
return &fieldError{
|
|
Type: ty,
|
|
Fld: fld,
|
|
Message: fmt.Sprintf("An error occurred decoding '%v.%v': %v", ty, fld, err),
|
|
}
|
|
}
|
|
|
|
func NewTypeFieldError(ty reflect.Type, fld string, err error) FieldError {
|
|
return NewFieldError(ty.Name(), fld, err)
|
|
}
|
|
|
|
func (e *fieldError) Error() string { return e.Message }
|
|
func (e *fieldError) Field() string { return e.Fld }
|
|
func (e *fieldError) Reason() string { return e.Message }
|
|
|
|
// MissingError is used when a required field is missing on an object of a given type.
|
|
type MissingError struct {
|
|
Type reflect.Type
|
|
Fld string
|
|
Message string
|
|
}
|
|
|
|
var _ error = (*MissingError)(nil) // ensure this implements the error interface.
|
|
var _ FieldError = (*MissingError)(nil) // ensure this implements the FieldError interface.
|
|
|
|
func NewMissingError(ty reflect.Type, fld string) *MissingError {
|
|
return &MissingError{
|
|
Type: ty,
|
|
Fld: fld,
|
|
Message: fmt.Sprintf("Missing required field '%v' on '%v'", fld, ty),
|
|
}
|
|
}
|
|
|
|
func (e *MissingError) Error() string { return e.Message }
|
|
func (e *MissingError) Field() string { return e.Fld }
|
|
func (e *MissingError) Reason() string { return e.Message }
|
|
|
|
// UnrecognizedError is used when a field is unrecognized on the given type.
|
|
type UnrecognizedError struct {
|
|
Type reflect.Type
|
|
Fld string
|
|
Message string
|
|
}
|
|
|
|
var _ error = (*UnrecognizedError)(nil) // ensure this implements the error interface.
|
|
var _ FieldError = (*UnrecognizedError)(nil) // ensure this implements the FieldError interface.
|
|
|
|
func NewUnrecognizedError(ty reflect.Type, fld string) *UnrecognizedError {
|
|
return &UnrecognizedError{
|
|
Type: ty,
|
|
Fld: fld,
|
|
Message: fmt.Sprintf("Unrecognized field '%v' on '%v'", fld, ty),
|
|
}
|
|
}
|
|
|
|
func (e *UnrecognizedError) Error() string { return e.Message }
|
|
func (e *UnrecognizedError) Field() string { return e.Fld }
|
|
func (e *UnrecognizedError) Reason() string { return e.Message }
|
|
|
|
type WrongTypeError struct {
|
|
Type reflect.Type
|
|
Fld string
|
|
Expect reflect.Type
|
|
Actual reflect.Type
|
|
Message string
|
|
}
|
|
|
|
var _ error = (*WrongTypeError)(nil) // ensure this implements the error interface.
|
|
var _ FieldError = (*WrongTypeError)(nil) // ensure this implements the FieldError interface.
|
|
|
|
func NewWrongTypeError(ty reflect.Type, fld string, expect reflect.Type, actual reflect.Type) *WrongTypeError {
|
|
return &WrongTypeError{
|
|
Type: ty,
|
|
Fld: fld,
|
|
Expect: expect,
|
|
Actual: actual,
|
|
Message: fmt.Sprintf(
|
|
"Field '%v' on '%v' must be a '%v'; got '%v' instead", fld, ty, expect, actual),
|
|
}
|
|
}
|
|
|
|
func (e *WrongTypeError) Error() string { return e.Message }
|
|
func (e *WrongTypeError) Field() string { return e.Fld }
|
|
func (e *WrongTypeError) Reason() string { return e.Message }
|