blob: 2f8040a8ef6eb4522bfdfd0e8475b22a9b756670 [file] [log] [blame]
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build fuchsia
package fidl
import (
"reflect"
"strconv"
)
// ValidationError represents an error produced in validating a FIDL structure.
type ValidationError interface {
error
// Code returns the underlying ErrorCode value, which all ValidationErrors
// must have.
Code() ErrorCode
}
// Assert that valueError and expectError both implement the ValidationError
// interface.
var _ = []ValidationError{
valueError{},
expectError{},
}
// ErrorCode represents a set of machine-readable error codes each ValidationError
// has.
type ErrorCode uint32
const (
Invalid ErrorCode = iota
ErrUnknownOrdinal
ErrInvalidInlineType
ErrInvalidPointerType
ErrVectorTooLong
ErrStringTooLong
ErrEnvelopeTooLong
ErrUnexpectedOrdinal
ErrUnexpectedNullHandle
ErrUnexpectedNullRef
ErrInvalidBoolValue
ErrNotEnoughHandles
ErrTooManyHandles
ErrBadHandleEncoding
ErrNonZeroPadding
ErrBadRefEncoding
ErrMessageTooSmall
ErrStructIsNotPayload
ErrInvalidUnionTag
ErrInvalidXUnionTag
ErrPayloadTooSmall
ErrInvalidEmptyStruct
ErrUnexpectedNumBytes
ErrUnexpectedNumHandles
ErrStringNotUTF8
)
var errorCodeNames = []string{
Invalid: "Invalid",
ErrUnknownOrdinal: "ErrUnknownOrdinal",
ErrInvalidInlineType: "ErrInvalidInlineType",
ErrInvalidPointerType: "ErrInvalidPointerType",
ErrVectorTooLong: "ErrVectorTooLong",
ErrStringTooLong: "ErrStringTooLong",
ErrEnvelopeTooLong: "ErrEnvelopeTooLong",
ErrUnexpectedOrdinal: "ErrUnexpectedOrdinal",
ErrUnexpectedNullHandle: "ErrUnexpectedNullHandle",
ErrUnexpectedNullRef: "ErrUnexpectedNullRef",
ErrInvalidBoolValue: "ErrInvalidBoolValue",
ErrNotEnoughHandles: "ErrNotEnoughHandles",
ErrTooManyHandles: "ErrTooManyHandles",
ErrNonZeroPadding: "ErrNonZeroPadding",
ErrBadHandleEncoding: "ErrBadHandleEncoding",
ErrBadRefEncoding: "ErrBadRefEncoding",
ErrMessageTooSmall: "ErrMessageTooSmall",
ErrStructIsNotPayload: "ErrStructIsNotPayload",
ErrInvalidUnionTag: "ErrInvalidUnionTag",
ErrInvalidXUnionTag: "ErrInvalidXUnionTag",
ErrPayloadTooSmall: "ErrPayloadTooSmall",
ErrInvalidEmptyStruct: "ErrInvalidEmptyStruct",
ErrUnexpectedNumBytes: "ErrUnexpectedNumBytes",
ErrUnexpectedNumHandles: "ErrUnexpectedNumHandles",
ErrStringNotUTF8: "ErrStringNotUTF8",
}
func (c ErrorCode) String() string {
if len(errorCodeNames) < int(c) {
return strconv.Itoa(int(c))
}
return errorCodeNames[int(c)]
}
// Error implements error for ErrorCode
func (e ErrorCode) Error() string {
switch e {
case ErrUnknownOrdinal:
return "unknown ordinal"
case ErrInvalidInlineType:
return "invalid inline type"
case ErrInvalidPointerType:
return "invalid pointer type"
case ErrVectorTooLong:
return "vector exceeds maximum size"
case ErrStringTooLong:
return "string exceeds maximum size"
case ErrEnvelopeTooLong:
return "envelope exceeds maximum size"
case ErrUnexpectedOrdinal:
return "unexpected ordinal"
case ErrUnexpectedNullHandle:
return "unexpected null handle"
case ErrUnexpectedNullRef:
return "unexpected null reference"
case ErrInvalidBoolValue:
return "unexpected boolean value"
case ErrNotEnoughHandles:
return "not enough handles"
case ErrTooManyHandles:
return "too many handles"
case ErrBadHandleEncoding:
return "bad encoding for handle"
case ErrNonZeroPadding:
return "invalid non-zero padding"
case ErrBadRefEncoding:
return "bad encoding for ref"
case ErrMessageTooSmall:
return "message too small to have FIDL header"
case ErrStructIsNotPayload:
return "golang struct type must implement Payload"
case ErrInvalidUnionTag:
return "union tag out of bounds"
case ErrInvalidXUnionTag:
return "strict xunion has unknown tag"
case ErrPayloadTooSmall:
return "payload too small"
case ErrInvalidEmptyStruct:
return "invalid empty struct"
case ErrUnexpectedNumBytes:
return "unexpected num bytes"
case ErrUnexpectedNumHandles:
return "unexpected num handles"
case ErrStringNotUTF8:
return "string is not valid UTF8"
default:
return e.String()
}
}
// Code implements the ValidationError interface.
func (e ErrorCode) Code() ErrorCode {
return e
}
// stringer is an interface for types for which a string representation
// may be derived.
type stringer interface {
String() string
}
// toString generates the string representation for a limited set of types.
func toString(value interface{}) string {
if e, ok := value.(error); ok {
return e.Error()
}
if s, ok := value.(stringer); ok {
return s.String()
}
t := reflect.TypeOf(value)
switch t.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(reflect.ValueOf(value).Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.FormatUint(reflect.ValueOf(value).Uint(), 10)
case reflect.String:
return value.(string)
default:
return "##BADVALUE##"
}
}
// valueError represents an error that refers to a single value.
type valueError struct {
ErrorCode
value interface{}
}
func newValueError(code ErrorCode, value interface{}) valueError {
return valueError{
ErrorCode: code,
value: value,
}
}
func (e valueError) Error() string {
return e.ErrorCode.Error() + ": " + toString(e.value)
}
// expectError represents an error that refers to the expectation of a
// certain value, and displays a comparison between the actual value and
// the expected value.
type expectError struct {
ErrorCode
expect interface{}
actual interface{}
}
func newExpectError(code ErrorCode, expect, actual interface{}) expectError {
return expectError{
ErrorCode: code,
expect: expect,
actual: actual,
}
}
func (e expectError) Error() string {
return e.ErrorCode.Error() + ": expected " + toString(e.expect) + ", got " + toString(e.actual)
}