forked from pinguo/pgo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathValue.go
188 lines (168 loc) · 4.55 KB
/
Value.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
package pgo
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"strconv"
"github.com/pinguo/pgo/Util"
)
func NewValue(data interface{}) *Value {
return &Value{data}
}
// Encode encode data to bytes
func Encode(data interface{}) []byte {
v := Value{data}
return v.Encode()
}
// Decode data bytes to ptr
func Decode(data interface{}, ptr interface{}) {
v := Value{data}
v.Decode(ptr)
}
// Value adapter for value of any type,
// provide uniform encoding and decoding.
type Value struct {
data interface{}
}
// Valid check the underlying data is nil
func (v *Value) Valid() bool {
return v.data != nil
}
// TryEncode try encode data, err is not nil if panic
func (v *Value) TryEncode() (output []byte, err error) {
defer func() {
if v := recover(); v != nil {
output, err = nil, errors.New(Util.ToString(v))
}
}()
return v.Encode(), nil
}
// TryDecode try decode data, err is not nil if panic
func (v *Value) TryDecode(ptr interface{}) (err error) {
defer func() {
if v := recover(); v != nil {
err = errors.New(Util.ToString(v))
}
}()
v.Decode(ptr)
return nil
}
// Encode encode data to bytes, panic if failed
func (v *Value) Encode() []byte {
var output []byte
switch d := v.data.(type) {
case []byte:
output = d
case string:
output = []byte(d)
case bool:
output = strconv.AppendBool(output, d)
case float32, float64:
f64 := reflect.ValueOf(v.data).Float()
output = strconv.AppendFloat(output, f64, 'g', -1, 64)
case int, int8, int16, int32, int64:
i64 := reflect.ValueOf(v.data).Int()
output = strconv.AppendInt(output, i64, 10)
case uint, uint8, uint16, uint32, uint64:
u64 := reflect.ValueOf(v.data).Uint()
output = strconv.AppendUint(output, u64, 10)
default:
if j, e := json.Marshal(v.data); e == nil {
output = j
} else {
panic("Value.Encode: " + e.Error())
}
}
return output
}
// Decode decode data bytes to ptr, panic if failed
func (v *Value) Decode(ptr interface{}) {
switch p := ptr.(type) {
case *[]byte:
*p = v.Bytes()
case *string:
*p = v.String()
case *bool:
*p = Util.ToBool(v.data)
case *float32, *float64:
fv := Util.ToFloat(v.data)
rv := reflect.ValueOf(ptr).Elem()
rv.Set(reflect.ValueOf(fv).Convert(rv.Type()))
case *int, *int8, *int16, *int32, *int64:
iv := Util.ToInt(v.data)
rv := reflect.ValueOf(ptr).Elem()
rv.Set(reflect.ValueOf(iv).Convert(rv.Type()))
case *uint, *uint8, *uint16, *uint32, *uint64:
iv := Util.ToInt(v.data)
rv := reflect.ValueOf(ptr).Elem()
rv.Set(reflect.ValueOf(iv).Convert(rv.Type()))
default:
if e := json.Unmarshal(v.Bytes(), ptr); e != nil {
rv := reflect.ValueOf(ptr)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
panic("Value.Decode: require a valid pointer")
}
if rv = rv.Elem(); rv.Kind() == reflect.Interface {
rv.Set(reflect.ValueOf(v.data))
} else {
panic("Value.Decode: " + e.Error())
}
}
}
}
// Data return underlying data
func (v *Value) Data() interface{} {
return v.data
}
// Bool return underlying data as bool
func (v *Value) Bool() bool {
return Util.ToBool(v.data)
}
// Int return underlying data as int
func (v *Value) Int() int {
return Util.ToInt(v.data)
}
// Float return underlying data as float64
func (v *Value) Float() float64 {
return Util.ToFloat(v.data)
}
// String return underlying data as string
func (v *Value) String() string {
switch d := v.data.(type) {
case []byte:
return string(d)
case string:
return d
default:
if j, e := json.Marshal(v.data); e == nil {
return string(j)
}
return fmt.Sprintf("%+v", v.data)
}
}
// Bytes return underlying data as bytes
func (v *Value) Bytes() []byte {
switch d := v.data.(type) {
case []byte:
return d
case string:
return []byte(d)
default:
if j, e := json.Marshal(v.data); e == nil {
return j
}
return []byte(fmt.Sprintf("%+v", v.data))
}
}
func (v *Value) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
func (v *Value) UnmarshalJSON(b []byte) error {
var s string
if e := json.Unmarshal(b, &s); e != nil {
return e
}
v.data = s
return nil
}