mirror of https://github.com/databricks/cli.git
100 lines
2.6 KiB
Go
100 lines
2.6 KiB
Go
package jsonloader
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/databricks/cli/libs/dyn"
|
|
)
|
|
|
|
type loader struct {
|
|
}
|
|
|
|
func newLoader() *loader {
|
|
return &loader{}
|
|
}
|
|
|
|
func errorf(loc dyn.Location, format string, args ...interface{}) error {
|
|
return fmt.Errorf("json (%s): %s", loc, fmt.Sprintf(format, args...))
|
|
}
|
|
|
|
func (d *loader) load(node any, loc dyn.Location) (dyn.Value, error) {
|
|
var value dyn.Value
|
|
var err error
|
|
|
|
if node == nil {
|
|
return dyn.NilValue, nil
|
|
}
|
|
|
|
if reflect.TypeOf(node).Kind() == reflect.Ptr {
|
|
return d.load(reflect.ValueOf(node).Elem().Interface(), loc)
|
|
}
|
|
|
|
switch reflect.TypeOf(node).Kind() {
|
|
case reflect.Map:
|
|
value, err = d.loadMapping(node.(map[string]interface{}), loc)
|
|
case reflect.Slice:
|
|
value, err = d.loadSequence(node.([]interface{}), loc)
|
|
case reflect.String, reflect.Bool,
|
|
reflect.Float64, reflect.Float32,
|
|
reflect.Int, reflect.Int32, reflect.Int64,
|
|
reflect.Uint, reflect.Uint32, reflect.Uint64:
|
|
value, err = d.loadScalar(node, loc)
|
|
|
|
default:
|
|
return dyn.InvalidValue, errorf(loc, "unknown node kind: %v", reflect.TypeOf(node).Kind())
|
|
}
|
|
|
|
if err != nil {
|
|
return dyn.InvalidValue, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
func (d *loader) loadScalar(node any, loc dyn.Location) (dyn.Value, error) {
|
|
switch reflect.TypeOf(node).Kind() {
|
|
case reflect.String:
|
|
return dyn.NewValue(node.(string), []dyn.Location{loc}), nil
|
|
case reflect.Bool:
|
|
return dyn.NewValue(node.(bool), []dyn.Location{loc}), nil
|
|
case reflect.Float64, reflect.Float32:
|
|
return dyn.NewValue(node.(float64), []dyn.Location{loc}), nil
|
|
case reflect.Int, reflect.Int32, reflect.Int64:
|
|
return dyn.NewValue(node.(int64), []dyn.Location{loc}), nil
|
|
case reflect.Uint, reflect.Uint32, reflect.Uint64:
|
|
return dyn.NewValue(node.(uint64), []dyn.Location{loc}), nil
|
|
default:
|
|
return dyn.InvalidValue, errorf(loc, "unknown scalar type: %v", reflect.TypeOf(node).Kind())
|
|
}
|
|
}
|
|
|
|
func (d *loader) loadSequence(node []interface{}, loc dyn.Location) (dyn.Value, error) {
|
|
dst := make([]dyn.Value, len(node))
|
|
for i, value := range node {
|
|
v, err := d.load(value, loc)
|
|
if err != nil {
|
|
return dyn.InvalidValue, err
|
|
}
|
|
dst[i] = v
|
|
}
|
|
return dyn.NewValue(dst, []dyn.Location{loc}), nil
|
|
}
|
|
|
|
func (d *loader) loadMapping(node map[string]interface{}, loc dyn.Location) (dyn.Value, error) {
|
|
dst := make(map[string]dyn.Value)
|
|
index := 0
|
|
for key, value := range node {
|
|
index += 1
|
|
v, err := d.load(value, dyn.Location{
|
|
Line: loc.Line + index,
|
|
Column: loc.Column,
|
|
})
|
|
if err != nil {
|
|
return dyn.InvalidValue, err
|
|
}
|
|
dst[key] = v
|
|
}
|
|
return dyn.NewValue(dst, []dyn.Location{loc}), nil
|
|
}
|