pulumi/sdk/go/common/util/mapper/errors.go

170 lines
5.1 KiB
Go

// Copyright 2016-2018, Pulumi Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
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.
_ 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.
_ 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.
_ 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.
_ 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 }