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

interp: Make tovalue output behave as jq value

Now ex "tovalue | .some.thing" on a decode value will make some.thing be jq value
instead of a decode value which woud be displayed as a decode treee, seems confusing.

I think this is more intuetive and make more sense.
This commit is contained in:
Mattias Wadman 2023-04-28 18:44:24 +02:00
parent 6194b87954
commit ee66fece18
5 changed files with 41 additions and 23 deletions

View File

@ -24,6 +24,17 @@ func IsNull(x any) bool {
}
func ToGoJQValue(v any) (any, bool) {
return ToGoJQValueFn(v, func(v any) (any, bool) {
switch v := v.(type) {
case gojq.JQValue:
return v.JQValueToGoJQ(), true
default:
return nil, false
}
})
}
func ToGoJQValueFn(v any, valueFn func(v any) (any, bool)) (any, bool) {
switch vv := v.(type) {
case nil:
return vv, true
@ -51,25 +62,16 @@ func ToGoJQValue(v any) (any, bool) {
if vv >= math.MinInt && vv <= math.MaxInt {
return int(vv), true
}
return vv, true
} else if vv.IsUint64() {
vv := vv.Uint64()
if vv <= math.MaxInt {
return int(vv), true
}
return vv, true
}
return vv, true
case string:
return vv, true
case []byte:
return string(vv), true
case gojq.JQValue:
return ToGoJQValue(vv.JQValueToGoJQ())
case []any:
vvs := make([]any, len(vv))
for i, v := range vv {
v, ok := ToGoJQValue(v)
v, ok := ToGoJQValueFn(v, valueFn)
if !ok {
return nil, false
}
@ -79,7 +81,7 @@ func ToGoJQValue(v any) (any, bool) {
case map[string]any:
vvs := make(map[string]any, len(vv))
for k, v := range vv {
v, ok := ToGoJQValue(v)
v, ok := ToGoJQValueFn(v, valueFn)
if !ok {
return nil, false
}
@ -87,6 +89,9 @@ func ToGoJQValue(v any) (any, bool) {
}
return vvs, true
default:
if nv, ok := valueFn(vv); ok {
return ToGoJQValueFn(nv, valueFn)
}
return nil, false
}
}

View File

@ -305,19 +305,23 @@ func valueHas(key any, a func(name string) any, b func(key any) any) any {
return b(key)
}
// optsFn is a function as toValue is used by tovalue/0 so needs to be fast
// TODO: make more efficient somehow? shallow values but might be hard
// when things like tovalue.key should behave like a jq value and not a decode value etc
func toValue(optsFn func() Options, v any) any {
switch v := v.(type) {
case JQValueEx:
if optsFn == nil {
return v.JQValueToGoJQ()
nv, _ := gojqex.ToGoJQValueFn(v, func(v any) (any, bool) {
switch v := v.(type) {
case JQValueEx:
if optsFn == nil {
return v.JQValueToGoJQ(), true
}
return v.JQValueToGoJQEx(optsFn), true
case gojq.JQValue:
return v.JQValueToGoJQ(), true
default:
return v, true
}
return v.JQValueToGoJQEx(optsFn)
case gojq.JQValue:
return v.JQValueToGoJQ()
default:
return v
}
})
return nv
}
type decodeValueKind int

View File

@ -16,7 +16,8 @@ def display($opts):
( . as $c
| options($opts) as $opts
| try _todisplay catch $c
| if ($opts.value_output | not) and _can_display then _display($opts)
| if $opts.value_output then tovalue end
| if _can_display then _display($opts)
else
( if _is_string and $opts.raw_string then print
else _print_color_json($opts)

View File

@ -1,4 +1,8 @@
# TODO: use test format
$ fq -i . test.mp3
mp3> .headers[0] | tovalue.header.magic
"ID3"
mp3> ^D
$ fq -i
null> "aaa" | mp3_frame | .gap0 | tovalue, tovalue({sizebase: 2})
"aaa"

View File

@ -20,3 +20,7 @@ ID3
"unused": 0
}
35
$ fq -o bits_format=base64 -V '.frames[0].audio_data' test.mp3
"AAAAAAA="
$ fq -o bits_format=base64 -Vr '.frames[0].audio_data' test.mp3
AAAAAAA=