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