mirror of
https://github.com/robertkrimen/otto
synced 2025-10-12 20:27:30 +08:00
807 lines
20 KiB
Go
807 lines
20 KiB
Go
package otto
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"reflect"
|
|
"strconv"
|
|
)
|
|
|
|
type _valueType int
|
|
|
|
const (
|
|
valueEmpty _valueType = iota
|
|
valueNull
|
|
valueUndefined
|
|
valueNumber
|
|
valueString
|
|
valueBoolean
|
|
valueObject
|
|
valueReference
|
|
)
|
|
|
|
// Value is the representation of a JavaScript value.
|
|
type Value struct {
|
|
_valueType
|
|
value interface{}
|
|
}
|
|
|
|
// ToValue will convert an interface{} value to a value digestible by otto/JavaScript
|
|
// This function will not work for advanced types (struct, map, slice/array, etc.) and
|
|
// you probably should not use it.
|
|
//
|
|
// ToValue may be deprecated and removed in the near future.
|
|
//
|
|
// Try Otto.ToValue for a reaplcement.
|
|
func ToValue(value interface{}) (Value, error) {
|
|
result := UndefinedValue()
|
|
err := catchPanic(func() {
|
|
result = toValue(value)
|
|
})
|
|
return result, err
|
|
}
|
|
|
|
// Empty
|
|
|
|
func emptyValue() Value {
|
|
return Value{_valueType: valueEmpty}
|
|
}
|
|
|
|
func (value Value) isEmpty() bool {
|
|
return value._valueType == valueEmpty
|
|
}
|
|
|
|
// Undefined
|
|
|
|
// UndefinedValue will return a Value representing undefined.
|
|
func UndefinedValue() Value {
|
|
return Value{_valueType: valueUndefined}
|
|
}
|
|
|
|
// IsDefined will return false if the value is undefined, and true otherwise.
|
|
func (value Value) IsDefined() bool {
|
|
return value._valueType != valueUndefined
|
|
}
|
|
|
|
// IsUndefined will return true if the value is undefined, and false otherwise.
|
|
func (value Value) IsUndefined() bool {
|
|
return value._valueType == valueUndefined
|
|
}
|
|
|
|
// NullValue will return a Value representing null.
|
|
func NullValue() Value {
|
|
return Value{_valueType: valueNull}
|
|
}
|
|
|
|
// IsNull will return true if the value is null, and false otherwise.
|
|
func (value Value) IsNull() bool {
|
|
return value._valueType == valueNull
|
|
}
|
|
|
|
// ---
|
|
|
|
func (value Value) isCallable() bool {
|
|
switch value := value.value.(type) {
|
|
case *_object:
|
|
return value._Function != nil
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (value Value) isReference() bool {
|
|
return value._valueType == valueReference
|
|
}
|
|
|
|
// Call the value as a function with the given this value and argument list and
|
|
// return the result of invocation. It is essentially equivalent to:
|
|
//
|
|
// value.apply(thisValue, argumentList)
|
|
//
|
|
// An undefined value and an error will result if:
|
|
//
|
|
// 1. There is an error during conversion of the argument list
|
|
// 2. The value is not actually a function
|
|
// 3. An (uncaught) exception is thrown
|
|
//
|
|
func (value Value) Call(this Value, argumentList ...interface{}) (Value, error) {
|
|
result := UndefinedValue()
|
|
err := catchPanic(func() {
|
|
result = value.call(this, argumentList...)
|
|
})
|
|
return result, err
|
|
}
|
|
|
|
func (value Value) call(this Value, argumentList ...interface{}) Value {
|
|
switch value := value.value.(type) {
|
|
case *_object:
|
|
return value.Call(this, argumentList...)
|
|
}
|
|
panic(newTypeError())
|
|
}
|
|
|
|
// IsPrimitive will return true if value is a primitive (any kind of primitive).
|
|
func (value Value) IsPrimitive() bool {
|
|
return !value.IsObject()
|
|
}
|
|
|
|
// IsBoolean will return true if value is a boolean (primitive).
|
|
func (value Value) IsBoolean() bool {
|
|
return value._valueType == valueBoolean
|
|
}
|
|
|
|
// IsNumber will return true if value is a number (primitive).
|
|
func (value Value) IsNumber() bool {
|
|
return value._valueType == valueNumber
|
|
}
|
|
|
|
// IsNaN will return true if value is NaN (or would convert to NaN).
|
|
func (value Value) IsNaN() bool {
|
|
switch value := value.value.(type) {
|
|
case float64:
|
|
return math.IsNaN(value)
|
|
case float32:
|
|
return math.IsNaN(float64(value))
|
|
case int, int8, int32, int64:
|
|
return false
|
|
case uint, uint8, uint32, uint64:
|
|
return false
|
|
}
|
|
|
|
return math.IsNaN(toFloat(value))
|
|
}
|
|
|
|
// IsString will return true if value is a string (primitive).
|
|
func (value Value) IsString() bool {
|
|
return value._valueType == valueString
|
|
}
|
|
|
|
// IsObject will return true if value is an object.
|
|
func (value Value) IsObject() bool {
|
|
return value._valueType == valueObject
|
|
}
|
|
|
|
// IsFunction will return true if value is a function.
|
|
func (value Value) IsFunction() bool {
|
|
if value._valueType != valueObject {
|
|
return false
|
|
}
|
|
return value.value.(*_object).class == "Function"
|
|
}
|
|
|
|
// Class will return the class string of the value or the empty string if value is not an object.
|
|
//
|
|
// The return value will (generally) be one of:
|
|
//
|
|
// Object
|
|
// Function
|
|
// Array
|
|
// String
|
|
// Number
|
|
// Boolean
|
|
// Date
|
|
// RegExp
|
|
//
|
|
func (value Value) Class() string {
|
|
if value._valueType != valueObject {
|
|
return ""
|
|
}
|
|
return value.value.(*_object).class
|
|
}
|
|
|
|
func (value Value) isArray() bool {
|
|
if value._valueType != valueObject {
|
|
return false
|
|
}
|
|
return value.value.(*_object).class == "Array"
|
|
}
|
|
|
|
func (value Value) isStringObject() bool {
|
|
if value._valueType != valueObject {
|
|
return false
|
|
}
|
|
return value.value.(*_object).class == "String"
|
|
}
|
|
|
|
func (value Value) isBooleanObject() bool {
|
|
if value._valueType != valueObject {
|
|
return false
|
|
}
|
|
return value.value.(*_object).class == "Boolean"
|
|
}
|
|
|
|
func (value Value) isNumberObject() bool {
|
|
if value._valueType != valueObject {
|
|
return false
|
|
}
|
|
return value.value.(*_object).class == "Number"
|
|
}
|
|
|
|
func (value Value) isDate() bool {
|
|
if value._valueType != valueObject {
|
|
return false
|
|
}
|
|
return value.value.(*_object).class == "Date"
|
|
}
|
|
|
|
func (value Value) isRegExp() bool {
|
|
if value._valueType != valueObject {
|
|
return false
|
|
}
|
|
return value.value.(*_object).class == "RegExp"
|
|
}
|
|
|
|
func (value Value) isError() bool {
|
|
if value._valueType != valueObject {
|
|
return false
|
|
}
|
|
return value.value.(*_object).class == "Error"
|
|
}
|
|
|
|
// ---
|
|
|
|
func toValue_reflectValuePanic(value interface{}, kind reflect.Kind) {
|
|
switch kind {
|
|
case reflect.Struct:
|
|
panic(newTypeError("Invalid value (struct): Missing runtime: %v (%T)", value, value))
|
|
case reflect.Map:
|
|
panic(newTypeError("Invalid value (map): Missing runtime: %v (%T)", value, value))
|
|
case reflect.Slice:
|
|
panic(newTypeError("Invalid value (slice): Missing runtime: %v (%T)", value, value))
|
|
}
|
|
}
|
|
|
|
// TODO toValue(nil)?
|
|
func toValue(value interface{}) Value {
|
|
switch value := value.(type) {
|
|
case Value:
|
|
return value
|
|
case bool:
|
|
return Value{valueBoolean, value}
|
|
case int:
|
|
return Value{valueNumber, value}
|
|
case int8:
|
|
return Value{valueNumber, value}
|
|
case int16:
|
|
return Value{valueNumber, value}
|
|
case int32:
|
|
return Value{valueNumber, value}
|
|
case int64:
|
|
return Value{valueNumber, value}
|
|
case uint:
|
|
return Value{valueNumber, value}
|
|
case uint8:
|
|
return Value{valueNumber, value}
|
|
case uint16:
|
|
return Value{valueNumber, value}
|
|
case uint32:
|
|
return Value{valueNumber, value}
|
|
case uint64:
|
|
return Value{valueNumber, value}
|
|
case float32:
|
|
return Value{valueNumber, float64(value)}
|
|
case float64:
|
|
return Value{valueNumber, value}
|
|
case string:
|
|
return Value{valueString, value}
|
|
// A rune is actually an int32, which is handled above
|
|
case *_object:
|
|
return Value{valueObject, value}
|
|
case *Object:
|
|
return Value{valueObject, value.object}
|
|
case Object:
|
|
return Value{valueObject, value.object}
|
|
case _reference: // reference is an interface (already a pointer)
|
|
return Value{valueReference, value}
|
|
case reflect.Value:
|
|
value = reflect.Indirect(value)
|
|
switch value.Kind() {
|
|
case reflect.Bool:
|
|
return Value{valueBoolean, bool(value.Bool())}
|
|
case reflect.Int:
|
|
return Value{valueNumber, int(value.Int())}
|
|
case reflect.Int8:
|
|
return Value{valueNumber, int8(value.Int())}
|
|
case reflect.Int16:
|
|
return Value{valueNumber, int16(value.Int())}
|
|
case reflect.Int32:
|
|
return Value{valueNumber, int32(value.Int())}
|
|
case reflect.Int64:
|
|
return Value{valueNumber, int64(value.Int())}
|
|
case reflect.Uint:
|
|
return Value{valueNumber, uint(value.Uint())}
|
|
case reflect.Uint8:
|
|
return Value{valueNumber, uint8(value.Uint())}
|
|
case reflect.Uint16:
|
|
return Value{valueNumber, uint16(value.Uint())}
|
|
case reflect.Uint32:
|
|
return Value{valueNumber, uint32(value.Uint())}
|
|
case reflect.Uint64:
|
|
return Value{valueNumber, uint64(value.Uint())}
|
|
case reflect.Float32:
|
|
return Value{valueNumber, float32(value.Float())}
|
|
case reflect.Float64:
|
|
return Value{valueNumber, float64(value.Float())}
|
|
case reflect.String:
|
|
return Value{valueString, string(value.String())}
|
|
default:
|
|
toValue_reflectValuePanic(value.Interface(), value.Kind())
|
|
}
|
|
default:
|
|
{
|
|
value := reflect.Indirect(reflect.ValueOf(value))
|
|
toValue_reflectValuePanic(value.Interface(), value.Kind())
|
|
}
|
|
}
|
|
panic(newTypeError("Invalid value: Unsupported: %v (%T)", value, value))
|
|
}
|
|
|
|
// String will return the value as a string.
|
|
//
|
|
// This method will make return the empty string if there is an error.
|
|
func (value Value) String() string {
|
|
result := ""
|
|
catchPanic(func() {
|
|
result = value.toString()
|
|
})
|
|
return result
|
|
}
|
|
|
|
func (value Value) toBoolean() bool {
|
|
return toBoolean(value)
|
|
}
|
|
|
|
// ToBoolean will convert the value to a boolean (bool).
|
|
//
|
|
// ToValue(0).ToBoolean() => false
|
|
// ToValue("").ToBoolean() => false
|
|
// ToValue(true).ToBoolean() => true
|
|
// ToValue(1).ToBoolean() => true
|
|
// ToValue("Nothing happens").ToBoolean() => true
|
|
//
|
|
// If there is an error during the conversion process (like an uncaught exception), then the result will be false and an error.
|
|
func (value Value) ToBoolean() (bool, error) {
|
|
result := false
|
|
err := catchPanic(func() {
|
|
result = toBoolean(value)
|
|
})
|
|
return result, err
|
|
}
|
|
|
|
func (value Value) toNumber() Value {
|
|
return toNumber(value)
|
|
}
|
|
|
|
func (value Value) toFloat() float64 {
|
|
return toFloat(value)
|
|
}
|
|
|
|
// ToFloat will convert the value to a number (float64).
|
|
//
|
|
// ToValue(0).ToFloat() => 0.
|
|
// ToValue(1.1).ToFloat() => 1.1
|
|
// ToValue("11").ToFloat() => 11.
|
|
//
|
|
// If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error.
|
|
func (value Value) ToFloat() (float64, error) {
|
|
result := float64(0)
|
|
err := catchPanic(func() {
|
|
result = toFloat(value)
|
|
})
|
|
return result, err
|
|
}
|
|
|
|
// ToInteger will convert the value to a number (int64).
|
|
//
|
|
// ToValue(0).ToInteger() => 0
|
|
// ToValue(1.1).ToInteger() => 1
|
|
// ToValue("11").ToInteger() => 11
|
|
//
|
|
// If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error.
|
|
func (value Value) ToInteger() (int64, error) {
|
|
result := int64(0)
|
|
err := catchPanic(func() {
|
|
result = toInteger(value)
|
|
})
|
|
return result, err
|
|
}
|
|
|
|
func (value Value) toString() string {
|
|
return toString(value)
|
|
}
|
|
|
|
// ToString will convert the value to a string (string).
|
|
//
|
|
// ToValue(0).ToString() => "0"
|
|
// ToValue(false).ToString() => "false"
|
|
// ToValue(1.1).ToString() => "1.1"
|
|
// ToValue("11").ToString() => "11"
|
|
// ToValue('Nothing happens.').ToString() => "Nothing happens."
|
|
//
|
|
// If there is an error during the conversion process (like an uncaught exception), then the result will be the empty string ("") and an error.
|
|
func (value Value) ToString() (string, error) {
|
|
result := ""
|
|
err := catchPanic(func() {
|
|
result = toString(value)
|
|
})
|
|
return result, err
|
|
}
|
|
|
|
func (value Value) _object() *_object {
|
|
switch value := value.value.(type) {
|
|
case *_object:
|
|
return value
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Object will return the object of the value, or nil if value is not an object.
|
|
//
|
|
// This method will not do any implicit conversion. For example, calling this method on a string primitive value will not return a String object.
|
|
func (value Value) Object() *Object {
|
|
switch object := value.value.(type) {
|
|
case *_object:
|
|
return _newObject(object, value)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (value Value) reference() _reference {
|
|
switch value := value.value.(type) {
|
|
case _reference:
|
|
return value
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
__NaN__ float64 = math.NaN()
|
|
__PositiveInfinity__ float64 = math.Inf(+1)
|
|
__NegativeInfinity__ float64 = math.Inf(-1)
|
|
__PositiveZero__ float64 = 0
|
|
__NegativeZero__ float64 = math.Float64frombits(0 | (1 << 63))
|
|
)
|
|
|
|
func positiveInfinity() float64 {
|
|
return __PositiveInfinity__
|
|
}
|
|
|
|
func negativeInfinity() float64 {
|
|
return __NegativeInfinity__
|
|
}
|
|
|
|
func positiveZero() float64 {
|
|
return __PositiveZero__
|
|
}
|
|
|
|
func negativeZero() float64 {
|
|
return __NegativeZero__
|
|
}
|
|
|
|
// NaNValue will return a value representing NaN.
|
|
//
|
|
// It is equivalent to:
|
|
//
|
|
// ToValue(math.NaN())
|
|
//
|
|
func NaNValue() Value {
|
|
return Value{valueNumber, __NaN__}
|
|
}
|
|
|
|
func positiveInfinityValue() Value {
|
|
return Value{valueNumber, __PositiveInfinity__}
|
|
}
|
|
|
|
func negativeInfinityValue() Value {
|
|
return Value{valueNumber, __NegativeInfinity__}
|
|
}
|
|
|
|
func positiveZeroValue() Value {
|
|
return Value{valueNumber, __PositiveZero__}
|
|
}
|
|
|
|
func negativeZeroValue() Value {
|
|
return Value{valueNumber, __NegativeZero__}
|
|
}
|
|
|
|
// TrueValue will return a value represting true.
|
|
//
|
|
// It is equivalent to:
|
|
//
|
|
// ToValue(true)
|
|
//
|
|
func TrueValue() Value {
|
|
return Value{valueBoolean, true}
|
|
}
|
|
|
|
// FalseValue will return a value represting false.
|
|
//
|
|
// It is equivalent to:
|
|
//
|
|
// ToValue(false)
|
|
//
|
|
func FalseValue() Value {
|
|
return Value{valueBoolean, false}
|
|
}
|
|
|
|
func sameValue(x Value, y Value) bool {
|
|
if x._valueType != y._valueType {
|
|
return false
|
|
}
|
|
result := false
|
|
switch x._valueType {
|
|
case valueUndefined, valueNull:
|
|
result = true
|
|
case valueNumber:
|
|
x := x.toFloat()
|
|
y := y.toFloat()
|
|
if math.IsNaN(x) && math.IsNaN(y) {
|
|
result = true
|
|
} else {
|
|
result = x == y
|
|
if result && x == 0 {
|
|
// Since +0 != -0
|
|
result = math.Signbit(x) == math.Signbit(y)
|
|
}
|
|
}
|
|
case valueString:
|
|
result = x.toString() == y.toString()
|
|
case valueBoolean:
|
|
result = x.toBoolean() == y.toBoolean()
|
|
case valueObject:
|
|
result = x._object() == y._object()
|
|
default:
|
|
panic(hereBeDragons())
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// Export will convert the value to its closest go representation
|
|
//
|
|
// undefined -> nil, error undefined
|
|
// null -> nil, nil
|
|
// boolean -> bool, nil
|
|
// number -> float64, nil
|
|
// string -> string, nil
|
|
// Array -> []interface{}, nil
|
|
// Object -> map[string]interface{}, nil
|
|
|
|
func (value Value) Export() (interface{}, error) {
|
|
|
|
switch value._valueType {
|
|
case valueUndefined:
|
|
return nil, fmt.Errorf("undefined")
|
|
case valueNull:
|
|
return nil, nil
|
|
case valueNumber:
|
|
return value.toFloat(), nil
|
|
case valueString:
|
|
return value.toString(), nil
|
|
case valueBoolean:
|
|
return value.toBoolean(), nil
|
|
case valueObject:
|
|
|
|
// get the names of things inside
|
|
propNames := make([]string, 0)
|
|
value.value.(*_object).enumerate(func(name string) {
|
|
propNames = append(propNames, name)
|
|
})
|
|
|
|
if value.value.(*_object).class == "Array" {
|
|
|
|
// format non-undefined inner values in array
|
|
result := make([]interface{}, 0)
|
|
for _, v := range propNames {
|
|
inner_value := value.value.(*_object).get(v)
|
|
export_value, export_error := inner_value.Export()
|
|
if export_error == nil {
|
|
result = append(result, export_value)
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
} else {
|
|
// format non-undefined inner values in object
|
|
result := make(map[string]interface{})
|
|
for _, v := range propNames {
|
|
inner_value := value.value.(*_object).get(v)
|
|
export_value, export_error := inner_value.Export()
|
|
if export_error == nil {
|
|
result[v] = export_value
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
default:
|
|
panic(hereBeDragons())
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
|
|
func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) {
|
|
switch kind {
|
|
case reflect.Bool:
|
|
return reflect.ValueOf(value.toBoolean()), nil
|
|
case reflect.Int:
|
|
tmp := toIntegerFloat(value)
|
|
if tmp < _MinInt_ || tmp > _MaxInt_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(int(tmp)), nil
|
|
}
|
|
case reflect.Int8:
|
|
tmp := toInteger(value)
|
|
if tmp < _MinInt8_ || tmp > _MaxInt8_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int8", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(int8(tmp)), nil
|
|
}
|
|
case reflect.Int16:
|
|
tmp := toInteger(value)
|
|
if tmp < _MinInt16_ || tmp > _MaxInt16_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int16", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(int16(tmp)), nil
|
|
}
|
|
case reflect.Int32:
|
|
tmp := toInteger(value)
|
|
if tmp < _MinInt32_ || tmp > _MaxInt32_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int32", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(int32(tmp)), nil
|
|
}
|
|
case reflect.Int64:
|
|
tmp := toIntegerFloat(value)
|
|
if tmp < _MinInt64_ || tmp > _MaxInt64_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(int64(tmp)), nil
|
|
}
|
|
case reflect.Uint:
|
|
tmp := toIntegerFloat(value)
|
|
if tmp < 0 || tmp > _MaxUint_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(uint(tmp)), nil
|
|
}
|
|
case reflect.Uint8:
|
|
tmp := toInteger(value)
|
|
if tmp < 0 || tmp > _MaxUint8_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint8", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(uint8(tmp)), nil
|
|
}
|
|
case reflect.Uint16:
|
|
tmp := toInteger(value)
|
|
if tmp < 0 || tmp > _MaxUint16_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint16", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(uint16(tmp)), nil
|
|
}
|
|
case reflect.Uint32:
|
|
tmp := toInteger(value)
|
|
if tmp < 0 || tmp > _MaxUint32_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint32", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(uint32(tmp)), nil
|
|
}
|
|
case reflect.Uint64:
|
|
tmp := toIntegerFloat(value)
|
|
if tmp < 0 || tmp > _MaxUint64_ {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint64", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(uint64(tmp)), nil
|
|
}
|
|
case reflect.Float32:
|
|
tmp := toFloat(value)
|
|
tmp1 := tmp
|
|
if 0 > tmp1 {
|
|
tmp1 = -tmp1
|
|
}
|
|
if tmp1 < math.SmallestNonzeroFloat32 || tmp1 > math.MaxFloat32 {
|
|
return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to float32", tmp, value)
|
|
} else {
|
|
return reflect.ValueOf(float32(tmp)), nil
|
|
}
|
|
case reflect.Float64:
|
|
value := toFloat(value)
|
|
return reflect.ValueOf(float64(value)), nil
|
|
case reflect.String:
|
|
return reflect.ValueOf(value.toString()), nil
|
|
}
|
|
|
|
dbgf("%/panic//%@: Invalid: (%v) to reflect.Kind: %v", value, kind)
|
|
panic("")
|
|
}
|
|
|
|
func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error) {
|
|
switch kind {
|
|
case reflect.Bool:
|
|
value, err := strconv.ParseBool(value)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(value), nil
|
|
case reflect.Int:
|
|
value, err := strconv.ParseInt(value, 0, 0)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(int(value)), nil
|
|
case reflect.Int8:
|
|
value, err := strconv.ParseInt(value, 0, 8)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(int8(value)), nil
|
|
case reflect.Int16:
|
|
value, err := strconv.ParseInt(value, 0, 16)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(int16(value)), nil
|
|
case reflect.Int32:
|
|
value, err := strconv.ParseInt(value, 0, 32)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(int32(value)), nil
|
|
case reflect.Int64:
|
|
value, err := strconv.ParseInt(value, 0, 64)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(int64(value)), nil
|
|
case reflect.Uint:
|
|
value, err := strconv.ParseUint(value, 0, 0)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(uint(value)), nil
|
|
case reflect.Uint8:
|
|
value, err := strconv.ParseUint(value, 0, 8)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(uint8(value)), nil
|
|
case reflect.Uint16:
|
|
value, err := strconv.ParseUint(value, 0, 16)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(uint16(value)), nil
|
|
case reflect.Uint32:
|
|
value, err := strconv.ParseUint(value, 0, 32)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(uint32(value)), nil
|
|
case reflect.Uint64:
|
|
value, err := strconv.ParseUint(value, 0, 64)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(uint64(value)), nil
|
|
case reflect.Float32:
|
|
value, err := strconv.ParseFloat(value, 32)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(float32(value)), nil
|
|
case reflect.Float64:
|
|
value, err := strconv.ParseFloat(value, 64)
|
|
if err != nil {
|
|
return reflect.Value{}, err
|
|
}
|
|
return reflect.ValueOf(float64(value)), nil
|
|
case reflect.String:
|
|
return reflect.ValueOf(value), nil
|
|
}
|
|
|
|
dbgf("%/panic//%@: Invalid: \"%s\" to reflect.Kind: %v", value, kind)
|
|
panic("")
|
|
}
|