1// Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved. 2// Use of this source code is governed by a MIT license found in the LICENSE file. 3 4package codec 5 6import ( 7 "math/rand" 8 "time" 9) 10 11// NoopHandle returns a no-op handle. It basically does nothing. 12// It is only useful for benchmarking, as it gives an idea of the 13// overhead from the codec framework. 14// 15// LIBRARY USERS: *** DO NOT USE *** 16func NoopHandle(slen int) *noopHandle { 17 h := noopHandle{} 18 h.rand = rand.New(rand.NewSource(time.Now().UnixNano())) 19 h.B = make([][]byte, slen) 20 h.S = make([]string, slen) 21 for i := 0; i < len(h.S); i++ { 22 b := make([]byte, i+1) 23 for j := 0; j < len(b); j++ { 24 b[j] = 'a' + byte(i) 25 } 26 h.B[i] = b 27 h.S[i] = string(b) 28 } 29 return &h 30} 31 32// noopHandle does nothing. 33// It is used to simulate the overhead of the codec framework. 34type noopHandle struct { 35 BasicHandle 36 binaryEncodingType 37 noopDrv // noopDrv is unexported here, so we can get a copy of it when needed. 38} 39 40type noopDrv struct { 41 d *Decoder 42 e *Encoder 43 i int 44 S []string 45 B [][]byte 46 mks []bool // stack. if map (true), else if array (false) 47 mk bool // top of stack. what container are we on? map or array? 48 ct valueType // last response for IsContainerType. 49 cb int // counter for ContainerType 50 rand *rand.Rand 51} 52 53func (h *noopDrv) r(v int) int { return h.rand.Intn(v) } 54func (h *noopDrv) m(v int) int { h.i++; return h.i % v } 55 56func (h *noopDrv) newEncDriver(e *Encoder) encDriver { h.e = e; return h } 57func (h *noopDrv) newDecDriver(d *Decoder) decDriver { h.d = d; return h } 58 59func (h *noopDrv) reset() {} 60func (h *noopDrv) uncacheRead() {} 61 62// --- encDriver 63 64// stack functions (for map and array) 65func (h *noopDrv) start(b bool) { 66 // println("start", len(h.mks)+1) 67 h.mks = append(h.mks, b) 68 h.mk = b 69} 70func (h *noopDrv) end() { 71 // println("end: ", len(h.mks)-1) 72 h.mks = h.mks[:len(h.mks)-1] 73 if len(h.mks) > 0 { 74 h.mk = h.mks[len(h.mks)-1] 75 } else { 76 h.mk = false 77 } 78} 79 80func (h *noopDrv) EncodeBuiltin(rt uintptr, v interface{}) {} 81func (h *noopDrv) EncodeNil() {} 82func (h *noopDrv) EncodeInt(i int64) {} 83func (h *noopDrv) EncodeUint(i uint64) {} 84func (h *noopDrv) EncodeBool(b bool) {} 85func (h *noopDrv) EncodeFloat32(f float32) {} 86func (h *noopDrv) EncodeFloat64(f float64) {} 87func (h *noopDrv) EncodeRawExt(re *RawExt, e *Encoder) {} 88func (h *noopDrv) EncodeArrayStart(length int) { h.start(true) } 89func (h *noopDrv) EncodeMapStart(length int) { h.start(false) } 90func (h *noopDrv) EncodeEnd() { h.end() } 91 92func (h *noopDrv) EncodeString(c charEncoding, v string) {} 93func (h *noopDrv) EncodeSymbol(v string) {} 94func (h *noopDrv) EncodeStringBytes(c charEncoding, v []byte) {} 95 96func (h *noopDrv) EncodeExt(rv interface{}, xtag uint64, ext Ext, e *Encoder) {} 97 98// ---- decDriver 99func (h *noopDrv) initReadNext() {} 100func (h *noopDrv) CheckBreak() bool { return false } 101func (h *noopDrv) IsBuiltinType(rt uintptr) bool { return false } 102func (h *noopDrv) DecodeBuiltin(rt uintptr, v interface{}) {} 103func (h *noopDrv) DecodeInt(bitsize uint8) (i int64) { return int64(h.m(15)) } 104func (h *noopDrv) DecodeUint(bitsize uint8) (ui uint64) { return uint64(h.m(35)) } 105func (h *noopDrv) DecodeFloat(chkOverflow32 bool) (f float64) { return float64(h.m(95)) } 106func (h *noopDrv) DecodeBool() (b bool) { return h.m(2) == 0 } 107func (h *noopDrv) DecodeString() (s string) { return h.S[h.m(8)] } 108 109// func (h *noopDrv) DecodeStringAsBytes(bs []byte) []byte { return h.DecodeBytes(bs) } 110 111func (h *noopDrv) DecodeBytes(bs []byte, isstring, zerocopy bool) []byte { return h.B[h.m(len(h.B))] } 112 113func (h *noopDrv) ReadEnd() { h.end() } 114 115// toggle map/slice 116func (h *noopDrv) ReadMapStart() int { h.start(true); return h.m(10) } 117func (h *noopDrv) ReadArrayStart() int { h.start(false); return h.m(10) } 118 119func (h *noopDrv) ContainerType() (vt valueType) { 120 // return h.m(2) == 0 121 // handle kStruct, which will bomb is it calls this and doesn't get back a map or array. 122 // consequently, if the return value is not map or array, reset it to one of them based on h.m(7) % 2 123 // for kstruct: at least one out of every 2 times, return one of valueTypeMap or Array (else kstruct bombs) 124 // however, every 10th time it is called, we just return something else. 125 var vals = [...]valueType{valueTypeArray, valueTypeMap} 126 // ------------ TAKE ------------ 127 // if h.cb%2 == 0 { 128 // if h.ct == valueTypeMap || h.ct == valueTypeArray { 129 // } else { 130 // h.ct = vals[h.m(2)] 131 // } 132 // } else if h.cb%5 == 0 { 133 // h.ct = valueType(h.m(8)) 134 // } else { 135 // h.ct = vals[h.m(2)] 136 // } 137 // ------------ TAKE ------------ 138 // if h.cb%16 == 0 { 139 // h.ct = valueType(h.cb % 8) 140 // } else { 141 // h.ct = vals[h.cb%2] 142 // } 143 h.ct = vals[h.cb%2] 144 h.cb++ 145 return h.ct 146 147 // if h.ct == valueTypeNil || h.ct == valueTypeString || h.ct == valueTypeBytes { 148 // return h.ct 149 // } 150 // return valueTypeUnset 151 // TODO: may need to tweak this so it works. 152 // if h.ct == valueTypeMap && vt == valueTypeArray || h.ct == valueTypeArray && vt == valueTypeMap { 153 // h.cb = !h.cb 154 // h.ct = vt 155 // return h.cb 156 // } 157 // // go in a loop and check it. 158 // h.ct = vt 159 // h.cb = h.m(7) == 0 160 // return h.cb 161} 162func (h *noopDrv) TryDecodeAsNil() bool { 163 if h.mk { 164 return false 165 } else { 166 return h.m(8) == 0 167 } 168} 169func (h *noopDrv) DecodeExt(rv interface{}, xtag uint64, ext Ext) uint64 { 170 return 0 171} 172 173func (h *noopDrv) DecodeNaked() { 174 // use h.r (random) not h.m() because h.m() could cause the same value to be given. 175 var sk int 176 if h.mk { 177 // if mapkey, do not support values of nil OR bytes, array, map or rawext 178 sk = h.r(7) + 1 179 } else { 180 sk = h.r(12) 181 } 182 n := &h.d.n 183 switch sk { 184 case 0: 185 n.v = valueTypeNil 186 case 1: 187 n.v, n.b = valueTypeBool, false 188 case 2: 189 n.v, n.b = valueTypeBool, true 190 case 3: 191 n.v, n.i = valueTypeInt, h.DecodeInt(64) 192 case 4: 193 n.v, n.u = valueTypeUint, h.DecodeUint(64) 194 case 5: 195 n.v, n.f = valueTypeFloat, h.DecodeFloat(true) 196 case 6: 197 n.v, n.f = valueTypeFloat, h.DecodeFloat(false) 198 case 7: 199 n.v, n.s = valueTypeString, h.DecodeString() 200 case 8: 201 n.v, n.l = valueTypeBytes, h.B[h.m(len(h.B))] 202 case 9: 203 n.v = valueTypeArray 204 case 10: 205 n.v = valueTypeMap 206 default: 207 n.v = valueTypeExt 208 n.u = h.DecodeUint(64) 209 n.l = h.B[h.m(len(h.B))] 210 } 211 h.ct = n.v 212 return 213} 214