2020-06-08 03:29:51 +03:00
|
|
|
package decode
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2021-09-16 11:32:29 +03:00
|
|
|
"context"
|
2020-06-08 03:29:51 +03:00
|
|
|
"fmt"
|
2021-09-19 21:49:15 +03:00
|
|
|
"io"
|
2020-06-08 03:29:51 +03:00
|
|
|
"io/ioutil"
|
2021-08-17 13:06:32 +03:00
|
|
|
|
|
|
|
"github.com/wader/fq/internal/recoverfn"
|
|
|
|
"github.com/wader/fq/pkg/bitio"
|
|
|
|
"github.com/wader/fq/pkg/ranges"
|
2021-12-02 00:48:25 +03:00
|
|
|
"github.com/wader/fq/pkg/scalar"
|
2020-06-08 03:29:51 +03:00
|
|
|
)
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
//go:generate sh -c "cat decode_gen.go.tmpl | go run ../../dev/tmpl.go types.json | gofmt > decode_gen.go"
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
type Endian int
|
|
|
|
|
|
|
|
const (
|
|
|
|
// BigEndian byte order
|
|
|
|
BigEndian = iota
|
|
|
|
// LittleEndian byte order
|
|
|
|
LittleEndian
|
|
|
|
)
|
|
|
|
|
2021-09-27 12:01:14 +03:00
|
|
|
type Options struct {
|
2021-09-16 15:42:32 +03:00
|
|
|
Name string
|
|
|
|
Description string
|
2021-11-16 15:03:45 +03:00
|
|
|
Force bool
|
2021-10-18 22:38:16 +03:00
|
|
|
FillGaps bool
|
2020-06-08 03:29:51 +03:00
|
|
|
IsRoot bool
|
2021-10-18 22:38:16 +03:00
|
|
|
Range ranges.Range // if zero use whole buffer
|
2020-06-08 03:29:51 +03:00
|
|
|
FormatOptions map[string]interface{}
|
|
|
|
FormatInArg interface{}
|
2021-09-14 19:54:59 +03:00
|
|
|
ReadBuf *[]byte
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
// Decode try decode group and return first success and all other decoder errors
|
|
|
|
func Decode(ctx context.Context, bb *bitio.Buffer, group Group, opts Options) (*Value, interface{}, error) {
|
|
|
|
return decode(ctx, bb, group, opts)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
func decode(ctx context.Context, bb *bitio.Buffer, group Group, opts Options) (*Value, interface{}, error) {
|
2021-11-16 15:03:45 +03:00
|
|
|
decodeRange := opts.Range
|
|
|
|
if decodeRange.IsZero() {
|
|
|
|
decodeRange = ranges.Range{Len: bb.Len()}
|
2021-10-18 22:38:16 +03:00
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
if group == nil {
|
|
|
|
panic("group is nil, failed to register format?")
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
formatsErr := FormatsError{}
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
for _, g := range group {
|
2021-11-16 15:03:45 +03:00
|
|
|
cbb, err := bb.BitBufRange(decodeRange.Start, decodeRange.Len)
|
2021-10-18 22:38:16 +03:00
|
|
|
if err != nil {
|
2021-11-16 19:11:26 +03:00
|
|
|
return nil, nil, IOError{Err: err, Op: "BitBufRange", ReadSize: decodeRange.Len, Pos: decodeRange.Start}
|
2021-10-18 22:38:16 +03:00
|
|
|
}
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
d := newDecoder(ctx, g, cbb, opts)
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2021-10-18 22:38:16 +03:00
|
|
|
var decodeV interface{}
|
2020-06-08 03:29:51 +03:00
|
|
|
r, rOk := recoverfn.Run(func() {
|
2021-11-17 18:46:10 +03:00
|
|
|
decodeV = g.DecodeFn(d, opts.FormatInArg)
|
2020-06-08 03:29:51 +03:00
|
|
|
})
|
|
|
|
|
2021-09-16 11:32:29 +03:00
|
|
|
if ctx != nil && ctx.Err() != nil {
|
|
|
|
return nil, nil, ctx.Err()
|
|
|
|
}
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
if !rOk {
|
2021-11-01 19:35:37 +03:00
|
|
|
if re, ok := r.RecoverV.(RecoverableErrorer); ok && re.IsRecoverableError() {
|
|
|
|
panicErr, _ := re.(error)
|
2020-06-08 03:29:51 +03:00
|
|
|
formatErr := FormatError{
|
|
|
|
Err: panicErr,
|
2021-11-17 18:46:10 +03:00
|
|
|
Format: g,
|
2020-06-08 03:29:51 +03:00
|
|
|
Stacktrace: r,
|
|
|
|
}
|
2021-11-17 18:46:10 +03:00
|
|
|
formatsErr.Errs = append(formatsErr.Errs, formatErr)
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2021-11-03 19:19:33 +03:00
|
|
|
switch vv := d.Value.V.(type) {
|
|
|
|
case Compound:
|
|
|
|
// TODO: hack, changes V
|
|
|
|
vv.Err = formatErr
|
|
|
|
d.Value.V = vv
|
|
|
|
}
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
if len(group) != 1 {
|
2020-06-08 03:29:51 +03:00
|
|
|
continue
|
|
|
|
}
|
2021-11-01 19:35:37 +03:00
|
|
|
} else {
|
2020-06-08 03:29:51 +03:00
|
|
|
r.RePanic()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-18 22:38:16 +03:00
|
|
|
// TODO: maybe move to Format* funcs?
|
|
|
|
if opts.FillGaps {
|
2021-11-16 15:03:45 +03:00
|
|
|
d.FillGaps(ranges.Range{Start: 0, Len: decodeRange.Len}, "unknown")
|
2021-10-18 22:38:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
var minMaxRange ranges.Range
|
2021-10-18 16:06:08 +03:00
|
|
|
if err := d.Value.WalkRootPreOrder(func(v *Value, rootV *Value, depth int, rootDepth int) error {
|
2021-10-18 22:38:16 +03:00
|
|
|
minMaxRange = ranges.MinMax(minMaxRange, v.Range)
|
2021-11-16 15:03:45 +03:00
|
|
|
v.Range.Start += decodeRange.Start
|
2021-10-18 22:38:16 +03:00
|
|
|
v.RootBitBuf = bb
|
2020-06-08 03:29:51 +03:00
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
2021-11-16 15:03:45 +03:00
|
|
|
d.Value.Range = ranges.Range{Start: decodeRange.Start, Len: minMaxRange.Len}
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2021-09-16 16:29:11 +03:00
|
|
|
if opts.IsRoot {
|
2020-06-08 03:29:51 +03:00
|
|
|
d.Value.postProcess()
|
|
|
|
}
|
|
|
|
|
2021-11-20 18:22:00 +03:00
|
|
|
if len(formatsErr.Errs) > 0 {
|
|
|
|
return d.Value, decodeV, formatsErr
|
|
|
|
}
|
|
|
|
|
|
|
|
return d.Value, decodeV, nil
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
return nil, nil, formatsErr
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
type D struct {
|
2021-09-16 11:32:29 +03:00
|
|
|
Ctx context.Context
|
2020-06-08 03:29:51 +03:00
|
|
|
Endian Endian
|
|
|
|
Value *Value
|
2021-11-16 15:03:45 +03:00
|
|
|
Options Options
|
2020-06-08 03:29:51 +03:00
|
|
|
|
|
|
|
bitBuf *bitio.Buffer
|
|
|
|
|
2021-09-14 19:54:59 +03:00
|
|
|
readBuf *[]byte
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: new struct decoder?
|
2021-10-18 22:38:16 +03:00
|
|
|
// note bb is assumed to be a non-shared buffer
|
2021-11-17 18:46:10 +03:00
|
|
|
func newDecoder(ctx context.Context, format Format, bb *bitio.Buffer, opts Options) *D {
|
2021-09-16 17:26:31 +03:00
|
|
|
name := format.RootName
|
|
|
|
if opts.Name != "" {
|
|
|
|
name = opts.Name
|
|
|
|
}
|
2021-11-03 19:19:33 +03:00
|
|
|
rootV := Compound{
|
|
|
|
IsArray: format.RootArray,
|
|
|
|
Children: new([]*Value),
|
|
|
|
Description: opts.Description,
|
2021-11-17 18:46:10 +03:00
|
|
|
Format: &format,
|
2021-09-16 17:26:31 +03:00
|
|
|
}
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
return &D{
|
2021-09-16 11:32:29 +03:00
|
|
|
Ctx: ctx,
|
2020-06-08 03:29:51 +03:00
|
|
|
Endian: BigEndian,
|
|
|
|
Value: &Value{
|
2021-11-03 19:19:33 +03:00
|
|
|
Name: name,
|
|
|
|
V: rootV,
|
|
|
|
RootBitBuf: bb,
|
|
|
|
Range: ranges.Range{Start: 0, Len: 0},
|
|
|
|
IsRoot: opts.IsRoot,
|
2020-06-08 03:29:51 +03:00
|
|
|
},
|
2021-11-16 15:03:45 +03:00
|
|
|
Options: opts,
|
2020-06-08 03:29:51 +03:00
|
|
|
|
2021-10-18 22:38:16 +03:00
|
|
|
bitBuf: bb,
|
2021-09-14 19:54:59 +03:00
|
|
|
readBuf: opts.ReadBuf,
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-18 00:14:49 +03:00
|
|
|
func (d *D) FieldDecoder(name string, bitBuf *bitio.Buffer, v interface{}) *D {
|
|
|
|
return &D{
|
|
|
|
Ctx: d.Ctx,
|
|
|
|
Endian: d.Endian,
|
|
|
|
Value: &Value{
|
|
|
|
Name: name,
|
|
|
|
V: v,
|
|
|
|
Range: ranges.Range{Start: d.Pos(), Len: 0},
|
|
|
|
RootBitBuf: bitBuf,
|
|
|
|
},
|
|
|
|
Options: d.Options,
|
|
|
|
|
|
|
|
bitBuf: bitBuf,
|
|
|
|
readBuf: d.readBuf,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) Copy(r io.Writer, w io.Reader) (int64, error) {
|
|
|
|
// TODO: what size? now same as io.Copy
|
|
|
|
buf := d.SharedReadBuf(32 * 1024)
|
|
|
|
return io.CopyBuffer(r, w, buf)
|
|
|
|
}
|
|
|
|
|
2021-11-18 03:17:41 +03:00
|
|
|
func (d *D) MustCopy(r io.Writer, w io.Reader) int64 {
|
|
|
|
n, err := d.Copy(r, w)
|
|
|
|
if err != nil {
|
2021-11-24 23:20:46 +03:00
|
|
|
d.IOPanic(err, "MustCopy")
|
2021-11-18 03:17:41 +03:00
|
|
|
}
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) MustNewBitBufFromReader(r io.Reader) *bitio.Buffer {
|
|
|
|
b := &bytes.Buffer{}
|
|
|
|
d.MustCopy(b, r)
|
|
|
|
return bitio.NewBufferFromBytes(b.Bytes(), -1)
|
|
|
|
}
|
|
|
|
|
2021-09-16 13:24:53 +03:00
|
|
|
func (d *D) SharedReadBuf(n int) []byte {
|
2021-09-14 19:54:59 +03:00
|
|
|
if d.readBuf == nil {
|
|
|
|
d.readBuf = new([]byte)
|
|
|
|
}
|
2021-09-16 13:24:53 +03:00
|
|
|
if len(*d.readBuf) < n {
|
2021-09-14 19:54:59 +03:00
|
|
|
*d.readBuf = make([]byte, n)
|
|
|
|
}
|
|
|
|
return *d.readBuf
|
|
|
|
}
|
|
|
|
|
2021-10-18 22:38:16 +03:00
|
|
|
func (d *D) FillGaps(r ranges.Range, namePrefix string) {
|
2020-06-08 03:29:51 +03:00
|
|
|
makeWalkFn := func(fn func(iv *Value)) func(iv *Value, rootV *Value, depth int, rootDepth int) error {
|
|
|
|
return func(iv *Value, rootV *Value, depth int, rootDepth int) error {
|
|
|
|
switch iv.V.(type) {
|
2021-11-03 19:19:33 +03:00
|
|
|
case Compound:
|
2020-06-08 03:29:51 +03:00
|
|
|
default:
|
|
|
|
fn(iv)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-18 22:38:16 +03:00
|
|
|
// TODO: redo this, tries to get rid of slice grow
|
2020-06-08 03:29:51 +03:00
|
|
|
// TODO: pre-sorted somehow?
|
|
|
|
n := 0
|
2021-10-18 16:06:08 +03:00
|
|
|
_ = d.Value.WalkRootPreOrder(makeWalkFn(func(iv *Value) { n++ }))
|
2020-06-08 03:29:51 +03:00
|
|
|
valueRanges := make([]ranges.Range, n)
|
|
|
|
i := 0
|
2021-10-18 16:06:08 +03:00
|
|
|
_ = d.Value.WalkRootPreOrder(makeWalkFn(func(iv *Value) {
|
2020-06-08 03:29:51 +03:00
|
|
|
valueRanges[i] = iv.Range
|
|
|
|
i++
|
|
|
|
}))
|
|
|
|
|
2021-10-18 22:38:16 +03:00
|
|
|
gaps := ranges.Gaps(r, valueRanges)
|
2020-06-08 03:29:51 +03:00
|
|
|
for i, gap := range gaps {
|
2021-11-05 17:04:26 +03:00
|
|
|
bb, err := d.bitBuf.BitBufRange(gap.Start, gap.Len)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v := &Value{
|
|
|
|
Name: fmt.Sprintf("%s%d", namePrefix, i),
|
2021-12-02 00:48:25 +03:00
|
|
|
V: scalar.S{
|
2021-11-05 17:04:26 +03:00
|
|
|
Actual: bb,
|
|
|
|
Unknown: true,
|
|
|
|
},
|
|
|
|
RootBitBuf: d.bitBuf,
|
|
|
|
Range: gap,
|
|
|
|
}
|
|
|
|
|
|
|
|
d.AddChild(v)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-17 18:26:13 +03:00
|
|
|
// Errorf stops decode with a reason unless forced
|
|
|
|
func (d *D) Errorf(format string, a ...interface{}) {
|
2021-11-16 15:03:45 +03:00
|
|
|
if !d.Options.Force {
|
2021-11-20 18:22:00 +03:00
|
|
|
panic(DecoderError{Reason: fmt.Sprintf(format, a...), Pos: d.Pos()})
|
2021-11-16 15:03:45 +03:00
|
|
|
}
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-11-17 18:26:13 +03:00
|
|
|
// Fatalf stops decode with a reason regardless of forced
|
|
|
|
func (d *D) Fatalf(format string, a ...interface{}) {
|
2021-11-20 18:22:00 +03:00
|
|
|
panic(DecoderError{Reason: fmt.Sprintf(format, a...), Pos: d.Pos()})
|
2021-11-16 19:11:26 +03:00
|
|
|
}
|
|
|
|
|
2021-11-24 23:20:46 +03:00
|
|
|
func (d *D) IOPanic(err error, op string) {
|
|
|
|
panic(IOError{Err: err, Pos: d.Pos(), Op: op})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Bits reads nBits bits from buffer
|
|
|
|
func (d *D) bits(nBits int) (uint64, error) {
|
|
|
|
// 64 bits max, 9 byte worse case if not byte aligned
|
|
|
|
buf := d.SharedReadBuf(9)
|
|
|
|
_, err := bitio.ReadFull(d.bitBuf, buf, nBits)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return bitio.Read64(buf[:], 0, nBits), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bits reads nBits bits from buffer
|
|
|
|
func (d *D) Bits(nBits int) (uint64, error) {
|
|
|
|
n, err := d.bits(nBits)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return n, nil
|
|
|
|
}
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
func (d *D) PeekBits(nBits int) uint64 {
|
|
|
|
n, err := d.TryPeekBits(nBits)
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "PeekBits", ReadSize: int64(nBits), Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return n
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) PeekBytes(nBytes int) []byte {
|
|
|
|
bs, err := d.bitBuf.PeekBytes(nBytes)
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "PeekBytes", ReadSize: int64(nBytes) * 8, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return bs
|
|
|
|
}
|
|
|
|
|
2021-08-31 20:32:34 +03:00
|
|
|
func (d *D) PeekFind(nBits int, seekBits int64, fn func(v uint64) bool, maxLen int64) (int64, uint64) {
|
2021-09-07 15:05:48 +03:00
|
|
|
peekBits, v, err := d.TryPeekFind(nBits, seekBits, maxLen, fn)
|
2020-06-08 03:29:51 +03:00
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "PeekFind", ReadSize: 0, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
if peekBits == -1 {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: fmt.Errorf("not found"), Op: "PeekFind", ReadSize: 0, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
2021-08-31 20:32:34 +03:00
|
|
|
return peekBits, v
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) TryHasBytes(hb []byte) bool {
|
|
|
|
lenHb := len(hb)
|
|
|
|
if d.BitsLeft() < int64(lenHb*8) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
bs := d.PeekBytes(lenHb)
|
|
|
|
return bytes.Equal(hb, bs)
|
|
|
|
}
|
|
|
|
|
|
|
|
// PeekFindByte number of bytes to next v
|
|
|
|
func (d *D) PeekFindByte(findV uint8, maxLen int64) int64 {
|
2021-09-07 15:05:48 +03:00
|
|
|
peekBits, _, err := d.TryPeekFind(8, 8, maxLen*8, func(v uint64) bool {
|
2020-06-08 03:29:51 +03:00
|
|
|
return uint64(findV) == v
|
2021-09-07 15:05:48 +03:00
|
|
|
})
|
2020-06-08 03:29:51 +03:00
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "PeekFindByte", ReadSize: 0, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
|
|
|
|
}
|
|
|
|
return peekBits / 8
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
// PeekBits peek nBits bits from buffer
|
|
|
|
// TODO: share code?
|
|
|
|
func (d *D) TryPeekBits(nBits int) (uint64, error) {
|
|
|
|
start, err := d.bitBuf.SeekBits(0, io.SeekCurrent)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
n, err := d.bits(nBits)
|
|
|
|
if _, err := d.bitBuf.SeekBits(start, io.SeekStart); err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) TryPeekFind(nBits int, seekBits int64, maxLen int64, fn func(v uint64) bool) (int64, uint64, error) {
|
|
|
|
start, err := d.bitBuf.SeekBits(0, io.SeekCurrent)
|
|
|
|
if err != nil {
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var count int64
|
2021-11-01 15:08:52 +03:00
|
|
|
|
|
|
|
if seekBits < 0 {
|
|
|
|
count = int64(-nBits)
|
|
|
|
if _, err := d.bitBuf.SeekBits(start+count, io.SeekStart); err != nil {
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
found := false
|
2021-11-05 17:04:26 +03:00
|
|
|
var v uint64
|
|
|
|
for {
|
2021-11-01 15:08:52 +03:00
|
|
|
if (seekBits > 0 && maxLen > 0 && count >= maxLen) || (seekBits < 0 && maxLen > 0 && count < -maxLen) {
|
2021-11-05 17:04:26 +03:00
|
|
|
break
|
|
|
|
}
|
|
|
|
v, err = d.TryU(nBits)
|
|
|
|
if err != nil {
|
|
|
|
if _, err := d.bitBuf.SeekBits(start, io.SeekStart); err != nil {
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
if fn(v) {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
count += seekBits
|
|
|
|
if _, err := d.bitBuf.SeekBits(start+count, io.SeekStart); err != nil {
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if _, err := d.bitBuf.SeekBits(start, io.SeekStart); err != nil {
|
|
|
|
return 0, 0, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
return -1, 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return count, v, nil
|
|
|
|
}
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
func (d *D) BytesRange(firstBit int64, nBytes int) []byte {
|
|
|
|
bs, err := d.bitBuf.BytesRange(firstBit, nBytes)
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "BytesRange", ReadSize: int64(nBytes) * 8, Pos: firstBit})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return bs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) BytesLen(nBytes int) []byte {
|
|
|
|
bs, err := d.bitBuf.BytesLen(nBytes)
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "BytesLen", ReadSize: int64(nBytes) * 8, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return bs
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: rename/remove BitBuf name?
|
|
|
|
func (d *D) BitBufRange(firstBit int64, nBits int64) *bitio.Buffer {
|
|
|
|
bb, err := d.bitBuf.BitBufRange(firstBit, nBits)
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "BitBufRange", ReadSize: nBits, Pos: firstBit})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return bb
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) Pos() int64 {
|
|
|
|
bPos, err := d.bitBuf.Pos()
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "Pos", ReadSize: 0, Pos: bPos})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return bPos
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) Len() int64 {
|
|
|
|
return d.bitBuf.Len()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) End() bool {
|
|
|
|
bEnd, err := d.bitBuf.End()
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "Len", ReadSize: 0, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return bEnd
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) NotEnd() bool { return !d.End() }
|
|
|
|
|
|
|
|
func (d *D) BitsLeft() int64 {
|
|
|
|
bBitsLeft, err := d.bitBuf.BitsLeft()
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "BitsLeft", ReadSize: 0, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return bBitsLeft
|
|
|
|
}
|
|
|
|
|
2021-11-23 00:08:36 +03:00
|
|
|
func (d *D) AlignBits(nBits int) int {
|
|
|
|
bByteAlignBits, err := d.bitBuf.AlignBits(nBits)
|
|
|
|
if err != nil {
|
|
|
|
panic(IOError{Err: err, Op: "AlignBits", ReadSize: 0, Pos: d.Pos()})
|
|
|
|
}
|
|
|
|
return bByteAlignBits
|
|
|
|
}
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
func (d *D) ByteAlignBits() int {
|
|
|
|
bByteAlignBits, err := d.bitBuf.ByteAlignBits()
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "ByteAlignBits", ReadSize: 0, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return bByteAlignBits
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) BytePos() int64 {
|
|
|
|
bBytePos, err := d.bitBuf.BytePos()
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "BytePos", ReadSize: 0, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return bBytePos
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) SeekRel(deltaBits int64) int64 {
|
|
|
|
pos, err := d.bitBuf.SeekRel(deltaBits)
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "SeekRel", SeekPos: deltaBits, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return pos
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) SeekAbs(pos int64) int64 {
|
|
|
|
pos, err := d.bitBuf.SeekAbs(pos)
|
|
|
|
if err != nil {
|
2021-10-18 22:38:16 +03:00
|
|
|
panic(IOError{Err: err, Op: "SeekAbs", SeekPos: pos, Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
return pos
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) AddChild(v *Value) {
|
|
|
|
v.Parent = d.Value
|
|
|
|
|
|
|
|
switch fv := d.Value.V.(type) {
|
2021-11-03 19:19:33 +03:00
|
|
|
case Compound:
|
|
|
|
if !fv.IsArray {
|
|
|
|
for _, ff := range *fv.Children {
|
|
|
|
if ff.Name == v.Name {
|
2021-11-17 18:26:13 +03:00
|
|
|
d.Fatalf("%q already exist in struct %s", v.Name, d.Value.Name)
|
2021-11-03 19:19:33 +03:00
|
|
|
}
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
}
|
2021-11-03 19:19:33 +03:00
|
|
|
*fv.Children = append(*fv.Children, v)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) FieldRemove(name string) *Value {
|
|
|
|
switch fv := d.Value.V.(type) {
|
2021-11-03 19:19:33 +03:00
|
|
|
case Compound:
|
|
|
|
for fi, ff := range *fv.Children {
|
2020-06-08 03:29:51 +03:00
|
|
|
if ff.Name == name {
|
2021-11-03 19:19:33 +03:00
|
|
|
*fv.Children = append((*fv.Children)[0:fi], (*fv.Children)[fi+1:]...)
|
|
|
|
d.Value.V = fv
|
2020-06-08 03:29:51 +03:00
|
|
|
return ff
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Sprintf("%s not found in struct %s", name, d.Value.Name))
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("%s is not a struct", d.Value.Name))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) FieldMustRemove(name string) *Value {
|
|
|
|
if v := d.FieldRemove(name); v != nil {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
panic(fmt.Sprintf("%s not found in struct %s", name, d.Value.Name))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) FieldGet(name string) *Value {
|
|
|
|
switch fv := d.Value.V.(type) {
|
2021-11-03 19:19:33 +03:00
|
|
|
case Compound:
|
|
|
|
for _, ff := range *fv.Children {
|
2020-06-08 03:29:51 +03:00
|
|
|
if ff.Name == name {
|
|
|
|
return ff
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("%s is not a struct", d.Value.Name))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) FieldMustGet(name string) *Value {
|
|
|
|
if v := d.FieldGet(name); v != nil {
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
panic(fmt.Sprintf("%s not found in struct %s", name, d.Value.Name))
|
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
func (d *D) FieldArray(name string, fn func(d *D), sms ...scalar.Mapper) *D {
|
2021-11-03 19:19:33 +03:00
|
|
|
cd := d.FieldDecoder(name, d.bitBuf, Compound{IsArray: true, Children: new([]*Value)})
|
2020-06-08 03:29:51 +03:00
|
|
|
d.AddChild(cd.Value)
|
2021-11-21 15:08:18 +03:00
|
|
|
fn(cd)
|
2020-06-08 03:29:51 +03:00
|
|
|
return cd
|
|
|
|
}
|
|
|
|
|
2021-11-21 15:08:18 +03:00
|
|
|
func (d *D) FieldArrayValue(name string) *D {
|
|
|
|
return d.FieldArray(name, func(d *D) {})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) FieldStruct(name string, fn func(d *D)) *D {
|
2021-11-03 19:19:33 +03:00
|
|
|
cd := d.FieldDecoder(name, d.bitBuf, Compound{Children: new([]*Value)})
|
2020-06-08 03:29:51 +03:00
|
|
|
d.AddChild(cd.Value)
|
2021-11-21 15:08:18 +03:00
|
|
|
fn(cd)
|
2020-06-08 03:29:51 +03:00
|
|
|
return cd
|
|
|
|
}
|
|
|
|
|
2021-11-21 15:08:18 +03:00
|
|
|
func (d *D) FieldStructValue(name string) *D {
|
|
|
|
return d.FieldStruct(name, func(d *D) {})
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
func (d *D) FieldStructArrayLoop(name string, structName string, condFn func() bool, fn func(d *D)) *D {
|
|
|
|
return d.FieldArray(name, func(d *D) {
|
2020-06-08 03:29:51 +03:00
|
|
|
for condFn() {
|
2021-11-05 17:04:26 +03:00
|
|
|
d.FieldStruct(structName, fn)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
func (d *D) FieldArrayLoop(name string, condFn func() bool, fn func(d *D)) *D {
|
|
|
|
return d.FieldArray(name, func(d *D) {
|
2020-06-08 03:29:51 +03:00
|
|
|
for condFn() {
|
|
|
|
fn(d)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) FieldRangeFn(name string, firstBit int64, nBits int64, fn func() *Value) *Value {
|
|
|
|
v := fn()
|
|
|
|
v.Name = name
|
|
|
|
v.RootBitBuf = d.bitBuf
|
|
|
|
v.Range = ranges.Range{Start: firstBit, Len: nBits}
|
|
|
|
d.AddChild(v)
|
|
|
|
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
func (d *D) AssertAtLeastBitsLeft(nBits int64) {
|
2021-11-16 15:03:45 +03:00
|
|
|
if d.Options.Force {
|
|
|
|
return
|
|
|
|
}
|
2020-06-08 03:29:51 +03:00
|
|
|
bl := d.BitsLeft()
|
|
|
|
if bl < nBits {
|
|
|
|
// TODO:
|
2021-11-17 18:26:13 +03:00
|
|
|
panic(DecoderError{Reason: fmt.Sprintf("expected bits left %d, found %d", nBits, bl), Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
func (d *D) AssertLeastBytesLeft(nBytes int64) {
|
2021-11-16 15:03:45 +03:00
|
|
|
if d.Options.Force {
|
|
|
|
return
|
|
|
|
}
|
2020-06-08 03:29:51 +03:00
|
|
|
bl := d.BitsLeft()
|
|
|
|
if bl < nBytes*8 {
|
|
|
|
// TODO:
|
2021-11-17 18:26:13 +03:00
|
|
|
panic(DecoderError{Reason: fmt.Sprintf("expected bytes left %d, found %d bits", nBytes, bl), Pos: d.Pos()})
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: rethink
|
2021-12-02 00:48:25 +03:00
|
|
|
func (d *D) FieldValueU(name string, a uint64, sms ...scalar.Mapper) {
|
|
|
|
d.FieldScalar(name, func(_ scalar.S) (scalar.S, error) { return scalar.S{Actual: a}, nil }, sms...)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
func (d *D) FieldValueS(name string, a int64, sms ...scalar.Mapper) {
|
|
|
|
d.FieldScalar(name, func(_ scalar.S) (scalar.S, error) { return scalar.S{Actual: a}, nil }, sms...)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
func (d *D) FieldValueBool(name string, a bool, sms ...scalar.Mapper) {
|
|
|
|
d.FieldScalar(name, func(_ scalar.S) (scalar.S, error) { return scalar.S{Actual: a}, nil }, sms...)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
func (d *D) FieldValueFloat(name string, a float64, sms ...scalar.Mapper) {
|
|
|
|
d.FieldScalar(name, func(_ scalar.S) (scalar.S, error) { return scalar.S{Actual: a}, nil }, sms...)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
func (d *D) FieldValueStr(name string, a string, sms ...scalar.Mapper) {
|
|
|
|
d.FieldScalar(name, func(_ scalar.S) (scalar.S, error) { return scalar.S{Actual: a}, nil }, sms...)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-12-02 00:48:25 +03:00
|
|
|
func (d *D) FieldValueRaw(name string, a []byte, sms ...scalar.Mapper) {
|
|
|
|
d.FieldScalar(name, func(_ scalar.S) (scalar.S, error) {
|
|
|
|
return scalar.S{Actual: bitio.NewBufferFromBytes(a, -1)}, nil
|
|
|
|
}, sms...)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
func (d *D) LenFn(nBits int64, fn func(d *D)) {
|
|
|
|
d.RangeFn(d.Pos(), nBits, fn)
|
2020-06-08 03:29:51 +03:00
|
|
|
d.SeekRel(nBits)
|
|
|
|
}
|
|
|
|
|
2021-11-05 17:04:26 +03:00
|
|
|
func (d *D) RangeFn(firstBit int64, nBits int64, fn func(d *D)) {
|
2020-06-08 03:29:51 +03:00
|
|
|
var subV interface{}
|
2021-11-03 19:19:33 +03:00
|
|
|
switch vv := d.Value.V.(type) {
|
|
|
|
case Compound:
|
|
|
|
subV = Compound{IsArray: vv.IsArray, Children: new([]*Value)}
|
2020-06-08 03:29:51 +03:00
|
|
|
default:
|
|
|
|
panic("unreachable")
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: do some kind of DecodeLimitedLen/RangeFn?
|
|
|
|
bb := d.BitBufRange(0, firstBit+nBits)
|
|
|
|
if _, err := bb.SeekAbs(firstBit); err != nil {
|
|
|
|
panic(IOError{Err: err, Op: "SeekAbs", Pos: firstBit})
|
|
|
|
}
|
2021-09-15 01:52:57 +03:00
|
|
|
sd := d.FieldDecoder("", bb, subV)
|
2020-06-08 03:29:51 +03:00
|
|
|
|
|
|
|
fn(sd)
|
|
|
|
|
|
|
|
// TODO: refactor, similar to decode()
|
2021-10-18 16:06:08 +03:00
|
|
|
if err := sd.Value.WalkRootPreOrder(func(v *Value, rootV *Value, depth int, rootDepth int) error {
|
2020-06-08 03:29:51 +03:00
|
|
|
//v.Range.Start += firstBit
|
|
|
|
v.RootBitBuf = d.Value.RootBitBuf
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch vv := sd.Value.V.(type) {
|
2021-11-03 19:19:33 +03:00
|
|
|
case Compound:
|
|
|
|
for _, f := range *vv.Children {
|
2020-06-08 03:29:51 +03:00
|
|
|
d.AddChild(f)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic("unreachable")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
func (d *D) Format(group Group, inArg interface{}) interface{} {
|
|
|
|
dv, v, err := decode(d.Ctx, d.bitBuf, group, Options{
|
2021-11-16 15:03:45 +03:00
|
|
|
Force: d.Options.Force,
|
2021-10-18 22:38:16 +03:00
|
|
|
FillGaps: false,
|
2021-09-16 16:29:11 +03:00
|
|
|
IsRoot: false,
|
2021-10-18 22:38:16 +03:00
|
|
|
Range: ranges.Range{Start: d.Pos(), Len: d.BitsLeft()},
|
2021-09-16 16:29:11 +03:00
|
|
|
FormatInArg: inArg,
|
2021-11-16 15:03:45 +03:00
|
|
|
ReadBuf: d.readBuf,
|
2021-09-16 16:29:11 +03:00
|
|
|
})
|
2020-06-08 03:29:51 +03:00
|
|
|
if dv == nil || dv.Errors() != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch vv := dv.V.(type) {
|
2021-11-03 19:19:33 +03:00
|
|
|
case Compound:
|
|
|
|
for _, f := range *vv.Children {
|
2020-06-08 03:29:51 +03:00
|
|
|
d.AddChild(f)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic("unreachable")
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := d.bitBuf.SeekRel(dv.Range.Len); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2021-11-30 17:29:01 +03:00
|
|
|
func (d *D) TryFieldFormat(name string, group Group, inArg interface{}) (*Value, interface{}, error) {
|
2021-11-17 18:46:10 +03:00
|
|
|
dv, v, err := decode(d.Ctx, d.bitBuf, group, Options{
|
2021-09-16 16:29:11 +03:00
|
|
|
Name: name,
|
2021-11-16 15:03:45 +03:00
|
|
|
Force: d.Options.Force,
|
2021-10-18 22:38:16 +03:00
|
|
|
FillGaps: false,
|
2021-09-16 16:29:11 +03:00
|
|
|
IsRoot: false,
|
2021-10-18 22:38:16 +03:00
|
|
|
Range: ranges.Range{Start: d.Pos(), Len: d.BitsLeft()},
|
2021-09-16 16:29:11 +03:00
|
|
|
FormatInArg: inArg,
|
2021-11-16 15:03:45 +03:00
|
|
|
ReadBuf: d.readBuf,
|
2021-09-16 16:29:11 +03:00
|
|
|
})
|
2020-06-08 03:29:51 +03:00
|
|
|
if dv == nil || dv.Errors() != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
d.AddChild(dv)
|
|
|
|
if _, err := d.bitBuf.SeekRel(dv.Range.Len); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return dv, v, err
|
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
func (d *D) FieldFormat(name string, group Group, inArg interface{}) (*Value, interface{}) {
|
2021-11-30 17:29:01 +03:00
|
|
|
dv, v, err := d.TryFieldFormat(name, group, inArg)
|
2020-06-08 03:29:51 +03:00
|
|
|
if dv == nil || dv.Errors() != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return dv, v
|
|
|
|
}
|
|
|
|
|
2021-11-24 23:20:46 +03:00
|
|
|
func (d *D) TryFieldFormatLen(name string, nBits int64, group Group, inArg interface{}) (*Value, interface{}, error) {
|
2021-11-17 18:46:10 +03:00
|
|
|
dv, v, err := decode(d.Ctx, d.bitBuf, group, Options{
|
2021-09-16 16:29:11 +03:00
|
|
|
Name: name,
|
2021-11-16 15:03:45 +03:00
|
|
|
Force: d.Options.Force,
|
2021-10-18 22:38:16 +03:00
|
|
|
FillGaps: true,
|
2021-09-16 16:29:11 +03:00
|
|
|
IsRoot: false,
|
2021-10-18 22:38:16 +03:00
|
|
|
Range: ranges.Range{Start: d.Pos(), Len: nBits},
|
2021-09-16 16:29:11 +03:00
|
|
|
FormatInArg: inArg,
|
2021-11-16 15:03:45 +03:00
|
|
|
ReadBuf: d.readBuf,
|
2021-09-16 16:29:11 +03:00
|
|
|
})
|
2020-06-08 03:29:51 +03:00
|
|
|
if dv == nil || dv.Errors() != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
d.AddChild(dv)
|
|
|
|
if _, err := d.bitBuf.SeekRel(nBits); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return dv, v, err
|
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
func (d *D) FieldFormatLen(name string, nBits int64, group Group, inArg interface{}) (*Value, interface{}) {
|
2021-11-24 23:20:46 +03:00
|
|
|
dv, v, err := d.TryFieldFormatLen(name, nBits, group, inArg)
|
2020-06-08 03:29:51 +03:00
|
|
|
if dv == nil || dv.Errors() != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return dv, v
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: return decooder?
|
2021-11-30 17:29:01 +03:00
|
|
|
func (d *D) TryFieldFormatRange(name string, firstBit int64, nBits int64, group Group, inArg interface{}) (*Value, interface{}, error) {
|
2021-11-17 18:46:10 +03:00
|
|
|
dv, v, err := decode(d.Ctx, d.bitBuf, group, Options{
|
2021-09-16 16:29:11 +03:00
|
|
|
Name: name,
|
2021-11-16 15:03:45 +03:00
|
|
|
Force: d.Options.Force,
|
2021-10-18 22:38:16 +03:00
|
|
|
FillGaps: true,
|
2021-09-16 16:29:11 +03:00
|
|
|
IsRoot: false,
|
2021-10-18 22:38:16 +03:00
|
|
|
Range: ranges.Range{Start: firstBit, Len: nBits},
|
2021-09-16 16:29:11 +03:00
|
|
|
FormatInArg: inArg,
|
2021-11-16 15:03:45 +03:00
|
|
|
ReadBuf: d.readBuf,
|
2021-09-16 16:29:11 +03:00
|
|
|
})
|
2020-06-08 03:29:51 +03:00
|
|
|
if dv == nil || dv.Errors() != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
d.AddChild(dv)
|
|
|
|
|
|
|
|
return dv, v, err
|
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
func (d *D) FieldFormatRange(name string, firstBit int64, nBits int64, group Group, inArg interface{}) (*Value, interface{}) {
|
2021-11-30 17:29:01 +03:00
|
|
|
dv, v, err := d.TryFieldFormatRange(name, firstBit, nBits, group, inArg)
|
2020-06-08 03:29:51 +03:00
|
|
|
if dv == nil || dv.Errors() != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return dv, v
|
|
|
|
}
|
|
|
|
|
2021-11-20 18:22:00 +03:00
|
|
|
func (d *D) TryFieldFormatBitBuf(name string, bb *bitio.Buffer, group Group, inArg interface{}) (*Value, interface{}, error) {
|
2021-11-17 18:46:10 +03:00
|
|
|
dv, v, err := decode(d.Ctx, bb, group, Options{
|
2021-09-16 16:29:11 +03:00
|
|
|
Name: name,
|
2021-11-16 15:03:45 +03:00
|
|
|
Force: d.Options.Force,
|
2021-10-18 22:38:16 +03:00
|
|
|
FillGaps: true,
|
2021-09-16 16:29:11 +03:00
|
|
|
IsRoot: true,
|
|
|
|
FormatInArg: inArg,
|
2021-11-16 15:03:45 +03:00
|
|
|
ReadBuf: d.readBuf,
|
2021-09-16 16:29:11 +03:00
|
|
|
})
|
2020-06-08 03:29:51 +03:00
|
|
|
if dv == nil || dv.Errors() != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
2021-11-18 00:14:49 +03:00
|
|
|
dv.Range.Start = d.Pos()
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
d.AddChild(dv)
|
|
|
|
|
|
|
|
return dv, v, err
|
|
|
|
}
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
func (d *D) FieldFormatBitBuf(name string, bb *bitio.Buffer, group Group, inArg interface{}) (*Value, interface{}) {
|
2021-11-20 18:22:00 +03:00
|
|
|
dv, v, err := d.TryFieldFormatBitBuf(name, bb, group, inArg)
|
2020-06-08 03:29:51 +03:00
|
|
|
if dv == nil || dv.Errors() != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2021-11-18 00:14:49 +03:00
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
return dv, v
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: rethink this
|
|
|
|
func (d *D) FieldRootBitBuf(name string, bb *bitio.Buffer) *Value {
|
|
|
|
v := &Value{}
|
2021-12-02 00:48:25 +03:00
|
|
|
v.V = scalar.S{Actual: bb}
|
2020-06-08 03:29:51 +03:00
|
|
|
v.Name = name
|
|
|
|
v.RootBitBuf = bb
|
2021-11-03 19:19:33 +03:00
|
|
|
v.IsRoot = true
|
2021-11-18 00:14:49 +03:00
|
|
|
v.Range = ranges.Range{Start: d.Pos(), Len: bb.Len()}
|
2020-06-08 03:29:51 +03:00
|
|
|
d.AddChild(v)
|
|
|
|
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2021-10-28 02:44:09 +03:00
|
|
|
func (d *D) FieldStructRootBitBufFn(name string, bb *bitio.Buffer, fn func(d *D)) *Value {
|
2021-11-03 19:19:33 +03:00
|
|
|
cd := d.FieldDecoder(name, bb, Compound{Children: new([]*Value)})
|
2021-10-28 02:44:09 +03:00
|
|
|
cd.Value.IsRoot = true
|
|
|
|
d.AddChild(cd.Value)
|
|
|
|
fn(cd)
|
|
|
|
|
2021-11-18 00:14:49 +03:00
|
|
|
cd.Value.postProcess()
|
|
|
|
|
2021-10-28 02:44:09 +03:00
|
|
|
return cd.Value
|
|
|
|
}
|
|
|
|
|
2020-06-08 03:29:51 +03:00
|
|
|
// TODO: range?
|
2021-11-17 18:46:10 +03:00
|
|
|
func (d *D) FieldFormatReaderLen(name string, nBits int64, fn func(r io.Reader) (io.ReadCloser, error), group Group) (*Value, interface{}) {
|
2020-06-08 03:29:51 +03:00
|
|
|
bb, err := d.bitBuf.BitBufLen(nBits)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2021-09-19 21:49:15 +03:00
|
|
|
zr, err := fn(bb)
|
2020-06-08 03:29:51 +03:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
zd, err := ioutil.ReadAll(zr)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
zbb := bitio.NewBufferFromBytes(zd, -1)
|
|
|
|
|
2021-11-17 18:46:10 +03:00
|
|
|
return d.FieldFormatBitBuf(name, zbb, group, nil)
|
2020-06-08 03:29:51 +03:00
|
|
|
}
|
2021-11-20 18:22:00 +03:00
|
|
|
|
2021-11-24 17:25:27 +03:00
|
|
|
// TODO: too mant return values
|
2021-11-20 18:22:00 +03:00
|
|
|
func (d *D) TryFieldReaderRangeFormat(name string, startBit int64, nBits int64, fn func(r io.Reader) io.Reader, group Group, inArg interface{}) (int64, *bitio.Buffer, *Value, interface{}, error) {
|
|
|
|
bitLen := nBits
|
|
|
|
if bitLen == -1 {
|
|
|
|
bitLen = d.BitsLeft()
|
|
|
|
}
|
|
|
|
bb, err := d.bitBuf.BitBufRange(startBit, bitLen)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
r := fn(bb)
|
|
|
|
// TODO: check if io.Closer?
|
|
|
|
rb, err := ioutil.ReadAll(r)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
cz, err := bb.Pos()
|
|
|
|
rbb := bitio.NewBufferFromBytes(rb, -1)
|
|
|
|
if err != nil {
|
|
|
|
return 0, nil, nil, nil, err
|
|
|
|
}
|
|
|
|
dv, v, err := d.TryFieldFormatBitBuf(name, rbb, group, inArg)
|
2021-11-21 15:08:18 +03:00
|
|
|
|
2021-11-20 18:22:00 +03:00
|
|
|
return cz, rbb, dv, v, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) FieldReaderRangeFormat(name string, startBit int64, nBits int64, fn func(r io.Reader) io.Reader, group Group, inArg interface{}) (int64, *bitio.Buffer, *Value, interface{}) {
|
|
|
|
cz, rbb, dv, v, err := d.TryFieldReaderRangeFormat(name, startBit, nBits, fn, group, inArg)
|
|
|
|
if err != nil {
|
2021-11-24 23:20:46 +03:00
|
|
|
d.IOPanic(err, "TryFieldReaderRangeFormat")
|
2021-11-20 18:22:00 +03:00
|
|
|
}
|
|
|
|
return cz, rbb, dv, v
|
|
|
|
}
|
2021-12-02 00:48:25 +03:00
|
|
|
|
|
|
|
func (d *D) TryFieldValue(name string, fn func() (*Value, error)) (*Value, error) {
|
|
|
|
start := d.Pos()
|
|
|
|
v, err := fn()
|
|
|
|
stop := d.Pos()
|
|
|
|
v.Name = name
|
|
|
|
v.RootBitBuf = d.bitBuf
|
|
|
|
v.Range = ranges.Range{Start: start, Len: stop - start}
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
d.AddChild(v)
|
|
|
|
|
|
|
|
return v, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) FieldValue(name string, fn func() *Value) *Value {
|
|
|
|
v, err := d.TryFieldValue(name, func() (*Value, error) { return fn(), nil })
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
// looks a bit weird to force at least one ScalarFn arg
|
|
|
|
func (d *D) TryFieldScalar(name string, sfn scalar.Fn, sms ...scalar.Mapper) (scalar.S, error) {
|
|
|
|
v, err := d.TryFieldValue(name, func() (*Value, error) {
|
|
|
|
s, err := sfn(scalar.S{})
|
|
|
|
if err != nil {
|
|
|
|
return &Value{V: s}, err
|
|
|
|
}
|
|
|
|
for _, sm := range sms {
|
|
|
|
s, err = sm.MapScalar(s)
|
|
|
|
if err != nil {
|
|
|
|
return &Value{V: s}, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &Value{V: s}, nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return scalar.S{}, err
|
|
|
|
}
|
|
|
|
return v.V.(scalar.S), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *D) FieldScalar(name string, sfn scalar.Fn, sms ...scalar.Mapper) scalar.S {
|
|
|
|
v, err := d.TryFieldScalar(name, sfn, sms...)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|