wip: decoder errors

This commit is contained in:
Thomas Pelletier
2021-03-30 19:52:02 -04:00
parent bcd5333b03
commit 18d45c446b
4 changed files with 43 additions and 8 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ func parseInteger(b []byte) (int64, error) {
case 'o':
return parseIntOct(b)
default:
return 0, fmt.Errorf("invalid base: '%c'", b[1])
return 0, newDecodeError(b[1:2], "invalid base: '%c'", b[1])
}
}
return parseIntDec(b)
+27 -6
View File
@@ -22,6 +22,24 @@ type DecodeError struct {
human string
}
// internal version of DecodeError that is used as the base to create a
// DecodeError with full context.
type decodeError struct {
highlight []byte
message string
}
func (de *decodeError) Error() string {
return de.message
}
func newDecodeError(highlight []byte, format string, args ...interface{}) error {
return &decodeError{
highlight: highlight,
message: fmt.Sprintf(format, args...),
}
}
// Error returns the error message contained in the DecodeError.
func (e *DecodeError) Error() string {
return e.message
@@ -45,15 +63,18 @@ func (e *DecodeError) Position() (row int, column int) {
//
// The function copies all bytes used in DecodeError, so that document and
// highlight can be freely deallocated.
func decodeErrorFromHighlight(document []byte, highlight []byte, message string) error {
func wrapDecodeError(document []byte, de *decodeError) error {
if de == nil {
return nil
}
err := &DecodeError{
message: message,
message: de.message,
}
offset := unsafe.SubsliceOffset(document, highlight)
offset := unsafe.SubsliceOffset(document, de.highlight)
err.line, err.column = positionAtEnd(document[:offset])
before, after := linesOfContext(document, highlight, offset, 3)
before, after := linesOfContext(document, de.highlight, offset, 3)
var buf strings.Builder
@@ -74,7 +95,7 @@ func decodeErrorFromHighlight(document []byte, highlight []byte, message string)
if len(before) > 0 {
buf.Write(before[0])
}
buf.Write(highlight)
buf.Write(de.highlight)
if len(after) > 0 {
buf.Write(after[0])
}
@@ -84,7 +105,7 @@ func decodeErrorFromHighlight(document []byte, highlight []byte, message string)
if len(before) > 0 {
buf.WriteString(strings.Repeat(" ", len(before[0])))
}
buf.WriteString(strings.Repeat("~", len(highlight)))
buf.WriteString(strings.Repeat("~", len(de.highlight)))
buf.WriteString(" ")
buf.WriteString(err.message)
+4 -1
View File
@@ -136,7 +136,10 @@ before `, "highlighted", ``},
doc := b.Bytes()
hl := doc[start:end]
err := decodeErrorFromHighlight(doc, hl, e.msg)
err := wrapDecodeError(doc, &decodeError{
highlight: hl,
message: e.msg,
})
derr := err.(*DecodeError)
assert.Equal(t, strings.Trim(e.expected, "\n"), derr.String())
})
+11
View File
@@ -66,6 +66,17 @@ func (d *decoder) arrayIndex(append bool, v reflect.Value) int {
}
func (d *decoder) FromParser(p *parser, v interface{}) error {
err := d.fromParser(p, v)
if err != nil {
de, ok := err.(*decodeError)
if ok {
err = wrapDecodeError(p.data, de)
}
}
return err
}
func (d *decoder) fromParser(p *parser, v interface{}) error {
r := reflect.ValueOf(v)
if r.Kind() != reflect.Ptr {
return fmt.Errorf("need to target a pointer, not %s", r.Kind())