1
1
mirror of https://github.com/wader/fq.git synced 2024-11-10 10:11:39 +03:00

gojqextra,decode: Add generic lazy JQValue

This commit is contained in:
Mattias Wadman 2021-11-22 01:23:59 +01:00
parent 5ad048daf4
commit fdb811ec54
3 changed files with 75 additions and 64 deletions

View File

@ -345,7 +345,7 @@ func frameDecode(d *decode.D, in interface{}) interface{} {
}
if sampleRate == 0 {
d.Errorf("zero sample rate")
d.Fatalf("zero sample rate")
}
calcFrameBytes := int64(144*bitRate/sampleRate + paddingBytes)

View File

@ -241,66 +241,6 @@ func (v String) JQValueToNumber() interface{} { return gojq.NormalizeNumbers(str
func (v String) JQValueToString() interface{} { return string(v) }
func (v String) JQValueToGoJQ() interface{} { return string(v) }
// lazy string
var _ gojq.JQValue = &LazyString{}
type LazyString struct {
Fn func() ([]rune, error)
called bool
rs []rune
}
func (v *LazyString) wrap(fn func(rs []rune) interface{}) interface{} {
if !v.called {
rs, err := v.Fn()
if err != nil {
return err
}
v.called = true
v.rs = rs
}
return fn(v.rs)
}
func (v *LazyString) JQValueLength() interface{} {
return v.wrap(func(rs []rune) interface{} { return len(rs) })
}
func (v *LazyString) JQValueSliceLen() interface{} {
return v.wrap(func(rs []rune) interface{} { return len(rs) })
}
func (v *LazyString) JQValueIndex(index int) interface{} {
// -1 outside after string, -2 outside before string
if index < 0 {
return ""
}
return v.wrap(func(rs []rune) interface{} { return fmt.Sprintf("%c", rs[index]) })
}
func (v *LazyString) JQValueSlice(start int, end int) interface{} {
return v.wrap(func(rs []rune) interface{} { return string(rs[start:end]) })
}
func (v *LazyString) JQValueKey(name string) interface{} { return ExpectedObjectError{Typ: "string"} }
func (v *LazyString) JQValueUpdate(key interface{}, u interface{}, delpath bool) interface{} {
return expectedArrayOrObject(key, "string")
}
func (v *LazyString) JQValueEach() interface{} { return IteratorError{Typ: "string"} }
func (v *LazyString) JQValueKeys() interface{} { return FuncTypeNameError{Name: "keys", Typ: "string"} }
func (v *LazyString) JQValueHas(key interface{}) interface{} {
return FuncTypeNameError{Name: "has", Typ: "string"}
}
func (v *LazyString) JQValueType() string { return "string" }
func (v *LazyString) JQValueToNumber() interface{} {
return v.wrap(func(rs []rune) interface{} { return gojq.NormalizeNumbers(string(rs)) })
}
func (v *LazyString) JQValueToString() interface{} {
return v.wrap(func(rs []rune) interface{} { return string(rs) })
}
func (v *LazyString) JQValueToGoJQ() interface{} {
return v.wrap(func(rs []rune) interface{} { return string(rs) })
}
// boolean
var _ gojq.JQValue = Boolean(true)
@ -389,3 +329,74 @@ func (v Base) JQValueType() string { return v.Typ }
func (v Base) JQValueToNumber() interface{} { return FuncTypeNameError{Name: "tonumber", Typ: v.Typ} }
func (v Base) JQValueToString() interface{} { return FuncTypeNameError{Name: "tostring", Typ: v.Typ} }
func (v Base) JQValueToGoJQ() interface{} { return nil }
// lazy
var _ gojq.JQValue = &Lazy{}
type Lazy struct {
Fn func() (gojq.JQValue, error)
called bool
err error
jv gojq.JQValue
}
func (v *Lazy) v() (gojq.JQValue, error) {
if !v.called {
v.jv, v.err = v.Fn()
v.called = true
}
return v.jv, v.err
}
func (v *Lazy) f(fn func(jv gojq.JQValue) interface{}) interface{} {
jv, err := v.v()
if err != nil {
return err
}
return fn(jv)
}
func (v *Lazy) JQValueLength() interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueLength() })
}
func (v *Lazy) JQValueSliceLen() interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueSliceLen() })
}
func (v *Lazy) JQValueIndex(index int) interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueIndex(index) })
}
func (v *Lazy) JQValueSlice(start int, end int) interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueSlice(start, end) })
}
func (v *Lazy) JQValueKey(name string) interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueKey(name) })
}
func (v *Lazy) JQValueUpdate(key interface{}, u interface{}, delpath bool) interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueUpdate(key, u, delpath) })
}
func (v *Lazy) JQValueEach() interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueEach() })
}
func (v *Lazy) JQValueKeys() interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueKeys() })
}
func (v *Lazy) JQValueHas(key interface{}) interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueHas(key) })
}
func (v *Lazy) JQValueType() string {
jv, err := v.v()
if err != nil {
return "error"
}
return jv.JQValueType()
}
func (v *Lazy) JQValueToNumber() interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueToNumber() })
}
func (v *Lazy) JQValueToString() interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueToString() })
}
func (v *Lazy) JQValueToGoJQ() interface{} {
return v.f(func(jv gojq.JQValue) interface{} { return jv.JQValueToGoJQ() })
}

View File

@ -195,13 +195,13 @@ func makeDecodeValue(dv *decode.Value) interface{} {
// create another buffer we don't have to read and create a string, ex:
// .unknown0 | tobytes[1:] | ...
return decodeValue{
JQValue: &gojqextra.LazyString{
Fn: func() ([]rune, error) {
JQValue: &gojqextra.Lazy{
Fn: func() (gojq.JQValue, error) {
buf := &bytes.Buffer{}
if _, err := io.Copy(buf, vv.Clone()); err != nil {
return nil, err
}
return []rune(buf.String()), nil
return gojqextra.String([]rune(buf.String())), nil
},
},
decodeValueBase: decodeValueBase{dv},