1// +build !go1.7 safe appengine
2
3// Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
4// Use of this source code is governed by a MIT license found in the LICENSE file.
5
6package codec
7
8import (
9	"reflect"
10	"sync/atomic"
11	"time"
12)
13
14const safeMode = true
15
16// stringView returns a view of the []byte as a string.
17// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
18// In regular safe mode, it is an allocation and copy.
19//
20// Usage: Always maintain a reference to v while result of this call is in use,
21//        and call keepAlive4BytesView(v) at point where done with view.
22func stringView(v []byte) string {
23	return string(v)
24}
25
26// bytesView returns a view of the string as a []byte.
27// In unsafe mode, it doesn't incur allocation and copying caused by conversion.
28// In regular safe mode, it is an allocation and copy.
29//
30// Usage: Always maintain a reference to v while result of this call is in use,
31//        and call keepAlive4BytesView(v) at point where done with view.
32func bytesView(v string) []byte {
33	return []byte(v)
34}
35
36func definitelyNil(v interface{}) bool {
37	// this is a best-effort option.
38	// We just return false, so we don't unnecessarily incur the cost of reflection this early.
39	return false
40}
41
42func rv2i(rv reflect.Value) interface{} {
43	return rv.Interface()
44}
45
46func rt2id(rt reflect.Type) uintptr {
47	return reflect.ValueOf(rt).Pointer()
48}
49
50func rv2rtid(rv reflect.Value) uintptr {
51	return reflect.ValueOf(rv.Type()).Pointer()
52}
53
54func i2rtid(i interface{}) uintptr {
55	return reflect.ValueOf(reflect.TypeOf(i)).Pointer()
56}
57
58// --------------------------
59
60func isEmptyValue(v reflect.Value, tinfos *TypeInfos, deref, checkStruct bool) bool {
61	switch v.Kind() {
62	case reflect.Invalid:
63		return true
64	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
65		return v.Len() == 0
66	case reflect.Bool:
67		return !v.Bool()
68	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
69		return v.Int() == 0
70	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
71		return v.Uint() == 0
72	case reflect.Float32, reflect.Float64:
73		return v.Float() == 0
74	case reflect.Interface, reflect.Ptr:
75		if deref {
76			if v.IsNil() {
77				return true
78			}
79			return isEmptyValue(v.Elem(), tinfos, deref, checkStruct)
80		}
81		return v.IsNil()
82	case reflect.Struct:
83		return isEmptyStruct(v, tinfos, deref, checkStruct)
84	}
85	return false
86}
87
88// --------------------------
89// type ptrToRvMap struct{}
90
91// func (*ptrToRvMap) init() {}
92// func (*ptrToRvMap) get(i interface{}) reflect.Value {
93// 	return reflect.ValueOf(i).Elem()
94// }
95
96// --------------------------
97type atomicTypeInfoSlice struct { // expected to be 2 words
98	v atomic.Value
99}
100
101func (x *atomicTypeInfoSlice) load() []rtid2ti {
102	i := x.v.Load()
103	if i == nil {
104		return nil
105	}
106	return i.([]rtid2ti)
107}
108
109func (x *atomicTypeInfoSlice) store(p []rtid2ti) {
110	x.v.Store(p)
111}
112
113// --------------------------
114func (d *Decoder) raw(f *codecFnInfo, rv reflect.Value) {
115	rv.SetBytes(d.rawBytes())
116}
117
118func (d *Decoder) kString(f *codecFnInfo, rv reflect.Value) {
119	rv.SetString(d.d.DecodeString())
120}
121
122func (d *Decoder) kBool(f *codecFnInfo, rv reflect.Value) {
123	rv.SetBool(d.d.DecodeBool())
124}
125
126func (d *Decoder) kTime(f *codecFnInfo, rv reflect.Value) {
127	rv.Set(reflect.ValueOf(d.d.DecodeTime()))
128}
129
130func (d *Decoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
131	fv := d.d.DecodeFloat64()
132	if chkOvf.Float32(fv) {
133		d.errorf("float32 overflow: %v", fv)
134	}
135	rv.SetFloat(fv)
136}
137
138func (d *Decoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
139	rv.SetFloat(d.d.DecodeFloat64())
140}
141
142func (d *Decoder) kInt(f *codecFnInfo, rv reflect.Value) {
143	rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), intBitsize))
144}
145
146func (d *Decoder) kInt8(f *codecFnInfo, rv reflect.Value) {
147	rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 8))
148}
149
150func (d *Decoder) kInt16(f *codecFnInfo, rv reflect.Value) {
151	rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 16))
152}
153
154func (d *Decoder) kInt32(f *codecFnInfo, rv reflect.Value) {
155	rv.SetInt(chkOvf.IntV(d.d.DecodeInt64(), 32))
156}
157
158func (d *Decoder) kInt64(f *codecFnInfo, rv reflect.Value) {
159	rv.SetInt(d.d.DecodeInt64())
160}
161
162func (d *Decoder) kUint(f *codecFnInfo, rv reflect.Value) {
163	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
164}
165
166func (d *Decoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
167	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), uintBitsize))
168}
169
170func (d *Decoder) kUint8(f *codecFnInfo, rv reflect.Value) {
171	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 8))
172}
173
174func (d *Decoder) kUint16(f *codecFnInfo, rv reflect.Value) {
175	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 16))
176}
177
178func (d *Decoder) kUint32(f *codecFnInfo, rv reflect.Value) {
179	rv.SetUint(chkOvf.UintV(d.d.DecodeUint64(), 32))
180}
181
182func (d *Decoder) kUint64(f *codecFnInfo, rv reflect.Value) {
183	rv.SetUint(d.d.DecodeUint64())
184}
185
186// ----------------
187
188func (e *Encoder) kBool(f *codecFnInfo, rv reflect.Value) {
189	e.e.EncodeBool(rv.Bool())
190}
191
192func (e *Encoder) kTime(f *codecFnInfo, rv reflect.Value) {
193	e.e.EncodeTime(rv2i(rv).(time.Time))
194}
195
196func (e *Encoder) kString(f *codecFnInfo, rv reflect.Value) {
197	e.e.EncodeString(cUTF8, rv.String())
198}
199
200func (e *Encoder) kFloat64(f *codecFnInfo, rv reflect.Value) {
201	e.e.EncodeFloat64(rv.Float())
202}
203
204func (e *Encoder) kFloat32(f *codecFnInfo, rv reflect.Value) {
205	e.e.EncodeFloat32(float32(rv.Float()))
206}
207
208func (e *Encoder) kInt(f *codecFnInfo, rv reflect.Value) {
209	e.e.EncodeInt(rv.Int())
210}
211
212func (e *Encoder) kInt8(f *codecFnInfo, rv reflect.Value) {
213	e.e.EncodeInt(rv.Int())
214}
215
216func (e *Encoder) kInt16(f *codecFnInfo, rv reflect.Value) {
217	e.e.EncodeInt(rv.Int())
218}
219
220func (e *Encoder) kInt32(f *codecFnInfo, rv reflect.Value) {
221	e.e.EncodeInt(rv.Int())
222}
223
224func (e *Encoder) kInt64(f *codecFnInfo, rv reflect.Value) {
225	e.e.EncodeInt(rv.Int())
226}
227
228func (e *Encoder) kUint(f *codecFnInfo, rv reflect.Value) {
229	e.e.EncodeUint(rv.Uint())
230}
231
232func (e *Encoder) kUint8(f *codecFnInfo, rv reflect.Value) {
233	e.e.EncodeUint(rv.Uint())
234}
235
236func (e *Encoder) kUint16(f *codecFnInfo, rv reflect.Value) {
237	e.e.EncodeUint(rv.Uint())
238}
239
240func (e *Encoder) kUint32(f *codecFnInfo, rv reflect.Value) {
241	e.e.EncodeUint(rv.Uint())
242}
243
244func (e *Encoder) kUint64(f *codecFnInfo, rv reflect.Value) {
245	e.e.EncodeUint(rv.Uint())
246}
247
248func (e *Encoder) kUintptr(f *codecFnInfo, rv reflect.Value) {
249	e.e.EncodeUint(rv.Uint())
250}
251
252// // keepAlive4BytesView maintains a reference to the input parameter for bytesView.
253// //
254// // Usage: call this at point where done with the bytes view.
255// func keepAlive4BytesView(v string) {}
256
257// // keepAlive4BytesView maintains a reference to the input parameter for stringView.
258// //
259// // Usage: call this at point where done with the string view.
260// func keepAlive4StringView(v []byte) {}
261
262// func definitelyNil(v interface{}) bool {
263// 	rv := reflect.ValueOf(v)
264// 	switch rv.Kind() {
265// 	case reflect.Invalid:
266// 		return true
267// 	case reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Slice, reflect.Map, reflect.Func:
268// 		return rv.IsNil()
269// 	default:
270// 		return false
271// 	}
272// }
273