1// Copyright (c) 2012-2018 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"
8	"time"
9)
10
11const bincDoPrune = true // No longer needed. Needed before as C lib did not support pruning.
12
13// vd as low 4 bits (there are 16 slots)
14const (
15	bincVdSpecial byte = iota
16	bincVdPosInt
17	bincVdNegInt
18	bincVdFloat
19
20	bincVdString
21	bincVdByteArray
22	bincVdArray
23	bincVdMap
24
25	bincVdTimestamp
26	bincVdSmallInt
27	bincVdUnicodeOther
28	bincVdSymbol
29
30	bincVdDecimal
31	_               // open slot
32	_               // open slot
33	bincVdCustomExt = 0x0f
34)
35
36const (
37	bincSpNil byte = iota
38	bincSpFalse
39	bincSpTrue
40	bincSpNan
41	bincSpPosInf
42	bincSpNegInf
43	bincSpZeroFloat
44	bincSpZero
45	bincSpNegOne
46)
47
48const (
49	bincFlBin16 byte = iota
50	bincFlBin32
51	_ // bincFlBin32e
52	bincFlBin64
53	_ // bincFlBin64e
54	// others not currently supported
55)
56
57func bincdesc(vd, vs byte) string {
58	switch vd {
59	case bincVdSpecial:
60		switch vs {
61		case bincSpNil:
62			return "nil"
63		case bincSpFalse:
64			return "false"
65		case bincSpTrue:
66			return "true"
67		case bincSpNan, bincSpPosInf, bincSpNegInf, bincSpZeroFloat:
68			return "float"
69		case bincSpZero:
70			return "uint"
71		case bincSpNegOne:
72			return "int"
73		default:
74			return "unknown"
75		}
76	case bincVdSmallInt, bincVdPosInt:
77		return "uint"
78	case bincVdNegInt:
79		return "int"
80	case bincVdFloat:
81		return "float"
82	case bincVdSymbol:
83		return "string"
84	case bincVdString:
85		return "string"
86	case bincVdByteArray:
87		return "bytes"
88	case bincVdTimestamp:
89		return "time"
90	case bincVdCustomExt:
91		return "ext"
92	case bincVdArray:
93		return "array"
94	case bincVdMap:
95		return "map"
96	default:
97		return "unknown"
98	}
99}
100
101type bincEncDriver struct {
102	noBuiltInTypes
103	encDriverNoopContainerWriter
104	h *BincHandle
105	m map[string]uint16 // symbols
106	b [8]byte           // scratch, used for encoding numbers - bigendian style
107	s uint16            // symbols sequencer
108	_ [4]uint64         // padding
109	e Encoder
110}
111
112func (e *bincEncDriver) encoder() *Encoder {
113	return &e.e
114}
115
116func (e *bincEncDriver) EncodeNil() {
117	e.e.encWr.writen1(bincVdSpecial<<4 | bincSpNil)
118}
119
120func (e *bincEncDriver) EncodeTime(t time.Time) {
121	if t.IsZero() {
122		e.EncodeNil()
123	} else {
124		bs := bincEncodeTime(t)
125		e.e.encWr.writen1(bincVdTimestamp<<4 | uint8(len(bs)))
126		e.e.encWr.writeb(bs)
127	}
128}
129
130func (e *bincEncDriver) EncodeBool(b bool) {
131	if b {
132		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpTrue)
133	} else {
134		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpFalse)
135	}
136}
137
138func (e *bincEncDriver) EncodeFloat32(f float32) {
139	if f == 0 {
140		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
141		return
142	}
143	e.e.encWr.writen1(bincVdFloat<<4 | bincFlBin32)
144	bigenHelper{e.b[:4], e.e.w()}.writeUint32(math.Float32bits(f))
145}
146
147func (e *bincEncDriver) EncodeFloat64(f float64) {
148	if f == 0 {
149		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpZeroFloat)
150		return
151	}
152	bigen.PutUint64(e.b[:8], math.Float64bits(f))
153	if bincDoPrune {
154		i := 7
155		for ; i >= 0 && (e.b[i] == 0); i-- {
156		}
157		i++
158		if i <= 6 {
159			e.e.encWr.writen1(bincVdFloat<<4 | 0x8 | bincFlBin64)
160			e.e.encWr.writen1(byte(i))
161			e.e.encWr.writeb(e.b[:i])
162			return
163		}
164	}
165	e.e.encWr.writen1(bincVdFloat<<4 | bincFlBin64)
166	e.e.encWr.writeb(e.b[:8])
167}
168
169func (e *bincEncDriver) encIntegerPrune(bd byte, pos bool, v uint64, lim uint8) {
170	if lim == 4 {
171		bigen.PutUint32(e.b[:lim], uint32(v))
172	} else {
173		bigen.PutUint64(e.b[:lim], v)
174	}
175	if bincDoPrune {
176		i := pruneSignExt(e.b[:lim], pos)
177		e.e.encWr.writen1(bd | lim - 1 - byte(i))
178		e.e.encWr.writeb(e.b[i:lim])
179	} else {
180		e.e.encWr.writen1(bd | lim - 1)
181		e.e.encWr.writeb(e.b[:lim])
182	}
183}
184
185func (e *bincEncDriver) EncodeInt(v int64) {
186	// const nbd byte = bincVdNegInt << 4
187	if v >= 0 {
188		e.encUint(bincVdPosInt<<4, true, uint64(v))
189	} else if v == -1 {
190		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpNegOne)
191	} else {
192		e.encUint(bincVdNegInt<<4, false, uint64(-v))
193	}
194}
195
196func (e *bincEncDriver) EncodeUint(v uint64) {
197	e.encUint(bincVdPosInt<<4, true, v)
198}
199
200func (e *bincEncDriver) encUint(bd byte, pos bool, v uint64) {
201	if v == 0 {
202		e.e.encWr.writen1(bincVdSpecial<<4 | bincSpZero)
203	} else if pos && v >= 1 && v <= 16 {
204		e.e.encWr.writen1(bincVdSmallInt<<4 | byte(v-1))
205	} else if v <= math.MaxUint8 {
206		e.e.encWr.writen2(bd|0x0, byte(v))
207	} else if v <= math.MaxUint16 {
208		e.e.encWr.writen1(bd | 0x01)
209		bigenHelper{e.b[:2], e.e.w()}.writeUint16(uint16(v))
210	} else if v <= math.MaxUint32 {
211		e.encIntegerPrune(bd, pos, v, 4)
212	} else {
213		e.encIntegerPrune(bd, pos, v, 8)
214	}
215}
216
217func (e *bincEncDriver) EncodeExt(v interface{}, xtag uint64, ext Ext) {
218	var bs []byte
219	if ext == SelfExt {
220		bs = e.e.blist.get(1024)[:0]
221		e.e.sideEncode(v, &bs)
222	} else {
223		bs = ext.WriteExt(v)
224	}
225	if bs == nil {
226		e.EncodeNil()
227		return
228	}
229	e.encodeExtPreamble(uint8(xtag), len(bs))
230	e.e.encWr.writeb(bs)
231	if ext == SelfExt {
232		e.e.blist.put(bs)
233	}
234}
235
236func (e *bincEncDriver) EncodeRawExt(re *RawExt) {
237	e.encodeExtPreamble(uint8(re.Tag), len(re.Data))
238	e.e.encWr.writeb(re.Data)
239}
240
241func (e *bincEncDriver) encodeExtPreamble(xtag byte, length int) {
242	e.encLen(bincVdCustomExt<<4, uint64(length))
243	e.e.encWr.writen1(xtag)
244}
245
246func (e *bincEncDriver) WriteArrayStart(length int) {
247	e.encLen(bincVdArray<<4, uint64(length))
248}
249
250func (e *bincEncDriver) WriteMapStart(length int) {
251	e.encLen(bincVdMap<<4, uint64(length))
252}
253
254func (e *bincEncDriver) EncodeSymbol(v string) {
255	// if WriteSymbolsNoRefs {
256	// 	e.encodeString(cUTF8, v)
257	// 	return
258	// }
259
260	//symbols only offer benefit when string length > 1.
261	//This is because strings with length 1 take only 2 bytes to store
262	//(bd with embedded length, and single byte for string val).
263
264	l := len(v)
265	if l == 0 {
266		e.encBytesLen(cUTF8, 0)
267		return
268	} else if l == 1 {
269		e.encBytesLen(cUTF8, 1)
270		e.e.encWr.writen1(v[0])
271		return
272	}
273	if e.m == nil {
274		e.m = make(map[string]uint16, 16)
275	}
276	ui, ok := e.m[v]
277	if ok {
278		if ui <= math.MaxUint8 {
279			e.e.encWr.writen2(bincVdSymbol<<4, byte(ui))
280		} else {
281			e.e.encWr.writen1(bincVdSymbol<<4 | 0x8)
282			bigenHelper{e.b[:2], e.e.w()}.writeUint16(ui)
283		}
284	} else {
285		e.s++
286		ui = e.s
287		//ui = uint16(atomic.AddUint32(&e.s, 1))
288		e.m[v] = ui
289		var lenprec uint8
290		if l <= math.MaxUint8 {
291			// lenprec = 0
292		} else if l <= math.MaxUint16 {
293			lenprec = 1
294		} else if int64(l) <= math.MaxUint32 {
295			lenprec = 2
296		} else {
297			lenprec = 3
298		}
299		if ui <= math.MaxUint8 {
300			e.e.encWr.writen2(bincVdSymbol<<4|0x0|0x4|lenprec, byte(ui))
301		} else {
302			e.e.encWr.writen1(bincVdSymbol<<4 | 0x8 | 0x4 | lenprec)
303			bigenHelper{e.b[:2], e.e.w()}.writeUint16(ui)
304		}
305		if lenprec == 0 {
306			e.e.encWr.writen1(byte(l))
307		} else if lenprec == 1 {
308			bigenHelper{e.b[:2], e.e.w()}.writeUint16(uint16(l))
309		} else if lenprec == 2 {
310			bigenHelper{e.b[:4], e.e.w()}.writeUint32(uint32(l))
311		} else {
312			bigenHelper{e.b[:8], e.e.w()}.writeUint64(uint64(l))
313		}
314		e.e.encWr.writestr(v)
315	}
316}
317
318func (e *bincEncDriver) EncodeString(v string) {
319	if e.h.StringToRaw {
320		e.encLen(bincVdByteArray<<4, uint64(len(v))) // e.encBytesLen(c, l)
321		if len(v) > 0 {
322			e.e.encWr.writestr(v)
323		}
324		return
325	}
326	e.EncodeStringEnc(cUTF8, v)
327}
328
329func (e *bincEncDriver) EncodeStringEnc(c charEncoding, v string) {
330	if e.e.c == containerMapKey && c == cUTF8 && (e.h.AsSymbols == 1) {
331		e.EncodeSymbol(v)
332		return
333	}
334	e.encLen(bincVdString<<4, uint64(len(v))) // e.encBytesLen(c, l)
335	if len(v) > 0 {
336		e.e.encWr.writestr(v)
337	}
338}
339
340func (e *bincEncDriver) EncodeStringBytesRaw(v []byte) {
341	if v == nil {
342		e.EncodeNil()
343		return
344	}
345	e.encLen(bincVdByteArray<<4, uint64(len(v))) // e.encBytesLen(c, l)
346	if len(v) > 0 {
347		e.e.encWr.writeb(v)
348	}
349}
350
351func (e *bincEncDriver) encBytesLen(c charEncoding, length uint64) {
352	// NOTE: we currently only support UTF-8 (string) and RAW (bytearray).
353	// We should consider supporting bincUnicodeOther.
354
355	if c == cRAW {
356		e.encLen(bincVdByteArray<<4, length)
357	} else {
358		e.encLen(bincVdString<<4, length)
359	}
360}
361
362func (e *bincEncDriver) encLen(bd byte, l uint64) {
363	if l < 12 {
364		e.e.encWr.writen1(bd | uint8(l+4))
365	} else {
366		e.encLenNumber(bd, l)
367	}
368}
369
370func (e *bincEncDriver) encLenNumber(bd byte, v uint64) {
371	if v <= math.MaxUint8 {
372		e.e.encWr.writen2(bd, byte(v))
373	} else if v <= math.MaxUint16 {
374		e.e.encWr.writen1(bd | 0x01)
375		bigenHelper{e.b[:2], e.e.w()}.writeUint16(uint16(v))
376	} else if v <= math.MaxUint32 {
377		e.e.encWr.writen1(bd | 0x02)
378		bigenHelper{e.b[:4], e.e.w()}.writeUint32(uint32(v))
379	} else {
380		e.e.encWr.writen1(bd | 0x03)
381		bigenHelper{e.b[:8], e.e.w()}.writeUint64(uint64(v))
382	}
383}
384
385//------------------------------------
386
387type bincDecDriver struct {
388	decDriverNoopContainerReader
389	noBuiltInTypes
390
391	h      *BincHandle
392	bdRead bool
393	bd     byte
394	vd     byte
395	vs     byte
396
397	fnil bool
398	// _      [3]byte // padding
399	// linear searching on this slice is ok,
400	// because we typically expect < 32 symbols in each stream.
401	s map[uint16][]byte // []bincDecSymbol
402
403	b [8]byte   // scratch for decoding numbers - big endian style
404	_ [4]uint64 // padding cache-aligned
405
406	d Decoder
407}
408
409func (d *bincDecDriver) decoder() *Decoder {
410	return &d.d
411}
412
413func (d *bincDecDriver) readNextBd() {
414	d.bd = d.d.decRd.readn1()
415	d.vd = d.bd >> 4
416	d.vs = d.bd & 0x0f
417	d.bdRead = true
418}
419
420func (d *bincDecDriver) uncacheRead() {
421	if d.bdRead {
422		d.d.decRd.unreadn1()
423		d.bdRead = false
424	}
425}
426
427func (d *bincDecDriver) advanceNil() (null bool) {
428	d.fnil = false
429	if !d.bdRead {
430		d.readNextBd()
431	}
432	if d.bd == bincVdSpecial<<4|bincSpNil {
433		d.bdRead = false
434		d.fnil = true
435		null = true
436	}
437	return
438}
439
440func (d *bincDecDriver) Nil() bool {
441	return d.fnil
442}
443
444func (d *bincDecDriver) TryNil() bool {
445	return d.advanceNil()
446}
447
448func (d *bincDecDriver) ContainerType() (vt valueType) {
449	if !d.bdRead {
450		d.readNextBd()
451	}
452	d.fnil = false
453	// if d.vd == bincVdSpecial && d.vs == bincSpNil {
454	if d.bd == bincVdSpecial<<4|bincSpNil {
455		d.bdRead = false
456		d.fnil = true
457		return valueTypeNil
458	} else if d.vd == bincVdByteArray {
459		return valueTypeBytes
460	} else if d.vd == bincVdString {
461		return valueTypeString
462	} else if d.vd == bincVdArray {
463		return valueTypeArray
464	} else if d.vd == bincVdMap {
465		return valueTypeMap
466	}
467	return valueTypeUnset
468}
469
470func (d *bincDecDriver) DecodeTime() (t time.Time) {
471	if d.advanceNil() {
472		return
473	}
474	if d.vd != bincVdTimestamp {
475		d.d.errorf("cannot decode time - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
476		return
477	}
478	t, err := bincDecodeTime(d.d.decRd.readx(uint(d.vs)))
479	if err != nil {
480		panic(err)
481	}
482	d.bdRead = false
483	return
484}
485
486func (d *bincDecDriver) decFloatPre(vs, defaultLen byte) {
487	if vs&0x8 == 0 {
488		d.d.decRd.readb(d.b[0:defaultLen])
489	} else {
490		l := d.d.decRd.readn1()
491		if l > 8 {
492			d.d.errorf("cannot read float - at most 8 bytes used to represent float - received %v bytes", l)
493			return
494		}
495		for i := l; i < 8; i++ {
496			d.b[i] = 0
497		}
498		d.d.decRd.readb(d.b[0:l])
499	}
500}
501
502func (d *bincDecDriver) decFloat() (f float64) {
503	//if true { f = math.Float64frombits(bigen.Uint64(d.d.decRd.readx(8))); break; }
504	if x := d.vs & 0x7; x == bincFlBin32 {
505		d.decFloatPre(d.vs, 4)
506		f = float64(math.Float32frombits(bigen.Uint32(d.b[0:4])))
507	} else if x == bincFlBin64 {
508		d.decFloatPre(d.vs, 8)
509		f = math.Float64frombits(bigen.Uint64(d.b[0:8]))
510	} else {
511		d.d.errorf("read float - only float32 and float64 are supported - %s %x-%x/%s",
512			msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
513		return
514	}
515	return
516}
517
518func (d *bincDecDriver) decUint() (v uint64) {
519	// need to inline the code (interface conversion and type assertion expensive)
520	switch d.vs {
521	case 0:
522		v = uint64(d.d.decRd.readn1())
523	case 1:
524		d.d.decRd.readb(d.b[6:8])
525		v = uint64(bigen.Uint16(d.b[6:8]))
526	case 2:
527		d.b[4] = 0
528		d.d.decRd.readb(d.b[5:8])
529		v = uint64(bigen.Uint32(d.b[4:8]))
530	case 3:
531		d.d.decRd.readb(d.b[4:8])
532		v = uint64(bigen.Uint32(d.b[4:8]))
533	case 4, 5, 6:
534		lim := 7 - d.vs
535		d.d.decRd.readb(d.b[lim:8])
536		for i := uint8(0); i < lim; i++ {
537			d.b[i] = 0
538		}
539		v = uint64(bigen.Uint64(d.b[:8]))
540	case 7:
541		d.d.decRd.readb(d.b[:8])
542		v = uint64(bigen.Uint64(d.b[:8]))
543	default:
544		d.d.errorf("unsigned integers with greater than 64 bits of precision not supported")
545		return
546	}
547	return
548}
549
550func (d *bincDecDriver) decCheckInteger() (ui uint64, neg bool) {
551	vd, vs := d.vd, d.vs
552	if vd == bincVdPosInt {
553		ui = d.decUint()
554	} else if vd == bincVdNegInt {
555		ui = d.decUint()
556		neg = true
557	} else if vd == bincVdSmallInt {
558		ui = uint64(d.vs) + 1
559	} else if vd == bincVdSpecial {
560		if vs == bincSpZero {
561			//i = 0
562		} else if vs == bincSpNegOne {
563			neg = true
564			ui = 1
565		} else {
566			d.d.errorf("integer decode fails - invalid special value from descriptor %x-%x/%s",
567				d.vd, d.vs, bincdesc(d.vd, d.vs))
568			return
569		}
570	} else {
571		d.d.errorf("integer can only be decoded from int/uint. d.bd: 0x%x, d.vd: 0x%x", d.bd, d.vd)
572		return
573	}
574	return
575}
576
577func (d *bincDecDriver) DecodeInt64() (i int64) {
578	if d.advanceNil() {
579		return
580	}
581	ui, neg := d.decCheckInteger()
582	i = chkOvf.SignedIntV(ui)
583	if neg {
584		i = -i
585	}
586	d.bdRead = false
587	return
588}
589
590func (d *bincDecDriver) DecodeUint64() (ui uint64) {
591	if d.advanceNil() {
592		return
593	}
594	ui, neg := d.decCheckInteger()
595	if neg {
596		d.d.errorf("assigning negative signed value to unsigned integer type")
597		return
598	}
599	d.bdRead = false
600	return
601}
602
603func (d *bincDecDriver) DecodeFloat64() (f float64) {
604	if d.advanceNil() {
605		return
606	}
607	vd, vs := d.vd, d.vs
608	if vd == bincVdSpecial {
609		d.bdRead = false
610		if vs == bincSpNan {
611			return math.NaN()
612		} else if vs == bincSpPosInf {
613			return math.Inf(1)
614		} else if vs == bincSpZeroFloat || vs == bincSpZero {
615			return
616		} else if vs == bincSpNegInf {
617			return math.Inf(-1)
618		} else {
619			d.d.errorf("float - invalid special value from descriptor %x-%x/%s",
620				d.vd, d.vs, bincdesc(d.vd, d.vs))
621			return
622		}
623	} else if vd == bincVdFloat {
624		f = d.decFloat()
625	} else {
626		f = float64(d.DecodeInt64())
627	}
628	d.bdRead = false
629	return
630}
631
632// bool can be decoded from bool only (single byte).
633func (d *bincDecDriver) DecodeBool() (b bool) {
634	if d.advanceNil() {
635		return
636	}
637	if d.bd == (bincVdSpecial | bincSpFalse) {
638		// b = false
639	} else if d.bd == (bincVdSpecial | bincSpTrue) {
640		b = true
641	} else {
642		d.d.errorf("bool - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
643		return
644	}
645	d.bdRead = false
646	return
647}
648
649func (d *bincDecDriver) ReadMapStart() (length int) {
650	if d.advanceNil() {
651		return decContainerLenNil
652	}
653	if d.vd != bincVdMap {
654		d.d.errorf("map - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
655		return
656	}
657	length = d.decLen()
658	d.bdRead = false
659	return
660}
661
662func (d *bincDecDriver) ReadArrayStart() (length int) {
663	if d.advanceNil() {
664		return decContainerLenNil
665	}
666	if d.vd != bincVdArray {
667		d.d.errorf("array - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
668		return
669	}
670	length = d.decLen()
671	d.bdRead = false
672	return
673}
674
675func (d *bincDecDriver) decLen() int {
676	if d.vs > 3 {
677		return int(d.vs - 4)
678	}
679	return int(d.decLenNumber())
680}
681
682func (d *bincDecDriver) decLenNumber() (v uint64) {
683	if x := d.vs; x == 0 {
684		v = uint64(d.d.decRd.readn1())
685	} else if x == 1 {
686		d.d.decRd.readb(d.b[6:8])
687		v = uint64(bigen.Uint16(d.b[6:8]))
688	} else if x == 2 {
689		d.d.decRd.readb(d.b[4:8])
690		v = uint64(bigen.Uint32(d.b[4:8]))
691	} else {
692		d.d.decRd.readb(d.b[:8])
693		v = bigen.Uint64(d.b[:8])
694	}
695	return
696}
697
698func (d *bincDecDriver) decStringBytes(bs []byte, zerocopy bool) (bs2 []byte) {
699	if d.advanceNil() {
700		return
701	}
702	var slen = -1
703	// var ok bool
704	switch d.vd {
705	case bincVdString, bincVdByteArray:
706		slen = d.decLen()
707		if zerocopy {
708			if d.d.bytes {
709				bs2 = d.d.decRd.readx(uint(slen))
710			} else if len(bs) == 0 {
711				bs2 = decByteSlice(d.d.r(), slen, d.d.h.MaxInitLen, d.d.b[:])
712			} else {
713				bs2 = decByteSlice(d.d.r(), slen, d.d.h.MaxInitLen, bs)
714			}
715		} else {
716			bs2 = decByteSlice(d.d.r(), slen, d.d.h.MaxInitLen, bs)
717		}
718	case bincVdSymbol:
719		// zerocopy doesn't apply for symbols,
720		// as the values must be stored in a table for later use.
721		//
722		//from vs: extract numSymbolBytes, containsStringVal, strLenPrecision,
723		//extract symbol
724		//if containsStringVal, read it and put in map
725		//else look in map for string value
726		var symbol uint16
727		vs := d.vs
728		if vs&0x8 == 0 {
729			symbol = uint16(d.d.decRd.readn1())
730		} else {
731			symbol = uint16(bigen.Uint16(d.d.decRd.readx(2)))
732		}
733		if d.s == nil {
734			// d.s = pool4mapU16Bytes.Get().(map[uint16][]byte) // make([]bincDecSymbol, 0, 16)
735			d.s = make(map[uint16][]byte, 16)
736		}
737
738		if vs&0x4 == 0 {
739			bs2 = d.s[symbol]
740		} else {
741			switch vs & 0x3 {
742			case 0:
743				slen = int(d.d.decRd.readn1())
744			case 1:
745				slen = int(bigen.Uint16(d.d.decRd.readx(2)))
746			case 2:
747				slen = int(bigen.Uint32(d.d.decRd.readx(4)))
748			case 3:
749				slen = int(bigen.Uint64(d.d.decRd.readx(8)))
750			}
751			// since using symbols, do not store any part of
752			// the parameter bs in the map, as it might be a shared buffer.
753			// bs2 = decByteSlice(d.d.r(), slen, bs)
754			bs2 = decByteSlice(d.d.r(), slen, d.d.h.MaxInitLen, nil)
755			d.s[symbol] = bs2
756			// d.s = append(d.s, bincDecSymbol{i: symbol, s: s, b: bs2})
757		}
758	default:
759		d.d.errorf("string/bytes - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
760		return
761	}
762	d.bdRead = false
763	return
764}
765
766func (d *bincDecDriver) DecodeStringAsBytes() (s []byte) {
767	return d.decStringBytes(d.d.b[:], true)
768}
769
770func (d *bincDecDriver) DecodeBytes(bs []byte, zerocopy bool) (bsOut []byte) {
771	if d.advanceNil() {
772		return
773	}
774	// check if an "array" of uint8's (see ContainerType for how to infer if an array)
775	if d.vd == bincVdArray {
776		if zerocopy && len(bs) == 0 {
777			bs = d.d.b[:]
778		}
779		// bsOut, _ = fastpathTV.DecSliceUint8V(bs, true, d.d)
780		slen := d.ReadArrayStart()
781		bs = usableByteSlice(bs, slen)
782		for i := 0; i < slen; i++ {
783			bs[i] = uint8(chkOvf.UintV(d.DecodeUint64(), 8))
784		}
785		return bs
786	}
787	var clen int
788	if d.vd == bincVdString || d.vd == bincVdByteArray {
789		clen = d.decLen()
790	} else {
791		d.d.errorf("bytes - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
792		return
793	}
794	d.bdRead = false
795	if zerocopy {
796		if d.d.bytes {
797			return d.d.decRd.readx(uint(clen))
798		} else if len(bs) == 0 {
799			bs = d.d.b[:]
800		}
801	}
802	return decByteSlice(d.d.r(), clen, d.d.h.MaxInitLen, bs)
803}
804
805func (d *bincDecDriver) DecodeExt(rv interface{}, xtag uint64, ext Ext) {
806	if xtag > 0xff {
807		d.d.errorf("ext: tag must be <= 0xff; got: %v", xtag)
808		return
809	}
810	if d.advanceNil() {
811		return
812	}
813	realxtag1, xbs := d.decodeExtV(ext != nil, uint8(xtag))
814	realxtag := uint64(realxtag1)
815	if ext == nil {
816		re := rv.(*RawExt)
817		re.Tag = realxtag
818		re.Data = detachZeroCopyBytes(d.d.bytes, re.Data, xbs)
819	} else if ext == SelfExt {
820		d.d.sideDecode(rv, xbs)
821	} else {
822		ext.ReadExt(rv, xbs)
823	}
824}
825
826func (d *bincDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs []byte) {
827	if d.vd == bincVdCustomExt {
828		l := d.decLen()
829		xtag = d.d.decRd.readn1()
830		if verifyTag && xtag != tag {
831			d.d.errorf("wrong extension tag - got %b, expecting: %v", xtag, tag)
832			return
833		}
834		if d.d.bytes {
835			xbs = d.d.decRd.readx(uint(l))
836		} else {
837			xbs = decByteSlice(d.d.r(), l, d.d.h.MaxInitLen, d.d.b[:])
838		}
839	} else if d.vd == bincVdByteArray {
840		xbs = d.DecodeBytes(nil, true)
841	} else {
842		d.d.errorf("ext - expecting extensions or byte array - %s %x-%x/%s",
843			msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
844		return
845	}
846	d.bdRead = false
847	return
848}
849
850func (d *bincDecDriver) DecodeNaked() {
851	if !d.bdRead {
852		d.readNextBd()
853	}
854
855	d.fnil = false
856	n := d.d.naked()
857	var decodeFurther bool
858
859	switch d.vd {
860	case bincVdSpecial:
861		switch d.vs {
862		case bincSpNil:
863			n.v = valueTypeNil
864			d.fnil = true
865		case bincSpFalse:
866			n.v = valueTypeBool
867			n.b = false
868		case bincSpTrue:
869			n.v = valueTypeBool
870			n.b = true
871		case bincSpNan:
872			n.v = valueTypeFloat
873			n.f = math.NaN()
874		case bincSpPosInf:
875			n.v = valueTypeFloat
876			n.f = math.Inf(1)
877		case bincSpNegInf:
878			n.v = valueTypeFloat
879			n.f = math.Inf(-1)
880		case bincSpZeroFloat:
881			n.v = valueTypeFloat
882			n.f = float64(0)
883		case bincSpZero:
884			n.v = valueTypeUint
885			n.u = uint64(0) // int8(0)
886		case bincSpNegOne:
887			n.v = valueTypeInt
888			n.i = int64(-1) // int8(-1)
889		default:
890			d.d.errorf("cannot infer value - unrecognized special value from descriptor %x-%x/%s",
891				d.vd, d.vs, bincdesc(d.vd, d.vs))
892		}
893	case bincVdSmallInt:
894		n.v = valueTypeUint
895		n.u = uint64(int8(d.vs)) + 1 // int8(d.vs) + 1
896	case bincVdPosInt:
897		n.v = valueTypeUint
898		n.u = d.decUint()
899	case bincVdNegInt:
900		n.v = valueTypeInt
901		n.i = -(int64(d.decUint()))
902	case bincVdFloat:
903		n.v = valueTypeFloat
904		n.f = d.decFloat()
905	case bincVdSymbol:
906		n.v = valueTypeSymbol
907		n.s = string(d.DecodeStringAsBytes())
908	case bincVdString:
909		n.v = valueTypeString
910		n.s = string(d.DecodeStringAsBytes())
911	case bincVdByteArray:
912		decNakedReadRawBytes(d, &d.d, n, d.h.RawToString)
913	case bincVdTimestamp:
914		n.v = valueTypeTime
915		tt, err := bincDecodeTime(d.d.decRd.readx(uint(d.vs)))
916		if err != nil {
917			panic(err)
918		}
919		n.t = tt
920	case bincVdCustomExt:
921		n.v = valueTypeExt
922		l := d.decLen()
923		n.u = uint64(d.d.decRd.readn1())
924		if d.d.bytes {
925			n.l = d.d.decRd.readx(uint(l))
926		} else {
927			n.l = decByteSlice(d.d.r(), l, d.d.h.MaxInitLen, d.d.b[:])
928		}
929	case bincVdArray:
930		n.v = valueTypeArray
931		decodeFurther = true
932	case bincVdMap:
933		n.v = valueTypeMap
934		decodeFurther = true
935	default:
936		d.d.errorf("cannot infer value - %s %x-%x/%s", msgBadDesc, d.vd, d.vs, bincdesc(d.vd, d.vs))
937	}
938
939	if !decodeFurther {
940		d.bdRead = false
941	}
942	if n.v == valueTypeUint && d.h.SignedInteger {
943		n.v = valueTypeInt
944		n.i = int64(n.u)
945	}
946}
947
948//------------------------------------
949
950//BincHandle is a Handle for the Binc Schema-Free Encoding Format
951//defined at https://github.com/ugorji/binc .
952//
953//BincHandle currently supports all Binc features with the following EXCEPTIONS:
954//  - only integers up to 64 bits of precision are supported.
955//    big integers are unsupported.
956//  - Only IEEE 754 binary32 and binary64 floats are supported (ie Go float32 and float64 types).
957//    extended precision and decimal IEEE 754 floats are unsupported.
958//  - Only UTF-8 strings supported.
959//    Unicode_Other Binc types (UTF16, UTF32) are currently unsupported.
960//
961//Note that these EXCEPTIONS are temporary and full support is possible and may happen soon.
962type BincHandle struct {
963	BasicHandle
964	binaryEncodingType
965	// noElemSeparators
966
967	// AsSymbols defines what should be encoded as symbols.
968	//
969	// Encoding as symbols can reduce the encoded size significantly.
970	//
971	// However, during decoding, each string to be encoded as a symbol must
972	// be checked to see if it has been seen before. Consequently, encoding time
973	// will increase if using symbols, because string comparisons has a clear cost.
974	//
975	// Values:
976	// - 0: default: library uses best judgement
977	// - 1: use symbols
978	// - 2: do not use symbols
979	AsSymbols uint8
980
981	// AsSymbols: may later on introduce more options ...
982	// - m: map keys
983	// - s: struct fields
984	// - n: none
985	// - a: all: same as m, s, ...
986
987	_ [7]uint64 // padding (cache-aligned)
988}
989
990// Name returns the name of the handle: binc
991func (h *BincHandle) Name() string { return "binc" }
992
993func (h *BincHandle) newEncDriver() encDriver {
994	var e = &bincEncDriver{h: h}
995	e.e.e = e
996	e.e.init(h)
997	e.reset()
998	return e
999}
1000
1001func (h *BincHandle) newDecDriver() decDriver {
1002	d := &bincDecDriver{h: h}
1003	d.d.d = d
1004	d.d.init(h)
1005	d.reset()
1006	return d
1007}
1008
1009func (e *bincEncDriver) reset() {
1010	e.s = 0
1011	e.m = nil
1012}
1013
1014func (e *bincEncDriver) atEndOfEncode() {
1015	if e.m != nil {
1016		for k := range e.m {
1017			delete(e.m, k)
1018		}
1019	}
1020}
1021
1022func (d *bincDecDriver) reset() {
1023	d.s = nil
1024	d.bd, d.bdRead, d.vd, d.vs = 0, false, 0, 0
1025	d.fnil = false
1026}
1027
1028func (d *bincDecDriver) atEndOfDecode() {
1029	if d.s != nil {
1030		for k := range d.s {
1031			delete(d.s, k)
1032		}
1033	}
1034}
1035
1036// var timeDigits = [...]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
1037
1038// EncodeTime encodes a time.Time as a []byte, including
1039// information on the instant in time and UTC offset.
1040//
1041// Format Description
1042//
1043//   A timestamp is composed of 3 components:
1044//
1045//   - secs: signed integer representing seconds since unix epoch
1046//   - nsces: unsigned integer representing fractional seconds as a
1047//     nanosecond offset within secs, in the range 0 <= nsecs < 1e9
1048//   - tz: signed integer representing timezone offset in minutes east of UTC,
1049//     and a dst (daylight savings time) flag
1050//
1051//   When encoding a timestamp, the first byte is the descriptor, which
1052//   defines which components are encoded and how many bytes are used to
1053//   encode secs and nsecs components. *If secs/nsecs is 0 or tz is UTC, it
1054//   is not encoded in the byte array explicitly*.
1055//
1056//       Descriptor 8 bits are of the form `A B C DDD EE`:
1057//           A:   Is secs component encoded? 1 = true
1058//           B:   Is nsecs component encoded? 1 = true
1059//           C:   Is tz component encoded? 1 = true
1060//           DDD: Number of extra bytes for secs (range 0-7).
1061//                If A = 1, secs encoded in DDD+1 bytes.
1062//                    If A = 0, secs is not encoded, and is assumed to be 0.
1063//                    If A = 1, then we need at least 1 byte to encode secs.
1064//                    DDD says the number of extra bytes beyond that 1.
1065//                    E.g. if DDD=0, then secs is represented in 1 byte.
1066//                         if DDD=2, then secs is represented in 3 bytes.
1067//           EE:  Number of extra bytes for nsecs (range 0-3).
1068//                If B = 1, nsecs encoded in EE+1 bytes (similar to secs/DDD above)
1069//
1070//   Following the descriptor bytes, subsequent bytes are:
1071//
1072//       secs component encoded in `DDD + 1` bytes (if A == 1)
1073//       nsecs component encoded in `EE + 1` bytes (if B == 1)
1074//       tz component encoded in 2 bytes (if C == 1)
1075//
1076//   secs and nsecs components are integers encoded in a BigEndian
1077//   2-complement encoding format.
1078//
1079//   tz component is encoded as 2 bytes (16 bits). Most significant bit 15 to
1080//   Least significant bit 0 are described below:
1081//
1082//       Timezone offset has a range of -12:00 to +14:00 (ie -720 to +840 minutes).
1083//       Bit 15 = have\_dst: set to 1 if we set the dst flag.
1084//       Bit 14 = dst\_on: set to 1 if dst is in effect at the time, or 0 if not.
1085//       Bits 13..0 = timezone offset in minutes. It is a signed integer in Big Endian format.
1086//
1087func bincEncodeTime(t time.Time) []byte {
1088	// t := rv2i(rv).(time.Time)
1089	tsecs, tnsecs := t.Unix(), t.Nanosecond()
1090	var (
1091		bd   byte
1092		btmp [8]byte
1093		bs   [16]byte
1094		i    int = 1
1095	)
1096	l := t.Location()
1097	if l == time.UTC {
1098		l = nil
1099	}
1100	if tsecs != 0 {
1101		bd = bd | 0x80
1102		bigen.PutUint64(btmp[:], uint64(tsecs))
1103		f := pruneSignExt(btmp[:], tsecs >= 0)
1104		bd = bd | (byte(7-f) << 2)
1105		copy(bs[i:], btmp[f:])
1106		i = i + (8 - f)
1107	}
1108	if tnsecs != 0 {
1109		bd = bd | 0x40
1110		bigen.PutUint32(btmp[:4], uint32(tnsecs))
1111		f := pruneSignExt(btmp[:4], true)
1112		bd = bd | byte(3-f)
1113		copy(bs[i:], btmp[f:4])
1114		i = i + (4 - f)
1115	}
1116	if l != nil {
1117		bd = bd | 0x20
1118		// Note that Go Libs do not give access to dst flag.
1119		_, zoneOffset := t.Zone()
1120		// zoneName, zoneOffset := t.Zone()
1121		zoneOffset /= 60
1122		z := uint16(zoneOffset)
1123		bigen.PutUint16(btmp[:2], z)
1124		// clear dst flags
1125		bs[i] = btmp[0] & 0x3f
1126		bs[i+1] = btmp[1]
1127		i = i + 2
1128	}
1129	bs[0] = bd
1130	return bs[0:i]
1131}
1132
1133// bincDecodeTime decodes a []byte into a time.Time.
1134func bincDecodeTime(bs []byte) (tt time.Time, err error) {
1135	bd := bs[0]
1136	var (
1137		tsec  int64
1138		tnsec uint32
1139		tz    uint16
1140		i     byte = 1
1141		i2    byte
1142		n     byte
1143	)
1144	if bd&(1<<7) != 0 {
1145		var btmp [8]byte
1146		n = ((bd >> 2) & 0x7) + 1
1147		i2 = i + n
1148		copy(btmp[8-n:], bs[i:i2])
1149		// if first bit of bs[i] is set, then fill btmp[0..8-n] with 0xff (ie sign extend it)
1150		if bs[i]&(1<<7) != 0 {
1151			copy(btmp[0:8-n], bsAll0xff)
1152			// for j,k := byte(0), 8-n; j < k; j++ {	btmp[j] = 0xff }
1153		}
1154		i = i2
1155		tsec = int64(bigen.Uint64(btmp[:]))
1156	}
1157	if bd&(1<<6) != 0 {
1158		var btmp [4]byte
1159		n = (bd & 0x3) + 1
1160		i2 = i + n
1161		copy(btmp[4-n:], bs[i:i2])
1162		i = i2
1163		tnsec = bigen.Uint32(btmp[:])
1164	}
1165	if bd&(1<<5) == 0 {
1166		tt = time.Unix(tsec, int64(tnsec)).UTC()
1167		return
1168	}
1169	// In stdlib time.Parse, when a date is parsed without a zone name, it uses "" as zone name.
1170	// However, we need name here, so it can be shown when time is printf.d.
1171	// Zone name is in form: UTC-08:00.
1172	// Note that Go Libs do not give access to dst flag, so we ignore dst bits
1173
1174	i2 = i + 2
1175	tz = bigen.Uint16(bs[i:i2])
1176	// i = i2
1177	// sign extend sign bit into top 2 MSB (which were dst bits):
1178	if tz&(1<<13) == 0 { // positive
1179		tz = tz & 0x3fff //clear 2 MSBs: dst bits
1180	} else { // negative
1181		tz = tz | 0xc000 //set 2 MSBs: dst bits
1182	}
1183	tzint := int16(tz)
1184	if tzint == 0 {
1185		tt = time.Unix(tsec, int64(tnsec)).UTC()
1186	} else {
1187		// For Go Time, do not use a descriptive timezone.
1188		// It's unnecessary, and makes it harder to do a reflect.DeepEqual.
1189		// The Offset already tells what the offset should be, if not on UTC and unknown zone name.
1190		// var zoneName = timeLocUTCName(tzint)
1191		tt = time.Unix(tsec, int64(tnsec)).In(time.FixedZone("", int(tzint)*60))
1192	}
1193	return
1194}
1195
1196// func timeLocUTCName(tzint int16) string {
1197// 	if tzint == 0 {
1198// 		return "UTC"
1199// 	}
1200// 	var tzname = []byte("UTC+00:00")
1201// 	//tzname := fmt.Sprintf("UTC%s%02d:%02d", tzsign, tz/60, tz%60) //perf issue using Sprintf.. inline below.
1202// 	//tzhr, tzmin := tz/60, tz%60 //faster if u convert to int first
1203// 	var tzhr, tzmin int16
1204// 	if tzint < 0 {
1205// 		tzname[3] = '-'
1206// 		tzhr, tzmin = -tzint/60, (-tzint)%60
1207// 	} else {
1208// 		tzhr, tzmin = tzint/60, tzint%60
1209// 	}
1210// 	tzname[4] = timeDigits[tzhr/10]
1211// 	tzname[5] = timeDigits[tzhr%10]
1212// 	tzname[7] = timeDigits[tzmin/10]
1213// 	tzname[8] = timeDigits[tzmin%10]
1214// 	return string(tzname)
1215// 	//return time.FixedZone(string(tzname), int(tzint)*60)
1216// }
1217
1218var _ decDriver = (*bincDecDriver)(nil)
1219var _ encDriver = (*bincEncDriver)(nil)
1220