1
2
3
4
5
6
7 package jsontext
8
9 import (
10 "bytes"
11 "io"
12 "strconv"
13
14 "encoding/json/internal/jsonwire"
15 )
16
17 const errorPrefix = "jsontext: "
18
19 type ioError struct {
20 action string
21 err error
22 }
23
24 func (e *ioError) Error() string {
25 return errorPrefix + e.action + " error: " + e.err.Error()
26 }
27 func (e *ioError) Unwrap() error {
28 return e.err
29 }
30
31
32
33
34
35 type SyntacticError struct {
36 requireKeyedLiterals
37 nonComparable
38
39
40 ByteOffset int64
41
42
43 JSONPointer Pointer
44
45
46 Err error
47 }
48
49
50
51
52
53
54
55
56
57
58
59 func wrapSyntacticError(state interface {
60 offsetAt(pos int) int64
61 AppendStackPointer(b []byte, where int) []byte
62 }, err error, pos, where int) error {
63 if _, ok := err.(*ioError); err == io.EOF || ok {
64 return err
65 }
66 offset := state.offsetAt(pos)
67 ptr := state.AppendStackPointer(nil, where)
68 if serr, ok := err.(*pointerSuffixError); ok {
69 ptr = serr.appendPointer(ptr)
70 err = serr.error
71 }
72 if d, ok := state.(*decoderState); ok && err == errMismatchDelim {
73 where := "at start of value"
74 if len(d.Tokens.Stack) > 0 && d.Tokens.Last.Length() > 0 {
75 switch {
76 case d.Tokens.Last.isArray():
77 where = "after array element (expecting ',' or ']')"
78 ptr = []byte(Pointer(ptr).Parent())
79 case d.Tokens.Last.isObject():
80 where = "after object value (expecting ',' or '}')"
81 ptr = []byte(Pointer(ptr).Parent())
82 }
83 }
84 err = jsonwire.NewInvalidCharacterError(d.buf[pos:], where)
85 }
86 return &SyntacticError{ByteOffset: offset, JSONPointer: Pointer(ptr), Err: err}
87 }
88
89 func (e *SyntacticError) Error() string {
90 pointer := e.JSONPointer
91 offset := e.ByteOffset
92 b := []byte(errorPrefix)
93 if e.Err != nil {
94 b = append(b, e.Err.Error()...)
95 if e.Err == ErrDuplicateName {
96 b = strconv.AppendQuote(append(b, ' '), pointer.LastToken())
97 pointer = pointer.Parent()
98 offset = 0
99 }
100 } else {
101 b = append(b, "syntactic error"...)
102 }
103 if pointer != "" {
104 b = strconv.AppendQuote(append(b, " within "...), jsonwire.TruncatePointer(string(pointer), 100))
105 }
106 if offset > 0 {
107 b = strconv.AppendInt(append(b, " after offset "...), offset, 10)
108 }
109 return string(b)
110 }
111
112 func (e *SyntacticError) Unwrap() error {
113 return e.Err
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 type pointerSuffixError struct {
144 error
145
146
147 reversePointer []byte
148 }
149
150
151
152 func wrapWithObjectName(err error, quotedName []byte) error {
153 serr, _ := err.(*pointerSuffixError)
154 if serr == nil {
155 serr = &pointerSuffixError{error: err}
156 }
157 name := jsonwire.UnquoteMayCopy(quotedName, false)
158 serr.reversePointer = appendEscapePointerName(append(serr.reversePointer, '/'), name)
159 return serr
160 }
161
162
163 func wrapWithArrayIndex(err error, index int64) error {
164 serr, _ := err.(*pointerSuffixError)
165 if serr == nil {
166 serr = &pointerSuffixError{error: err}
167 }
168 serr.reversePointer = strconv.AppendUint(append(serr.reversePointer, '/'), uint64(index), 10)
169 return serr
170 }
171
172
173 func (e *pointerSuffixError) appendPointer(pointer []byte) []byte {
174
175
176 bi, bo := e.reversePointer, pointer
177 for len(bi) > 0 {
178 i := bytes.LastIndexByte(bi, '/')
179 bi, bo = bi[:i], append(bo, bi[i:]...)
180 }
181 return bo
182 }
183
View as plain text