diff options
Diffstat (limited to 'src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go')
-rw-r--r-- | src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go | 1015 |
1 files changed, 0 insertions, 1015 deletions
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go deleted file mode 100644 index ca29815495c..00000000000 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/go.mongodb.org/mongo-driver/x/bsonx/bsoncore/value.go +++ /dev/null @@ -1,1015 +0,0 @@ -// Copyright (C) MongoDB, Inc. 2017-present. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -package bsoncore - -import ( - "bytes" - "encoding/base64" - "fmt" - "math" - "sort" - "strconv" - "strings" - "time" - "unicode/utf8" - - "go.mongodb.org/mongo-driver/bson/bsontype" - "go.mongodb.org/mongo-driver/bson/primitive" -) - -// ElementTypeError specifies that a method to obtain a BSON value an incorrect type was called on a bson.Value. -type ElementTypeError struct { - Method string - Type bsontype.Type -} - -// Error implements the error interface. -func (ete ElementTypeError) Error() string { - return "Call of " + ete.Method + " on " + ete.Type.String() + " type" -} - -// Value represents a BSON value with a type and raw bytes. -type Value struct { - Type bsontype.Type - Data []byte -} - -// Validate ensures the value is a valid BSON value. -func (v Value) Validate() error { - _, _, valid := readValue(v.Data, v.Type) - if !valid { - return NewInsufficientBytesError(v.Data, v.Data) - } - return nil -} - -// IsNumber returns true if the type of v is a numeric BSON type. -func (v Value) IsNumber() bool { - switch v.Type { - case bsontype.Double, bsontype.Int32, bsontype.Int64, bsontype.Decimal128: - return true - default: - return false - } -} - -// AsInt32 returns a BSON number as an int32. If the BSON type is not a numeric one, this method -// will panic. -// -// TODO(skriptble): Add support for Decimal128. -func (v Value) AsInt32() int32 { - if !v.IsNumber() { - panic(ElementTypeError{"bsoncore.Value.AsInt32", v.Type}) - } - var i32 int32 - switch v.Type { - case bsontype.Double: - f64, _, ok := ReadDouble(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - i32 = int32(f64) - case bsontype.Int32: - var ok bool - i32, _, ok = ReadInt32(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - case bsontype.Int64: - i64, _, ok := ReadInt64(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - i32 = int32(i64) - case bsontype.Decimal128: - panic(ElementTypeError{"bsoncore.Value.AsInt32", v.Type}) - } - return i32 -} - -// AsInt32OK functions the same as AsInt32 but returns a boolean instead of panicking. False -// indicates an error. -// -// TODO(skriptble): Add support for Decimal128. -func (v Value) AsInt32OK() (int32, bool) { - if !v.IsNumber() { - return 0, false - } - var i32 int32 - switch v.Type { - case bsontype.Double: - f64, _, ok := ReadDouble(v.Data) - if !ok { - return 0, false - } - i32 = int32(f64) - case bsontype.Int32: - var ok bool - i32, _, ok = ReadInt32(v.Data) - if !ok { - return 0, false - } - case bsontype.Int64: - i64, _, ok := ReadInt64(v.Data) - if !ok { - return 0, false - } - i32 = int32(i64) - case bsontype.Decimal128: - return 0, false - } - return i32, true -} - -// AsInt64 returns a BSON number as an int64. If the BSON type is not a numeric one, this method -// will panic. -// -// TODO(skriptble): Add support for Decimal128. -func (v Value) AsInt64() int64 { - if !v.IsNumber() { - panic(ElementTypeError{"bsoncore.Value.AsInt64", v.Type}) - } - var i64 int64 - switch v.Type { - case bsontype.Double: - f64, _, ok := ReadDouble(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - i64 = int64(f64) - case bsontype.Int32: - var ok bool - i32, _, ok := ReadInt32(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - i64 = int64(i32) - case bsontype.Int64: - var ok bool - i64, _, ok = ReadInt64(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - case bsontype.Decimal128: - panic(ElementTypeError{"bsoncore.Value.AsInt64", v.Type}) - } - return i64 -} - -// AsInt64OK functions the same as AsInt64 but returns a boolean instead of panicking. False -// indicates an error. -// -// TODO(skriptble): Add support for Decimal128. -func (v Value) AsInt64OK() (int64, bool) { - if !v.IsNumber() { - return 0, false - } - var i64 int64 - switch v.Type { - case bsontype.Double: - f64, _, ok := ReadDouble(v.Data) - if !ok { - return 0, false - } - i64 = int64(f64) - case bsontype.Int32: - var ok bool - i32, _, ok := ReadInt32(v.Data) - if !ok { - return 0, false - } - i64 = int64(i32) - case bsontype.Int64: - var ok bool - i64, _, ok = ReadInt64(v.Data) - if !ok { - return 0, false - } - case bsontype.Decimal128: - return 0, false - } - return i64, true -} - -// AsFloat64 returns a BSON number as an float64. If the BSON type is not a numeric one, this method -// will panic. -// -// TODO(skriptble): Add support for Decimal128. -func (v Value) AsFloat64() float64 { return 0 } - -// AsFloat64OK functions the same as AsFloat64 but returns a boolean instead of panicking. False -// indicates an error. -// -// TODO(skriptble): Add support for Decimal128. -func (v Value) AsFloat64OK() (float64, bool) { return 0, false } - -// Add will add this value to another. This is currently only implemented for strings and numbers. -// If either value is a string, the other type is coerced into a string and added to the other. -// -// This method will alter v and will attempt to reuse the []byte of v. If the []byte is too small, -// it will be expanded. -func (v *Value) Add(v2 Value) error { return nil } - -// Equal compaes v to v2 and returns true if they are equal. -func (v Value) Equal(v2 Value) bool { - if v.Type != v2.Type { - return false - } - - return bytes.Equal(v.Data, v2.Data) -} - -// String implements the fmt.String interface. This method will return values in extended JSON -// format. If the value is not valid, this returns an empty string -func (v Value) String() string { - switch v.Type { - case bsontype.Double: - f64, ok := v.DoubleOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$numberDouble":"%s"}`, formatDouble(f64)) - case bsontype.String: - str, ok := v.StringValueOK() - if !ok { - return "" - } - return escapeString(str) - case bsontype.EmbeddedDocument: - doc, ok := v.DocumentOK() - if !ok { - return "" - } - return doc.String() - case bsontype.Array: - arr, ok := v.ArrayOK() - if !ok { - return "" - } - return docAsArray(arr, false) - case bsontype.Binary: - subtype, data, ok := v.BinaryOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$binary":{"base64":"%s","subType":"%02x"}}`, base64.StdEncoding.EncodeToString(data), subtype) - case bsontype.Undefined: - return `{"$undefined":true}` - case bsontype.ObjectID: - oid, ok := v.ObjectIDOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$oid":"%s"}`, oid.Hex()) - case bsontype.Boolean: - b, ok := v.BooleanOK() - if !ok { - return "" - } - return strconv.FormatBool(b) - case bsontype.DateTime: - dt, ok := v.DateTimeOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$date":{"$numberLong":"%d"}}`, dt) - case bsontype.Null: - return "null" - case bsontype.Regex: - pattern, options, ok := v.RegexOK() - if !ok { - return "" - } - return fmt.Sprintf( - `{"$regularExpression":{"pattern":%s,"options":"%s"}}`, - escapeString(pattern), sortStringAlphebeticAscending(options), - ) - case bsontype.DBPointer: - ns, pointer, ok := v.DBPointerOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$dbPointer":{"$ref":%s,"$id":{"$oid":"%s"}}}`, escapeString(ns), pointer.Hex()) - case bsontype.JavaScript: - js, ok := v.JavaScriptOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$code":%s}`, escapeString(js)) - case bsontype.Symbol: - symbol, ok := v.SymbolOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$symbol":%s}`, escapeString(symbol)) - case bsontype.CodeWithScope: - code, scope, ok := v.CodeWithScopeOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$code":%s,"$scope":%s}`, code, scope) - case bsontype.Int32: - i32, ok := v.Int32OK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$numberInt":"%d"}`, i32) - case bsontype.Timestamp: - t, i, ok := v.TimestampOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$timestamp":{"t":"%s","i":"%s"}}`, strconv.FormatUint(uint64(t), 10), strconv.FormatUint(uint64(i), 10)) - case bsontype.Int64: - i64, ok := v.Int64OK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$numberLong":"%d"}`, i64) - case bsontype.Decimal128: - d128, ok := v.Decimal128OK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$numberDecimal":"%s"}`, d128.String()) - case bsontype.MinKey: - return `{"$minKey":1}` - case bsontype.MaxKey: - return `{"$maxKey":1}` - default: - return "" - } -} - -// DebugString outputs a human readable version of Document. It will attempt to stringify the -// valid components of the document even if the entire document is not valid. -func (v Value) DebugString() string { - switch v.Type { - case bsontype.String: - str, ok := v.StringValueOK() - if !ok { - return "<malformed>" - } - return escapeString(str) - case bsontype.EmbeddedDocument: - doc, ok := v.DocumentOK() - if !ok { - return "<malformed>" - } - return doc.DebugString() - case bsontype.Array: - arr, ok := v.ArrayOK() - if !ok { - return "<malformed>" - } - return docAsArray(arr, true) - case bsontype.CodeWithScope: - code, scope, ok := v.CodeWithScopeOK() - if !ok { - return "" - } - return fmt.Sprintf(`{"$code":%s,"$scope":%s}`, code, scope.DebugString()) - default: - str := v.String() - if str == "" { - return "<malformed>" - } - return str - } -} - -// Double returns the float64 value for this element. -// It panics if e's BSON type is not bsontype.Double. -func (v Value) Double() float64 { - if v.Type != bsontype.Double { - panic(ElementTypeError{"bsoncore.Value.Double", v.Type}) - } - f64, _, ok := ReadDouble(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return f64 -} - -// DoubleOK is the same as Double, but returns a boolean instead of panicking. -func (v Value) DoubleOK() (float64, bool) { - if v.Type != bsontype.Double { - return 0, false - } - f64, _, ok := ReadDouble(v.Data) - if !ok { - return 0, false - } - return f64, true -} - -// StringValue returns the string balue for this element. -// It panics if e's BSON type is not bsontype.String. -// -// NOTE: This method is called StringValue to avoid a collision with the String method which -// implements the fmt.Stringer interface. -func (v Value) StringValue() string { - if v.Type != bsontype.String { - panic(ElementTypeError{"bsoncore.Value.StringValue", v.Type}) - } - str, _, ok := ReadString(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return str -} - -// StringValueOK is the same as StringValue, but returns a boolean instead of -// panicking. -func (v Value) StringValueOK() (string, bool) { - if v.Type != bsontype.String { - return "", false - } - str, _, ok := ReadString(v.Data) - if !ok { - return "", false - } - return str, true -} - -// Document returns the BSON document the Value represents as a Document. It panics if the -// value is a BSON type other than document. -func (v Value) Document() Document { - if v.Type != bsontype.EmbeddedDocument { - panic(ElementTypeError{"bsoncore.Value.Document", v.Type}) - } - doc, _, ok := ReadDocument(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return doc -} - -// DocumentOK is the same as Document, except it returns a boolean -// instead of panicking. -func (v Value) DocumentOK() (Document, bool) { - if v.Type != bsontype.EmbeddedDocument { - return nil, false - } - doc, _, ok := ReadDocument(v.Data) - if !ok { - return nil, false - } - return doc, true -} - -// Array returns the BSON array the Value represents as an Array. It panics if the -// value is a BSON type other than array. -func (v Value) Array() Document { - if v.Type != bsontype.Array { - panic(ElementTypeError{"bsoncore.Value.Array", v.Type}) - } - arr, _, ok := ReadArray(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return arr -} - -// ArrayOK is the same as Array, except it returns a boolean instead -// of panicking. -func (v Value) ArrayOK() (Document, bool) { - if v.Type != bsontype.Array { - return nil, false - } - arr, _, ok := ReadArray(v.Data) - if !ok { - return nil, false - } - return arr, true -} - -// Binary returns the BSON binary value the Value represents. It panics if the value is a BSON type -// other than binary. -func (v Value) Binary() (subtype byte, data []byte) { - if v.Type != bsontype.Binary { - panic(ElementTypeError{"bsoncore.Value.Binary", v.Type}) - } - subtype, data, _, ok := ReadBinary(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return subtype, data -} - -// BinaryOK is the same as Binary, except it returns a boolean instead of -// panicking. -func (v Value) BinaryOK() (subtype byte, data []byte, ok bool) { - if v.Type != bsontype.Binary { - return 0x00, nil, false - } - subtype, data, _, ok = ReadBinary(v.Data) - if !ok { - return 0x00, nil, false - } - return subtype, data, true -} - -// ObjectID returns the BSON objectid value the Value represents. It panics if the value is a BSON -// type other than objectid. -func (v Value) ObjectID() primitive.ObjectID { - if v.Type != bsontype.ObjectID { - panic(ElementTypeError{"bsoncore.Value.ObjectID", v.Type}) - } - oid, _, ok := ReadObjectID(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return oid -} - -// ObjectIDOK is the same as ObjectID, except it returns a boolean instead of -// panicking. -func (v Value) ObjectIDOK() (primitive.ObjectID, bool) { - if v.Type != bsontype.ObjectID { - return primitive.ObjectID{}, false - } - oid, _, ok := ReadObjectID(v.Data) - if !ok { - return primitive.ObjectID{}, false - } - return oid, true -} - -// Boolean returns the boolean value the Value represents. It panics if the -// value is a BSON type other than boolean. -func (v Value) Boolean() bool { - if v.Type != bsontype.Boolean { - panic(ElementTypeError{"bsoncore.Value.Boolean", v.Type}) - } - b, _, ok := ReadBoolean(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return b -} - -// BooleanOK is the same as Boolean, except it returns a boolean instead of -// panicking. -func (v Value) BooleanOK() (bool, bool) { - if v.Type != bsontype.Boolean { - return false, false - } - b, _, ok := ReadBoolean(v.Data) - if !ok { - return false, false - } - return b, true -} - -// DateTime returns the BSON datetime value the Value represents as a -// unix timestamp. It panics if the value is a BSON type other than datetime. -func (v Value) DateTime() int64 { - if v.Type != bsontype.DateTime { - panic(ElementTypeError{"bsoncore.Value.DateTime", v.Type}) - } - dt, _, ok := ReadDateTime(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return dt -} - -// DateTimeOK is the same as DateTime, except it returns a boolean instead of -// panicking. -func (v Value) DateTimeOK() (int64, bool) { - if v.Type != bsontype.DateTime { - return 0, false - } - dt, _, ok := ReadDateTime(v.Data) - if !ok { - return 0, false - } - return dt, true -} - -// Time returns the BSON datetime value the Value represents. It panics if the value is a BSON -// type other than datetime. -func (v Value) Time() time.Time { - if v.Type != bsontype.DateTime { - panic(ElementTypeError{"bsoncore.Value.Time", v.Type}) - } - dt, _, ok := ReadDateTime(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return time.Unix(int64(dt)/1000, int64(dt)%1000*1000000) -} - -// TimeOK is the same as Time, except it returns a boolean instead of -// panicking. -func (v Value) TimeOK() (time.Time, bool) { - if v.Type != bsontype.DateTime { - return time.Time{}, false - } - dt, _, ok := ReadDateTime(v.Data) - if !ok { - return time.Time{}, false - } - return time.Unix(int64(dt)/1000, int64(dt)%1000*1000000), true -} - -// Regex returns the BSON regex value the Value represents. It panics if the value is a BSON -// type other than regex. -func (v Value) Regex() (pattern, options string) { - if v.Type != bsontype.Regex { - panic(ElementTypeError{"bsoncore.Value.Regex", v.Type}) - } - pattern, options, _, ok := ReadRegex(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return pattern, options -} - -// RegexOK is the same as Regex, except it returns a boolean instead of -// panicking. -func (v Value) RegexOK() (pattern, options string, ok bool) { - if v.Type != bsontype.Regex { - return "", "", false - } - pattern, options, _, ok = ReadRegex(v.Data) - if !ok { - return "", "", false - } - return pattern, options, true -} - -// DBPointer returns the BSON dbpointer value the Value represents. It panics if the value is a BSON -// type other than DBPointer. -func (v Value) DBPointer() (string, primitive.ObjectID) { - if v.Type != bsontype.DBPointer { - panic(ElementTypeError{"bsoncore.Value.DBPointer", v.Type}) - } - ns, pointer, _, ok := ReadDBPointer(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return ns, pointer -} - -// DBPointerOK is the same as DBPoitner, except that it returns a boolean -// instead of panicking. -func (v Value) DBPointerOK() (string, primitive.ObjectID, bool) { - if v.Type != bsontype.DBPointer { - return "", primitive.ObjectID{}, false - } - ns, pointer, _, ok := ReadDBPointer(v.Data) - if !ok { - return "", primitive.ObjectID{}, false - } - return ns, pointer, true -} - -// JavaScript returns the BSON JavaScript code value the Value represents. It panics if the value is -// a BSON type other than JavaScript code. -func (v Value) JavaScript() string { - if v.Type != bsontype.JavaScript { - panic(ElementTypeError{"bsoncore.Value.JavaScript", v.Type}) - } - js, _, ok := ReadJavaScript(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return js -} - -// JavaScriptOK is the same as Javascript, excepti that it returns a boolean -// instead of panicking. -func (v Value) JavaScriptOK() (string, bool) { - if v.Type != bsontype.JavaScript { - return "", false - } - js, _, ok := ReadJavaScript(v.Data) - if !ok { - return "", false - } - return js, true -} - -// Symbol returns the BSON symbol value the Value represents. It panics if the value is a BSON -// type other than symbol. -func (v Value) Symbol() string { - if v.Type != bsontype.Symbol { - panic(ElementTypeError{"bsoncore.Value.Symbol", v.Type}) - } - symbol, _, ok := ReadSymbol(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return symbol -} - -// SymbolOK is the same as Symbol, excepti that it returns a boolean -// instead of panicking. -func (v Value) SymbolOK() (string, bool) { - if v.Type != bsontype.Symbol { - return "", false - } - symbol, _, ok := ReadSymbol(v.Data) - if !ok { - return "", false - } - return symbol, true -} - -// CodeWithScope returns the BSON JavaScript code with scope the Value represents. -// It panics if the value is a BSON type other than JavaScript code with scope. -func (v Value) CodeWithScope() (string, Document) { - if v.Type != bsontype.CodeWithScope { - panic(ElementTypeError{"bsoncore.Value.CodeWithScope", v.Type}) - } - code, scope, _, ok := ReadCodeWithScope(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return code, scope -} - -// CodeWithScopeOK is the same as CodeWithScope, except that it returns a boolean instead of -// panicking. -func (v Value) CodeWithScopeOK() (string, Document, bool) { - if v.Type != bsontype.CodeWithScope { - return "", nil, false - } - code, scope, _, ok := ReadCodeWithScope(v.Data) - if !ok { - return "", nil, false - } - return code, scope, true -} - -// Int32 returns the int32 the Value represents. It panics if the value is a BSON type other than -// int32. -func (v Value) Int32() int32 { - if v.Type != bsontype.Int32 { - panic(ElementTypeError{"bsoncore.Value.Int32", v.Type}) - } - i32, _, ok := ReadInt32(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return i32 -} - -// Int32OK is the same as Int32, except that it returns a boolean instead of -// panicking. -func (v Value) Int32OK() (int32, bool) { - if v.Type != bsontype.Int32 { - return 0, false - } - i32, _, ok := ReadInt32(v.Data) - if !ok { - return 0, false - } - return i32, true -} - -// Timestamp returns the BSON timestamp value the Value represents. It panics if the value is a -// BSON type other than timestamp. -func (v Value) Timestamp() (t, i uint32) { - if v.Type != bsontype.Timestamp { - panic(ElementTypeError{"bsoncore.Value.Timestamp", v.Type}) - } - t, i, _, ok := ReadTimestamp(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return t, i -} - -// TimestampOK is the same as Timestamp, except that it returns a boolean -// instead of panicking. -func (v Value) TimestampOK() (t, i uint32, ok bool) { - if v.Type != bsontype.Timestamp { - return 0, 0, false - } - t, i, _, ok = ReadTimestamp(v.Data) - if !ok { - return 0, 0, false - } - return t, i, true -} - -// Int64 returns the int64 the Value represents. It panics if the value is a BSON type other than -// int64. -func (v Value) Int64() int64 { - if v.Type != bsontype.Int64 { - panic(ElementTypeError{"bsoncore.Value.Int64", v.Type}) - } - i64, _, ok := ReadInt64(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return i64 -} - -// Int64OK is the same as Int64, except that it returns a boolean instead of -// panicking. -func (v Value) Int64OK() (int64, bool) { - if v.Type != bsontype.Int64 { - return 0, false - } - i64, _, ok := ReadInt64(v.Data) - if !ok { - return 0, false - } - return i64, true -} - -// Decimal128 returns the decimal the Value represents. It panics if the value is a BSON type other than -// decimal. -func (v Value) Decimal128() primitive.Decimal128 { - if v.Type != bsontype.Decimal128 { - panic(ElementTypeError{"bsoncore.Value.Decimal128", v.Type}) - } - d128, _, ok := ReadDecimal128(v.Data) - if !ok { - panic(NewInsufficientBytesError(v.Data, v.Data)) - } - return d128 -} - -// Decimal128OK is the same as Decimal128, except that it returns a boolean -// instead of panicking. -func (v Value) Decimal128OK() (primitive.Decimal128, bool) { - if v.Type != bsontype.Decimal128 { - return primitive.Decimal128{}, false - } - d128, _, ok := ReadDecimal128(v.Data) - if !ok { - return primitive.Decimal128{}, false - } - return d128, true -} - -var hexChars = "0123456789abcdef" - -func escapeString(s string) string { - escapeHTML := true - var buf bytes.Buffer - buf.WriteByte('"') - start := 0 - for i := 0; i < len(s); { - if b := s[i]; b < utf8.RuneSelf { - if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) { - i++ - continue - } - if start < i { - buf.WriteString(s[start:i]) - } - switch b { - case '\\', '"': - buf.WriteByte('\\') - buf.WriteByte(b) - case '\n': - buf.WriteByte('\\') - buf.WriteByte('n') - case '\r': - buf.WriteByte('\\') - buf.WriteByte('r') - case '\t': - buf.WriteByte('\\') - buf.WriteByte('t') - case '\b': - buf.WriteByte('\\') - buf.WriteByte('b') - case '\f': - buf.WriteByte('\\') - buf.WriteByte('f') - default: - // This encodes bytes < 0x20 except for \t, \n and \r. - // If escapeHTML is set, it also escapes <, >, and & - // because they can lead to security holes when - // user-controlled strings are rendered into JSON - // and served to some browsers. - buf.WriteString(`\u00`) - buf.WriteByte(hexChars[b>>4]) - buf.WriteByte(hexChars[b&0xF]) - } - i++ - start = i - continue - } - c, size := utf8.DecodeRuneInString(s[i:]) - if c == utf8.RuneError && size == 1 { - if start < i { - buf.WriteString(s[start:i]) - } - buf.WriteString(`\ufffd`) - i += size - start = i - continue - } - // U+2028 is LINE SEPARATOR. - // U+2029 is PARAGRAPH SEPARATOR. - // They are both technically valid characters in JSON strings, - // but don't work in JSONP, which has to be evaluated as JavaScript, - // and can lead to security holes there. It is valid JSON to - // escape them, so we do so unconditionally. - // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. - if c == '\u2028' || c == '\u2029' { - if start < i { - buf.WriteString(s[start:i]) - } - buf.WriteString(`\u202`) - buf.WriteByte(hexChars[c&0xF]) - i += size - start = i - continue - } - i += size - } - if start < len(s) { - buf.WriteString(s[start:]) - } - buf.WriteByte('"') - return buf.String() -} - -func formatDouble(f float64) string { - var s string - if math.IsInf(f, 1) { - s = "Infinity" - } else if math.IsInf(f, -1) { - s = "-Infinity" - } else if math.IsNaN(f) { - s = "NaN" - } else { - // Print exactly one decimalType place for integers; otherwise, print as many are necessary to - // perfectly represent it. - s = strconv.FormatFloat(f, 'G', -1, 64) - if !strings.ContainsRune(s, '.') { - s += ".0" - } - } - - return s -} - -type sortableString []rune - -func (ss sortableString) Len() int { - return len(ss) -} - -func (ss sortableString) Less(i, j int) bool { - return ss[i] < ss[j] -} - -func (ss sortableString) Swap(i, j int) { - oldI := ss[i] - ss[i] = ss[j] - ss[j] = oldI -} - -func sortStringAlphebeticAscending(s string) string { - ss := sortableString([]rune(s)) - sort.Sort(ss) - return string([]rune(ss)) -} - -func docAsArray(d Document, debug bool) string { - if len(d) < 5 { - return "" - } - var buf bytes.Buffer - buf.WriteByte('[') - - length, rem, _ := ReadLength(d) // We know we have enough bytes to read the length - - length -= 4 - - var elem Element - var ok bool - first := true - for length > 1 { - if !first { - buf.WriteByte(',') - } - elem, rem, ok = ReadElement(rem) - length -= int32(len(elem)) - if !ok { - return "" - } - if debug { - fmt.Fprintf(&buf, "%s ", elem.Value().DebugString()) - } else { - fmt.Fprintf(&buf, "%s", elem.Value()) - } - first = false - } - buf.WriteByte(']') - - return buf.String() -} |