1
1
mirror of https://github.com/wader/fq.git synced 2024-12-23 21:31:33 +03:00

decode,interp: Add RecoverableErrorer interface instead of enumerate

This commit is contained in:
Mattias Wadman 2021-11-01 17:35:37 +01:00
parent 96cc1283cd
commit 58ba84ff93
3 changed files with 121 additions and 85 deletions

View File

@ -11,83 +11,11 @@ import (
"io/ioutil" "io/ioutil"
"strings" "strings"
"github.com/wader/fq/internal/num"
"github.com/wader/fq/internal/recoverfn" "github.com/wader/fq/internal/recoverfn"
"github.com/wader/fq/pkg/bitio" "github.com/wader/fq/pkg/bitio"
"github.com/wader/fq/pkg/ranges" "github.com/wader/fq/pkg/ranges"
) )
type FormatsError struct {
Errs []FormatError
}
func (de FormatsError) Error() string {
var errs []string
for _, err := range de.Errs {
errs = append(errs, err.Error())
}
return strings.Join(errs, ", ")
}
type FormatError struct {
Err error
Format *Format
Stacktrace recoverfn.Raw
}
func (fe FormatError) Error() string {
// var fns []string
// for _, f := range fe.Stacktrace.Frames() {
// fns = append(fns, fmt.Sprintf("%s:%d:%s", f.File, f.Line, f.Function))
// }
return fe.Err.Error()
}
func (fe FormatError) Value() interface{} {
var st []interface{}
for _, f := range fe.Stacktrace.Frames() {
st = append(st, f.Function)
}
return map[string]interface{}{
"format": fe.Format.Name,
"error": fe.Err.Error(),
"stacktrace": st,
}
}
type IOError struct {
Err error
Name string
Op string
ReadSize int64
SeekPos int64
Pos int64
}
func (e IOError) Error() string {
var prefix string
if e.Name != "" {
prefix = e.Op + "(" + e.Name + ")"
} else {
prefix = e.Op
}
return fmt.Sprintf("%s: failed at position %s (read size %s seek pos %s): %s",
prefix, num.Bits(e.Pos).StringByteBits(10), num.Bits(e.ReadSize).StringByteBits(10), num.Bits(e.SeekPos).StringByteBits(10), e.Err)
}
func (e IOError) Unwrap() error { return e.Err }
type ValidateError struct {
Reason string
Pos int64
}
func (e ValidateError) Error() string {
return fmt.Sprintf("failed to validate at position %s: %s", num.Bits(e.Pos).StringByteBits(16), e.Reason)
}
type Endian int type Endian int
const ( const (
@ -144,9 +72,8 @@ func decode(ctx context.Context, bb *bitio.Buffer, formats []*Format, opts Optio
} }
if !rOk { if !rOk {
switch panicV := r.RecoverV.(type) { if re, ok := r.RecoverV.(RecoverableErrorer); ok && re.IsRecoverableError() {
case IOError, ValidateError, FormatsError: panicErr, _ := re.(error)
panicErr, _ := panicV.(error)
formatErr := FormatError{ formatErr := FormatError{
Err: panicErr, Err: panicErr,
Format: f, Format: f,
@ -159,7 +86,7 @@ func decode(ctx context.Context, bb *bitio.Buffer, formats []*Format, opts Optio
if !forceOne { if !forceOne {
continue continue
} }
default: } else {
r.RePanic() r.RePanic()
} }
} }
@ -720,18 +647,24 @@ func (d *D) FieldValidateUFn(name string, v uint64, fn func() uint64) {
} }
} }
func (d *D) FieldValidateUTF8Fn(name string, v string, fn func() string) { func (d *D) ValidateUTF8Any(name string, nBytes int, vs []string) {
pos := d.Pos() pos := d.Pos()
found := false
s := d.FieldStrFn(name, func() (string, string) { s := d.FieldStrFn(name, func() (string, string) {
str := fn() str, err := d.TryUTF8(nBytes)
s := "Correct" if err != nil {
if str != v { panic(IOError{Err: err, Name: name, Op: "FieldValidateUTF8", ReadSize: int64(nBytes) * 8, Pos: d.Pos()})
s = "Incorrect"
} }
return str, s for _, v := range vs {
if v == str {
found = true
return str, "Correct"
}
}
return str, "Incorrect"
}) })
if s != v { if !found {
panic(ValidateError{Pos: pos}) panic(ValidateError{Reason: fmt.Sprintf("expected any of %q found %q", vs, s), Pos: pos})
} }
} }
@ -752,7 +685,7 @@ func (d *D) FieldValidateUTF8Any(name string, nBytes int, vs []string) {
return str, "Incorrect" return str, "Incorrect"
}) })
if !found { if !found {
panic(ValidateError{Reason: fmt.Sprintf("expected any of %v found %s", vs, s), Pos: pos}) panic(ValidateError{Reason: fmt.Sprintf("expected any of %q found %q", vs, s), Pos: pos})
} }
} }

90
pkg/decode/errors.go Normal file
View File

@ -0,0 +1,90 @@
package decode
import (
"fmt"
"strings"
"github.com/wader/fq/internal/num"
"github.com/wader/fq/internal/recoverfn"
)
type RecoverableErrorer interface {
IsRecoverableError() bool
}
type FormatError struct {
Err error
Format *Format
Stacktrace recoverfn.Raw
}
type FormatsError struct {
Errs []FormatError
}
func (fe FormatsError) Error() string {
var errs []string
for _, err := range fe.Errs {
errs = append(errs, err.Error())
}
return strings.Join(errs, ", ")
}
func (fe FormatError) Error() string {
// var fns []string
// for _, f := range fe.Stacktrace.Frames() {
// fns = append(fns, fmt.Sprintf("%s:%d:%s", f.File, f.Line, f.Function))
// }
return fe.Err.Error()
}
func (fe FormatError) Value() interface{} {
var st []interface{}
for _, f := range fe.Stacktrace.Frames() {
st = append(st, f.Function)
}
return map[string]interface{}{
"format": fe.Format.Name,
"error": fe.Err.Error(),
"stacktrace": st,
}
}
func (FormatsError) IsRecoverableError() bool { return true }
type IOError struct {
Err error
Name string
Op string
ReadSize int64
SeekPos int64
Pos int64
}
func (e IOError) Error() string {
var prefix string
if e.Name != "" {
prefix = e.Op + "(" + e.Name + ")"
} else {
prefix = e.Op
}
return fmt.Sprintf("%s: failed at position %s (read size %s seek pos %s): %s",
prefix, num.Bits(e.Pos).StringByteBits(10), num.Bits(e.ReadSize).StringByteBits(10), num.Bits(e.SeekPos).StringByteBits(10), e.Err)
}
func (e IOError) Unwrap() error { return e.Err }
func (IOError) IsRecoverableError() bool { return true }
type ValidateError struct {
Reason string
Pos int64
}
func (e ValidateError) Error() string {
return fmt.Sprintf("failed to validate at position %s: %s", num.Bits(e.Pos).StringByteBits(16), e.Reason)
}
func (ValidateError) IsRecoverableError() bool { return true }

View File

@ -40,3 +40,16 @@ mp3> probe({})
* |until 0x283.7 (end) (599) | | * |until 0x283.7 (end) (599) | |
| | | footers: [0] | | | footers: [0]
mp3> ^D mp3> ^D
$ fq -d raw 'png | d' /test.mp3
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.: {} (png)
| | | error: png: failed to validate at position 0x0: expected any of ["\x89PNG\r\n\x1a\n"] found "ID3\x04\x00\x00\x00\x00"
0x000|49 44 33 04 00 00 00 00 |ID3..... | signature: "ID3\x04\x00\x00\x00\x00" (Incorrect)
0x000| 00 23 54 53 53 45 00 00| .#TSSE..| unknown0: 0023545353450000000f0000034c6176...
0x010|00 0f 00 00 03 4c 61 76 66 35 38 2e 34 35 2e 31|.....Lavf58.45.1|
* |until 0x283.7 (end) (636) | |
$ fq -d raw 'tobytes[0:1] | png | d' /test.mp3
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.: {} (png)
| | | error: png: FieldValidateUTF8(signature): failed at position 1 (read size 8 seek pos 0): unexpected EOF
0x0|49 |I | unknown0: 49
$ fq -d raw 'tobytes[0:1] | try probe catch . | type' /test.mp3
"array"