Skip to content

Commit

Permalink
interp,decode: Support decode group argument
Browse files Browse the repository at this point in the history
Will be used for probing via -d <string> and filename
  • Loading branch information
wader committed May 3, 2023
1 parent ee729c2 commit 684a083
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 73 deletions.
36 changes: 34 additions & 2 deletions format/format.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package format

import "github.com/wader/fq/pkg/decode"
import (
"path/filepath"
"strings"

"github.com/wader/fq/pkg/decode"
)

// TODO: do before-format somehow and topology sort?
const (
Expand All @@ -12,9 +17,36 @@ const (

// TODO: move to group package somehow?

type Probe_In struct {
IsProbe bool
Filename string
}

// Use HasExt("cer", "CeR", ...)
func (pi Probe_In) HasExt(ss ...string) bool {
ext := filepath.Ext(pi.Filename)
if ext == "" {
return false
}
ext = ext[1:]
for _, s := range ss {
if strings.EqualFold(s, ext) {
return true
}
}
return false
}

type Probe_Args_In struct {
IsProbeArgs bool
Filename string
DecodeGroup string
}

var (
Image = &decode.Group{Name: "image"}
Probe = &decode.Group{Name: "probe"}
Probe = &decode.Group{Name: "probe", DefaultInArg: Probe_In{}}
Probe_Args = &decode.Group{Name: "probe_args", DefaultInArg: Probe_Args_In{}}
Link_Frame = &decode.Group{Name: "link_frame", DefaultInArg: Link_Frame_In{}} // ex: ethernet
INET_Packet = &decode.Group{Name: "inet_packet", DefaultInArg: INET_Packet_In{}} // ex: ipv4
IP_Packet = &decode.Group{Name: "ip_packet", DefaultInArg: INET_Packet_In{}} // ex: tcp
Expand Down
4 changes: 4 additions & 0 deletions internal/aheadreadseeker/aheadreadseeker.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,7 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) {

return absOff, nil
}

func (r *Reader) Unwrap() any {
return r.rs
}
4 changes: 4 additions & 0 deletions internal/ctxreadseeker/ctxreadseeker.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,7 @@ func (r *Reader) Close() (err error) {
}
return err
}

func (r *Reader) Unwrap() any {
return r.rs
}
12 changes: 12 additions & 0 deletions internal/ioex/ioex.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,15 @@ func (o DiscardCtxWriter) Write(p []byte) (n int, err error) {
}
return n, nil
}

func Unwrap(r any) any {
for {
u, ok := r.(interface {
Unwrap() any
})
if !ok {
return r
}
r = u.Unwrap()
}
}
4 changes: 4 additions & 0 deletions internal/progressreadseeker/progressreaderseeker.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,7 @@ func (prs *Reader) Seek(offset int64, whence int) (int64, error) {
prs.pos = pos
return pos, err
}

func (prs *Reader) Unwrap() any {
return prs.rs
}
4 changes: 4 additions & 0 deletions pkg/bitio/iobitreadseeker.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,7 @@ func (r *IOBitReadSeeker) CloneReadAtSeeker() (ReadAtSeeker, error) {
func (r *IOBitReadSeeker) CloneReaderAtSeeker() (ReaderAtSeeker, error) {
return NewIOBitReadSeeker(r.rs), nil
}

func (r *IOBitReadSeeker) Unwrap() any {
return r.rs
}
4 changes: 4 additions & 0 deletions pkg/bitio/iobitwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@ func (w *IOBitWriter) Flush() error {

return err
}

func (w *IOBitWriter) Unwrap() any {
return w.w
}
4 changes: 4 additions & 0 deletions pkg/bitio/ioreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,7 @@ func (r *IOReader) ReadByte() (byte, error) {
_, err := r.Read(rb[:])
return rb[0], err
}

func (r *IOReader) Unwrap() any {
return r.r
}
4 changes: 4 additions & 0 deletions pkg/bitio/ioreadseeker.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ func (r *IOReadSeeker) Seek(offset int64, whence int) (int64, error) {

return n / 8, err
}

func (r *IOReadSeeker) Unwrap() any {
return r.IOReader
}
4 changes: 4 additions & 0 deletions pkg/bitio/limitreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ func (l *LimitReader) CloneReader() (Reader, error) {
}
return &LimitReader{r: rc, n: l.n}, nil
}

func (r *LimitReader) Unwrap() any {
return r.r
}
4 changes: 4 additions & 0 deletions pkg/bitio/sectiontreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,7 @@ func (r *SectionReader) CloneReaderAtSeeker() (ReaderAtSeeker, error) {
bitLimit: r.bitLimit,
}, nil
}

func (r *SectionReader) Unwrap() any {
return r.r
}
112 changes: 62 additions & 50 deletions pkg/decode/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ const (
)

type Options struct {
Name string
Description string
Force bool
FillGaps bool
IsRoot bool
Range ranges.Range // if zero use whole buffer
InArg any
FormatInArgFn func(init any) any
ReadBuf *[]byte
Name string
Description string
Force bool
FillGaps bool
IsRoot bool
Range ranges.Range // if zero use whole buffer
InArg any
ParseOptsFn func(init any) any
ReadBuf *[]byte
}

// Decode try decode group and return first success and all other decoder errors
Expand All @@ -60,6 +60,15 @@ func decode(ctx context.Context, br bitio.ReaderAtSeeker, group *Group, opts Opt
panic("group is nil, failed to register format?")
}

hasGroupOpts := false
groupArg := group.DefaultInArg
if opts.ParseOptsFn != nil && groupArg != nil {
if groupOptArg := opts.ParseOptsFn(groupArg); groupOptArg != nil {
hasGroupOpts = true
groupArg = groupOptArg
}
}

formatsErr := FormatsError{}

for _, f := range group.Formats {
Expand All @@ -68,9 +77,8 @@ func decode(ctx context.Context, br bitio.ReaderAtSeeker, group *Group, opts Opt
// figure out if there are format specific arg passed as options
hasFormatOpts := false
formatArg := f.DefaultInArg
if formatArg != nil && opts.FormatInArgFn != nil {
formatOptArg := opts.FormatInArgFn(formatArg)
if formatOptArg != nil {
if opts.ParseOptsFn != nil && formatArg != nil {
if formatOptArg := opts.ParseOptsFn(formatArg); formatOptArg != nil {
hasFormatOpts = true
formatArg = formatOptArg
}
Expand All @@ -87,6 +95,10 @@ func decode(ctx context.Context, br bitio.ReaderAtSeeker, group *Group, opts Opt
inArgs = append(inArgs, f.DefaultInArg)
}

if hasGroupOpts {
inArgs = append(inArgs, groupArg)
}

cBR, err := bitioex.Range(br, decodeRange.Start, decodeRange.Len)
if err != nil {
return nil, nil, IOError{Err: err, Op: "BitBufRange", ReadSize: decodeRange.Len, Pos: decodeRange.Start}
Expand Down Expand Up @@ -953,13 +965,13 @@ func (d *D) RangeFn(firstBit int64, nBits int64, fn func(d *D)) int64 {

func (d *D) Format(group *Group, inArg any) any {
dv, v, err := decode(d.Ctx, d.bitBuf, group, Options{
Force: d.Options.Force,
FillGaps: false,
IsRoot: false,
Range: ranges.Range{Start: d.Pos(), Len: d.BitsLeft()},
InArg: inArg,
FormatInArgFn: d.Options.FormatInArgFn,
ReadBuf: d.readBuf,
Force: d.Options.Force,
FillGaps: false,
IsRoot: false,
Range: ranges.Range{Start: d.Pos(), Len: d.BitsLeft()},
InArg: inArg,
ParseOptsFn: d.Options.ParseOptsFn,
ReadBuf: d.readBuf,
})
if dv == nil || dv.Errors() != nil {
d.IOPanic(err, "Format: decode")
Expand All @@ -983,14 +995,14 @@ func (d *D) Format(group *Group, inArg any) any {

func (d *D) TryFieldFormat(name string, group *Group, inArg any) (*Value, any, error) {
dv, v, err := decode(d.Ctx, d.bitBuf, group, Options{
Name: name,
Force: d.Options.Force,
FillGaps: false,
IsRoot: false,
Range: ranges.Range{Start: d.Pos(), Len: d.BitsLeft()},
InArg: inArg,
FormatInArgFn: d.Options.FormatInArgFn,
ReadBuf: d.readBuf,
Name: name,
Force: d.Options.Force,
FillGaps: false,
IsRoot: false,
Range: ranges.Range{Start: d.Pos(), Len: d.BitsLeft()},
InArg: inArg,
ParseOptsFn: d.Options.ParseOptsFn,
ReadBuf: d.readBuf,
})
if dv == nil || dv.Errors() != nil {
return nil, nil, err
Expand Down Expand Up @@ -1022,14 +1034,14 @@ func (d *D) FieldFormatOrRaw(name string, group *Group, inArg any) (*Value, any)

func (d *D) TryFieldFormatLen(name string, nBits int64, group *Group, inArg any) (*Value, any, error) {
dv, v, err := decode(d.Ctx, d.bitBuf, group, Options{
Name: name,
Force: d.Options.Force,
FillGaps: true,
IsRoot: false,
Range: ranges.Range{Start: d.Pos(), Len: nBits},
InArg: inArg,
FormatInArgFn: d.Options.FormatInArgFn,
ReadBuf: d.readBuf,
Name: name,
Force: d.Options.Force,
FillGaps: true,
IsRoot: false,
Range: ranges.Range{Start: d.Pos(), Len: nBits},
InArg: inArg,
ParseOptsFn: d.Options.ParseOptsFn,
ReadBuf: d.readBuf,
})
if dv == nil || dv.Errors() != nil {
return nil, nil, err
Expand Down Expand Up @@ -1062,14 +1074,14 @@ func (d *D) FieldFormatOrRawLen(name string, nBits int64, group *Group, inArg an
// TODO: return decooder?
func (d *D) TryFieldFormatRange(name string, firstBit int64, nBits int64, group *Group, inArg any) (*Value, any, error) {
dv, v, err := decode(d.Ctx, d.bitBuf, group, Options{
Name: name,
Force: d.Options.Force,
FillGaps: true,
IsRoot: false,
Range: ranges.Range{Start: firstBit, Len: nBits},
InArg: inArg,
FormatInArgFn: d.Options.FormatInArgFn,
ReadBuf: d.readBuf,
Name: name,
Force: d.Options.Force,
FillGaps: true,
IsRoot: false,
Range: ranges.Range{Start: firstBit, Len: nBits},
InArg: inArg,
ParseOptsFn: d.Options.ParseOptsFn,
ReadBuf: d.readBuf,
})
if dv == nil || dv.Errors() != nil {
return nil, nil, err
Expand All @@ -1091,13 +1103,13 @@ func (d *D) FieldFormatRange(name string, firstBit int64, nBits int64, group *Gr

func (d *D) TryFieldFormatBitBuf(name string, br bitio.ReaderAtSeeker, group *Group, inArg any) (*Value, any, error) {
dv, v, err := decode(d.Ctx, br, group, Options{
Name: name,
Force: d.Options.Force,
FillGaps: true,
IsRoot: true,
InArg: inArg,
FormatInArgFn: d.Options.FormatInArgFn,
ReadBuf: d.readBuf,
Name: name,
Force: d.Options.Force,
FillGaps: true,
IsRoot: true,
InArg: inArg,
ParseOptsFn: d.Options.ParseOptsFn,
ReadBuf: d.readBuf,
})
if dv == nil || dv.Errors() != nil {
return nil, nil, err
Expand Down
33 changes: 21 additions & 12 deletions pkg/interp/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,11 +293,12 @@ func (Binary) ExtType() string { return "binary" }

func (Binary) ExtKeys() []string {
return []string{
"bits",
"bytes",
"name",
"size",
"start",
"stop",
"bits",
"bytes",
}
}

Expand Down Expand Up @@ -338,6 +339,24 @@ func (b Binary) JQValueSlice(start int, end int) any {
}
func (b Binary) JQValueKey(name string) any {
switch name {
case "bits":
if b.unit == 1 {
return b
}
return Binary{br: b.br, r: b.r, unit: 1}
case "bytes":
if b.unit == 8 {
return b
}
return Binary{br: b.br, r: b.r, unit: 8}

case "name":
f := ioex.Unwrap(b.br)
// this exploits the fact that *os.File has Name()
if n, ok := f.(interface{ Name() string }); ok {
return n.Name()
}
return nil
case "size":
return new(big.Int).SetInt64(b.r.Len / int64(b.unit))
case "start":
Expand All @@ -349,16 +368,6 @@ func (b Binary) JQValueKey(name string) any {
stopUnits++
}
return new(big.Int).SetInt64(stopUnits)
case "bits":
if b.unit == 1 {
return b
}
return Binary{br: b.br, r: b.r, unit: 1}
case "bytes":
if b.unit == 8 {
return b
}
return Binary{br: b.br, r: b.r, unit: 8}
}
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/interp/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ func (i *Interp) _decode(c any, format string, opts decodeOpts) any {
Force: opts.Force,
Range: bv.r,
Description: filename,
FormatInArgFn: func(init any) any {
ParseOptsFn: func(init any) any {
v, err := copystructure.Copy(init)
if err != nil {
return nil
Expand Down

0 comments on commit 684a083

Please sign in to comment.