Skip to content

Commit 3eb511b

Browse files
committed
Move parse context to separate struct
1 parent 7f64445 commit 3eb511b

File tree

2 files changed

+79
-43
lines changed

2 files changed

+79
-43
lines changed

bite.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const DefaultParseContextLen = 100
1010
// Bite implements Eater interface.
1111
type Bite struct {
1212
DisableParseContext bool // Do not provide parsing context on error.
13-
ParseContextLen int // Maximum length of error context to provide.
13+
ParseContextLen int // Maximum length of error context to provide. A negative integer instructs to copy the whole parse context.
1414

1515
noms []Nom
1616
}
@@ -42,8 +42,10 @@ func (bite *Bite) Eat(ctx context.Context, p Plate) (err error) {
4242

4343
if err != nil && !bite.DisableParseContext {
4444
var ctxLen = bite.ParseContextLen
45-
if ctxLen < 1 {
45+
if ctxLen == 0 {
4646
ctxLen = DefaultParseContextLen
47+
} else if ctxLen < 0 {
48+
ctxLen = errPos - startPos
4749
}
4850

4951
var e = &ErrParseFailed{

errors.go

Lines changed: 75 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ type ErrParseFailed struct {
5656
Err error
5757
StartPos int
5858
EndPos int
59-
Context []byte
59+
Context *ParseContext
6060
Breadcrumbs []Breadcrumb
6161
}
6262

@@ -65,10 +65,9 @@ func (e *ErrParseFailed) Error() string {
6565
sb.WriteString(e.Err.Error())
6666
sb.WriteString(fmt.Sprintf(", start position: %d, end position: %d", e.StartPos, e.EndPos))
6767

68-
if len(e.Context) > 0 {
69-
sb.WriteString(", context: '")
70-
_, _ = sb.Write(e.Context)
71-
sb.WriteByte('\'')
68+
if e.Context != nil {
69+
sb.WriteString(", context: ")
70+
sb.WriteString(e.Context.String())
7271
}
7372

7473
if len(e.Breadcrumbs) > 0 {
@@ -91,45 +90,31 @@ func (e *ErrParseFailed) Unwrap() error {
9190
}
9291

9392
func (e *ErrParseFailed) CopyContext(ctx context.Context, p Plate, startPos, endPos, chunkLen int) {
94-
var ctxLen = endPos - startPos
93+
e.Context = new(ParseContext)
94+
95+
var (
96+
ctxLen = endPos - startPos
97+
buf []byte
98+
)
9599
if ctxLen <= chunkLen {
96-
if buf, err := p.ByteSlice(ctx, startPos, endPos); err == nil {
97-
e.Context = make([]byte, ctxLen)
98-
copy(e.Context, buf)
100+
if buf, e.Context.HeadErr = p.ByteSlice(ctx, startPos, endPos); e.Context.HeadErr == nil {
101+
e.Context.Head = make([]byte, len(buf))
102+
copy(e.Context.Head, buf)
99103
}
100104
} else {
101-
var leftLen = ctxLen / 2
102-
leftBuf, leftErr := p.ByteSlice(ctx, startPos, startPos+leftLen)
103-
104-
var rightLen = ctxLen - leftLen
105-
rightBuf, rightErr := p.ByteSlice(ctx, endPos-rightLen, endPos)
106-
107-
if leftErr == nil && rightErr == nil {
108-
var (
109-
bytesRemain = ctxLen - chunkLen
110-
remainMsg = []byte(fmt.Sprintf("..[%d bytes]..", bytesRemain))
111-
msgLen = len(remainMsg)
112-
)
113-
e.Context = make([]byte, ctxLen+msgLen)
114-
copy(e.Context[:leftLen], leftBuf)
115-
copy(e.Context[leftLen:leftLen+msgLen], remainMsg)
116-
copy(e.Context[leftLen+msgLen:], rightBuf)
117-
} else if leftErr == nil {
118-
var (
119-
remainMsg = []byte("..[more bytes]")
120-
msgLen = len(remainMsg)
121-
)
122-
e.Context = make([]byte, leftLen+msgLen)
123-
copy(e.Context[:leftLen], leftBuf)
124-
copy(e.Context[leftLen:leftLen+msgLen], remainMsg)
125-
} else if rightErr == nil {
126-
var (
127-
remainMsg = []byte("[more bytes]..")
128-
msgLen = len(remainMsg)
129-
)
130-
e.Context = make([]byte, rightLen+msgLen)
131-
copy(e.Context[:msgLen], remainMsg)
132-
copy(e.Context[msgLen:], rightBuf)
105+
e.Context.Parted = true
106+
e.Context.BytesRemain = ctxLen - chunkLen
107+
108+
var leftLen = chunkLen / 2
109+
if buf, e.Context.HeadErr = p.ByteSlice(ctx, startPos, startPos+leftLen); e.Context.HeadErr == nil {
110+
e.Context.Head = make([]byte, len(buf))
111+
copy(e.Context.Head, buf)
112+
}
113+
114+
var rightLen = chunkLen - leftLen
115+
if buf, e.Context.TailErr = p.ByteSlice(ctx, endPos-rightLen, endPos); e.Context.TailErr == nil {
116+
e.Context.Tail = make([]byte, len(buf))
117+
copy(e.Context.Tail, buf)
133118
}
134119
}
135120
}
@@ -183,6 +168,55 @@ func ExtendBreadcrumb(err error, startPos, endPos int) error {
183168
return err
184169
}
185170

171+
type ParseContext struct {
172+
Head []byte
173+
HeadErr error
174+
Tail []byte
175+
TailErr error
176+
BytesRemain int
177+
Parted bool
178+
}
179+
180+
func (pc ParseContext) String() string {
181+
var sb strings.Builder
182+
183+
if pc.Parted {
184+
if pc.HeadErr == nil && pc.TailErr == nil {
185+
sb.WriteByte('\'')
186+
_, _ = sb.Write(pc.Head)
187+
if pc.BytesRemain > 0 {
188+
sb.WriteString("..[")
189+
sb.WriteString(strconv.Itoa(pc.BytesRemain))
190+
sb.WriteString(" bytes]..")
191+
}
192+
_, _ = sb.Write(pc.Tail)
193+
sb.WriteByte('\'')
194+
} else if pc.HeadErr == nil {
195+
sb.WriteByte('\'')
196+
_, _ = sb.Write(pc.Head)
197+
sb.WriteString("..[more bytes]'")
198+
} else if pc.TailErr == nil {
199+
sb.WriteString("'[more bytes]..")
200+
_, _ = sb.Write(pc.Tail)
201+
sb.WriteByte('\'')
202+
} else {
203+
sb.WriteByte('!')
204+
sb.WriteString(pc.HeadErr.Error())
205+
}
206+
} else {
207+
if pc.HeadErr == nil {
208+
sb.WriteByte('\'')
209+
_, _ = sb.Write(pc.Head)
210+
sb.WriteByte('\'')
211+
} else {
212+
sb.WriteByte('!')
213+
sb.WriteString(pc.HeadErr.Error())
214+
}
215+
}
216+
217+
return sb.String()
218+
}
219+
186220
type Breadcrumb struct {
187221
Name string
188222
Index int

0 commit comments

Comments
 (0)