summaryrefslogtreecommitdiff
path: root/errors.go
blob: da9de4deef3bdbea76840a546989884b505464d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// Copyright (C) 2022-2023  Luke Shumaker <lukeshu@lukeshu.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later

package lowmemjson

import (
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strings"

	"git.lukeshu.com/go/lowmemjson/internal/jsonparse"
)

// ErrInvalidUnreadRune is returned to Decodable.DecodeJSON(scanner)
// implementations from scanner.UnreadRune() if the last operation was
// not a successful .ReadRune() call.
var ErrInvalidUnreadRune = errors.New("lowmemjson: invalid use of UnreadRune")

// parser errors ///////////////////////////////////////////////////////////////////////////////////

// ErrParserExceededMaxDepth is the base error that a
// *DecodeSyntaxError wraps when the depth of the JSON document
// exceeds 10000.
var ErrParserExceededMaxDepth = jsonparse.ErrParserExceededMaxDepth

// low-level decode errors /////////////////////////////////////////////////////////////////////////
// These will be wrapped in a *DecodeError.

// A DecodeReadError is returned from Decode (wrapped in a
// *DecodeError) if there is an I/O error reading the input.
type DecodeReadError struct {
	Err    error
	Offset int64
}

func (e *DecodeReadError) Error() string {
	return fmt.Sprintf("json: I/O error at input byte %v: %v", e.Offset, e.Err)
}
func (e *DecodeReadError) Unwrap() error { return e.Err }

// A DecodeSyntaxError is returned from Decode (wrapped in a
// *DecodeError) if there is a syntax error in the input.
type DecodeSyntaxError struct {
	Err    error
	Offset int64
}

func (e *DecodeSyntaxError) Error() string {
	return fmt.Sprintf("json: syntax error at input byte %v: %v", e.Offset, e.Err)
}
func (e *DecodeSyntaxError) Unwrap() error { return e.Err }

// A DecodeTypeError is returned from Decode (wrapped in a
// *DecodeError) if the JSON input is not appropriate for the given Go
// type.
//
// If a .DecodeJSON, .UnmarshalJSON, or .UnmashaleText method returns
// an error, it is wrapped in a *DecodeTypeError.
type DecodeTypeError struct {
	JSONType string //  (optional)
	GoType   reflect.Type
	Offset   int64
	Err      error // (optional)
}

func (e *DecodeTypeError) Error() string {
	var buf strings.Builder
	buf.WriteString("json: cannot decode ")
	if e.JSONType != "" {
		fmt.Fprintf(&buf, "JSON %s ", e.JSONType)
	}
	fmt.Fprintf(&buf, "at input byte %v into Go %v", e.Offset, e.GoType)
	if e.Err != nil {
		fmt.Fprintf(&buf, ": %v", strings.TrimPrefix(e.Err.Error(), "json: "))
	}
	return buf.String()
}

func (e *DecodeTypeError) Unwrap() error { return e.Err }

// ErrDecodeNonEmptyInterface is the base error that a
// *DecodeTypeError wraps when Decode is asked to unmarshal into an
// `interface` type that has one or more methods.
var ErrDecodeNonEmptyInterface = errors.New("cannot decode into non-empty interface")

// high-level decode errors ////////////////////////////////////////////////////////////////////////

// A DecodeArgumentError is returned from Decode if the argument is
// not a non-nil pointer or is not settable.
//
// Alternatively, a *DecodeArgument error may be found inside of a
// *DecodeTypeError if the type being decoded into is not a type that
// can be decoded into (such as map with non-stringable type as keys).
//
//	type DecodeArgumentError struct {
//	    Type reflect.Type
//	}
type DecodeArgumentError = json.InvalidUnmarshalError

// A DecodeError is returned from Decode for all errors except for
// *DecodeArgumentError.
//
// A *DecodeError wraps *DecodeSyntaxError for malformed or illegal
// input, *DecodeTypeError for Go type issues, or *DecodeReadError for
// I/O errors.
type DecodeError struct {
	Field string // Where in the JSON the error was, in the form "v[idx][idx][idx]".
	Err   error  // What the error was.

	FieldParent string // for compat; the same as encoding/json.UnmarshalTypeError.Struct
	FieldName   string // for compat; the same as encoding/json.UnmarshalTypeError.Field
}

func (e *DecodeError) Error() string {
	return fmt.Sprintf("json: %s: %s", e.Field, strings.TrimPrefix(e.Err.Error(), "json: "))
}
func (e *DecodeError) Unwrap() error { return e.Err }

// encode errors ///////////////////////////////////////////////////////////////////////////////////

// A EncodeWriteError is returned from Encode if there is an error
// writing to the output stream.
type EncodeWriteError struct {
	Err    error
	Offset int64
}

func (e *EncodeWriteError) Error() string {
	return fmt.Sprintf("json: I/O error at output byte %v: %v", e.Offset, e.Err)
}
func (e *EncodeWriteError) Unwrap() error { return e.Err }

// An EncodeTypeError is returned by Encode when attempting to encode
// an unsupported type.
//
//	type EncodeTypeError struct {
//	    Type reflect.Type
//	}
type EncodeTypeError = json.UnsupportedTypeError

// An EncodeValueError is returned by Encode when attempting to encode
// an unsupported value (such as a datastructure with a cycle, or (if
// InvalidUTF8=InvalidUTF8Error) a string with invalid UTF-8).
//
//	type UnsupportedValueError struct {
//	    Value reflect.Value
//	    Str   string
//	}
type EncodeValueError = json.UnsupportedValueError

// An EncodeMethodError either wraps an error that is returned from an
// object's method when encoding that object to JSON, or wraps a
// *ReEncodeSyntaxError for the method's output.
type EncodeMethodError struct {
	Type       reflect.Type // The Go type that the method is on
	SourceFunc string       // The method: "EncodeJSON", "MarshalJSON", or "MarshalText"
	Err        error        // The error that the method returned
}

func (e *EncodeMethodError) Error() string {
	return fmt.Sprintf("json: error calling %v for type %v: %v",
		e.SourceFunc, e.Type, strings.TrimPrefix(e.Err.Error(), "json: "))
}
func (e *EncodeMethodError) Unwrap() error { return e.Err }

// reencode errors /////////////////////////////////////////////////////////////////////////////////

// A ReEncodeWriteError is returned from ReEncoder's methods if there
// is an error writing to the output stream.
type ReEncodeWriteError struct {
	Err    error
	Offset int64
}

func (e *ReEncodeWriteError) Error() string {
	return fmt.Sprintf("json: I/O error at output byte %v: %v", e.Offset, e.Err)
}
func (e *ReEncodeWriteError) Unwrap() error { return e.Err }

// A ReEncodeSyntaxError is returned from ReEncoder's methods if there
// is a syntax error in the input.
type ReEncodeSyntaxError struct {
	Err    error
	Offset int64
}

func (e *ReEncodeSyntaxError) Error() string {
	return fmt.Sprintf("json: syntax error at input byte %v: %v", e.Offset, e.Err)
}
func (e *ReEncodeSyntaxError) Unwrap() error { return e.Err }