github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go (about) 1 // Copyright (C) MongoDB, Inc. 2017-present. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 6 7 package bsonrw 8 9 import ( 10 "bytes" 11 "encoding/base64" 12 "fmt" 13 "io" 14 "math" 15 "sort" 16 "strconv" 17 "strings" 18 "sync" 19 "time" 20 "unicode/utf8" 21 22 "go.mongodb.org/mongo-driver/bson/primitive" 23 ) 24 25 // ExtJSONValueWriterPool is a pool for ExtJSON ValueWriters. 26 // 27 // Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. 28 type ExtJSONValueWriterPool struct { 29 pool sync.Pool 30 } 31 32 // NewExtJSONValueWriterPool creates a new pool for ValueWriter instances that write to ExtJSON. 33 // 34 // Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. 35 func NewExtJSONValueWriterPool() *ExtJSONValueWriterPool { 36 return &ExtJSONValueWriterPool{ 37 pool: sync.Pool{ 38 New: func() interface{} { 39 return new(extJSONValueWriter) 40 }, 41 }, 42 } 43 } 44 45 // Get retrieves a ExtJSON ValueWriter from the pool and resets it to use w as the destination. 46 // 47 // Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. 48 func (bvwp *ExtJSONValueWriterPool) Get(w io.Writer, canonical, escapeHTML bool) ValueWriter { 49 vw := bvwp.pool.Get().(*extJSONValueWriter) 50 if writer, ok := w.(*SliceWriter); ok { 51 vw.reset(*writer, canonical, escapeHTML) 52 vw.w = writer 53 return vw 54 } 55 vw.buf = vw.buf[:0] 56 vw.w = w 57 return vw 58 } 59 60 // Put inserts a ValueWriter into the pool. If the ValueWriter is not a ExtJSON ValueWriter, nothing 61 // happens and ok will be false. 62 // 63 // Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. 64 func (bvwp *ExtJSONValueWriterPool) Put(vw ValueWriter) (ok bool) { 65 bvw, ok := vw.(*extJSONValueWriter) 66 if !ok { 67 return false 68 } 69 70 if _, ok := bvw.w.(*SliceWriter); ok { 71 bvw.buf = nil 72 } 73 bvw.w = nil 74 75 bvwp.pool.Put(bvw) 76 return true 77 } 78 79 type ejvwState struct { 80 mode mode 81 } 82 83 type extJSONValueWriter struct { 84 w io.Writer 85 buf []byte 86 87 stack []ejvwState 88 frame int64 89 canonical bool 90 escapeHTML bool 91 newlines bool 92 } 93 94 // NewExtJSONValueWriter creates a ValueWriter that writes Extended JSON to w. 95 func NewExtJSONValueWriter(w io.Writer, canonical, escapeHTML bool) (ValueWriter, error) { 96 if w == nil { 97 return nil, errNilWriter 98 } 99 100 // Enable newlines for all Extended JSON value writers created by NewExtJSONValueWriter. We 101 // expect these value writers to be used with an Encoder, which should add newlines after 102 // encoded Extended JSON documents. 103 return newExtJSONWriter(w, canonical, escapeHTML, true), nil 104 } 105 106 func newExtJSONWriter(w io.Writer, canonical, escapeHTML, newlines bool) *extJSONValueWriter { 107 stack := make([]ejvwState, 1, 5) 108 stack[0] = ejvwState{mode: mTopLevel} 109 110 return &extJSONValueWriter{ 111 w: w, 112 buf: []byte{}, 113 stack: stack, 114 canonical: canonical, 115 escapeHTML: escapeHTML, 116 newlines: newlines, 117 } 118 } 119 120 func newExtJSONWriterFromSlice(buf []byte, canonical, escapeHTML bool) *extJSONValueWriter { 121 stack := make([]ejvwState, 1, 5) 122 stack[0] = ejvwState{mode: mTopLevel} 123 124 return &extJSONValueWriter{ 125 buf: buf, 126 stack: stack, 127 canonical: canonical, 128 escapeHTML: escapeHTML, 129 } 130 } 131 132 func (ejvw *extJSONValueWriter) reset(buf []byte, canonical, escapeHTML bool) { 133 if ejvw.stack == nil { 134 ejvw.stack = make([]ejvwState, 1, 5) 135 } 136 137 ejvw.stack = ejvw.stack[:1] 138 ejvw.stack[0] = ejvwState{mode: mTopLevel} 139 ejvw.canonical = canonical 140 ejvw.escapeHTML = escapeHTML 141 ejvw.frame = 0 142 ejvw.buf = buf 143 ejvw.w = nil 144 } 145 146 func (ejvw *extJSONValueWriter) advanceFrame() { 147 if ejvw.frame+1 >= int64(len(ejvw.stack)) { // We need to grow the stack 148 length := len(ejvw.stack) 149 if length+1 >= cap(ejvw.stack) { 150 // double it 151 buf := make([]ejvwState, 2*cap(ejvw.stack)+1) 152 copy(buf, ejvw.stack) 153 ejvw.stack = buf 154 } 155 ejvw.stack = ejvw.stack[:length+1] 156 } 157 ejvw.frame++ 158 } 159 160 func (ejvw *extJSONValueWriter) push(m mode) { 161 ejvw.advanceFrame() 162 163 ejvw.stack[ejvw.frame].mode = m 164 } 165 166 func (ejvw *extJSONValueWriter) pop() { 167 switch ejvw.stack[ejvw.frame].mode { 168 case mElement, mValue: 169 ejvw.frame-- 170 case mDocument, mArray, mCodeWithScope: 171 ejvw.frame -= 2 // we pop twice to jump over the mElement: mDocument -> mElement -> mDocument/mTopLevel/etc... 172 } 173 } 174 175 func (ejvw *extJSONValueWriter) invalidTransitionErr(destination mode, name string, modes []mode) error { 176 te := TransitionError{ 177 name: name, 178 current: ejvw.stack[ejvw.frame].mode, 179 destination: destination, 180 modes: modes, 181 action: "write", 182 } 183 if ejvw.frame != 0 { 184 te.parent = ejvw.stack[ejvw.frame-1].mode 185 } 186 return te 187 } 188 189 func (ejvw *extJSONValueWriter) ensureElementValue(destination mode, callerName string, addmodes ...mode) error { 190 switch ejvw.stack[ejvw.frame].mode { 191 case mElement, mValue: 192 default: 193 modes := []mode{mElement, mValue} 194 if addmodes != nil { 195 modes = append(modes, addmodes...) 196 } 197 return ejvw.invalidTransitionErr(destination, callerName, modes) 198 } 199 200 return nil 201 } 202 203 func (ejvw *extJSONValueWriter) writeExtendedSingleValue(key string, value string, quotes bool) { 204 var s string 205 if quotes { 206 s = fmt.Sprintf(`{"$%s":"%s"}`, key, value) 207 } else { 208 s = fmt.Sprintf(`{"$%s":%s}`, key, value) 209 } 210 211 ejvw.buf = append(ejvw.buf, []byte(s)...) 212 } 213 214 func (ejvw *extJSONValueWriter) WriteArray() (ArrayWriter, error) { 215 if err := ejvw.ensureElementValue(mArray, "WriteArray"); err != nil { 216 return nil, err 217 } 218 219 ejvw.buf = append(ejvw.buf, '[') 220 221 ejvw.push(mArray) 222 return ejvw, nil 223 } 224 225 func (ejvw *extJSONValueWriter) WriteBinary(b []byte) error { 226 return ejvw.WriteBinaryWithSubtype(b, 0x00) 227 } 228 229 func (ejvw *extJSONValueWriter) WriteBinaryWithSubtype(b []byte, btype byte) error { 230 if err := ejvw.ensureElementValue(mode(0), "WriteBinaryWithSubtype"); err != nil { 231 return err 232 } 233 234 var buf bytes.Buffer 235 buf.WriteString(`{"$binary":{"base64":"`) 236 buf.WriteString(base64.StdEncoding.EncodeToString(b)) 237 buf.WriteString(fmt.Sprintf(`","subType":"%02x"}},`, btype)) 238 239 ejvw.buf = append(ejvw.buf, buf.Bytes()...) 240 241 ejvw.pop() 242 return nil 243 } 244 245 func (ejvw *extJSONValueWriter) WriteBoolean(b bool) error { 246 if err := ejvw.ensureElementValue(mode(0), "WriteBoolean"); err != nil { 247 return err 248 } 249 250 ejvw.buf = append(ejvw.buf, []byte(strconv.FormatBool(b))...) 251 ejvw.buf = append(ejvw.buf, ',') 252 253 ejvw.pop() 254 return nil 255 } 256 257 func (ejvw *extJSONValueWriter) WriteCodeWithScope(code string) (DocumentWriter, error) { 258 if err := ejvw.ensureElementValue(mCodeWithScope, "WriteCodeWithScope"); err != nil { 259 return nil, err 260 } 261 262 var buf bytes.Buffer 263 buf.WriteString(`{"$code":`) 264 writeStringWithEscapes(code, &buf, ejvw.escapeHTML) 265 buf.WriteString(`,"$scope":{`) 266 267 ejvw.buf = append(ejvw.buf, buf.Bytes()...) 268 269 ejvw.push(mCodeWithScope) 270 return ejvw, nil 271 } 272 273 func (ejvw *extJSONValueWriter) WriteDBPointer(ns string, oid primitive.ObjectID) error { 274 if err := ejvw.ensureElementValue(mode(0), "WriteDBPointer"); err != nil { 275 return err 276 } 277 278 var buf bytes.Buffer 279 buf.WriteString(`{"$dbPointer":{"$ref":"`) 280 buf.WriteString(ns) 281 buf.WriteString(`","$id":{"$oid":"`) 282 buf.WriteString(oid.Hex()) 283 buf.WriteString(`"}}},`) 284 285 ejvw.buf = append(ejvw.buf, buf.Bytes()...) 286 287 ejvw.pop() 288 return nil 289 } 290 291 func (ejvw *extJSONValueWriter) WriteDateTime(dt int64) error { 292 if err := ejvw.ensureElementValue(mode(0), "WriteDateTime"); err != nil { 293 return err 294 } 295 296 t := time.Unix(dt/1e3, dt%1e3*1e6).UTC() 297 298 if ejvw.canonical || t.Year() < 1970 || t.Year() > 9999 { 299 s := fmt.Sprintf(`{"$numberLong":"%d"}`, dt) 300 ejvw.writeExtendedSingleValue("date", s, false) 301 } else { 302 ejvw.writeExtendedSingleValue("date", t.Format(rfc3339Milli), true) 303 } 304 305 ejvw.buf = append(ejvw.buf, ',') 306 307 ejvw.pop() 308 return nil 309 } 310 311 func (ejvw *extJSONValueWriter) WriteDecimal128(d primitive.Decimal128) error { 312 if err := ejvw.ensureElementValue(mode(0), "WriteDecimal128"); err != nil { 313 return err 314 } 315 316 ejvw.writeExtendedSingleValue("numberDecimal", d.String(), true) 317 ejvw.buf = append(ejvw.buf, ',') 318 319 ejvw.pop() 320 return nil 321 } 322 323 func (ejvw *extJSONValueWriter) WriteDocument() (DocumentWriter, error) { 324 if ejvw.stack[ejvw.frame].mode == mTopLevel { 325 ejvw.buf = append(ejvw.buf, '{') 326 return ejvw, nil 327 } 328 329 if err := ejvw.ensureElementValue(mDocument, "WriteDocument", mTopLevel); err != nil { 330 return nil, err 331 } 332 333 ejvw.buf = append(ejvw.buf, '{') 334 ejvw.push(mDocument) 335 return ejvw, nil 336 } 337 338 func (ejvw *extJSONValueWriter) WriteDouble(f float64) error { 339 if err := ejvw.ensureElementValue(mode(0), "WriteDouble"); err != nil { 340 return err 341 } 342 343 s := formatDouble(f) 344 345 if ejvw.canonical { 346 ejvw.writeExtendedSingleValue("numberDouble", s, true) 347 } else { 348 switch s { 349 case "Infinity": 350 fallthrough 351 case "-Infinity": 352 fallthrough 353 case "NaN": 354 s = fmt.Sprintf(`{"$numberDouble":"%s"}`, s) 355 } 356 ejvw.buf = append(ejvw.buf, []byte(s)...) 357 } 358 359 ejvw.buf = append(ejvw.buf, ',') 360 361 ejvw.pop() 362 return nil 363 } 364 365 func (ejvw *extJSONValueWriter) WriteInt32(i int32) error { 366 if err := ejvw.ensureElementValue(mode(0), "WriteInt32"); err != nil { 367 return err 368 } 369 370 s := strconv.FormatInt(int64(i), 10) 371 372 if ejvw.canonical { 373 ejvw.writeExtendedSingleValue("numberInt", s, true) 374 } else { 375 ejvw.buf = append(ejvw.buf, []byte(s)...) 376 } 377 378 ejvw.buf = append(ejvw.buf, ',') 379 380 ejvw.pop() 381 return nil 382 } 383 384 func (ejvw *extJSONValueWriter) WriteInt64(i int64) error { 385 if err := ejvw.ensureElementValue(mode(0), "WriteInt64"); err != nil { 386 return err 387 } 388 389 s := strconv.FormatInt(i, 10) 390 391 if ejvw.canonical { 392 ejvw.writeExtendedSingleValue("numberLong", s, true) 393 } else { 394 ejvw.buf = append(ejvw.buf, []byte(s)...) 395 } 396 397 ejvw.buf = append(ejvw.buf, ',') 398 399 ejvw.pop() 400 return nil 401 } 402 403 func (ejvw *extJSONValueWriter) WriteJavascript(code string) error { 404 if err := ejvw.ensureElementValue(mode(0), "WriteJavascript"); err != nil { 405 return err 406 } 407 408 var buf bytes.Buffer 409 writeStringWithEscapes(code, &buf, ejvw.escapeHTML) 410 411 ejvw.writeExtendedSingleValue("code", buf.String(), false) 412 ejvw.buf = append(ejvw.buf, ',') 413 414 ejvw.pop() 415 return nil 416 } 417 418 func (ejvw *extJSONValueWriter) WriteMaxKey() error { 419 if err := ejvw.ensureElementValue(mode(0), "WriteMaxKey"); err != nil { 420 return err 421 } 422 423 ejvw.writeExtendedSingleValue("maxKey", "1", false) 424 ejvw.buf = append(ejvw.buf, ',') 425 426 ejvw.pop() 427 return nil 428 } 429 430 func (ejvw *extJSONValueWriter) WriteMinKey() error { 431 if err := ejvw.ensureElementValue(mode(0), "WriteMinKey"); err != nil { 432 return err 433 } 434 435 ejvw.writeExtendedSingleValue("minKey", "1", false) 436 ejvw.buf = append(ejvw.buf, ',') 437 438 ejvw.pop() 439 return nil 440 } 441 442 func (ejvw *extJSONValueWriter) WriteNull() error { 443 if err := ejvw.ensureElementValue(mode(0), "WriteNull"); err != nil { 444 return err 445 } 446 447 ejvw.buf = append(ejvw.buf, []byte("null")...) 448 ejvw.buf = append(ejvw.buf, ',') 449 450 ejvw.pop() 451 return nil 452 } 453 454 func (ejvw *extJSONValueWriter) WriteObjectID(oid primitive.ObjectID) error { 455 if err := ejvw.ensureElementValue(mode(0), "WriteObjectID"); err != nil { 456 return err 457 } 458 459 ejvw.writeExtendedSingleValue("oid", oid.Hex(), true) 460 ejvw.buf = append(ejvw.buf, ',') 461 462 ejvw.pop() 463 return nil 464 } 465 466 func (ejvw *extJSONValueWriter) WriteRegex(pattern string, options string) error { 467 if err := ejvw.ensureElementValue(mode(0), "WriteRegex"); err != nil { 468 return err 469 } 470 471 var buf bytes.Buffer 472 buf.WriteString(`{"$regularExpression":{"pattern":`) 473 writeStringWithEscapes(pattern, &buf, ejvw.escapeHTML) 474 buf.WriteString(`,"options":"`) 475 buf.WriteString(sortStringAlphebeticAscending(options)) 476 buf.WriteString(`"}},`) 477 478 ejvw.buf = append(ejvw.buf, buf.Bytes()...) 479 480 ejvw.pop() 481 return nil 482 } 483 484 func (ejvw *extJSONValueWriter) WriteString(s string) error { 485 if err := ejvw.ensureElementValue(mode(0), "WriteString"); err != nil { 486 return err 487 } 488 489 var buf bytes.Buffer 490 writeStringWithEscapes(s, &buf, ejvw.escapeHTML) 491 492 ejvw.buf = append(ejvw.buf, buf.Bytes()...) 493 ejvw.buf = append(ejvw.buf, ',') 494 495 ejvw.pop() 496 return nil 497 } 498 499 func (ejvw *extJSONValueWriter) WriteSymbol(symbol string) error { 500 if err := ejvw.ensureElementValue(mode(0), "WriteSymbol"); err != nil { 501 return err 502 } 503 504 var buf bytes.Buffer 505 writeStringWithEscapes(symbol, &buf, ejvw.escapeHTML) 506 507 ejvw.writeExtendedSingleValue("symbol", buf.String(), false) 508 ejvw.buf = append(ejvw.buf, ',') 509 510 ejvw.pop() 511 return nil 512 } 513 514 func (ejvw *extJSONValueWriter) WriteTimestamp(t uint32, i uint32) error { 515 if err := ejvw.ensureElementValue(mode(0), "WriteTimestamp"); err != nil { 516 return err 517 } 518 519 var buf bytes.Buffer 520 buf.WriteString(`{"$timestamp":{"t":`) 521 buf.WriteString(strconv.FormatUint(uint64(t), 10)) 522 buf.WriteString(`,"i":`) 523 buf.WriteString(strconv.FormatUint(uint64(i), 10)) 524 buf.WriteString(`}},`) 525 526 ejvw.buf = append(ejvw.buf, buf.Bytes()...) 527 528 ejvw.pop() 529 return nil 530 } 531 532 func (ejvw *extJSONValueWriter) WriteUndefined() error { 533 if err := ejvw.ensureElementValue(mode(0), "WriteUndefined"); err != nil { 534 return err 535 } 536 537 ejvw.writeExtendedSingleValue("undefined", "true", false) 538 ejvw.buf = append(ejvw.buf, ',') 539 540 ejvw.pop() 541 return nil 542 } 543 544 func (ejvw *extJSONValueWriter) WriteDocumentElement(key string) (ValueWriter, error) { 545 switch ejvw.stack[ejvw.frame].mode { 546 case mDocument, mTopLevel, mCodeWithScope: 547 var buf bytes.Buffer 548 writeStringWithEscapes(key, &buf, ejvw.escapeHTML) 549 550 ejvw.buf = append(ejvw.buf, []byte(fmt.Sprintf(`%s:`, buf.String()))...) 551 ejvw.push(mElement) 552 default: 553 return nil, ejvw.invalidTransitionErr(mElement, "WriteDocumentElement", []mode{mDocument, mTopLevel, mCodeWithScope}) 554 } 555 556 return ejvw, nil 557 } 558 559 func (ejvw *extJSONValueWriter) WriteDocumentEnd() error { 560 switch ejvw.stack[ejvw.frame].mode { 561 case mDocument, mTopLevel, mCodeWithScope: 562 default: 563 return fmt.Errorf("incorrect mode to end document: %s", ejvw.stack[ejvw.frame].mode) 564 } 565 566 // close the document 567 if ejvw.buf[len(ejvw.buf)-1] == ',' { 568 ejvw.buf[len(ejvw.buf)-1] = '}' 569 } else { 570 ejvw.buf = append(ejvw.buf, '}') 571 } 572 573 switch ejvw.stack[ejvw.frame].mode { 574 case mCodeWithScope: 575 ejvw.buf = append(ejvw.buf, '}') 576 fallthrough 577 case mDocument: 578 ejvw.buf = append(ejvw.buf, ',') 579 case mTopLevel: 580 // If the value writer has newlines enabled, end top-level documents with a newline so that 581 // multiple documents encoded to the same writer are separated by newlines. That matches the 582 // Go json.Encoder behavior and also works with bsonrw.NewExtJSONValueReader. 583 if ejvw.newlines { 584 ejvw.buf = append(ejvw.buf, '\n') 585 } 586 if ejvw.w != nil { 587 if _, err := ejvw.w.Write(ejvw.buf); err != nil { 588 return err 589 } 590 ejvw.buf = ejvw.buf[:0] 591 } 592 } 593 594 ejvw.pop() 595 return nil 596 } 597 598 func (ejvw *extJSONValueWriter) WriteArrayElement() (ValueWriter, error) { 599 switch ejvw.stack[ejvw.frame].mode { 600 case mArray: 601 ejvw.push(mValue) 602 default: 603 return nil, ejvw.invalidTransitionErr(mValue, "WriteArrayElement", []mode{mArray}) 604 } 605 606 return ejvw, nil 607 } 608 609 func (ejvw *extJSONValueWriter) WriteArrayEnd() error { 610 switch ejvw.stack[ejvw.frame].mode { 611 case mArray: 612 // close the array 613 if ejvw.buf[len(ejvw.buf)-1] == ',' { 614 ejvw.buf[len(ejvw.buf)-1] = ']' 615 } else { 616 ejvw.buf = append(ejvw.buf, ']') 617 } 618 619 ejvw.buf = append(ejvw.buf, ',') 620 621 ejvw.pop() 622 default: 623 return fmt.Errorf("incorrect mode to end array: %s", ejvw.stack[ejvw.frame].mode) 624 } 625 626 return nil 627 } 628 629 func formatDouble(f float64) string { 630 var s string 631 if math.IsInf(f, 1) { 632 s = "Infinity" 633 } else if math.IsInf(f, -1) { 634 s = "-Infinity" 635 } else if math.IsNaN(f) { 636 s = "NaN" 637 } else { 638 // Print exactly one decimalType place for integers; otherwise, print as many are necessary to 639 // perfectly represent it. 640 s = strconv.FormatFloat(f, 'G', -1, 64) 641 if !strings.ContainsRune(s, 'E') && !strings.ContainsRune(s, '.') { 642 s += ".0" 643 } 644 } 645 646 return s 647 } 648 649 var hexChars = "0123456789abcdef" 650 651 func writeStringWithEscapes(s string, buf *bytes.Buffer, escapeHTML bool) { 652 buf.WriteByte('"') 653 start := 0 654 for i := 0; i < len(s); { 655 if b := s[i]; b < utf8.RuneSelf { 656 if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) { 657 i++ 658 continue 659 } 660 if start < i { 661 buf.WriteString(s[start:i]) 662 } 663 switch b { 664 case '\\', '"': 665 buf.WriteByte('\\') 666 buf.WriteByte(b) 667 case '\n': 668 buf.WriteByte('\\') 669 buf.WriteByte('n') 670 case '\r': 671 buf.WriteByte('\\') 672 buf.WriteByte('r') 673 case '\t': 674 buf.WriteByte('\\') 675 buf.WriteByte('t') 676 case '\b': 677 buf.WriteByte('\\') 678 buf.WriteByte('b') 679 case '\f': 680 buf.WriteByte('\\') 681 buf.WriteByte('f') 682 default: 683 // This encodes bytes < 0x20 except for \t, \n and \r. 684 // If escapeHTML is set, it also escapes <, >, and & 685 // because they can lead to security holes when 686 // user-controlled strings are rendered into JSON 687 // and served to some browsers. 688 buf.WriteString(`\u00`) 689 buf.WriteByte(hexChars[b>>4]) 690 buf.WriteByte(hexChars[b&0xF]) 691 } 692 i++ 693 start = i 694 continue 695 } 696 c, size := utf8.DecodeRuneInString(s[i:]) 697 if c == utf8.RuneError && size == 1 { 698 if start < i { 699 buf.WriteString(s[start:i]) 700 } 701 buf.WriteString(`\ufffd`) 702 i += size 703 start = i 704 continue 705 } 706 // U+2028 is LINE SEPARATOR. 707 // U+2029 is PARAGRAPH SEPARATOR. 708 // They are both technically valid characters in JSON strings, 709 // but don't work in JSONP, which has to be evaluated as JavaScript, 710 // and can lead to security holes there. It is valid JSON to 711 // escape them, so we do so unconditionally. 712 // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. 713 if c == '\u2028' || c == '\u2029' { 714 if start < i { 715 buf.WriteString(s[start:i]) 716 } 717 buf.WriteString(`\u202`) 718 buf.WriteByte(hexChars[c&0xF]) 719 i += size 720 start = i 721 continue 722 } 723 i += size 724 } 725 if start < len(s) { 726 buf.WriteString(s[start:]) 727 } 728 buf.WriteByte('"') 729 } 730 731 type sortableString []rune 732 733 func (ss sortableString) Len() int { 734 return len(ss) 735 } 736 737 func (ss sortableString) Less(i, j int) bool { 738 return ss[i] < ss[j] 739 } 740 741 func (ss sortableString) Swap(i, j int) { 742 oldI := ss[i] 743 ss[i] = ss[j] 744 ss[j] = oldI 745 } 746 747 func sortStringAlphebeticAscending(s string) string { 748 ss := sortableString([]rune(s)) 749 sort.Sort(ss) 750 return string([]rune(ss)) 751 }