Skip to content

Commit

Permalink
Add JQValue interface to support custom values
Browse files Browse the repository at this point in the history
  • Loading branch information
wader committed Jan 18, 2024
1 parent 77ea5a5 commit e920352
Show file tree
Hide file tree
Showing 11 changed files with 401 additions and 64 deletions.
6 changes: 6 additions & 0 deletions cli/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"sort"
"strconv"
"unicode/utf8"

"github.com/wader/gojq"
)

type encoder struct {
Expand Down Expand Up @@ -66,6 +68,10 @@ func (e *encoder) encode(v any) error {
if err := e.encodeObject(v); err != nil {
return err
}
case gojq.JQValue:
if err := e.encode(v.JQValueToGoJQ()); err != nil {
return err
}
default:
panic(fmt.Sprintf("invalid type: %[1]T (%[1]v)", v))
}
Expand Down
2 changes: 2 additions & 0 deletions debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ func debugValue(v any) string {
return fmt.Sprintf("gojq.Iter(%#v)", v)
case []pathValue:
return fmt.Sprintf("[]gojq.pathValue(%v)", v)
case JQValue:
return fmt.Sprintf("gojq.JQValue(%s)", Preview(v))
case [2]int:
return fmt.Sprintf("[%d,%d]", v[0], v[1])
case [3]int:
Expand Down
2 changes: 2 additions & 0 deletions encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ func (e *encoder) encode(v any) {
e.encodeArray(v)
case map[string]any:
e.encodeObject(v)
case JQValue:
e.encode(v.JQValueToGoJQ())
default:
panic(fmt.Sprintf("invalid type: %[1]T (%[1]v)", v))
}
Expand Down
39 changes: 38 additions & 1 deletion execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ loop:
m := make(map[string]any, n)
for i := 0; i < n; i++ {
v, k := env.pop(), env.pop()
if jv, ok := k.(JQValue); ok {
k = jv.JQValueToString()
}
s, ok := k.(string)
if !ok {
err = &objectKeyNotStringError{k}
Expand Down Expand Up @@ -141,7 +144,9 @@ loop:
pc = code.v.(int)
goto loop
case opjumpifnot:
if v := env.pop(); v == nil || v == false {
v := env.pop()
b, bOk := toBoolean(v)
if isNull(v) || (bOk && !b) {
pc = code.v.(int)
goto loop
}
Expand All @@ -151,6 +156,9 @@ loop:
}
p, v := code.v, env.pop()
if code.op == opindexarray && v != nil {
if jqv, ok := v.(JQValue); ok {
v = jqv.JQValueToGoJQ()
}
if _, ok := v.([]any); !ok {
err = &expectedArrayError{v}
break loop
Expand Down Expand Up @@ -312,6 +320,32 @@ loop:
continue
}
break loop
case JQValue:
if !env.paths.empty() && env.expdepth == 0 && !env.pathIntact(v) {
err = &invalidPathIterError{v}
break loop
}
xsv := v.JQValueEach()
if e, ok := xsv.(error); ok {
err = e
break loop
}
switch xsv := xsv.(type) {
case []PathValue:
// convert from external PathValue to internal pathValue to make it easier to follow upstream
xs = make([]pathValue, len(xsv))
if len(xsv) == 0 {
break loop
}
for i, pv := range xsv {
xs[i] = pathValue{path: pv.Path, value: pv.Value}
}
case nil:
break loop
default:
err = &iteratorError{xsv}
break loop
}
default:
err = &iteratorError{v}
env.push(emptyIter{})
Expand Down Expand Up @@ -423,6 +457,9 @@ func (env *env) pathIntact(v any) bool {
if w, ok := w.(float64); ok {
return v == w || math.IsNaN(v) && math.IsNaN(w)
}
case JQValue:
// TODO: JQValue: should understand this better
return true
}
return v == w
}
Expand Down

0 comments on commit e920352

Please sign in to comment.