errors.go 6.83 KB
Newer Older
tavit ohanian's avatar
tavit ohanian committed
1
package ld
2 3 4

import (
	"fmt"
Will Scott's avatar
Will Scott committed
5
	"strings"
6 7 8
)

// ErrWrongKind may be returned from functions on the Node interface when
9 10
// a method is invoked which doesn't make sense for the Kind that node
// concretely contains.
11 12
//
// For example, calling AsString on a map will return ErrWrongKind.
13
// Calling Lookup on an int will similarly return ErrWrongKind.
14
type ErrWrongKind struct {
15 16 17
	// TypeName may optionally indicate the named type of a node the function
	// was called on (if the node was typed!), or, may be the empty string.
	TypeName string
Eric Myhre's avatar
Eric Myhre committed
18

19 20
	// MethodName is literally the string for the operation attempted, e.g.
	// "AsString".
21 22
	//
	// For methods on nodebuilders, we say e.g. "NodeBuilder.CreateMap".
23 24
	MethodName string

25
	// ApprorpriateKind describes which Kinds the erroring method would
26
	// make sense for.
27
	AppropriateKind KindSet
28

29
	// ActualKind describes the Kind of the node the method was called on.
30 31 32
	//
	// In the case of typed nodes, this will typically refer to the 'natural'
	// data-model kind for such a type (e.g., structs will say 'map' here).
33
	ActualKind Kind
34 35 36
}

func (e ErrWrongKind) Error() string {
37 38 39 40 41
	if e.TypeName == "" {
		return fmt.Sprintf("func called on wrong kind: %s called on a %s node, but only makes sense on %s", e.MethodName, e.ActualKind, e.AppropriateKind)
	} else {
		return fmt.Sprintf("func called on wrong kind: %s called on a %s node (kind: %s), but only makes sense on %s", e.MethodName, e.TypeName, e.ActualKind, e.AppropriateKind)
	}
42
}
43

44 45
// ErrNotExists may be returned from the lookup functions of the Node interface
// to indicate a missing value.
46
//
47
// Note that schema.ErrNoSuchField is another type of error which sometimes
48 49 50 51 52
// occurs in similar places as ErrNotExists.  ErrNoSuchField is preferred
// when handling data with constraints provided by a schema that mean that
// a field can *never* exist (as differentiated from a map key which is
// simply absent in some data).
type ErrNotExists struct {
53
	Segment PathSegment
54 55 56 57 58
}

func (e ErrNotExists) Error() string {
	return fmt.Sprintf("key not found: %q", e.Segment)
}
59

Eric Myhre's avatar
Eric Myhre committed
60 61 62 63 64 65
// ErrRepeatedMapKey is an error indicating that a key was inserted
// into a map that already contains that key.
//
// This error may be returned by any methods that add data to a map --
// any of the methods on a NodeAssembler that was yielded by MapAssembler.AssignKey(),
// or from the MapAssembler.AssignDirectly() method.
66 67
type ErrRepeatedMapKey struct {
	Key Node
68 69
}

70
func (e ErrRepeatedMapKey) Error() string {
Daniel Martí's avatar
Daniel Martí committed
71
	return fmt.Sprintf("cannot repeat map key %q", e.Key)
72 73
}

Eric Myhre's avatar
Eric Myhre committed
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
// ErrInvalidKey indicates a key is invalid for some reason.
//
// This is only possible for typed nodes; specifically, it may show up when
// handling struct types, or maps with interesting key types.
// (Other kinds of key invalidity that happen for untyped maps
// fall under ErrRepeatedMapKey or ErrWrongKind.)
// (Union types use ErrInvalidUnionDiscriminant instead of ErrInvalidKey,
// even when their representation strategy is maplike.)
type ErrInvalidKey struct {
	// TypeName will indicate the named type of a node the function was called on.
	TypeName string

	// Key is the key that was rejected.
	Key Node

	// Reason, if set, may provide details (for example, the reason a key couldn't be converted to a type).
	// If absent, it'll be presumed "no such field".
91
	// ErrUnmatchable may show up as a reason for typed maps with complex keys.
Eric Myhre's avatar
Eric Myhre committed
92 93 94 95 96
	Reason error
}

func (e ErrInvalidKey) Error() string {
	if e.Reason == nil {
Daniel Martí's avatar
Daniel Martí committed
97
		return fmt.Sprintf("invalid key for map %s: %q: no such field", e.TypeName, e.Key)
Eric Myhre's avatar
Eric Myhre committed
98
	} else {
Daniel Martí's avatar
Daniel Martí committed
99
		return fmt.Sprintf("invalid key for map %s: %q: %s", e.TypeName, e.Key, e.Reason)
Eric Myhre's avatar
Eric Myhre committed
100 101 102
	}
}

103
// ErrInvalidSegmentForList is returned when using Node.LookupBySegment and the
Eric Myhre's avatar
Eric Myhre committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
// given PathSegment can't be applied to a list because it's unparsable as a number.
type ErrInvalidSegmentForList struct {
	// TypeName may indicate the named type of a node the function was called on,
	// or be empty string if working on untyped data.
	TypeName string

	// TroubleSegment is the segment we couldn't use.
	TroubleSegment PathSegment

	// Reason may explain more about why the PathSegment couldn't be used;
	// in practice, it's probably a 'strconv.NumError'.
	Reason error
}

func (e ErrInvalidSegmentForList) Error() string {
	v := "invalid segment for lookup on a list"
	if e.TypeName != "" {
		v += " of type " + e.TypeName
	}
123
	return v + fmt.Sprintf(": %q: %s", e.TroubleSegment.s, e.Reason)
Eric Myhre's avatar
Eric Myhre committed
124 125
}

Eric Myhre's avatar
Eric Myhre committed
126 127 128 129 130 131 132 133 134 135 136 137
// ErrHashMismatch is the error returned when loading data and verifying its hash
// and finding that the loaded data doesn't re-hash to the expected value.
// It is typically seen returned by functions like LinkSystem.Load or LinkSystem.Fill.
type ErrHashMismatch struct {
	Actual   Link
	Expected Link
}

func (e ErrHashMismatch) Error() string {
	return fmt.Sprintf("hash mismatch!  %v (actual) != %v (expected)", e.Actual, e.Expected)
}

138
// ErrUnmatchable is the error raised when processing data with LD Schemas and
Eric Myhre's avatar
Eric Myhre committed
139 140 141 142
// finding data which cannot be matched into the schema.
// It will be returned by NodeAssemblers and NodeBuilders when they are fed unmatchable data.
// As a result, it will also often be seen returned from unmarshalling
// when unmarshalling into schema-constrained NodeAssemblers.
143
//
Eric Myhre's avatar
Eric Myhre committed
144 145
// ErrUnmatchable provides the name of the type in the schema that data couldn't be matched to,
// and wraps another error as the more detailed reason.
146 147 148 149 150 151 152 153 154
type ErrUnmatchable struct {
	// TypeName will indicate the named type of a node the function was called on.
	TypeName string

	// Reason must always be present.  ErrUnmatchable doesn't say much otherwise.
	Reason error
}

func (e ErrUnmatchable) Error() string {
Eric Myhre's avatar
Eric Myhre committed
155 156 157 158 159 160 161
	return fmt.Sprintf("matching data to schema of %s rejected: %s", e.TypeName, e.Reason)
}

// Reasonf returns a new ErrUnmatchable with a Reason field set to the Errorf of the arguments.
// It's a helper function for creating untyped error reasons without importing the fmt package.
func (e ErrUnmatchable) Reasonf(format string, a ...interface{}) ErrUnmatchable {
	return ErrUnmatchable{e.TypeName, fmt.Errorf(format, a...)}
162 163
}

164 165 166 167 168 169 170
// ErrIteratorOverread is returned when calling 'Next' on a MapIterator or
// ListIterator when it is already done.
type ErrIteratorOverread struct{}

func (e ErrIteratorOverread) Error() string {
	return "iterator overread"
}
171

172
type ErrCannotBeNull struct{} // Review: arguably either ErrInvalidKindForNodePrototype.
173

Will Scott's avatar
Will Scott committed
174 175 176 177 178 179 180 181 182 183
// ErrMissingRequiredField is returned when calling 'Finish' on a NodeAssembler
// for a Struct that has not has all required fields set.
type ErrMissingRequiredField struct {
	Missing []string
}

func (e ErrMissingRequiredField) Error() string {
	return "missing required fields: " + strings.Join(e.Missing, ",")
}

184 185
type ErrListOverrun struct{}              // only possible for typed nodes -- specifically, struct types with list (aka tuple) representations.
type ErrInvalidUnionDiscriminant struct{} // only possible for typed nodes -- specifically, union types.