diff options
Diffstat (limited to 'vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go')
-rw-r--r-- | vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go | 751 |
1 files changed, 0 insertions, 751 deletions
diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go deleted file mode 100644 index bb9303167..000000000 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_writer.go +++ /dev/null @@ -1,751 +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 bsonrw - -import ( - "bytes" - "encoding/base64" - "fmt" - "io" - "math" - "sort" - "strconv" - "strings" - "sync" - "time" - "unicode/utf8" - - "go.mongodb.org/mongo-driver/bson/primitive" -) - -// ExtJSONValueWriterPool is a pool for ExtJSON ValueWriters. -// -// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. -type ExtJSONValueWriterPool struct { - pool sync.Pool -} - -// NewExtJSONValueWriterPool creates a new pool for ValueWriter instances that write to ExtJSON. -// -// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. -func NewExtJSONValueWriterPool() *ExtJSONValueWriterPool { - return &ExtJSONValueWriterPool{ - pool: sync.Pool{ - New: func() interface{} { - return new(extJSONValueWriter) - }, - }, - } -} - -// Get retrieves a ExtJSON ValueWriter from the pool and resets it to use w as the destination. -// -// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. -func (bvwp *ExtJSONValueWriterPool) Get(w io.Writer, canonical, escapeHTML bool) ValueWriter { - vw := bvwp.pool.Get().(*extJSONValueWriter) - if writer, ok := w.(*SliceWriter); ok { - vw.reset(*writer, canonical, escapeHTML) - vw.w = writer - return vw - } - vw.buf = vw.buf[:0] - vw.w = w - return vw -} - -// Put inserts a ValueWriter into the pool. If the ValueWriter is not a ExtJSON ValueWriter, nothing -// happens and ok will be false. -// -// Deprecated: ExtJSONValueWriterPool will not be supported in Go Driver 2.0. -func (bvwp *ExtJSONValueWriterPool) Put(vw ValueWriter) (ok bool) { - bvw, ok := vw.(*extJSONValueWriter) - if !ok { - return false - } - - if _, ok := bvw.w.(*SliceWriter); ok { - bvw.buf = nil - } - bvw.w = nil - - bvwp.pool.Put(bvw) - return true -} - -type ejvwState struct { - mode mode -} - -type extJSONValueWriter struct { - w io.Writer - buf []byte - - stack []ejvwState - frame int64 - canonical bool - escapeHTML bool - newlines bool -} - -// NewExtJSONValueWriter creates a ValueWriter that writes Extended JSON to w. -func NewExtJSONValueWriter(w io.Writer, canonical, escapeHTML bool) (ValueWriter, error) { - if w == nil { - return nil, errNilWriter - } - - // Enable newlines for all Extended JSON value writers created by NewExtJSONValueWriter. We - // expect these value writers to be used with an Encoder, which should add newlines after - // encoded Extended JSON documents. - return newExtJSONWriter(w, canonical, escapeHTML, true), nil -} - -func newExtJSONWriter(w io.Writer, canonical, escapeHTML, newlines bool) *extJSONValueWriter { - stack := make([]ejvwState, 1, 5) - stack[0] = ejvwState{mode: mTopLevel} - - return &extJSONValueWriter{ - w: w, - buf: []byte{}, - stack: stack, - canonical: canonical, - escapeHTML: escapeHTML, - newlines: newlines, - } -} - -func newExtJSONWriterFromSlice(buf []byte, canonical, escapeHTML bool) *extJSONValueWriter { - stack := make([]ejvwState, 1, 5) - stack[0] = ejvwState{mode: mTopLevel} - - return &extJSONValueWriter{ - buf: buf, - stack: stack, - canonical: canonical, - escapeHTML: escapeHTML, - } -} - -func (ejvw *extJSONValueWriter) reset(buf []byte, canonical, escapeHTML bool) { - if ejvw.stack == nil { - ejvw.stack = make([]ejvwState, 1, 5) - } - - ejvw.stack = ejvw.stack[:1] - ejvw.stack[0] = ejvwState{mode: mTopLevel} - ejvw.canonical = canonical - ejvw.escapeHTML = escapeHTML - ejvw.frame = 0 - ejvw.buf = buf - ejvw.w = nil -} - -func (ejvw *extJSONValueWriter) advanceFrame() { - if ejvw.frame+1 >= int64(len(ejvw.stack)) { // We need to grow the stack - length := len(ejvw.stack) - if length+1 >= cap(ejvw.stack) { - // double it - buf := make([]ejvwState, 2*cap(ejvw.stack)+1) - copy(buf, ejvw.stack) - ejvw.stack = buf - } - ejvw.stack = ejvw.stack[:length+1] - } - ejvw.frame++ -} - -func (ejvw *extJSONValueWriter) push(m mode) { - ejvw.advanceFrame() - - ejvw.stack[ejvw.frame].mode = m -} - -func (ejvw *extJSONValueWriter) pop() { - switch ejvw.stack[ejvw.frame].mode { - case mElement, mValue: - ejvw.frame-- - case mDocument, mArray, mCodeWithScope: - ejvw.frame -= 2 // we pop twice to jump over the mElement: mDocument -> mElement -> mDocument/mTopLevel/etc... - } -} - -func (ejvw *extJSONValueWriter) invalidTransitionErr(destination mode, name string, modes []mode) error { - te := TransitionError{ - name: name, - current: ejvw.stack[ejvw.frame].mode, - destination: destination, - modes: modes, - action: "write", - } - if ejvw.frame != 0 { - te.parent = ejvw.stack[ejvw.frame-1].mode - } - return te -} - -func (ejvw *extJSONValueWriter) ensureElementValue(destination mode, callerName string, addmodes ...mode) error { - switch ejvw.stack[ejvw.frame].mode { - case mElement, mValue: - default: - modes := []mode{mElement, mValue} - if addmodes != nil { - modes = append(modes, addmodes...) - } - return ejvw.invalidTransitionErr(destination, callerName, modes) - } - - return nil -} - -func (ejvw *extJSONValueWriter) writeExtendedSingleValue(key string, value string, quotes bool) { - var s string - if quotes { - s = fmt.Sprintf(`{"$%s":"%s"}`, key, value) - } else { - s = fmt.Sprintf(`{"$%s":%s}`, key, value) - } - - ejvw.buf = append(ejvw.buf, []byte(s)...) -} - -func (ejvw *extJSONValueWriter) WriteArray() (ArrayWriter, error) { - if err := ejvw.ensureElementValue(mArray, "WriteArray"); err != nil { - return nil, err - } - - ejvw.buf = append(ejvw.buf, '[') - - ejvw.push(mArray) - return ejvw, nil -} - -func (ejvw *extJSONValueWriter) WriteBinary(b []byte) error { - return ejvw.WriteBinaryWithSubtype(b, 0x00) -} - -func (ejvw *extJSONValueWriter) WriteBinaryWithSubtype(b []byte, btype byte) error { - if err := ejvw.ensureElementValue(mode(0), "WriteBinaryWithSubtype"); err != nil { - return err - } - - var buf bytes.Buffer - buf.WriteString(`{"$binary":{"base64":"`) - buf.WriteString(base64.StdEncoding.EncodeToString(b)) - buf.WriteString(fmt.Sprintf(`","subType":"%02x"}},`, btype)) - - ejvw.buf = append(ejvw.buf, buf.Bytes()...) - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteBoolean(b bool) error { - if err := ejvw.ensureElementValue(mode(0), "WriteBoolean"); err != nil { - return err - } - - ejvw.buf = append(ejvw.buf, []byte(strconv.FormatBool(b))...) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteCodeWithScope(code string) (DocumentWriter, error) { - if err := ejvw.ensureElementValue(mCodeWithScope, "WriteCodeWithScope"); err != nil { - return nil, err - } - - var buf bytes.Buffer - buf.WriteString(`{"$code":`) - writeStringWithEscapes(code, &buf, ejvw.escapeHTML) - buf.WriteString(`,"$scope":{`) - - ejvw.buf = append(ejvw.buf, buf.Bytes()...) - - ejvw.push(mCodeWithScope) - return ejvw, nil -} - -func (ejvw *extJSONValueWriter) WriteDBPointer(ns string, oid primitive.ObjectID) error { - if err := ejvw.ensureElementValue(mode(0), "WriteDBPointer"); err != nil { - return err - } - - var buf bytes.Buffer - buf.WriteString(`{"$dbPointer":{"$ref":"`) - buf.WriteString(ns) - buf.WriteString(`","$id":{"$oid":"`) - buf.WriteString(oid.Hex()) - buf.WriteString(`"}}},`) - - ejvw.buf = append(ejvw.buf, buf.Bytes()...) - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteDateTime(dt int64) error { - if err := ejvw.ensureElementValue(mode(0), "WriteDateTime"); err != nil { - return err - } - - t := time.Unix(dt/1e3, dt%1e3*1e6).UTC() - - if ejvw.canonical || t.Year() < 1970 || t.Year() > 9999 { - s := fmt.Sprintf(`{"$numberLong":"%d"}`, dt) - ejvw.writeExtendedSingleValue("date", s, false) - } else { - ejvw.writeExtendedSingleValue("date", t.Format(rfc3339Milli), true) - } - - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteDecimal128(d primitive.Decimal128) error { - if err := ejvw.ensureElementValue(mode(0), "WriteDecimal128"); err != nil { - return err - } - - ejvw.writeExtendedSingleValue("numberDecimal", d.String(), true) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteDocument() (DocumentWriter, error) { - if ejvw.stack[ejvw.frame].mode == mTopLevel { - ejvw.buf = append(ejvw.buf, '{') - return ejvw, nil - } - - if err := ejvw.ensureElementValue(mDocument, "WriteDocument", mTopLevel); err != nil { - return nil, err - } - - ejvw.buf = append(ejvw.buf, '{') - ejvw.push(mDocument) - return ejvw, nil -} - -func (ejvw *extJSONValueWriter) WriteDouble(f float64) error { - if err := ejvw.ensureElementValue(mode(0), "WriteDouble"); err != nil { - return err - } - - s := formatDouble(f) - - if ejvw.canonical { - ejvw.writeExtendedSingleValue("numberDouble", s, true) - } else { - switch s { - case "Infinity": - fallthrough - case "-Infinity": - fallthrough - case "NaN": - s = fmt.Sprintf(`{"$numberDouble":"%s"}`, s) - } - ejvw.buf = append(ejvw.buf, []byte(s)...) - } - - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteInt32(i int32) error { - if err := ejvw.ensureElementValue(mode(0), "WriteInt32"); err != nil { - return err - } - - s := strconv.FormatInt(int64(i), 10) - - if ejvw.canonical { - ejvw.writeExtendedSingleValue("numberInt", s, true) - } else { - ejvw.buf = append(ejvw.buf, []byte(s)...) - } - - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteInt64(i int64) error { - if err := ejvw.ensureElementValue(mode(0), "WriteInt64"); err != nil { - return err - } - - s := strconv.FormatInt(i, 10) - - if ejvw.canonical { - ejvw.writeExtendedSingleValue("numberLong", s, true) - } else { - ejvw.buf = append(ejvw.buf, []byte(s)...) - } - - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteJavascript(code string) error { - if err := ejvw.ensureElementValue(mode(0), "WriteJavascript"); err != nil { - return err - } - - var buf bytes.Buffer - writeStringWithEscapes(code, &buf, ejvw.escapeHTML) - - ejvw.writeExtendedSingleValue("code", buf.String(), false) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteMaxKey() error { - if err := ejvw.ensureElementValue(mode(0), "WriteMaxKey"); err != nil { - return err - } - - ejvw.writeExtendedSingleValue("maxKey", "1", false) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteMinKey() error { - if err := ejvw.ensureElementValue(mode(0), "WriteMinKey"); err != nil { - return err - } - - ejvw.writeExtendedSingleValue("minKey", "1", false) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteNull() error { - if err := ejvw.ensureElementValue(mode(0), "WriteNull"); err != nil { - return err - } - - ejvw.buf = append(ejvw.buf, []byte("null")...) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteObjectID(oid primitive.ObjectID) error { - if err := ejvw.ensureElementValue(mode(0), "WriteObjectID"); err != nil { - return err - } - - ejvw.writeExtendedSingleValue("oid", oid.Hex(), true) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteRegex(pattern string, options string) error { - if err := ejvw.ensureElementValue(mode(0), "WriteRegex"); err != nil { - return err - } - - var buf bytes.Buffer - buf.WriteString(`{"$regularExpression":{"pattern":`) - writeStringWithEscapes(pattern, &buf, ejvw.escapeHTML) - buf.WriteString(`,"options":"`) - buf.WriteString(sortStringAlphebeticAscending(options)) - buf.WriteString(`"}},`) - - ejvw.buf = append(ejvw.buf, buf.Bytes()...) - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteString(s string) error { - if err := ejvw.ensureElementValue(mode(0), "WriteString"); err != nil { - return err - } - - var buf bytes.Buffer - writeStringWithEscapes(s, &buf, ejvw.escapeHTML) - - ejvw.buf = append(ejvw.buf, buf.Bytes()...) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteSymbol(symbol string) error { - if err := ejvw.ensureElementValue(mode(0), "WriteSymbol"); err != nil { - return err - } - - var buf bytes.Buffer - writeStringWithEscapes(symbol, &buf, ejvw.escapeHTML) - - ejvw.writeExtendedSingleValue("symbol", buf.String(), false) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteTimestamp(t uint32, i uint32) error { - if err := ejvw.ensureElementValue(mode(0), "WriteTimestamp"); err != nil { - return err - } - - var buf bytes.Buffer - buf.WriteString(`{"$timestamp":{"t":`) - buf.WriteString(strconv.FormatUint(uint64(t), 10)) - buf.WriteString(`,"i":`) - buf.WriteString(strconv.FormatUint(uint64(i), 10)) - buf.WriteString(`}},`) - - ejvw.buf = append(ejvw.buf, buf.Bytes()...) - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteUndefined() error { - if err := ejvw.ensureElementValue(mode(0), "WriteUndefined"); err != nil { - return err - } - - ejvw.writeExtendedSingleValue("undefined", "true", false) - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteDocumentElement(key string) (ValueWriter, error) { - switch ejvw.stack[ejvw.frame].mode { - case mDocument, mTopLevel, mCodeWithScope: - var buf bytes.Buffer - writeStringWithEscapes(key, &buf, ejvw.escapeHTML) - - ejvw.buf = append(ejvw.buf, []byte(fmt.Sprintf(`%s:`, buf.String()))...) - ejvw.push(mElement) - default: - return nil, ejvw.invalidTransitionErr(mElement, "WriteDocumentElement", []mode{mDocument, mTopLevel, mCodeWithScope}) - } - - return ejvw, nil -} - -func (ejvw *extJSONValueWriter) WriteDocumentEnd() error { - switch ejvw.stack[ejvw.frame].mode { - case mDocument, mTopLevel, mCodeWithScope: - default: - return fmt.Errorf("incorrect mode to end document: %s", ejvw.stack[ejvw.frame].mode) - } - - // close the document - if ejvw.buf[len(ejvw.buf)-1] == ',' { - ejvw.buf[len(ejvw.buf)-1] = '}' - } else { - ejvw.buf = append(ejvw.buf, '}') - } - - switch ejvw.stack[ejvw.frame].mode { - case mCodeWithScope: - ejvw.buf = append(ejvw.buf, '}') - fallthrough - case mDocument: - ejvw.buf = append(ejvw.buf, ',') - case mTopLevel: - // If the value writer has newlines enabled, end top-level documents with a newline so that - // multiple documents encoded to the same writer are separated by newlines. That matches the - // Go json.Encoder behavior and also works with bsonrw.NewExtJSONValueReader. - if ejvw.newlines { - ejvw.buf = append(ejvw.buf, '\n') - } - if ejvw.w != nil { - if _, err := ejvw.w.Write(ejvw.buf); err != nil { - return err - } - ejvw.buf = ejvw.buf[:0] - } - } - - ejvw.pop() - return nil -} - -func (ejvw *extJSONValueWriter) WriteArrayElement() (ValueWriter, error) { - switch ejvw.stack[ejvw.frame].mode { - case mArray: - ejvw.push(mValue) - default: - return nil, ejvw.invalidTransitionErr(mValue, "WriteArrayElement", []mode{mArray}) - } - - return ejvw, nil -} - -func (ejvw *extJSONValueWriter) WriteArrayEnd() error { - switch ejvw.stack[ejvw.frame].mode { - case mArray: - // close the array - if ejvw.buf[len(ejvw.buf)-1] == ',' { - ejvw.buf[len(ejvw.buf)-1] = ']' - } else { - ejvw.buf = append(ejvw.buf, ']') - } - - ejvw.buf = append(ejvw.buf, ',') - - ejvw.pop() - default: - return fmt.Errorf("incorrect mode to end array: %s", ejvw.stack[ejvw.frame].mode) - } - - return nil -} - -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, 'E') && !strings.ContainsRune(s, '.') { - s += ".0" - } - } - - return s -} - -var hexChars = "0123456789abcdef" - -func writeStringWithEscapes(s string, buf *bytes.Buffer, escapeHTML bool) { - 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('"') -} - -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)) -} |