Don Newton | 379ae25 | 2019-04-01 12:17:06 -0400 | [diff] [blame^] | 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 bson |
| 8 | |
| 9 | import ( |
| 10 | "errors" |
| 11 | "io" |
| 12 | |
| 13 | "github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore" |
| 14 | ) |
| 15 | |
| 16 | // ErrNilReader indicates that an operation was attempted on a nil bson.Reader. |
| 17 | var ErrNilReader = errors.New("nil reader") |
| 18 | var errValidateDone = errors.New("validation loop complete") |
| 19 | |
| 20 | // Raw is a wrapper around a byte slice. It will interpret the slice as a |
| 21 | // BSON document. This type is a wrapper around a bsoncore.Document. Errors returned from the |
| 22 | // methods on this type and associated types come from the bsoncore package. |
| 23 | type Raw []byte |
| 24 | |
| 25 | // NewFromIOReader reads in a document from the given io.Reader and constructs a Raw from |
| 26 | // it. |
| 27 | func NewFromIOReader(r io.Reader) (Raw, error) { |
| 28 | doc, err := bsoncore.NewDocumentFromReader(r) |
| 29 | return Raw(doc), err |
| 30 | } |
| 31 | |
| 32 | // Validate validates the document. This method only validates the first document in |
| 33 | // the slice, to validate other documents, the slice must be resliced. |
| 34 | func (r Raw) Validate() (err error) { return bsoncore.Document(r).Validate() } |
| 35 | |
| 36 | // Lookup search the document, potentially recursively, for the given key. If |
| 37 | // there are multiple keys provided, this method will recurse down, as long as |
| 38 | // the top and intermediate nodes are either documents or arrays.If an error |
| 39 | // occurs or if the value doesn't exist, an empty RawValue is returned. |
| 40 | func (r Raw) Lookup(key ...string) RawValue { |
| 41 | return convertFromCoreValue(bsoncore.Document(r).Lookup(key...)) |
| 42 | } |
| 43 | |
| 44 | // LookupErr searches the document and potentially subdocuments or arrays for the |
| 45 | // provided key. Each key provided to this method represents a layer of depth. |
| 46 | func (r Raw) LookupErr(key ...string) (RawValue, error) { |
| 47 | val, err := bsoncore.Document(r).LookupErr(key...) |
| 48 | return convertFromCoreValue(val), err |
| 49 | } |
| 50 | |
| 51 | // Elements returns this document as a slice of elements. The returned slice will contain valid |
| 52 | // elements. If the document is not valid, the elements up to the invalid point will be returned |
| 53 | // along with an error. |
| 54 | func (r Raw) Elements() ([]RawElement, error) { |
| 55 | elems, err := bsoncore.Document(r).Elements() |
| 56 | relems := make([]RawElement, 0, len(elems)) |
| 57 | for _, elem := range elems { |
| 58 | relems = append(relems, RawElement(elem)) |
| 59 | } |
| 60 | return relems, err |
| 61 | } |
| 62 | |
| 63 | // Values returns this document as a slice of values. The returned slice will contain valid values. |
| 64 | // If the document is not valid, the values up to the invalid point will be returned along with an |
| 65 | // error. |
| 66 | func (r Raw) Values() ([]RawValue, error) { |
| 67 | vals, err := bsoncore.Document(r).Values() |
| 68 | rvals := make([]RawValue, 0, len(vals)) |
| 69 | for _, val := range vals { |
| 70 | rvals = append(rvals, convertFromCoreValue(val)) |
| 71 | } |
| 72 | return rvals, err |
| 73 | } |
| 74 | |
| 75 | // Index searches for and retrieves the element at the given index. This method will panic if |
| 76 | // the document is invalid or if the index is out of bounds. |
| 77 | func (r Raw) Index(index uint) RawElement { return RawElement(bsoncore.Document(r).Index(index)) } |
| 78 | |
| 79 | // IndexErr searches for and retrieves the element at the given index. |
| 80 | func (r Raw) IndexErr(index uint) (RawElement, error) { |
| 81 | elem, err := bsoncore.Document(r).IndexErr(index) |
| 82 | return RawElement(elem), err |
| 83 | } |
| 84 | |
| 85 | // String implements the fmt.Stringer interface. |
| 86 | func (r Raw) String() string { return bsoncore.Document(r).String() } |
| 87 | |
| 88 | // readi32 is a helper function for reading an int32 from slice of bytes. |
| 89 | func readi32(b []byte) int32 { |
| 90 | _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 |
| 91 | return int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24 |
| 92 | } |