errors.go 6.15 KB
Newer Older
1 2 3 4
package ipld

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

// ErrWrongKind may be returned from functions on the Node interface when
// a method is invoked which doesn't make sense for the Kind and/or ReprKind
// that node concretely contains.
//
// 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 26 27 28 29
	// ApprorpriateKind describes which ReprKinds the erroring method would
	// make sense for.
	AppropriateKind ReprKindSet

	// ActualKind describes the ReprKind 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 ReprKind
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 71
func (e ErrRepeatedMapKey) Error() string {
	return fmt.Sprintf("cannot repeat map key (\"%s\")", 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 97 98 99 100 101 102
	Reason error
}

func (e ErrInvalidKey) Error() string {
	if e.Reason == nil {
		return fmt.Sprintf("invalid key for map %s: \"%s\": no such field", e.TypeName, e.Key)
	} else {
		return fmt.Sprintf("invalid key for map %s: \"%s\": %s", e.TypeName, e.Key, e.Reason)
	}
}

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
}

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
// ErrUnmatchable is the catch-all type for parse errors in schema representation work.
//
// REVIEW: are builders at type level ever going to return this?  i don't think so.
// REVIEW: can this ever be triggered during the marshalling direction?  perhaps not.
// REVIEW: do things like ErrWrongKind end up being wrapped by this?  that doesn't seem pretty.
// REVIEW: do natural representations ever trigger this?  i don't think so.  maybe that's a hint towards a better name.
// REVIEW: are user validation functions encouraged to return this?  or something else?
//
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 {
	return fmt.Sprintf("parsing of %s rejected: %s", e.TypeName, e.Reason)
}

146 147 148 149 150 151 152
// 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"
}
153

154
type ErrCannotBeNull struct{} // Review: arguably either ErrInvalidKindForNodePrototype.
155

Will Scott's avatar
Will Scott committed
156 157 158 159 160 161 162 163 164 165
// 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, ",")
}

166 167
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.