* Use vendored go-swagger * vendor go-swagger * revert un wanteed change * remove un-needed GO111MODULE * Update Makefile Co-Authored-By: techknowlogick <matti@mdranta.net>
		
			
				
	
	
		
			390 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			390 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| // 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.
 | |
| type Copier struct{}
 | |
| 
 | |
| // NewCopier creates a new copier with the given registry. If a nil registry is provided
 | |
| // a default registry is used.
 | |
| func NewCopier() Copier {
 | |
| 	return Copier{}
 | |
| }
 | |
| 
 | |
| // CopyDocument handles copying a document from src to dst.
 | |
| func CopyDocument(dst ValueWriter, src ValueReader) error {
 | |
| 	return Copier{}.CopyDocument(dst, src)
 | |
| }
 | |
| 
 | |
| // CopyDocument handles copying one document from the src to the dst.
 | |
| 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)
 | |
| }
 | |
| 
 | |
| // CopyDocumentFromBytes copies the values from a BSON document represented as a
 | |
| // []byte to a ValueWriter.
 | |
| 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()
 | |
| }
 | |
| 
 | |
| // CopyBytesToDocumentWriter copies the values from a BSON document represented as a []byte to a
 | |
| // DocumentWriter.
 | |
| func (c Copier) CopyBytesToDocumentWriter(dst DocumentWriter, src []byte) 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)
 | |
| 		}
 | |
| 		dvw, err := dst.WriteDocumentElement(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(dvw, t, val.Data)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // CopyDocumentToBytes copies an entire document from the ValueReader and
 | |
| // returns it as bytes.
 | |
| 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.
 | |
| 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
 | |
| }
 | |
| 
 | |
| // CopyValueFromBytes will write the value represtend by t and src to dst.
 | |
| 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.
 | |
| 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.
 | |
| 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.
 | |
| 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()
 | |
| }
 |