azkustodata/value/dynamic.go (96 lines of code) (raw):
package value
import (
"encoding/json"
"fmt"
"github.com/Azure/azure-kusto-go/azkustodata/types"
"reflect"
)
// Dynamic represents a Kusto dynamic type. Dynamic implements Kusto.
type Dynamic struct {
Value []byte
}
// NewDynamic creates a new Dynamic.
func NewDynamic(v []byte) *Dynamic { return &Dynamic{v} }
// NewNullDynamic creates a new null Dynamic.
func NewNullDynamic() *Dynamic { return &Dynamic{nil} }
func (d *Dynamic) GetValue() interface{} {
return d.Value
}
func (d *Dynamic) String() string {
if d.Value == nil {
return ""
}
return string(d.Value)
}
func DynamicFromInterface(v interface{}) *Dynamic {
marshal, err := json.Marshal(v)
if err != nil {
return NewNullDynamic()
}
return NewDynamic(marshal)
}
func (*Dynamic) isKustoVal() {}
// Unmarshal unmarshal's i into Dynamic. i must be a string, []byte, map[string]interface{}, []interface{}, other JSON serializable value or nil.
// If []byte or string, must be a JSON representation of a value.
func (d *Dynamic) Unmarshal(i interface{}) error {
if i == nil {
d.Value = nil
return nil
}
switch v := i.(type) {
case []byte:
d.Value = v
return nil
case string:
d.Value = []byte(v)
return nil
}
b, err := json.Marshal(i)
if err != nil {
return parseError(d, i, err)
}
d.Value = b
return nil
}
// Convert Dynamic into reflect value.
func (d *Dynamic) Convert(v reflect.Value) error {
t := v.Type()
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if d.Value == nil {
return nil
}
var valueToSet reflect.Value
switch {
case t.ConvertibleTo(reflect.TypeOf(Dynamic{})):
valueToSet = reflect.ValueOf(*d)
case t.ConvertibleTo(reflect.TypeOf([]byte{})):
if t.Kind() == reflect.String {
s := string(d.Value)
valueToSet = reflect.ValueOf(s)
} else {
valueToSet = reflect.ValueOf(d.Value)
}
case t.Kind() == reflect.Slice || t.Kind() == reflect.Map:
ptr := reflect.New(t)
if err := json.Unmarshal([]byte(d.Value), ptr.Interface()); err != nil {
return fmt.Errorf("Error occurred while trying to unmarshal Dynamic into a %s: %s", t.Kind(), err)
}
valueToSet = ptr.Elem()
case t.Kind() == reflect.Struct:
structPtr := reflect.New(t)
if err := json.Unmarshal([]byte(d.Value), structPtr.Interface()); err != nil {
return fmt.Errorf("Could not unmarshal type dynamic into receiver: %s", err)
}
valueToSet = structPtr.Elem()
default:
return fmt.Errorf("Column was type Kusto.Dynamic, receiver had base Kind %s ", t.Kind())
}
if v.Type().Kind() != reflect.Ptr {
v.Set(valueToSet)
} else {
if v.IsZero() {
v.Set(reflect.New(valueToSet.Type()))
}
v.Elem().Set(valueToSet)
}
return nil
}
// GetType returns the type of the value.
func (d *Dynamic) GetType() types.Column {
return types.Dynamic
}