func ValueFromString()

in memstore/common/data_value.go [350:503]


func ValueFromString(str string, dataType DataType) (val DataValue, err error) {
	val.DataType = dataType

	if len(str) == 0 || str == "null" {
		return
	}

	var b bool
	var i int64
	var f float64
	var ui uint64

	switch dataType {
	case Bool:
		val.IsBool = true
		b, err = strconv.ParseBool(str)
		if err != nil {
			err = utils.StackError(err, "")
			return
		}
		val.Valid = true
		val.BoolVal = b
		return
	case Int8:
		i, err = strconv.ParseInt(str, 10, 8)
		if err != nil {
			err = utils.StackError(err, "")
			return
		}

		// We need to convert it from i64 to i8 since strconv.ParseXXX
		// always returns the largest bit size value.
		i8 := int8(i)
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&i8)
		return
	case Uint8, SmallEnum:
		ui, err = strconv.ParseUint(str, 10, 8)
		if err != nil {
			err = utils.StackError(err, "")
			return
		}
		ui8 := uint8(ui)
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&ui8)
		return
	case Int16:
		i, err = strconv.ParseInt(str, 10, 16)
		if err != nil {
			err = utils.StackError(err, "")
			return
		}
		i16 := int16(i)
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&i16)
		return
	case Uint16, BigEnum:
		ui, err = strconv.ParseUint(str, 10, 16)
		if err != nil {
			err = utils.StackError(err, "")
			return
		}
		ui16 := uint16(ui)
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&ui16)
		return
	case Int32:
		i, err = strconv.ParseInt(str, 10, 32)
		if err != nil {
			err = utils.StackError(err, "")
			return
		}
		i32 := int32(i)
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&i32)
		return
	case Uint32:
		ui, err = strconv.ParseUint(str, 10, 32)
		if err != nil {
			err = utils.StackError(err, "")
			return
		}
		ui32 := uint32(ui)
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&ui32)
		return
	case Int64:
		i, err = strconv.ParseInt(str, 10, 64)
		if err != nil {
			err = utils.StackError(err, "")
			return
		}
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&i)
		return
	case Float32:
		f, err = strconv.ParseFloat(str, 32)
		if err != nil {
			err = utils.StackError(err, "")
			return
		}
		f32 := float32(f)
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&f32)
		return
	case UUID:
		var uuidBytes []byte
		if strings.HasPrefix(str, "0x") {
			str = str[2:]
		}
		uuidBytes, err = hex.DecodeString(strings.Replace(str, "-", "", -1))
		if err != nil || len(uuidBytes) != 16 {
			err = utils.StackError(err, "Failed to decode uuid string: %s", str)
			return
		}
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&uuidBytes[0])
		return
	case GeoPoint:
		var point [2]float32
		point, err = GeoPointFromString(str)
		if err != nil {
			err = utils.StackError(err, "Failed to read geopoint string: %s", str)
			return
		}
		val.Valid = true
		val.OtherVal = unsafe.Pointer(&point[0])
		return
	default:
		if IsArrayType(dataType) {
			var value interface{}
			value, err = ArrayValueFromString(str, GetElementDataType(dataType))
			if err != nil {
				err = utils.StackError(err, "Failed to read array string: %s", str)
				return
			}
			arrayValue := value.(*ArrayValue)
			bytes := arrayValue.GetSerBytes()
			buffer := make([]byte, bytes)
			valueWriter := utils.NewBufferWriter(buffer)
			err = arrayValue.Write(&valueWriter)
			if err != nil {
				err = utils.StackError(err, "Unable to write array value to buffer: %s", str)
				return
			}

			val.Valid = true
			val.OtherVal = unsafe.Pointer(&buffer[0])
			return
		}
		err = utils.StackError(nil, "Unsupported data type value %#x", dataType)
		return
	}
}