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:
parent
96cc1283cd
commit
58ba84ff93
@ -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
90
pkg/decode/errors.go
Normal 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 }
|
13
pkg/interp/testdata/decode.fqtest
vendored
13
pkg/interp/testdata/decode.fqtest
vendored
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user