blob: 17f7e8fd068b55907c3159b34e81d4880b866706 [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
}
// ErrorCode represents a set of machine-readable error codes each ValidationError
// has.
type ErrorCode uint32
const (
ErrUnknownOrdinal ErrorCode = iota
ErrInvalidInlineType
ErrInvalidPointerType
ErrVectorTooLong
ErrStringTooLong
ErrUnexpectedOrdinal
ErrUnexpectedNullHandle
ErrUnexpectedNullRef
ErrInvalidBoolValue
ErrNotEnoughHandles
ErrBadHandleEncoding
ErrBadRefEncoding
ErrMessageTooSmall
ErrStructIsNotPayload
ErrInvalidUnionTag
)
// 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 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 ErrBadHandleEncoding:
return "bad encoding for handle"
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"
default:
return "unknown error code"
}
}
// 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)
}