123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- // 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 (
- "fmt"
- "io"
- "go.mongodb.org/mongo-driver/bson/bsontype"
- "go.mongodb.org/mongo-driver/bson/primitive"
- "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
- )
- // Copier is a type that allows copying between ValueReaders, ValueWriters, and
- // []byte values.
- //
- // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- type Copier struct{}
- // NewCopier creates a new copier with the given registry. If a nil registry is provided
- // a default registry is used.
- //
- // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func NewCopier() Copier {
- return Copier{}
- }
- // CopyDocument handles copying a document from src to dst.
- //
- // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func CopyDocument(dst ValueWriter, src ValueReader) error {
- return Copier{}.CopyDocument(dst, src)
- }
- // CopyDocument handles copying one document from the src to the dst.
- //
- // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func (c Copier) CopyDocument(dst ValueWriter, src ValueReader) error {
- dr, err := src.ReadDocument()
- if err != nil {
- return err
- }
- dw, err := dst.WriteDocument()
- if err != nil {
- return err
- }
- return c.copyDocumentCore(dw, dr)
- }
- // CopyArrayFromBytes copies the values from a BSON array represented as a
- // []byte to a ValueWriter.
- //
- // Deprecated: Copying BSON arrays using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func (c Copier) CopyArrayFromBytes(dst ValueWriter, src []byte) error {
- aw, err := dst.WriteArray()
- if err != nil {
- return err
- }
- err = c.CopyBytesToArrayWriter(aw, src)
- if err != nil {
- return err
- }
- return aw.WriteArrayEnd()
- }
- // CopyDocumentFromBytes copies the values from a BSON document represented as a
- // []byte to a ValueWriter.
- //
- // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func (c Copier) CopyDocumentFromBytes(dst ValueWriter, src []byte) error {
- dw, err := dst.WriteDocument()
- if err != nil {
- return err
- }
- err = c.CopyBytesToDocumentWriter(dw, src)
- if err != nil {
- return err
- }
- return dw.WriteDocumentEnd()
- }
- type writeElementFn func(key string) (ValueWriter, error)
- // CopyBytesToArrayWriter copies the values from a BSON Array represented as a []byte to an
- // ArrayWriter.
- //
- // Deprecated: Copying BSON arrays using the ArrayWriter interface will not be supported in Go
- // Driver 2.0.
- func (c Copier) CopyBytesToArrayWriter(dst ArrayWriter, src []byte) error {
- wef := func(_ string) (ValueWriter, error) {
- return dst.WriteArrayElement()
- }
- return c.copyBytesToValueWriter(src, wef)
- }
- // CopyBytesToDocumentWriter copies the values from a BSON document represented as a []byte to a
- // DocumentWriter.
- //
- // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) error {
- wef := func(key string) (ValueWriter, error) {
- return dst.WriteDocumentElement(key)
- }
- return c.copyBytesToValueWriter(src, wef)
- }
- func (c Copier) copyBytesToValueWriter(src []byte, wef writeElementFn) error {
- // TODO(skriptble): Create errors types here. Anything thats a tag should be a property.
- length, rem, ok := bsoncore.ReadLength(src)
- if !ok {
- return fmt.Errorf("couldn't read length from src, not enough bytes. length=%d", len(src))
- }
- if len(src) < int(length) {
- return fmt.Errorf("length read exceeds number of bytes available. length=%d bytes=%d", len(src), length)
- }
- rem = rem[:length-4]
- var t bsontype.Type
- var key string
- var val bsoncore.Value
- for {
- t, rem, ok = bsoncore.ReadType(rem)
- if !ok {
- return io.EOF
- }
- if t == bsontype.Type(0) {
- if len(rem) != 0 {
- return fmt.Errorf("document end byte found before end of document. remaining bytes=%v", rem)
- }
- break
- }
- key, rem, ok = bsoncore.ReadKey(rem)
- if !ok {
- return fmt.Errorf("invalid key found. remaining bytes=%v", rem)
- }
- // write as either array element or document element using writeElementFn
- vw, err := wef(key)
- if err != nil {
- return err
- }
- val, rem, ok = bsoncore.ReadValue(rem, t)
- if !ok {
- return fmt.Errorf("not enough bytes available to read type. bytes=%d type=%s", len(rem), t)
- }
- err = c.CopyValueFromBytes(vw, t, val.Data)
- if err != nil {
- return err
- }
- }
- return nil
- }
- // CopyDocumentToBytes copies an entire document from the ValueReader and
- // returns it as bytes.
- //
- // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func (c Copier) CopyDocumentToBytes(src ValueReader) ([]byte, error) {
- return c.AppendDocumentBytes(nil, src)
- }
- // AppendDocumentBytes functions the same as CopyDocumentToBytes, but will
- // append the result to dst.
- //
- // Deprecated: Copying BSON documents using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func (c Copier) AppendDocumentBytes(dst []byte, src ValueReader) ([]byte, error) {
- if br, ok := src.(BytesReader); ok {
- _, dst, err := br.ReadValueBytes(dst)
- return dst, err
- }
- vw := vwPool.Get().(*valueWriter)
- defer vwPool.Put(vw)
- vw.reset(dst)
- err := c.CopyDocument(vw, src)
- dst = vw.buf
- return dst, err
- }
- // AppendArrayBytes copies an array from the ValueReader to dst.
- //
- // Deprecated: Copying BSON arrays using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func (c Copier) AppendArrayBytes(dst []byte, src ValueReader) ([]byte, error) {
- if br, ok := src.(BytesReader); ok {
- _, dst, err := br.ReadValueBytes(dst)
- return dst, err
- }
- vw := vwPool.Get().(*valueWriter)
- defer vwPool.Put(vw)
- vw.reset(dst)
- err := c.copyArray(vw, src)
- dst = vw.buf
- return dst, err
- }
- // CopyValueFromBytes will write the value represtend by t and src to dst.
- //
- // Deprecated: Use [go.mongodb.org/mongo-driver/bson.UnmarshalValue] instead.
- func (c Copier) CopyValueFromBytes(dst ValueWriter, t bsontype.Type, src []byte) error {
- if wvb, ok := dst.(BytesWriter); ok {
- return wvb.WriteValueBytes(t, src)
- }
- vr := vrPool.Get().(*valueReader)
- defer vrPool.Put(vr)
- vr.reset(src)
- vr.pushElement(t)
- return c.CopyValue(dst, vr)
- }
- // CopyValueToBytes copies a value from src and returns it as a bsontype.Type and a
- // []byte.
- //
- // Deprecated: Use [go.mongodb.org/mongo-driver/bson.MarshalValue] instead.
- func (c Copier) CopyValueToBytes(src ValueReader) (bsontype.Type, []byte, error) {
- return c.AppendValueBytes(nil, src)
- }
- // AppendValueBytes functions the same as CopyValueToBytes, but will append the
- // result to dst.
- //
- // Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go
- // Driver 2.0.
- func (c Copier) AppendValueBytes(dst []byte, src ValueReader) (bsontype.Type, []byte, error) {
- if br, ok := src.(BytesReader); ok {
- return br.ReadValueBytes(dst)
- }
- vw := vwPool.Get().(*valueWriter)
- defer vwPool.Put(vw)
- start := len(dst)
- vw.reset(dst)
- vw.push(mElement)
- err := c.CopyValue(vw, src)
- if err != nil {
- return 0, dst, err
- }
- return bsontype.Type(vw.buf[start]), vw.buf[start+2:], nil
- }
- // CopyValue will copy a single value from src to dst.
- //
- // Deprecated: Copying BSON values using the ValueWriter and ValueReader interfaces will not be
- // supported in Go Driver 2.0.
- func (c Copier) CopyValue(dst ValueWriter, src ValueReader) error {
- var err error
- switch src.Type() {
- case bsontype.Double:
- var f64 float64
- f64, err = src.ReadDouble()
- if err != nil {
- break
- }
- err = dst.WriteDouble(f64)
- case bsontype.String:
- var str string
- str, err = src.ReadString()
- if err != nil {
- return err
- }
- err = dst.WriteString(str)
- case bsontype.EmbeddedDocument:
- err = c.CopyDocument(dst, src)
- case bsontype.Array:
- err = c.copyArray(dst, src)
- case bsontype.Binary:
- var data []byte
- var subtype byte
- data, subtype, err = src.ReadBinary()
- if err != nil {
- break
- }
- err = dst.WriteBinaryWithSubtype(data, subtype)
- case bsontype.Undefined:
- err = src.ReadUndefined()
- if err != nil {
- break
- }
- err = dst.WriteUndefined()
- case bsontype.ObjectID:
- var oid primitive.ObjectID
- oid, err = src.ReadObjectID()
- if err != nil {
- break
- }
- err = dst.WriteObjectID(oid)
- case bsontype.Boolean:
- var b bool
- b, err = src.ReadBoolean()
- if err != nil {
- break
- }
- err = dst.WriteBoolean(b)
- case bsontype.DateTime:
- var dt int64
- dt, err = src.ReadDateTime()
- if err != nil {
- break
- }
- err = dst.WriteDateTime(dt)
- case bsontype.Null:
- err = src.ReadNull()
- if err != nil {
- break
- }
- err = dst.WriteNull()
- case bsontype.Regex:
- var pattern, options string
- pattern, options, err = src.ReadRegex()
- if err != nil {
- break
- }
- err = dst.WriteRegex(pattern, options)
- case bsontype.DBPointer:
- var ns string
- var pointer primitive.ObjectID
- ns, pointer, err = src.ReadDBPointer()
- if err != nil {
- break
- }
- err = dst.WriteDBPointer(ns, pointer)
- case bsontype.JavaScript:
- var js string
- js, err = src.ReadJavascript()
- if err != nil {
- break
- }
- err = dst.WriteJavascript(js)
- case bsontype.Symbol:
- var symbol string
- symbol, err = src.ReadSymbol()
- if err != nil {
- break
- }
- err = dst.WriteSymbol(symbol)
- case bsontype.CodeWithScope:
- var code string
- var srcScope DocumentReader
- code, srcScope, err = src.ReadCodeWithScope()
- if err != nil {
- break
- }
- var dstScope DocumentWriter
- dstScope, err = dst.WriteCodeWithScope(code)
- if err != nil {
- break
- }
- err = c.copyDocumentCore(dstScope, srcScope)
- case bsontype.Int32:
- var i32 int32
- i32, err = src.ReadInt32()
- if err != nil {
- break
- }
- err = dst.WriteInt32(i32)
- case bsontype.Timestamp:
- var t, i uint32
- t, i, err = src.ReadTimestamp()
- if err != nil {
- break
- }
- err = dst.WriteTimestamp(t, i)
- case bsontype.Int64:
- var i64 int64
- i64, err = src.ReadInt64()
- if err != nil {
- break
- }
- err = dst.WriteInt64(i64)
- case bsontype.Decimal128:
- var d128 primitive.Decimal128
- d128, err = src.ReadDecimal128()
- if err != nil {
- break
- }
- err = dst.WriteDecimal128(d128)
- case bsontype.MinKey:
- err = src.ReadMinKey()
- if err != nil {
- break
- }
- err = dst.WriteMinKey()
- case bsontype.MaxKey:
- err = src.ReadMaxKey()
- if err != nil {
- break
- }
- err = dst.WriteMaxKey()
- default:
- err = fmt.Errorf("Cannot copy unknown BSON type %s", src.Type())
- }
- return err
- }
- func (c Copier) copyArray(dst ValueWriter, src ValueReader) error {
- ar, err := src.ReadArray()
- if err != nil {
- return err
- }
- aw, err := dst.WriteArray()
- if err != nil {
- return err
- }
- for {
- vr, err := ar.ReadValue()
- if err == ErrEOA {
- break
- }
- if err != nil {
- return err
- }
- vw, err := aw.WriteArrayElement()
- if err != nil {
- return err
- }
- err = c.CopyValue(vw, vr)
- if err != nil {
- return err
- }
- }
- return aw.WriteArrayEnd()
- }
- func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error {
- for {
- key, vr, err := dr.ReadElement()
- if err == ErrEOD {
- break
- }
- if err != nil {
- return err
- }
- vw, err := dw.WriteDocumentElement(key)
- if err != nil {
- return err
- }
- err = c.CopyValue(vw, vr)
- if err != nil {
- return err
- }
- }
- return dw.WriteDocumentEnd()
- }
|