/
variant_types.go
148 lines (134 loc) · 3.59 KB
/
variant_types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package search
import (
"encoding/binary"
"errors"
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore/search/model"
"math"
"reflect"
)
type VariantValue []byte
type VariantType byte
const (
// variant type
VT_INTEGER VariantType = 0x0
VT_DOUBLE VariantType = 0x1
VT_BOOLEAN VariantType = 0x2
VT_STRING VariantType = 0x3
)
func ToVariantValue(value interface{}) (VariantValue, error) {
if value == nil {
return nil, errors.New("interface{} should not be nil")
}
t := reflect.TypeOf(value)
switch t.Kind() {
case reflect.String:
return VTString(value.(string)), nil
case reflect.Int:
return VTInteger(int64(value.(int))), nil
case reflect.Int64:
return VTInteger(value.(int64)), nil
case reflect.Float64:
return VTDouble(value.(float64)), nil
case reflect.Bool:
return VTBoolean(value.(bool)), nil
default:
return nil, errors.New("interface{} type must be string/int64/float64.")
}
}
func ForceConvertToDestColumnValue(bytes []byte) (*model.ColumnValue, error) {
if len(bytes) == 0 {
return nil, errors.New("the length of bytes must greater than 0")
}
columnValue := new(model.ColumnValue)
var err error
if bytes[0] == byte(VT_INTEGER) {
columnValue.Value, err = AsInteger(bytes)
if err != nil {
return nil, err
}
columnValue.Type = model.ColumnType_INTEGER
} else if bytes[0] == byte(VT_DOUBLE) {
columnValue.Value, err = AsDouble(bytes)
if err != nil {
return nil, err
}
columnValue.Type = model.ColumnType_DOUBLE
} else if bytes[0] == byte(VT_STRING) {
columnValue.Value, err = AsString(bytes)
if err != nil {
return nil, err
}
columnValue.Type = model.ColumnType_STRING
} else if bytes[0] == byte(VT_BOOLEAN) {
columnValue.Value, err = AsBoolean(bytes)
if err != nil {
return nil, err
}
columnValue.Type = model.ColumnType_BOOLEAN
} else {
return columnValue, errors.New("type must be string/int64/float64/boolean")
}
return columnValue, nil
}
func (v *VariantValue) GetType() VariantType {
return VariantType(([]byte)(*v)[0])
}
func VTInteger(v int64) VariantValue {
buf := make([]byte, 9)
buf[0] = byte(VT_INTEGER)
binary.LittleEndian.PutUint64(buf[1:9], uint64(v))
return (VariantValue)(buf)
}
func AsInteger(bytes []byte) (int64, error) {
if len(bytes) < 9 {
return -1, errors.New("the length of bytes must greater than or equal 9")
}
return int64(binary.LittleEndian.Uint64(bytes[1:9])), nil
}
func VTDouble(v float64) VariantValue {
buf := make([]byte, 9)
buf[0] = byte(VT_DOUBLE)
binary.LittleEndian.PutUint64(buf[1:9], math.Float64bits(v))
return (VariantValue)(buf)
}
func AsDouble(bytes []byte) (float64, error) {
if len(bytes) < 9 {
return 0.0, errors.New("the length of bytes must greater than or equal 9")
}
bits := binary.LittleEndian.Uint64(bytes[1:9])
return math.Float64frombits(bits), nil
}
func VTString(v string) VariantValue {
buf := make([]byte, 5+len(v))
buf[0] = byte(VT_STRING)
binary.LittleEndian.PutUint32(buf[1:5], uint32(len(v)))
copy(buf[5:], v)
return (VariantValue)(buf)
}
func AsString(bytes []byte) (string, error) {
if len(bytes) < 5 {
return "", errors.New("the length of bytes must greater than or equal 5")
}
length := binary.LittleEndian.Uint32(bytes[1:5])
return string(bytes[5 : 5+length]), nil
}
func VTBoolean(b bool) VariantValue {
buf := make([]byte, 2)
buf[0] = byte(VT_BOOLEAN)
if b {
buf[1] = 1
} else {
buf[1] = 0
}
return (VariantValue)(buf)
}
func AsBoolean(bytes []byte) (bool, error) {
if len(bytes) < 2 {
return true, errors.New("the length of bytes must greater than or equal 2")
}
if bytes[1] == 1 {
return true, nil
} else {
return false, nil
}
}