diff options
Diffstat (limited to 'Godeps/_workspace/src/github.com/robertkrimen/otto/value.go')
-rw-r--r-- | Godeps/_workspace/src/github.com/robertkrimen/otto/value.go | 1025 |
1 files changed, 0 insertions, 1025 deletions
diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/value.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/value.go deleted file mode 100644 index a1c341f4d..000000000 --- a/Godeps/_workspace/src/github.com/robertkrimen/otto/value.go +++ /dev/null @@ -1,1025 +0,0 @@ -package otto - -import ( - "fmt" - "math" - "reflect" - "strconv" - "unicode/utf16" -) - -type _valueKind int - -const ( - valueUndefined _valueKind = iota - valueNull - valueNumber - valueString - valueBoolean - valueObject - - // These are invalid outside of the runtime - valueEmpty - valueResult - valueReference -) - -// Value is the representation of a JavaScript value. -type Value struct { - kind _valueKind - value interface{} -} - -func (vl Value) safe() bool { - return vl.kind < valueEmpty -} - -var ( - emptyValue = Value{kind: valueEmpty} - nullValue = Value{kind: valueNull} - falseValue = Value{kind: valueBoolean, value: false} - trueValue = Value{kind: valueBoolean, value: true} -) - -// 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 should use Otto.ToValue instead. -func ToValue(value interface{}) (Value, error) { - result := Value{} - err := catchPanic(func() { - result = toValue(value) - }) - return result, err -} - -func (value Value) isEmpty() bool { - return value.kind == valueEmpty -} - -// Undefined - -// UndefinedValue will return a Value representing undefined. -func UndefinedValue() Value { - return Value{} -} - -// IsDefined will return false if the value is undefined, and true otherwise. -func (value Value) IsDefined() bool { - return value.kind != valueUndefined -} - -// IsUndefined will return true if the value is undefined, and false otherwise. -func (value Value) IsUndefined() bool { - return value.kind == valueUndefined -} - -// NullValue will return a Value representing null. -func NullValue() Value { - return Value{kind: valueNull} -} - -// IsNull will return true if the value is null, and false otherwise. -func (value Value) IsNull() bool { - return value.kind == valueNull -} - -// --- - -func (value Value) isCallable() bool { - switch value := value.value.(type) { - case *_object: - return value.isCall() - } - return false -} - -// 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 := Value{} - err := catchPanic(func() { - // FIXME - result = value.call(nil, this, argumentList...) - }) - if !value.safe() { - value = Value{} - } - return result, err -} - -func (value Value) call(rt *_runtime, this Value, argumentList ...interface{}) Value { - switch function := value.value.(type) { - case *_object: - return function.call(this, function.runtime.toValueArray(argumentList...), false, nativeFrame) - } - if rt == nil { - panic("FIXME TypeError") - } - panic(rt.panicTypeError()) -} - -func (value Value) constructSafe(rt *_runtime, this Value, argumentList ...interface{}) (Value, error) { - result := Value{} - err := catchPanic(func() { - result = value.construct(rt, this, argumentList...) - }) - return result, err -} - -func (value Value) construct(rt *_runtime, this Value, argumentList ...interface{}) Value { - switch fn := value.value.(type) { - case *_object: - return fn.construct(fn.runtime.toValueArray(argumentList...)) - } - if rt == nil { - panic("FIXME TypeError") - } - panic(rt.panicTypeError()) -} - -// 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.kind == valueBoolean -} - -// IsNumber will return true if value is a number (primitive). -func (value Value) IsNumber() bool { - return value.kind == 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(value.float64()) -} - -// IsString will return true if value is a string (primitive). -func (value Value) IsString() bool { - return value.kind == valueString -} - -// IsObject will return true if value is an object. -func (value Value) IsObject() bool { - return value.kind == valueObject -} - -// IsFunction will return true if value is a function. -func (value Value) IsFunction() bool { - if value.kind != 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.kind != valueObject { - return "" - } - return value.value.(*_object).class -} - -func (value Value) isArray() bool { - if value.kind != valueObject { - return false - } - return isArray(value.value.(*_object)) -} - -func (value Value) isStringObject() bool { - if value.kind != valueObject { - return false - } - return value.value.(*_object).class == "String" -} - -func (value Value) isBooleanObject() bool { - if value.kind != valueObject { - return false - } - return value.value.(*_object).class == "Boolean" -} - -func (value Value) isNumberObject() bool { - if value.kind != valueObject { - return false - } - return value.value.(*_object).class == "Number" -} - -func (value Value) isDate() bool { - if value.kind != valueObject { - return false - } - return value.value.(*_object).class == "Date" -} - -func (value Value) isRegExp() bool { - if value.kind != valueObject { - return false - } - return value.value.(*_object).class == "RegExp" -} - -func (value Value) isError() bool { - if value.kind != valueObject { - return false - } - return value.value.(*_object).class == "Error" -} - -// --- - -func toValue_reflectValuePanic(value interface{}, kind reflect.Kind) { - // FIXME? - switch kind { - case reflect.Struct: - panic(newError(nil, "TypeError", "invalid value (struct): missing runtime: %v (%T)", value, value)) - case reflect.Map: - panic(newError(nil, "TypeError", "invalid value (map): missing runtime: %v (%T)", value, value)) - case reflect.Slice: - panic(newError(nil, "TypeError", "invalid value (slice): missing runtime: %v (%T)", value, value)) - } -} - -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 []uint16: - return Value{valueString, 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 _result: - return Value{valueResult, value} - case nil: - // TODO Ugh. - return Value{} - case reflect.Value: - for value.Kind() == reflect.Ptr { - // We were given a pointer, so we'll drill down until we get a non-pointer - // - // These semantics might change if we want to start supporting pointers to values transparently - // (It would be best not to depend on this behavior) - // FIXME: UNDEFINED - if value.IsNil() { - return Value{} - } - value = value.Elem() - } - 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: - return toValue(reflect.ValueOf(value)) - } - // FIXME? - panic(newError(nil, "TypeError", "invalid value: %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.string() - }) - return result -} - -// 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 = value.bool() - }) - return result, err -} - -func (value Value) numberValue() Value { - if value.kind == valueNumber { - return value - } - return Value{valueNumber, value.float64()} -} - -// 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 = value.float64() - }) - 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 = value.number().int64 - }) - return result, err -} - -// 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 = value.string() - }) - 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 -} - -func (value Value) resolve() Value { - switch value := value.value.(type) { - case _reference: - return value.getValue() - } - return value -} - -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 representing true. -// -// It is equivalent to: -// -// ToValue(true) -// -func TrueValue() Value { - return Value{valueBoolean, true} -} - -// FalseValue will return a value representing false. -// -// It is equivalent to: -// -// ToValue(false) -// -func FalseValue() Value { - return Value{valueBoolean, false} -} - -func sameValue(x Value, y Value) bool { - if x.kind != y.kind { - return false - } - result := false - switch x.kind { - case valueUndefined, valueNull: - result = true - case valueNumber: - x := x.float64() - y := y.float64() - 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.string() == y.string() - case valueBoolean: - result = x.bool() == y.bool() - case valueObject: - result = x._object() == y._object() - default: - panic(hereBeDragons()) - } - - return result -} - -func strictEqualityComparison(x Value, y Value) bool { - if x.kind != y.kind { - return false - } - result := false - switch x.kind { - case valueUndefined, valueNull: - result = true - case valueNumber: - x := x.float64() - y := y.float64() - if math.IsNaN(x) && math.IsNaN(y) { - result = false - } else { - result = x == y - } - case valueString: - result = x.string() == y.string() - case valueBoolean: - result = x.bool() == y.bool() - case valueObject: - result = x._object() == y._object() - default: - panic(hereBeDragons()) - } - - return result -} - -// Export will attempt to convert the value to a Go representation -// and return it via an interface{} kind. -// -// Export returns an error, but it will always be nil. It is present -// for backwards compatibility. -// -// If a reasonable conversion is not possible, then the original -// value is returned. -// -// undefined -> nil (FIXME?: Should be Value{}) -// null -> nil -// boolean -> bool -// number -> A number type (int, float32, uint64, ...) -// string -> string -// Array -> []interface{} -// Object -> map[string]interface{} -// -func (self Value) Export() (interface{}, error) { - return self.export(), nil -} - -func (self Value) export() interface{} { - - switch self.kind { - case valueUndefined: - return nil - case valueNull: - return nil - case valueNumber, valueBoolean: - return self.value - case valueString: - switch value := self.value.(type) { - case string: - return value - case []uint16: - return string(utf16.Decode(value)) - } - case valueObject: - object := self._object() - switch value := object.value.(type) { - case *_goStructObject: - return value.value.Interface() - case *_goMapObject: - return value.value.Interface() - case *_goArrayObject: - return value.value.Interface() - case *_goSliceObject: - return value.value.Interface() - } - if object.class == "Array" { - result := make([]interface{}, 0) - lengthValue := object.get("length") - length := lengthValue.value.(uint32) - kind := reflect.Invalid - state := 0 - var t reflect.Type - for index := uint32(0); index < length; index += 1 { - name := strconv.FormatInt(int64(index), 10) - if !object.hasProperty(name) { - continue - } - value := object.get(name).export() - t = reflect.TypeOf(value) - if state == 0 { - kind = t.Kind() - state = 1 - } else if state == 1 && kind != t.Kind() { - state = 2 - } - result = append(result, value) - } - - if state != 1 || kind == reflect.Interface { - // No common type - return result - } - - // Convert to the common type - val := reflect.MakeSlice(reflect.SliceOf(t), len(result), len(result)) - for i, v := range result { - val.Index(i).Set(reflect.ValueOf(v)) - } - return val.Interface() - } else { - result := make(map[string]interface{}) - // TODO Should we export everything? Or just what is enumerable? - object.enumerate(false, func(name string) bool { - value := object.get(name) - if value.IsDefined() { - result[name] = value.export() - } - return true - }) - return result - } - } - - if self.safe() { - return self - } - - return Value{} -} - -func (self Value) evaluateBreakContinue(labels []string) _resultKind { - result := self.value.(_result) - if result.kind == resultBreak || result.kind == resultContinue { - for _, label := range labels { - if label == result.target { - return result.kind - } - } - } - return resultReturn -} - -func (self Value) evaluateBreak(labels []string) _resultKind { - result := self.value.(_result) - if result.kind == resultBreak { - for _, label := range labels { - if label == result.target { - return result.kind - } - } - } - return resultReturn -} - -func (self Value) exportNative() interface{} { - - switch self.kind { - case valueUndefined: - return self - case valueNull: - return nil - case valueNumber, valueBoolean: - return self.value - case valueString: - switch value := self.value.(type) { - case string: - return value - case []uint16: - return string(utf16.Decode(value)) - } - case valueObject: - object := self._object() - switch value := object.value.(type) { - case *_goStructObject: - return value.value.Interface() - case *_goMapObject: - return value.value.Interface() - case *_goArrayObject: - return value.value.Interface() - case *_goSliceObject: - return value.value.Interface() - } - } - - return self -} - -// Make a best effort to return a reflect.Value corresponding to reflect.Kind, but -// fallback to just returning the Go value we have handy. -func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { - if kind != reflect.Float32 && kind != reflect.Float64 && kind != reflect.Interface { - switch value := value.value.(type) { - case float32: - _, frac := math.Modf(float64(value)) - if frac > 0 { - return reflect.Value{}, fmt.Errorf("RangeError: %v to reflect.Kind: %v", value, kind) - } - case float64: - _, frac := math.Modf(value) - if frac > 0 { - return reflect.Value{}, fmt.Errorf("RangeError: %v to reflect.Kind: %v", value, kind) - } - } - } - - switch kind { - case reflect.Bool: // Bool - return reflect.ValueOf(value.bool()), nil - case reflect.Int: // Int - // We convert to float64 here because converting to int64 will not tell us - // if a value is outside the range of int64 - tmp := toIntegerFloat(value) - if tmp < float_minInt || tmp > float_maxInt { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, value) - } else { - return reflect.ValueOf(int(tmp)), nil - } - case reflect.Int8: // Int8 - tmp := value.number().int64 - if tmp < int64_minInt8 || tmp > int64_maxInt8 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int8", tmp, value) - } else { - return reflect.ValueOf(int8(tmp)), nil - } - case reflect.Int16: // Int16 - tmp := value.number().int64 - if tmp < int64_minInt16 || tmp > int64_maxInt16 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int16", tmp, value) - } else { - return reflect.ValueOf(int16(tmp)), nil - } - case reflect.Int32: // Int32 - tmp := value.number().int64 - if tmp < int64_minInt32 || tmp > int64_maxInt32 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int32", tmp, value) - } else { - return reflect.ValueOf(int32(tmp)), nil - } - case reflect.Int64: // Int64 - // We convert to float64 here because converting to int64 will not tell us - // if a value is outside the range of int64 - tmp := toIntegerFloat(value) - if tmp < float_minInt64 || tmp > float_maxInt64 { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, value) - } else { - return reflect.ValueOf(int64(tmp)), nil - } - case reflect.Uint: // Uint - // We convert to float64 here because converting to int64 will not tell us - // if a value is outside the range of uint - tmp := toIntegerFloat(value) - if tmp < 0 || tmp > float_maxUint { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint", tmp, value) - } else { - return reflect.ValueOf(uint(tmp)), nil - } - case reflect.Uint8: // Uint8 - tmp := value.number().int64 - if tmp < 0 || tmp > int64_maxUint8 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint8", tmp, value) - } else { - return reflect.ValueOf(uint8(tmp)), nil - } - case reflect.Uint16: // Uint16 - tmp := value.number().int64 - if tmp < 0 || tmp > int64_maxUint16 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint16", tmp, value) - } else { - return reflect.ValueOf(uint16(tmp)), nil - } - case reflect.Uint32: // Uint32 - tmp := value.number().int64 - if tmp < 0 || tmp > int64_maxUint32 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint32", tmp, value) - } else { - return reflect.ValueOf(uint32(tmp)), nil - } - case reflect.Uint64: // Uint64 - // We convert to float64 here because converting to int64 will not tell us - // if a value is outside the range of uint64 - tmp := toIntegerFloat(value) - if tmp < 0 || tmp > float_maxUint64 { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint64", tmp, value) - } else { - return reflect.ValueOf(uint64(tmp)), nil - } - case reflect.Float32: // Float32 - tmp := value.float64() - tmp1 := tmp - if 0 > tmp1 { - tmp1 = -tmp1 - } - if tmp1 > 0 && (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: // Float64 - value := value.float64() - return reflect.ValueOf(float64(value)), nil - case reflect.String: // String - return reflect.ValueOf(value.string()), nil - case reflect.Invalid: // Invalid - case reflect.Complex64: // FIXME? Complex64 - case reflect.Complex128: // FIXME? Complex128 - case reflect.Chan: // FIXME? Chan - case reflect.Func: // FIXME? Func - case reflect.Ptr: // FIXME? Ptr - case reflect.UnsafePointer: // FIXME? UnsafePointer - default: - switch value.kind { - case valueObject: - object := value._object() - switch vl := object.value.(type) { - case *_goStructObject: // Struct - return reflect.ValueOf(vl.value.Interface()), nil - case *_goMapObject: // Map - return reflect.ValueOf(vl.value.Interface()), nil - case *_goArrayObject: // Array - return reflect.ValueOf(vl.value.Interface()), nil - case *_goSliceObject: // Slice - return reflect.ValueOf(vl.value.Interface()), nil - } - return reflect.ValueOf(value.exportNative()), nil - case valueEmpty, valueResult, valueReference: - // These are invalid, and should panic - default: - return reflect.ValueOf(value.value), nil - } - } - - // FIXME Should this end up as a TypeError? - panic(fmt.Errorf("invalid conversion of %v (%v) to reflect.Kind: %v", value.kind, value, kind)) -} - -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 - } - - // FIXME This should end up as a TypeError? - panic(fmt.Errorf("invalid conversion of %q to reflect.Kind: %v", value, kind)) -} |