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 7package bsoncore 8 9import ( 10 "bytes" 11 "encoding/base64" 12 "fmt" 13 "math" 14 "sort" 15 "strconv" 16 "strings" 17 "time" 18 "unicode/utf8" 19 20 "go.mongodb.org/mongo-driver/bson/bsontype" 21 "go.mongodb.org/mongo-driver/bson/primitive" 22) 23 24// ElementTypeError specifies that a method to obtain a BSON value an incorrect type was called on a bson.Value. 25type ElementTypeError struct { 26 Method string 27 Type bsontype.Type 28} 29 30// Error implements the error interface. 31func (ete ElementTypeError) Error() string { 32 return "Call of " + ete.Method + " on " + ete.Type.String() + " type" 33} 34 35// Value represents a BSON value with a type and raw bytes. 36type Value struct { 37 Type bsontype.Type 38 Data []byte 39} 40 41// Validate ensures the value is a valid BSON value. 42func (v Value) Validate() error { 43 _, _, valid := readValue(v.Data, v.Type) 44 if !valid { 45 return NewInsufficientBytesError(v.Data, v.Data) 46 } 47 return nil 48} 49 50// IsNumber returns true if the type of v is a numeric BSON type. 51func (v Value) IsNumber() bool { 52 switch v.Type { 53 case bsontype.Double, bsontype.Int32, bsontype.Int64, bsontype.Decimal128: 54 return true 55 default: 56 return false 57 } 58} 59 60// AsInt32 returns a BSON number as an int32. If the BSON type is not a numeric one, this method 61// will panic. 62// 63// TODO(skriptble): Add support for Decimal128. 64func (v Value) AsInt32() int32 { 65 if !v.IsNumber() { 66 panic(ElementTypeError{"bsoncore.Value.AsInt32", v.Type}) 67 } 68 var i32 int32 69 switch v.Type { 70 case bsontype.Double: 71 f64, _, ok := ReadDouble(v.Data) 72 if !ok { 73 panic(NewInsufficientBytesError(v.Data, v.Data)) 74 } 75 i32 = int32(f64) 76 case bsontype.Int32: 77 var ok bool 78 i32, _, ok = ReadInt32(v.Data) 79 if !ok { 80 panic(NewInsufficientBytesError(v.Data, v.Data)) 81 } 82 case bsontype.Int64: 83 i64, _, ok := ReadInt64(v.Data) 84 if !ok { 85 panic(NewInsufficientBytesError(v.Data, v.Data)) 86 } 87 i32 = int32(i64) 88 case bsontype.Decimal128: 89 panic(ElementTypeError{"bsoncore.Value.AsInt32", v.Type}) 90 } 91 return i32 92} 93 94// AsInt32OK functions the same as AsInt32 but returns a boolean instead of panicking. False 95// indicates an error. 96// 97// TODO(skriptble): Add support for Decimal128. 98func (v Value) AsInt32OK() (int32, bool) { 99 if !v.IsNumber() { 100 return 0, false 101 } 102 var i32 int32 103 switch v.Type { 104 case bsontype.Double: 105 f64, _, ok := ReadDouble(v.Data) 106 if !ok { 107 return 0, false 108 } 109 i32 = int32(f64) 110 case bsontype.Int32: 111 var ok bool 112 i32, _, ok = ReadInt32(v.Data) 113 if !ok { 114 return 0, false 115 } 116 case bsontype.Int64: 117 i64, _, ok := ReadInt64(v.Data) 118 if !ok { 119 return 0, false 120 } 121 i32 = int32(i64) 122 case bsontype.Decimal128: 123 return 0, false 124 } 125 return i32, true 126} 127 128// AsInt64 returns a BSON number as an int64. If the BSON type is not a numeric one, this method 129// will panic. 130// 131// TODO(skriptble): Add support for Decimal128. 132func (v Value) AsInt64() int64 { 133 if !v.IsNumber() { 134 panic(ElementTypeError{"bsoncore.Value.AsInt64", v.Type}) 135 } 136 var i64 int64 137 switch v.Type { 138 case bsontype.Double: 139 f64, _, ok := ReadDouble(v.Data) 140 if !ok { 141 panic(NewInsufficientBytesError(v.Data, v.Data)) 142 } 143 i64 = int64(f64) 144 case bsontype.Int32: 145 var ok bool 146 i32, _, ok := ReadInt32(v.Data) 147 if !ok { 148 panic(NewInsufficientBytesError(v.Data, v.Data)) 149 } 150 i64 = int64(i32) 151 case bsontype.Int64: 152 var ok bool 153 i64, _, ok = ReadInt64(v.Data) 154 if !ok { 155 panic(NewInsufficientBytesError(v.Data, v.Data)) 156 } 157 case bsontype.Decimal128: 158 panic(ElementTypeError{"bsoncore.Value.AsInt64", v.Type}) 159 } 160 return i64 161} 162 163// AsInt64OK functions the same as AsInt64 but returns a boolean instead of panicking. False 164// indicates an error. 165// 166// TODO(skriptble): Add support for Decimal128. 167func (v Value) AsInt64OK() (int64, bool) { 168 if !v.IsNumber() { 169 return 0, false 170 } 171 var i64 int64 172 switch v.Type { 173 case bsontype.Double: 174 f64, _, ok := ReadDouble(v.Data) 175 if !ok { 176 return 0, false 177 } 178 i64 = int64(f64) 179 case bsontype.Int32: 180 var ok bool 181 i32, _, ok := ReadInt32(v.Data) 182 if !ok { 183 return 0, false 184 } 185 i64 = int64(i32) 186 case bsontype.Int64: 187 var ok bool 188 i64, _, ok = ReadInt64(v.Data) 189 if !ok { 190 return 0, false 191 } 192 case bsontype.Decimal128: 193 return 0, false 194 } 195 return i64, true 196} 197 198// AsFloat64 returns a BSON number as an float64. If the BSON type is not a numeric one, this method 199// will panic. 200// 201// TODO(skriptble): Add support for Decimal128. 202func (v Value) AsFloat64() float64 { return 0 } 203 204// AsFloat64OK functions the same as AsFloat64 but returns a boolean instead of panicking. False 205// indicates an error. 206// 207// TODO(skriptble): Add support for Decimal128. 208func (v Value) AsFloat64OK() (float64, bool) { return 0, false } 209 210// Add will add this value to another. This is currently only implemented for strings and numbers. 211// If either value is a string, the other type is coerced into a string and added to the other. 212// 213// This method will alter v and will attempt to reuse the []byte of v. If the []byte is too small, 214// it will be expanded. 215func (v *Value) Add(v2 Value) error { return nil } 216 217// Equal compaes v to v2 and returns true if they are equal. 218func (v Value) Equal(v2 Value) bool { 219 if v.Type != v2.Type { 220 return false 221 } 222 223 return bytes.Equal(v.Data, v2.Data) 224} 225 226// String implements the fmt.String interface. This method will return values in extended JSON 227// format. If the value is not valid, this returns an empty string 228func (v Value) String() string { 229 switch v.Type { 230 case bsontype.Double: 231 f64, ok := v.DoubleOK() 232 if !ok { 233 return "" 234 } 235 return fmt.Sprintf(`{"$numberDouble":"%s"}`, formatDouble(f64)) 236 case bsontype.String: 237 str, ok := v.StringValueOK() 238 if !ok { 239 return "" 240 } 241 return escapeString(str) 242 case bsontype.EmbeddedDocument: 243 doc, ok := v.DocumentOK() 244 if !ok { 245 return "" 246 } 247 return doc.String() 248 case bsontype.Array: 249 arr, ok := v.ArrayOK() 250 if !ok { 251 return "" 252 } 253 return arr.String() 254 case bsontype.Binary: 255 subtype, data, ok := v.BinaryOK() 256 if !ok { 257 return "" 258 } 259 return fmt.Sprintf(`{"$binary":{"base64":"%s","subType":"%02x"}}`, base64.StdEncoding.EncodeToString(data), subtype) 260 case bsontype.Undefined: 261 return `{"$undefined":true}` 262 case bsontype.ObjectID: 263 oid, ok := v.ObjectIDOK() 264 if !ok { 265 return "" 266 } 267 return fmt.Sprintf(`{"$oid":"%s"}`, oid.Hex()) 268 case bsontype.Boolean: 269 b, ok := v.BooleanOK() 270 if !ok { 271 return "" 272 } 273 return strconv.FormatBool(b) 274 case bsontype.DateTime: 275 dt, ok := v.DateTimeOK() 276 if !ok { 277 return "" 278 } 279 return fmt.Sprintf(`{"$date":{"$numberLong":"%d"}}`, dt) 280 case bsontype.Null: 281 return "null" 282 case bsontype.Regex: 283 pattern, options, ok := v.RegexOK() 284 if !ok { 285 return "" 286 } 287 return fmt.Sprintf( 288 `{"$regularExpression":{"pattern":%s,"options":"%s"}}`, 289 escapeString(pattern), sortStringAlphebeticAscending(options), 290 ) 291 case bsontype.DBPointer: 292 ns, pointer, ok := v.DBPointerOK() 293 if !ok { 294 return "" 295 } 296 return fmt.Sprintf(`{"$dbPointer":{"$ref":%s,"$id":{"$oid":"%s"}}}`, escapeString(ns), pointer.Hex()) 297 case bsontype.JavaScript: 298 js, ok := v.JavaScriptOK() 299 if !ok { 300 return "" 301 } 302 return fmt.Sprintf(`{"$code":%s}`, escapeString(js)) 303 case bsontype.Symbol: 304 symbol, ok := v.SymbolOK() 305 if !ok { 306 return "" 307 } 308 return fmt.Sprintf(`{"$symbol":%s}`, escapeString(symbol)) 309 case bsontype.CodeWithScope: 310 code, scope, ok := v.CodeWithScopeOK() 311 if !ok { 312 return "" 313 } 314 return fmt.Sprintf(`{"$code":%s,"$scope":%s}`, code, scope) 315 case bsontype.Int32: 316 i32, ok := v.Int32OK() 317 if !ok { 318 return "" 319 } 320 return fmt.Sprintf(`{"$numberInt":"%d"}`, i32) 321 case bsontype.Timestamp: 322 t, i, ok := v.TimestampOK() 323 if !ok { 324 return "" 325 } 326 return fmt.Sprintf(`{"$timestamp":{"t":"%s","i":"%s"}}`, strconv.FormatUint(uint64(t), 10), strconv.FormatUint(uint64(i), 10)) 327 case bsontype.Int64: 328 i64, ok := v.Int64OK() 329 if !ok { 330 return "" 331 } 332 return fmt.Sprintf(`{"$numberLong":"%d"}`, i64) 333 case bsontype.Decimal128: 334 d128, ok := v.Decimal128OK() 335 if !ok { 336 return "" 337 } 338 return fmt.Sprintf(`{"$numberDecimal":"%s"}`, d128.String()) 339 case bsontype.MinKey: 340 return `{"$minKey":1}` 341 case bsontype.MaxKey: 342 return `{"$maxKey":1}` 343 default: 344 return "" 345 } 346} 347 348// DebugString outputs a human readable version of Document. It will attempt to stringify the 349// valid components of the document even if the entire document is not valid. 350func (v Value) DebugString() string { 351 switch v.Type { 352 case bsontype.String: 353 str, ok := v.StringValueOK() 354 if !ok { 355 return "<malformed>" 356 } 357 return escapeString(str) 358 case bsontype.EmbeddedDocument: 359 doc, ok := v.DocumentOK() 360 if !ok { 361 return "<malformed>" 362 } 363 return doc.DebugString() 364 case bsontype.Array: 365 arr, ok := v.ArrayOK() 366 if !ok { 367 return "<malformed>" 368 } 369 return arr.DebugString() 370 case bsontype.CodeWithScope: 371 code, scope, ok := v.CodeWithScopeOK() 372 if !ok { 373 return "" 374 } 375 return fmt.Sprintf(`{"$code":%s,"$scope":%s}`, code, scope.DebugString()) 376 default: 377 str := v.String() 378 if str == "" { 379 return "<malformed>" 380 } 381 return str 382 } 383} 384 385// Double returns the float64 value for this element. 386// It panics if e's BSON type is not bsontype.Double. 387func (v Value) Double() float64 { 388 if v.Type != bsontype.Double { 389 panic(ElementTypeError{"bsoncore.Value.Double", v.Type}) 390 } 391 f64, _, ok := ReadDouble(v.Data) 392 if !ok { 393 panic(NewInsufficientBytesError(v.Data, v.Data)) 394 } 395 return f64 396} 397 398// DoubleOK is the same as Double, but returns a boolean instead of panicking. 399func (v Value) DoubleOK() (float64, bool) { 400 if v.Type != bsontype.Double { 401 return 0, false 402 } 403 f64, _, ok := ReadDouble(v.Data) 404 if !ok { 405 return 0, false 406 } 407 return f64, true 408} 409 410// StringValue returns the string balue for this element. 411// It panics if e's BSON type is not bsontype.String. 412// 413// NOTE: This method is called StringValue to avoid a collision with the String method which 414// implements the fmt.Stringer interface. 415func (v Value) StringValue() string { 416 if v.Type != bsontype.String { 417 panic(ElementTypeError{"bsoncore.Value.StringValue", v.Type}) 418 } 419 str, _, ok := ReadString(v.Data) 420 if !ok { 421 panic(NewInsufficientBytesError(v.Data, v.Data)) 422 } 423 return str 424} 425 426// StringValueOK is the same as StringValue, but returns a boolean instead of 427// panicking. 428func (v Value) StringValueOK() (string, bool) { 429 if v.Type != bsontype.String { 430 return "", false 431 } 432 str, _, ok := ReadString(v.Data) 433 if !ok { 434 return "", false 435 } 436 return str, true 437} 438 439// Document returns the BSON document the Value represents as a Document. It panics if the 440// value is a BSON type other than document. 441func (v Value) Document() Document { 442 if v.Type != bsontype.EmbeddedDocument { 443 panic(ElementTypeError{"bsoncore.Value.Document", v.Type}) 444 } 445 doc, _, ok := ReadDocument(v.Data) 446 if !ok { 447 panic(NewInsufficientBytesError(v.Data, v.Data)) 448 } 449 return doc 450} 451 452// DocumentOK is the same as Document, except it returns a boolean 453// instead of panicking. 454func (v Value) DocumentOK() (Document, bool) { 455 if v.Type != bsontype.EmbeddedDocument { 456 return nil, false 457 } 458 doc, _, ok := ReadDocument(v.Data) 459 if !ok { 460 return nil, false 461 } 462 return doc, true 463} 464 465// Array returns the BSON array the Value represents as an Array. It panics if the 466// value is a BSON type other than array. 467func (v Value) Array() Array { 468 if v.Type != bsontype.Array { 469 panic(ElementTypeError{"bsoncore.Value.Array", v.Type}) 470 } 471 arr, _, ok := ReadArray(v.Data) 472 if !ok { 473 panic(NewInsufficientBytesError(v.Data, v.Data)) 474 } 475 return arr 476} 477 478// ArrayOK is the same as Array, except it returns a boolean instead 479// of panicking. 480func (v Value) ArrayOK() (Array, bool) { 481 if v.Type != bsontype.Array { 482 return nil, false 483 } 484 arr, _, ok := ReadArray(v.Data) 485 if !ok { 486 return nil, false 487 } 488 return arr, true 489} 490 491// Binary returns the BSON binary value the Value represents. It panics if the value is a BSON type 492// other than binary. 493func (v Value) Binary() (subtype byte, data []byte) { 494 if v.Type != bsontype.Binary { 495 panic(ElementTypeError{"bsoncore.Value.Binary", v.Type}) 496 } 497 subtype, data, _, ok := ReadBinary(v.Data) 498 if !ok { 499 panic(NewInsufficientBytesError(v.Data, v.Data)) 500 } 501 return subtype, data 502} 503 504// BinaryOK is the same as Binary, except it returns a boolean instead of 505// panicking. 506func (v Value) BinaryOK() (subtype byte, data []byte, ok bool) { 507 if v.Type != bsontype.Binary { 508 return 0x00, nil, false 509 } 510 subtype, data, _, ok = ReadBinary(v.Data) 511 if !ok { 512 return 0x00, nil, false 513 } 514 return subtype, data, true 515} 516 517// ObjectID returns the BSON objectid value the Value represents. It panics if the value is a BSON 518// type other than objectid. 519func (v Value) ObjectID() primitive.ObjectID { 520 if v.Type != bsontype.ObjectID { 521 panic(ElementTypeError{"bsoncore.Value.ObjectID", v.Type}) 522 } 523 oid, _, ok := ReadObjectID(v.Data) 524 if !ok { 525 panic(NewInsufficientBytesError(v.Data, v.Data)) 526 } 527 return oid 528} 529 530// ObjectIDOK is the same as ObjectID, except it returns a boolean instead of 531// panicking. 532func (v Value) ObjectIDOK() (primitive.ObjectID, bool) { 533 if v.Type != bsontype.ObjectID { 534 return primitive.ObjectID{}, false 535 } 536 oid, _, ok := ReadObjectID(v.Data) 537 if !ok { 538 return primitive.ObjectID{}, false 539 } 540 return oid, true 541} 542 543// Boolean returns the boolean value the Value represents. It panics if the 544// value is a BSON type other than boolean. 545func (v Value) Boolean() bool { 546 if v.Type != bsontype.Boolean { 547 panic(ElementTypeError{"bsoncore.Value.Boolean", v.Type}) 548 } 549 b, _, ok := ReadBoolean(v.Data) 550 if !ok { 551 panic(NewInsufficientBytesError(v.Data, v.Data)) 552 } 553 return b 554} 555 556// BooleanOK is the same as Boolean, except it returns a boolean instead of 557// panicking. 558func (v Value) BooleanOK() (bool, bool) { 559 if v.Type != bsontype.Boolean { 560 return false, false 561 } 562 b, _, ok := ReadBoolean(v.Data) 563 if !ok { 564 return false, false 565 } 566 return b, true 567} 568 569// DateTime returns the BSON datetime value the Value represents as a 570// unix timestamp. It panics if the value is a BSON type other than datetime. 571func (v Value) DateTime() int64 { 572 if v.Type != bsontype.DateTime { 573 panic(ElementTypeError{"bsoncore.Value.DateTime", v.Type}) 574 } 575 dt, _, ok := ReadDateTime(v.Data) 576 if !ok { 577 panic(NewInsufficientBytesError(v.Data, v.Data)) 578 } 579 return dt 580} 581 582// DateTimeOK is the same as DateTime, except it returns a boolean instead of 583// panicking. 584func (v Value) DateTimeOK() (int64, bool) { 585 if v.Type != bsontype.DateTime { 586 return 0, false 587 } 588 dt, _, ok := ReadDateTime(v.Data) 589 if !ok { 590 return 0, false 591 } 592 return dt, true 593} 594 595// Time returns the BSON datetime value the Value represents. It panics if the value is a BSON 596// type other than datetime. 597func (v Value) Time() time.Time { 598 if v.Type != bsontype.DateTime { 599 panic(ElementTypeError{"bsoncore.Value.Time", v.Type}) 600 } 601 dt, _, ok := ReadDateTime(v.Data) 602 if !ok { 603 panic(NewInsufficientBytesError(v.Data, v.Data)) 604 } 605 return time.Unix(int64(dt)/1000, int64(dt)%1000*1000000) 606} 607 608// TimeOK is the same as Time, except it returns a boolean instead of 609// panicking. 610func (v Value) TimeOK() (time.Time, bool) { 611 if v.Type != bsontype.DateTime { 612 return time.Time{}, false 613 } 614 dt, _, ok := ReadDateTime(v.Data) 615 if !ok { 616 return time.Time{}, false 617 } 618 return time.Unix(int64(dt)/1000, int64(dt)%1000*1000000), true 619} 620 621// Regex returns the BSON regex value the Value represents. It panics if the value is a BSON 622// type other than regex. 623func (v Value) Regex() (pattern, options string) { 624 if v.Type != bsontype.Regex { 625 panic(ElementTypeError{"bsoncore.Value.Regex", v.Type}) 626 } 627 pattern, options, _, ok := ReadRegex(v.Data) 628 if !ok { 629 panic(NewInsufficientBytesError(v.Data, v.Data)) 630 } 631 return pattern, options 632} 633 634// RegexOK is the same as Regex, except it returns a boolean instead of 635// panicking. 636func (v Value) RegexOK() (pattern, options string, ok bool) { 637 if v.Type != bsontype.Regex { 638 return "", "", false 639 } 640 pattern, options, _, ok = ReadRegex(v.Data) 641 if !ok { 642 return "", "", false 643 } 644 return pattern, options, true 645} 646 647// DBPointer returns the BSON dbpointer value the Value represents. It panics if the value is a BSON 648// type other than DBPointer. 649func (v Value) DBPointer() (string, primitive.ObjectID) { 650 if v.Type != bsontype.DBPointer { 651 panic(ElementTypeError{"bsoncore.Value.DBPointer", v.Type}) 652 } 653 ns, pointer, _, ok := ReadDBPointer(v.Data) 654 if !ok { 655 panic(NewInsufficientBytesError(v.Data, v.Data)) 656 } 657 return ns, pointer 658} 659 660// DBPointerOK is the same as DBPoitner, except that it returns a boolean 661// instead of panicking. 662func (v Value) DBPointerOK() (string, primitive.ObjectID, bool) { 663 if v.Type != bsontype.DBPointer { 664 return "", primitive.ObjectID{}, false 665 } 666 ns, pointer, _, ok := ReadDBPointer(v.Data) 667 if !ok { 668 return "", primitive.ObjectID{}, false 669 } 670 return ns, pointer, true 671} 672 673// JavaScript returns the BSON JavaScript code value the Value represents. It panics if the value is 674// a BSON type other than JavaScript code. 675func (v Value) JavaScript() string { 676 if v.Type != bsontype.JavaScript { 677 panic(ElementTypeError{"bsoncore.Value.JavaScript", v.Type}) 678 } 679 js, _, ok := ReadJavaScript(v.Data) 680 if !ok { 681 panic(NewInsufficientBytesError(v.Data, v.Data)) 682 } 683 return js 684} 685 686// JavaScriptOK is the same as Javascript, excepti that it returns a boolean 687// instead of panicking. 688func (v Value) JavaScriptOK() (string, bool) { 689 if v.Type != bsontype.JavaScript { 690 return "", false 691 } 692 js, _, ok := ReadJavaScript(v.Data) 693 if !ok { 694 return "", false 695 } 696 return js, true 697} 698 699// Symbol returns the BSON symbol value the Value represents. It panics if the value is a BSON 700// type other than symbol. 701func (v Value) Symbol() string { 702 if v.Type != bsontype.Symbol { 703 panic(ElementTypeError{"bsoncore.Value.Symbol", v.Type}) 704 } 705 symbol, _, ok := ReadSymbol(v.Data) 706 if !ok { 707 panic(NewInsufficientBytesError(v.Data, v.Data)) 708 } 709 return symbol 710} 711 712// SymbolOK is the same as Symbol, excepti that it returns a boolean 713// instead of panicking. 714func (v Value) SymbolOK() (string, bool) { 715 if v.Type != bsontype.Symbol { 716 return "", false 717 } 718 symbol, _, ok := ReadSymbol(v.Data) 719 if !ok { 720 return "", false 721 } 722 return symbol, true 723} 724 725// CodeWithScope returns the BSON JavaScript code with scope the Value represents. 726// It panics if the value is a BSON type other than JavaScript code with scope. 727func (v Value) CodeWithScope() (string, Document) { 728 if v.Type != bsontype.CodeWithScope { 729 panic(ElementTypeError{"bsoncore.Value.CodeWithScope", v.Type}) 730 } 731 code, scope, _, ok := ReadCodeWithScope(v.Data) 732 if !ok { 733 panic(NewInsufficientBytesError(v.Data, v.Data)) 734 } 735 return code, scope 736} 737 738// CodeWithScopeOK is the same as CodeWithScope, except that it returns a boolean instead of 739// panicking. 740func (v Value) CodeWithScopeOK() (string, Document, bool) { 741 if v.Type != bsontype.CodeWithScope { 742 return "", nil, false 743 } 744 code, scope, _, ok := ReadCodeWithScope(v.Data) 745 if !ok { 746 return "", nil, false 747 } 748 return code, scope, true 749} 750 751// Int32 returns the int32 the Value represents. It panics if the value is a BSON type other than 752// int32. 753func (v Value) Int32() int32 { 754 if v.Type != bsontype.Int32 { 755 panic(ElementTypeError{"bsoncore.Value.Int32", v.Type}) 756 } 757 i32, _, ok := ReadInt32(v.Data) 758 if !ok { 759 panic(NewInsufficientBytesError(v.Data, v.Data)) 760 } 761 return i32 762} 763 764// Int32OK is the same as Int32, except that it returns a boolean instead of 765// panicking. 766func (v Value) Int32OK() (int32, bool) { 767 if v.Type != bsontype.Int32 { 768 return 0, false 769 } 770 i32, _, ok := ReadInt32(v.Data) 771 if !ok { 772 return 0, false 773 } 774 return i32, true 775} 776 777// Timestamp returns the BSON timestamp value the Value represents. It panics if the value is a 778// BSON type other than timestamp. 779func (v Value) Timestamp() (t, i uint32) { 780 if v.Type != bsontype.Timestamp { 781 panic(ElementTypeError{"bsoncore.Value.Timestamp", v.Type}) 782 } 783 t, i, _, ok := ReadTimestamp(v.Data) 784 if !ok { 785 panic(NewInsufficientBytesError(v.Data, v.Data)) 786 } 787 return t, i 788} 789 790// TimestampOK is the same as Timestamp, except that it returns a boolean 791// instead of panicking. 792func (v Value) TimestampOK() (t, i uint32, ok bool) { 793 if v.Type != bsontype.Timestamp { 794 return 0, 0, false 795 } 796 t, i, _, ok = ReadTimestamp(v.Data) 797 if !ok { 798 return 0, 0, false 799 } 800 return t, i, true 801} 802 803// Int64 returns the int64 the Value represents. It panics if the value is a BSON type other than 804// int64. 805func (v Value) Int64() int64 { 806 if v.Type != bsontype.Int64 { 807 panic(ElementTypeError{"bsoncore.Value.Int64", v.Type}) 808 } 809 i64, _, ok := ReadInt64(v.Data) 810 if !ok { 811 panic(NewInsufficientBytesError(v.Data, v.Data)) 812 } 813 return i64 814} 815 816// Int64OK is the same as Int64, except that it returns a boolean instead of 817// panicking. 818func (v Value) Int64OK() (int64, bool) { 819 if v.Type != bsontype.Int64 { 820 return 0, false 821 } 822 i64, _, ok := ReadInt64(v.Data) 823 if !ok { 824 return 0, false 825 } 826 return i64, true 827} 828 829// Decimal128 returns the decimal the Value represents. It panics if the value is a BSON type other than 830// decimal. 831func (v Value) Decimal128() primitive.Decimal128 { 832 if v.Type != bsontype.Decimal128 { 833 panic(ElementTypeError{"bsoncore.Value.Decimal128", v.Type}) 834 } 835 d128, _, ok := ReadDecimal128(v.Data) 836 if !ok { 837 panic(NewInsufficientBytesError(v.Data, v.Data)) 838 } 839 return d128 840} 841 842// Decimal128OK is the same as Decimal128, except that it returns a boolean 843// instead of panicking. 844func (v Value) Decimal128OK() (primitive.Decimal128, bool) { 845 if v.Type != bsontype.Decimal128 { 846 return primitive.Decimal128{}, false 847 } 848 d128, _, ok := ReadDecimal128(v.Data) 849 if !ok { 850 return primitive.Decimal128{}, false 851 } 852 return d128, true 853} 854 855var hexChars = "0123456789abcdef" 856 857func escapeString(s string) string { 858 escapeHTML := true 859 var buf bytes.Buffer 860 buf.WriteByte('"') 861 start := 0 862 for i := 0; i < len(s); { 863 if b := s[i]; b < utf8.RuneSelf { 864 if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) { 865 i++ 866 continue 867 } 868 if start < i { 869 buf.WriteString(s[start:i]) 870 } 871 switch b { 872 case '\\', '"': 873 buf.WriteByte('\\') 874 buf.WriteByte(b) 875 case '\n': 876 buf.WriteByte('\\') 877 buf.WriteByte('n') 878 case '\r': 879 buf.WriteByte('\\') 880 buf.WriteByte('r') 881 case '\t': 882 buf.WriteByte('\\') 883 buf.WriteByte('t') 884 case '\b': 885 buf.WriteByte('\\') 886 buf.WriteByte('b') 887 case '\f': 888 buf.WriteByte('\\') 889 buf.WriteByte('f') 890 default: 891 // This encodes bytes < 0x20 except for \t, \n and \r. 892 // If escapeHTML is set, it also escapes <, >, and & 893 // because they can lead to security holes when 894 // user-controlled strings are rendered into JSON 895 // and served to some browsers. 896 buf.WriteString(`\u00`) 897 buf.WriteByte(hexChars[b>>4]) 898 buf.WriteByte(hexChars[b&0xF]) 899 } 900 i++ 901 start = i 902 continue 903 } 904 c, size := utf8.DecodeRuneInString(s[i:]) 905 if c == utf8.RuneError && size == 1 { 906 if start < i { 907 buf.WriteString(s[start:i]) 908 } 909 buf.WriteString(`\ufffd`) 910 i += size 911 start = i 912 continue 913 } 914 // U+2028 is LINE SEPARATOR. 915 // U+2029 is PARAGRAPH SEPARATOR. 916 // They are both technically valid characters in JSON strings, 917 // but don't work in JSONP, which has to be evaluated as JavaScript, 918 // and can lead to security holes there. It is valid JSON to 919 // escape them, so we do so unconditionally. 920 // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. 921 if c == '\u2028' || c == '\u2029' { 922 if start < i { 923 buf.WriteString(s[start:i]) 924 } 925 buf.WriteString(`\u202`) 926 buf.WriteByte(hexChars[c&0xF]) 927 i += size 928 start = i 929 continue 930 } 931 i += size 932 } 933 if start < len(s) { 934 buf.WriteString(s[start:]) 935 } 936 buf.WriteByte('"') 937 return buf.String() 938} 939 940func formatDouble(f float64) string { 941 var s string 942 if math.IsInf(f, 1) { 943 s = "Infinity" 944 } else if math.IsInf(f, -1) { 945 s = "-Infinity" 946 } else if math.IsNaN(f) { 947 s = "NaN" 948 } else { 949 // Print exactly one decimalType place for integers; otherwise, print as many are necessary to 950 // perfectly represent it. 951 s = strconv.FormatFloat(f, 'G', -1, 64) 952 if !strings.ContainsRune(s, '.') { 953 s += ".0" 954 } 955 } 956 957 return s 958} 959 960type sortableString []rune 961 962func (ss sortableString) Len() int { 963 return len(ss) 964} 965 966func (ss sortableString) Less(i, j int) bool { 967 return ss[i] < ss[j] 968} 969 970func (ss sortableString) Swap(i, j int) { 971 oldI := ss[i] 972 ss[i] = ss[j] 973 ss[j] = oldI 974} 975 976func sortStringAlphebeticAscending(s string) string { 977 ss := sortableString([]rune(s)) 978 sort.Sort(ss) 979 return string([]rune(ss)) 980} 981