github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/json/encoded.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package json 12 13 import ( 14 "bytes" 15 "fmt" 16 "sort" 17 "strconv" 18 "unsafe" 19 20 "github.com/cockroachdb/cockroach/pkg/util/syncutil" 21 "github.com/cockroachdb/errors" 22 ) 23 24 type jsonEncoded struct { 25 // containerLength is only set if this is an object or an array. 26 containerLen int 27 typ Type 28 // value contains the encoding of this JSON value. In the case of 29 // arrays and objects, value contains the container header, but it never 30 // contains a scalar container header. 31 value []byte 32 33 // TODO(justin): for simplicity right now we use a mutex, we could be using 34 // an atomic CAS though. 35 mu struct { 36 syncutil.RWMutex 37 38 cachedDecoded JSON 39 } 40 } 41 42 const jsonEncodedSize = unsafe.Sizeof(jsonEncoded{}) 43 44 // alreadyDecoded returns a decoded JSON value if this jsonEncoded has already 45 // been decoded, otherwise it returns nil. This allows us to fast-path certain 46 // operations if we've already done the work of decoding an object. 47 func (j *jsonEncoded) alreadyDecoded() JSON { 48 j.mu.RLock() 49 defer j.mu.RUnlock() 50 if j.mu.cachedDecoded != nil { 51 return j.mu.cachedDecoded 52 } 53 return nil 54 } 55 56 func (j *jsonEncoded) Type() Type { 57 return j.typ 58 } 59 60 // newEncodedFromRoot returns a jsonEncoded from a fully-encoded JSON document. 61 func newEncodedFromRoot(v []byte) (*jsonEncoded, error) { 62 v, typ, err := jsonTypeFromRootBuffer(v) 63 if err != nil { 64 return nil, err 65 } 66 67 containerLen := -1 68 if typ == ArrayJSONType || typ == ObjectJSONType { 69 containerHeader, err := getUint32At(v, 0) 70 if err != nil { 71 return nil, err 72 } 73 containerLen = int(containerHeader & containerHeaderLenMask) 74 } 75 76 return &jsonEncoded{ 77 typ: typ, 78 containerLen: containerLen, 79 // Manually set the capacity of the new slice to its length, so we properly 80 // report the memory size of this encoded json object. The original slice 81 // capacity is very large, since it probably points to the backing byte 82 // slice of a kv batch. 83 value: v[:len(v):len(v)], 84 }, nil 85 } 86 87 func jsonTypeFromRootBuffer(v []byte) ([]byte, Type, error) { 88 // Root buffers always have a container header. 89 containerHeader, err := getUint32At(v, 0) 90 if err != nil { 91 return v, 0, err 92 } 93 typeTag := containerHeader & containerHeaderTypeMask 94 switch typeTag { 95 case arrayContainerTag: 96 return v, ArrayJSONType, nil 97 case objectContainerTag: 98 return v, ObjectJSONType, nil 99 case scalarContainerTag: 100 entry, err := getUint32At(v, containerHeaderLen) 101 if err != nil { 102 return v, 0, err 103 } 104 switch entry & jEntryTypeMask { 105 case nullTag: 106 return v[containerHeaderLen+jEntryLen:], NullJSONType, nil 107 case trueTag: 108 return v[containerHeaderLen+jEntryLen:], TrueJSONType, nil 109 case falseTag: 110 return v[containerHeaderLen+jEntryLen:], FalseJSONType, nil 111 case numberTag: 112 return v[containerHeaderLen+jEntryLen:], NumberJSONType, nil 113 case stringTag: 114 return v[containerHeaderLen+jEntryLen:], StringJSONType, nil 115 } 116 } 117 return nil, 0, errors.AssertionFailedf("unknown json type %d", errors.Safe(typeTag)) 118 } 119 120 func newEncoded(e jEntry, v []byte) (JSON, error) { 121 var typ Type 122 var containerLen int 123 switch e.typCode { 124 case stringTag: 125 typ = StringJSONType 126 case numberTag: 127 typ = NumberJSONType 128 case nullTag: // Don't bother with returning a jsonEncoded for the singleton types. 129 return NullJSONValue, nil 130 case falseTag: 131 return FalseJSONValue, nil 132 case trueTag: 133 return TrueJSONValue, nil 134 case containerTag: 135 // Every container is prefixed with its uint32 container header. 136 containerHeader, err := getUint32At(v, 0) 137 if err != nil { 138 return nil, err 139 } 140 switch containerHeader & containerHeaderTypeMask { 141 case arrayContainerTag: 142 typ = ArrayJSONType 143 case objectContainerTag: 144 typ = ObjectJSONType 145 } 146 containerLen = int(containerHeader & containerHeaderLenMask) 147 } 148 149 return &jsonEncoded{ 150 typ: typ, 151 containerLen: containerLen, 152 value: v, 153 }, nil 154 } 155 156 func getUint32At(v []byte, idx int) (uint32, error) { 157 if idx+4 > len(v) { 158 return 0, errors.AssertionFailedf( 159 "insufficient bytes to decode uint32 int value: %+v", v) 160 } 161 162 return uint32(v[idx])<<24 | 163 uint32(v[idx+1])<<16 | 164 uint32(v[idx+2])<<8 | 165 uint32(v[idx+3]), nil 166 } 167 168 type encodedArrayIterator struct { 169 curDataIdx int 170 dataOffset int 171 idx int 172 len int 173 data []byte 174 } 175 176 func (e *encodedArrayIterator) nextEncoded() (nextJEntry jEntry, next []byte, ok bool, err error) { 177 if e.idx >= e.len { 178 return jEntry{}, nil, false, nil 179 } 180 181 // Recall the layout of an encoded array: 182 // [ container header ] [ all JEntries ] [ all values ] 183 nextJEntry, err = getJEntryAt(e.data, containerHeaderLen+e.idx*jEntryLen, e.curDataIdx) 184 if err != nil { 185 return jEntry{}, nil, false, err 186 } 187 nextLen := int(nextJEntry.length) 188 nextData := e.data[e.dataOffset+e.curDataIdx : e.dataOffset+e.curDataIdx+nextLen] 189 e.idx++ 190 e.curDataIdx += nextLen 191 return nextJEntry, nextData, true, nil 192 } 193 194 // iterArrayValues iterates through all the values of an encoded array without 195 // requiring decoding of all of them. 196 func (j *jsonEncoded) iterArrayValues() encodedArrayIterator { 197 if j.typ != ArrayJSONType { 198 panic("can only iterate through the array values of an array") 199 } 200 201 return encodedArrayIterator{ 202 dataOffset: containerHeaderLen + j.containerLen*jEntryLen, 203 curDataIdx: 0, 204 len: j.containerLen, 205 idx: 0, 206 data: j.value, 207 } 208 } 209 210 type encodedObjectIterator struct { 211 curKeyIdx int 212 keyOffset int 213 curValueIdx int 214 valueOffset int 215 idx int 216 len int 217 data []byte 218 } 219 220 func (e *encodedObjectIterator) nextEncoded() ( 221 nextKey []byte, 222 nextJEntry jEntry, 223 nextVal []byte, 224 ok bool, 225 err error, 226 ) { 227 if e.idx >= e.len { 228 return nil, jEntry{}, nil, false, nil 229 } 230 231 // Recall the layout of an encoded object: 232 // [ container header ] [ all key JEntries ] [ all value JEntries ] [ all key data ] [ all value data ]. 233 nextKeyJEntry, err := getJEntryAt(e.data, containerHeaderLen+e.idx*jEntryLen, e.curKeyIdx) 234 if err != nil { 235 return nil, jEntry{}, nil, false, err 236 } 237 nextKeyData := e.data[e.keyOffset+e.curKeyIdx : e.keyOffset+e.curKeyIdx+int(nextKeyJEntry.length)] 238 239 offsetFromBeginningOfData := e.curValueIdx + e.valueOffset - e.keyOffset 240 241 nextValueJEntry, err := getJEntryAt(e.data, containerHeaderLen+(e.idx+e.len)*jEntryLen, offsetFromBeginningOfData) 242 if err != nil { 243 return nil, jEntry{}, nil, false, err 244 } 245 nextValueData := e.data[e.valueOffset+e.curValueIdx : e.valueOffset+e.curValueIdx+int(nextValueJEntry.length)] 246 247 e.idx++ 248 e.curKeyIdx += int(nextKeyJEntry.length) 249 e.curValueIdx += int(nextValueJEntry.length) 250 return nextKeyData, nextValueJEntry, nextValueData, true, nil 251 } 252 253 // iterObject iterates through all the keys and values of an encoded object 254 // without requiring decoding of all of them. 255 func (j *jsonEncoded) iterObject() (encodedObjectIterator, error) { 256 if j.typ != ObjectJSONType { 257 panic("can only iterate through the object values of an object") 258 } 259 260 curKeyIdx := containerHeaderLen + j.containerLen*jEntryLen*2 261 curValueIdx := curKeyIdx 262 263 // We have to seek to the start of the value data. 264 for i := 0; i < j.containerLen; i++ { 265 entry, err := getJEntryAt(j.value, containerHeaderLen+i*jEntryLen, curValueIdx-curKeyIdx) 266 if err != nil { 267 return encodedObjectIterator{}, err 268 } 269 curValueIdx += int(entry.length) 270 } 271 272 return encodedObjectIterator{ 273 curKeyIdx: 0, 274 keyOffset: curKeyIdx, 275 curValueIdx: 0, 276 valueOffset: curValueIdx, 277 len: j.containerLen, 278 idx: 0, 279 data: j.value, 280 }, nil 281 } 282 283 func (j *jsonEncoded) StripNulls() (JSON, bool, error) { 284 dec, err := j.shallowDecode() 285 if err != nil { 286 return nil, false, err 287 } 288 return dec.StripNulls() 289 } 290 291 func (j *jsonEncoded) ObjectIter() (*ObjectIterator, error) { 292 dec, err := j.shallowDecode() 293 if err != nil { 294 return nil, err 295 } 296 return dec.ObjectIter() 297 } 298 299 func (j *jsonEncoded) nthJEntry(n int, off int) (jEntry, error) { 300 return getJEntryAt(j.value, containerHeaderLen+n*jEntryLen, off) 301 } 302 303 // objectGetDataRange returns the [begin, end) subslice of the object's data. 304 func (j *jsonEncoded) objectGetDataRange(begin, end int) []byte { 305 dataStart := containerHeaderLen + j.containerLen*jEntryLen*2 306 return j.value[dataStart+begin : dataStart+end] 307 } 308 309 // getNthEntryBounds returns the beginning, ending, and JEntry of the nth entry 310 // in the container. If the container is an object, the i-th entry is the i-th 311 // key, and the (i+length)-th entry is the i-th value. 312 func (j *jsonEncoded) getNthEntryBounds(n int) (begin, end int, entry jEntry, err error) { 313 // First, we seek for the beginning of the current entry by stepping 314 // backwards via beginningOfIdx. 315 begin, err = j.beginningOfIdx(n) 316 if err != nil { 317 return 0, 0, jEntry{}, err 318 } 319 320 // Once we know where this entry starts, we can derive the end from its own 321 // JEntry. 322 entry, err = j.nthJEntry(n, begin) 323 if err != nil { 324 return 0, 0, jEntry{}, err 325 } 326 return begin, begin + int(entry.length), entry, nil 327 } 328 329 // objectGetNthDataRange returns the byte subslice and jEntry of the given nth entry. 330 // If the container is an object, the i-th entry is the i-th key, and the 331 // (i+length)-th entry is the i-th value. 332 func (j *jsonEncoded) objectGetNthDataRange(n int) ([]byte, jEntry, error) { 333 begin, end, entry, err := j.getNthEntryBounds(n) 334 if err != nil { 335 return nil, jEntry{}, err 336 } 337 return j.objectGetDataRange(begin, end), entry, nil 338 } 339 340 // objectNthValue returns the nth value in the sorted-by-key representation of 341 // the object. 342 func (j *jsonEncoded) objectNthValue(n int) (JSON, error) { 343 data, entry, err := j.objectGetNthDataRange(j.containerLen + n) 344 if err != nil { 345 return nil, err 346 } 347 return newEncoded(entry, data) 348 } 349 350 func parseJEntry(jEntry uint32) (isOff bool, offlen int) { 351 return (jEntry & jEntryIsOffFlag) != 0, int(jEntry & jEntryOffLenMask) 352 } 353 354 // beginningOfIdx finds the offset to the beginning of the given entry. 355 func (j *jsonEncoded) beginningOfIdx(idx int) (int, error) { 356 if idx == 0 { 357 return 0, nil 358 } 359 360 offset := 0 361 curIdx := idx - 1 362 for curIdx >= 0 { 363 // We need to manually extract the JEntry here because this is a case where 364 // we logically care if it's an offset or a length. 365 e, err := getUint32At(j.value, containerHeaderLen+curIdx*jEntryLen) 366 if err != nil { 367 return 0, err 368 } 369 isOff, offlen := parseJEntry(e) 370 if isOff { 371 return offlen + offset, nil 372 } 373 offset += offlen 374 curIdx-- 375 } 376 return offset, nil 377 } 378 379 func (j *jsonEncoded) arrayGetDataRange(begin, end int) []byte { 380 dataStart := containerHeaderLen + j.containerLen*jEntryLen 381 return j.value[dataStart+begin : dataStart+end] 382 } 383 384 func (j *jsonEncoded) FetchValIdx(idx int) (JSON, error) { 385 if dec := j.alreadyDecoded(); dec != nil { 386 return dec.FetchValIdx(idx) 387 } 388 389 if j.Type() == ArrayJSONType { 390 if idx < 0 { 391 idx = j.containerLen + idx 392 } 393 if idx < 0 || idx >= j.containerLen { 394 return nil, nil 395 } 396 397 // We need to find the bounds for a given index, but this is nontrivial, 398 // since some headers store an offset and some store a length. 399 400 begin, end, entry, err := j.getNthEntryBounds(idx) 401 if err != nil { 402 return nil, err 403 } 404 405 return newEncoded(entry, j.arrayGetDataRange(begin, end)) 406 } 407 return nil, nil 408 } 409 410 func (j *jsonEncoded) FetchValKey(key string) (JSON, error) { 411 if dec := j.alreadyDecoded(); dec != nil { 412 return dec.FetchValKey(key) 413 } 414 415 if j.Type() == ObjectJSONType { 416 // TODO(justin): This is not as absolutely efficient as it could be - every 417 // lookup we have to seek to find the actual location of the key. We could 418 // be caching the locations of all the intermediate keys that we have to 419 // scan in order to get to this one, in case we need to look them up later, 420 // or maybe there's something fancier we could do if we know the locations 421 // of the offsets by strategically positioning our binary search guesses to 422 // land on them. 423 var err error 424 i := sort.Search(j.containerLen, func(idx int) bool { 425 data, _, err := j.objectGetNthDataRange(idx) 426 if err != nil { 427 return false 428 } 429 return string(data) >= key 430 }) 431 if err != nil { 432 return nil, err 433 } 434 435 // The sort.Search API implies that we have to double-check if the key we 436 // landed on is the one we were searching for in the first place. 437 if i >= j.containerLen { 438 return nil, nil 439 } 440 441 data, _, err := j.objectGetNthDataRange(i) 442 if err != nil { 443 return nil, err 444 } 445 446 if string(data) == key { 447 return j.objectNthValue(i) 448 } 449 } 450 return nil, nil 451 } 452 453 // shallowDecode decodes only the keys of an object, and doesn't decode any 454 // elements of an array. It can be used to save a decode-encode cycle for 455 // certain operations (say, key deletion). 456 func (j *jsonEncoded) shallowDecode() (JSON, error) { 457 if dec := j.alreadyDecoded(); dec != nil { 458 return dec, nil 459 } 460 461 switch j.typ { 462 case NumberJSONType, StringJSONType, TrueJSONType, FalseJSONType, NullJSONType: 463 return j.decode() 464 case ArrayJSONType: 465 iter := j.iterArrayValues() 466 result := make(jsonArray, j.containerLen) 467 for i := 0; i < j.containerLen; i++ { 468 entry, next, _, err := iter.nextEncoded() 469 if err != nil { 470 return nil, err 471 } 472 result[i], err = newEncoded(entry, next) 473 if err != nil { 474 return nil, err 475 } 476 } 477 return result, nil 478 case ObjectJSONType: 479 iter, err := j.iterObject() 480 if err != nil { 481 return nil, err 482 } 483 result := make(jsonObject, j.containerLen) 484 for i := 0; i < j.containerLen; i++ { 485 nextKey, entry, nextValue, _, err := iter.nextEncoded() 486 if err != nil { 487 return nil, err 488 } 489 v, err := newEncoded(entry, nextValue) 490 if err != nil { 491 return nil, err 492 } 493 result[i] = jsonKeyValuePair{ 494 k: jsonString(nextKey), 495 v: v, 496 } 497 } 498 j.mu.Lock() 499 defer j.mu.Unlock() 500 if j.mu.cachedDecoded == nil { 501 j.mu.cachedDecoded = result 502 } 503 return result, nil 504 default: 505 return nil, errors.AssertionFailedf("unknown json type: %v", errors.Safe(j.typ)) 506 } 507 } 508 509 func (j *jsonEncoded) mustDecode() JSON { 510 decoded, err := j.shallowDecode() 511 if err != nil { 512 panic(errors.NewAssertionErrorWithWrappedErrf(err, "invalid JSON data: %v", j.value)) 513 } 514 return decoded 515 } 516 517 // decode should be used in cases where you will definitely have to use the 518 // entire decoded JSON structure, like printing it out to a string. 519 func (j *jsonEncoded) decode() (JSON, error) { 520 switch j.typ { 521 case NumberJSONType: 522 _, j, err := decodeJSONNumber(j.value) 523 return j, err 524 case StringJSONType: 525 return jsonString(j.value), nil 526 case TrueJSONType: 527 return TrueJSONValue, nil 528 case FalseJSONType: 529 return FalseJSONValue, nil 530 case NullJSONType: 531 return NullJSONValue, nil 532 } 533 _, decoded, err := DecodeJSON(j.value) 534 535 j.mu.Lock() 536 defer j.mu.Unlock() 537 j.mu.cachedDecoded = decoded 538 539 return decoded, err 540 } 541 542 func (j *jsonEncoded) AsText() (*string, error) { 543 if dec := j.alreadyDecoded(); dec != nil { 544 return dec.AsText() 545 } 546 547 decoded, err := j.decode() 548 if err != nil { 549 return nil, err 550 } 551 return decoded.AsText() 552 } 553 554 func (j *jsonEncoded) Compare(other JSON) (int, error) { 555 if cmp := cmpJSONTypes(j.Type(), other.Type()); cmp != 0 { 556 return cmp, nil 557 } 558 // TODO(justin): this can be optimized in some cases. We don't necessarily 559 // need to decode all of an array or every object key. 560 dec, err := j.shallowDecode() 561 if err != nil { 562 return 0, err 563 } 564 return dec.Compare(other) 565 } 566 567 func (j *jsonEncoded) Exists(key string) (bool, error) { 568 if dec := j.alreadyDecoded(); dec != nil { 569 return dec.Exists(key) 570 } 571 572 switch j.typ { 573 case ObjectJSONType: 574 v, err := j.FetchValKey(key) 575 if err != nil { 576 return false, err 577 } 578 return v != nil, nil 579 case ArrayJSONType: 580 iter := j.iterArrayValues() 581 for { 582 nextJEntry, data, ok, err := iter.nextEncoded() 583 if err != nil { 584 return false, err 585 } 586 if !ok { 587 return false, nil 588 } 589 next, err := newEncoded(nextJEntry, data) 590 if err != nil { 591 return false, err 592 } 593 // This is a minor optimization - we know that newEncoded always returns a 594 // jsonEncoded if it's decoding a string, and we can save actually 595 // allocating that string for this check by not forcing a decode into a 596 // jsonString. This operates on two major assumptions: 597 // 1. newEncoded returns a jsonEncoded (and not a jsonString) for string 598 // types and 599 // 2. the `value` field on such a jsonEncoded directly corresponds to the string. 600 // This is tested sufficiently that if either of those assumptions is 601 // broken it will be caught. 602 if next.Type() == StringJSONType && string(next.(*jsonEncoded).value) == key { 603 return true, nil 604 } 605 } 606 default: 607 s, err := j.decode() 608 if err != nil { 609 return false, err 610 } 611 return s.Exists(key) 612 } 613 } 614 615 func (j *jsonEncoded) FetchValKeyOrIdx(key string) (JSON, error) { 616 switch j.typ { 617 case ObjectJSONType: 618 return j.FetchValKey(key) 619 case ArrayJSONType: 620 idx, err := strconv.Atoi(key) 621 if err != nil { 622 // We shouldn't return this error because it means we couldn't parse the 623 // number, meaning it was a string and that just means we can't find the 624 // value in an array. 625 return nil, nil //nolint:returnerrcheck 626 } 627 return j.FetchValIdx(idx) 628 } 629 return nil, nil 630 } 631 632 func (j *jsonEncoded) Format(buf *bytes.Buffer) { 633 decoded, err := j.decode() 634 if err != nil { 635 fmt.Fprintf(buf, `<corrupt JSON data: %s>`, err.Error()) 636 } else { 637 decoded.Format(buf) 638 } 639 } 640 641 // RemoveIndex implements the JSON interface. 642 func (j *jsonEncoded) RemoveIndex(idx int) (JSON, bool, error) { 643 decoded, err := j.shallowDecode() 644 if err != nil { 645 return nil, false, err 646 } 647 return decoded.RemoveIndex(idx) 648 } 649 650 // Concat implements the JSON interface. 651 func (j *jsonEncoded) Concat(other JSON) (JSON, error) { 652 decoded, err := j.shallowDecode() 653 if err != nil { 654 return nil, err 655 } 656 return decoded.Concat(other) 657 } 658 659 // RemoveString implements the JSON interface. 660 func (j *jsonEncoded) RemoveString(s string) (JSON, bool, error) { 661 decoded, err := j.shallowDecode() 662 if err != nil { 663 return nil, false, err 664 } 665 return decoded.RemoveString(s) 666 } 667 668 func (j *jsonEncoded) RemovePath(path []string) (JSON, bool, error) { 669 decoded, err := j.shallowDecode() 670 if err != nil { 671 return nil, false, err 672 } 673 return decoded.RemovePath(path) 674 } 675 676 func (j *jsonEncoded) doRemovePath(path []string) (JSON, bool, error) { 677 decoded, err := j.shallowDecode() 678 if err != nil { 679 return nil, false, err 680 } 681 return decoded.doRemovePath(path) 682 } 683 684 // Size implements the JSON interface. 685 func (j *jsonEncoded) Size() uintptr { 686 return jsonEncodedSize + uintptr(cap(j.value)) 687 } 688 689 func (j *jsonEncoded) String() string { 690 var buf bytes.Buffer 691 j.Format(&buf) 692 return buf.String() 693 } 694 695 // isScalar implements the JSON interface. 696 func (j *jsonEncoded) isScalar() bool { 697 return j.typ != ArrayJSONType && j.typ != ObjectJSONType 698 } 699 700 func (j *jsonEncoded) Len() int { 701 if j.typ != ArrayJSONType && j.typ != ObjectJSONType { 702 return 0 703 } 704 return j.containerLen 705 } 706 707 // EncodeInvertedIndexKeys implements the JSON interface. 708 func (j *jsonEncoded) encodeInvertedIndexKeys(b []byte) ([][]byte, error) { 709 // TODO(justin): this could possibly be optimized. 710 decoded, err := j.decode() 711 if err != nil { 712 return nil, err 713 } 714 return decoded.encodeInvertedIndexKeys(b) 715 } 716 717 // numInvertedIndexEntries implements the JSON interface. 718 func (j *jsonEncoded) numInvertedIndexEntries() (int, error) { 719 if j.isScalar() || j.containerLen == 0 { 720 return 1, nil 721 } 722 decoded, err := j.decode() 723 if err != nil { 724 return 0, err 725 } 726 return decoded.numInvertedIndexEntries() 727 } 728 729 func (j *jsonEncoded) allPaths() ([]JSON, error) { 730 decoded, err := j.decode() 731 if err != nil { 732 return nil, err 733 } 734 return decoded.allPaths() 735 } 736 737 // HasContainerLeaf implements the JSON interface. 738 func (j *jsonEncoded) HasContainerLeaf() (bool, error) { 739 decoded, err := j.decode() 740 if err != nil { 741 return false, err 742 } 743 return decoded.HasContainerLeaf() 744 } 745 746 // preprocessForContains implements the JSON interface. 747 func (j *jsonEncoded) preprocessForContains() (containsable, error) { 748 if dec := j.alreadyDecoded(); dec != nil { 749 return dec.preprocessForContains() 750 } 751 752 decoded, err := j.decode() 753 if err != nil { 754 return nil, err 755 } 756 return decoded.preprocessForContains() 757 } 758 759 // jEntry implements the JSON interface. 760 func (j *jsonEncoded) jEntry() jEntry { 761 var typeTag uint32 762 switch j.typ { 763 case NullJSONType: 764 typeTag = nullTag 765 case TrueJSONType: 766 typeTag = trueTag 767 case FalseJSONType: 768 typeTag = falseTag 769 case StringJSONType: 770 typeTag = stringTag 771 case NumberJSONType: 772 typeTag = numberTag 773 case ObjectJSONType, ArrayJSONType: 774 typeTag = containerTag 775 } 776 byteLen := uint32(len(j.value)) 777 return jEntry{typeTag, byteLen} 778 } 779 780 // encode implements the JSON interface. 781 func (j *jsonEncoded) encode(appendTo []byte) (jEntry jEntry, b []byte, err error) { 782 return j.jEntry(), append(appendTo, j.value...), nil 783 } 784 785 // MaybeDecode implements the JSON interface. 786 func (j *jsonEncoded) MaybeDecode() JSON { 787 return j.mustDecode() 788 } 789 790 // toGoRepr implements the JSON interface. 791 func (j *jsonEncoded) toGoRepr() (interface{}, error) { 792 decoded, err := j.shallowDecode() 793 if err != nil { 794 return nil, err 795 } 796 return decoded.toGoRepr() 797 } 798 799 // tryDecode implements the JSON interface. 800 func (j *jsonEncoded) tryDecode() (JSON, error) { 801 return j.shallowDecode() 802 }