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