1
2
3
4
5
6
7 package jsontext
8
9 import (
10 "bytes"
11 "io"
12 "strconv"
13
14 "encoding/json/internal/jsonflags"
15 "encoding/json/internal/jsonopts"
16 "encoding/json/internal/jsonwire"
17 )
18
19 const errorPrefix = "jsontext: "
20
21 type ioError struct {
22 action string
23 err error
24 }
25
26 func (e *ioError) Error() string {
27 return errorPrefix + e.action + " error: " + e.err.Error()
28 }
29 func (e *ioError) Unwrap() error {
30 return e.err
31 }
32
33 type numError struct {
34 accessor string
35 value string
36 err error
37 }
38
39 func (e *numError) Error() string {
40 return "jsontext.Token(" + e.value + ")." + e.accessor + " error: " + e.err.Error()
41 }
42 func (e *numError) Unwrap() error {
43 return e.err
44 }
45
46
47
48
49
50 type SyntacticError struct {
51 requireKeyedLiterals
52 nonComparable
53
54
55 ByteOffset int64
56
57
58 JSONPointer Pointer
59
60
61 Err error
62 }
63
64
65
66
67
68
69
70
71
72
73
74 func wrapSyntacticError(state interface {
75 options() *jsonopts.Struct
76 offsetAt(pos int) int64
77 AppendStackPointer(b []byte, where int) []byte
78 }, err error, pos, where int) error {
79 if _, ok := err.(*ioError); err == io.EOF || ok {
80 return err
81 }
82 offset := state.offsetAt(pos)
83 ptr := state.AppendStackPointer(nil, where)
84 if serr, ok := err.(*pointerSuffixError); ok {
85 ptr = serr.appendPointer(ptr)
86 err = serr.error
87 }
88 if d, ok := state.(*decoderState); ok && err == errMismatchDelim {
89 where := "at start of value"
90 if len(d.Tokens.Stack) > 0 && d.Tokens.Last.Length() > 0 {
91 switch {
92 case d.Tokens.Last.isArray():
93 where = "after array element (expecting ',' or ']')"
94 ptr = []byte(Pointer(ptr).Parent())
95 case d.Tokens.Last.isObject():
96 where = "after object value (expecting ',' or '}')"
97 ptr = []byte(Pointer(ptr).Parent())
98 }
99 }
100 err = jsonwire.NewInvalidCharacterError(d.buf[pos:], where)
101 }
102 if state.options().Flags.Get(jsonflags.ReportErrorsWithLegacySemantics) && err != io.ErrUnexpectedEOF {
103
104
105
106 if werr, ok := err.(*jsonwire.InvalidTextError); ok && werr != nil {
107 offset += int64(len(werr.What))
108 } else {
109
110
111
112
113
114 offset++
115 }
116 }
117 return &SyntacticError{ByteOffset: offset, JSONPointer: Pointer(ptr), Err: err}
118 }
119
120 func (e *SyntacticError) Error() string {
121 pointer := e.JSONPointer
122 offset := e.ByteOffset
123 b := []byte(errorPrefix)
124 if e.Err != nil {
125 b = append(b, e.Err.Error()...)
126 if e.Err == ErrDuplicateName {
127 b = strconv.AppendQuote(append(b, ' '), pointer.LastToken())
128 pointer = pointer.Parent()
129 offset = 0
130 }
131 } else {
132 b = append(b, "syntactic error"...)
133 }
134 if pointer != "" {
135 b = strconv.AppendQuote(append(b, " within "...), jsonwire.TruncatePointer(string(pointer), 100))
136 }
137 if offset > 0 {
138 b = strconv.AppendInt(append(b, " after offset "...), offset, 10)
139 }
140 return string(b)
141 }
142
143 func (e *SyntacticError) Unwrap() error {
144 return e.Err
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 type pointerSuffixError struct {
175 error
176
177
178 reversePointer []byte
179 }
180
181
182
183 func wrapWithObjectName(err error, quotedName []byte) error {
184 serr, _ := err.(*pointerSuffixError)
185 if serr == nil {
186 serr = &pointerSuffixError{error: err}
187 }
188 name := jsonwire.UnquoteMayCopy(quotedName, false)
189 serr.reversePointer = appendEscapePointerName(append(serr.reversePointer, '/'), name)
190 return serr
191 }
192
193
194 func wrapWithArrayIndex(err error, index int64) error {
195 serr, _ := err.(*pointerSuffixError)
196 if serr == nil {
197 serr = &pointerSuffixError{error: err}
198 }
199 serr.reversePointer = strconv.AppendUint(append(serr.reversePointer, '/'), uint64(index), 10)
200 return serr
201 }
202
203
204 func (e *pointerSuffixError) appendPointer(pointer []byte) []byte {
205
206
207 bi, bo := e.reversePointer, pointer
208 for len(bi) > 0 {
209 i := bytes.LastIndexByte(bi, '/')
210 bi, bo = bi[:i], append(bo, bi[i:]...)
211 }
212 return bo
213 }
214
View as plain text