2021-11-05 17:04:26 +03:00
|
|
|
package decode
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2021-11-24 13:15:42 +03:00
|
|
|
"encoding/binary"
|
2021-11-05 17:04:26 +03:00
|
|
|
"errors"
|
|
|
|
|
2022-08-12 16:27:51 +03:00
|
|
|
"github.com/wader/fq/internal/bitioex"
|
2021-11-05 17:04:26 +03:00
|
|
|
"github.com/wader/fq/pkg/bitio"
|
2021-12-02 00:48:25 +03:00
|
|
|
"github.com/wader/fq/pkg/scalar"
|
2021-11-05 17:04:26 +03:00
|
|
|
)
|
|
|
|
|
2022-09-30 14:58:23 +03:00
|
|
|
func bitBufIsZero(s scalar.BitBuf, isValidate bool) (scalar.BitBuf, error) {
|
|
|
|
br := s.Actual
|
2021-11-05 17:04:26 +03:00
|
|
|
|
|
|
|
isZero := true
|
2021-12-02 00:48:25 +03:00
|
|
|
// TODO: shared
|
|
|
|
b := make([]byte, 32*1024)
|
2022-01-24 23:21:48 +03:00
|
|
|
bLen := int64(len(b)) * 8
|
2022-08-12 16:27:51 +03:00
|
|
|
brLen, err := bitioex.Len(br)
|
2022-01-24 23:21:48 +03:00
|
|
|
if err != nil {
|
2022-09-30 14:58:23 +03:00
|
|
|
return scalar.BitBuf{}, err
|
2022-01-24 23:21:48 +03:00
|
|
|
}
|
|
|
|
brLeft := brLen
|
|
|
|
brPos := int64(0)
|
2021-11-05 17:04:26 +03:00
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
for brLeft > 0 {
|
|
|
|
rl := brLeft
|
|
|
|
if brLeft > bLen {
|
2021-11-05 17:04:26 +03:00
|
|
|
rl = bLen
|
|
|
|
}
|
|
|
|
// zero last byte if uneven read
|
|
|
|
if rl%8 != 0 {
|
|
|
|
b[rl/8] = 0
|
|
|
|
}
|
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
n, err := bitio.ReadAtFull(br, b, rl, brPos)
|
2021-11-05 17:04:26 +03:00
|
|
|
if err != nil {
|
|
|
|
return s, err
|
|
|
|
}
|
2022-01-24 23:21:48 +03:00
|
|
|
nb := int(bitio.BitsByteCount(n))
|
2021-11-05 17:04:26 +03:00
|
|
|
|
|
|
|
for i := 0; i < nb; i++ {
|
|
|
|
if b[i] != 0 {
|
|
|
|
isZero = false
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-24 23:21:48 +03:00
|
|
|
brLeft -= n
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if isZero {
|
|
|
|
s.Description = "all zero"
|
|
|
|
} else {
|
|
|
|
s.Description = "all not zero"
|
2021-12-02 00:48:25 +03:00
|
|
|
if isValidate {
|
2021-11-05 17:04:26 +03:00
|
|
|
return s, errors.New("validate is zero failed")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return s, nil
|
|
|
|
}
|
|
|
|
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) BitBufIsZero() scalar.BitBufMapper {
|
|
|
|
return scalar.BitBufFn(func(s scalar.BitBuf) (scalar.BitBuf, error) {
|
2021-12-02 00:48:25 +03:00
|
|
|
return bitBufIsZero(s, false)
|
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
|
|
|
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) BitBufValidateIsZero() scalar.BitBufMapper {
|
|
|
|
return scalar.BitBufFn(func(s scalar.BitBuf) (scalar.BitBuf, error) {
|
2021-12-02 00:48:25 +03:00
|
|
|
return bitBufIsZero(s, !d.Options.Force)
|
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: generate?
|
2022-09-30 14:58:23 +03:00
|
|
|
func assertBitBuf(s scalar.BitBuf, isErr bool, bss ...[]byte) (scalar.BitBuf, error) {
|
2022-01-24 23:21:48 +03:00
|
|
|
bb := &bytes.Buffer{}
|
2022-09-30 14:58:23 +03:00
|
|
|
if _, err := bitioex.CopyBits(bb, s.Actual); err != nil {
|
2021-12-02 00:48:25 +03:00
|
|
|
return s, err
|
|
|
|
}
|
|
|
|
for _, bs := range bss {
|
2022-01-24 23:21:48 +03:00
|
|
|
if bytes.Equal(bb.Bytes(), bs) {
|
2021-12-02 00:48:25 +03:00
|
|
|
s.Description = "valid"
|
|
|
|
return s, nil
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
|
|
|
}
|
2021-12-02 00:48:25 +03:00
|
|
|
s.Description = "invalid"
|
|
|
|
if isErr {
|
|
|
|
return s, errors.New("failed to validate raw")
|
|
|
|
}
|
|
|
|
return s, nil
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
|
|
|
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) AssertBitBuf(bss ...[]byte) scalar.BitBufMapper {
|
|
|
|
return scalar.BitBufFn(func(s scalar.BitBuf) (scalar.BitBuf, error) {
|
2021-12-02 00:48:25 +03:00
|
|
|
return assertBitBuf(s, !d.Options.Force, bss...)
|
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
2021-12-02 00:48:25 +03:00
|
|
|
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) ValidateBitBuf(bss ...[]byte) scalar.BitBufMapper {
|
|
|
|
return scalar.BitBufFn(func(s scalar.BitBuf) (scalar.BitBuf, error) {
|
2021-12-02 00:48:25 +03:00
|
|
|
return assertBitBuf(s, false, bss...)
|
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
|
|
|
|
2022-09-30 14:58:23 +03:00
|
|
|
func UintAssertBytes(s scalar.Uint, isErr bool, endian Endian, bss ...[]byte) (scalar.Uint, error) {
|
2021-11-24 13:15:42 +03:00
|
|
|
var bo binary.ByteOrder
|
|
|
|
switch endian {
|
|
|
|
case LittleEndian:
|
|
|
|
bo = binary.BigEndian
|
|
|
|
case BigEndian:
|
|
|
|
bo = binary.BigEndian
|
|
|
|
default:
|
|
|
|
panic("invalid endian")
|
|
|
|
}
|
|
|
|
|
2022-09-30 14:58:23 +03:00
|
|
|
au := s.Actual
|
2021-12-02 00:48:25 +03:00
|
|
|
for _, bs := range bss {
|
|
|
|
var bu uint64
|
|
|
|
switch len(bs) {
|
|
|
|
case 1:
|
|
|
|
bu = uint64(bs[0])
|
|
|
|
case 2:
|
|
|
|
bu = uint64(bo.Uint16(bs))
|
|
|
|
case 4:
|
|
|
|
bu = uint64(bo.Uint32(bs))
|
|
|
|
case 8:
|
|
|
|
bu = bo.Uint64(bs)
|
|
|
|
default:
|
|
|
|
panic("invalid bs length")
|
|
|
|
}
|
|
|
|
|
|
|
|
if au == bu {
|
|
|
|
s.Description = "valid"
|
|
|
|
return s, nil
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
|
|
|
}
|
2021-12-02 00:48:25 +03:00
|
|
|
s.Description = "invalid"
|
|
|
|
if isErr {
|
|
|
|
return s, errors.New("failed to validate raw")
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
|
|
|
return s, nil
|
|
|
|
}
|
|
|
|
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) UintAssertBytes(bss ...[]byte) scalar.UintMapper {
|
|
|
|
return scalar.UintFn(func(s scalar.Uint) (scalar.Uint, error) {
|
|
|
|
return UintAssertBytes(s, true, d.Endian, bss...)
|
2021-12-02 00:48:25 +03:00
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) UintValidateBytes(bss ...[]byte) scalar.UintMapper {
|
|
|
|
return scalar.UintFn(func(s scalar.Uint) (scalar.Uint, error) {
|
|
|
|
return UintAssertBytes(s, false, d.Endian, bss...)
|
2021-12-02 00:48:25 +03:00
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) AssertULEBytes(bss ...[]byte) scalar.UintMapper {
|
|
|
|
return scalar.UintFn(func(s scalar.Uint) (scalar.Uint, error) {
|
|
|
|
return UintAssertBytes(s, true, LittleEndian, bss...)
|
2021-12-02 00:48:25 +03:00
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) UintValidateLEBytes(bss ...[]byte) scalar.UintMapper {
|
|
|
|
return scalar.UintFn(func(s scalar.Uint) (scalar.Uint, error) {
|
|
|
|
return UintAssertBytes(s, false, LittleEndian, bss...)
|
2021-12-02 00:48:25 +03:00
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) AssertUBEBytes(bss ...[]byte) scalar.UintMapper {
|
|
|
|
return scalar.UintFn(func(s scalar.Uint) (scalar.Uint, error) {
|
|
|
|
return UintAssertBytes(s, true, BigEndian, bss...)
|
2021-12-02 00:48:25 +03:00
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|
2022-09-30 14:58:23 +03:00
|
|
|
func (d *D) UintValidateBEBytes(bss ...[]byte) scalar.UintMapper {
|
|
|
|
return scalar.UintFn(func(s scalar.Uint) (scalar.Uint, error) {
|
|
|
|
return UintAssertBytes(s, false, BigEndian, bss...)
|
2021-12-02 00:48:25 +03:00
|
|
|
})
|
2021-11-05 17:04:26 +03:00
|
|
|
}
|