...

Source file src/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go

Documentation: go.mongodb.org/mongo-driver/x/bsonx/bsoncore

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

View as plain text